File:
1.00.10a/server/base/phpmailer/class.smtp.php (
View as Code)
1: 2: /*~ class.smtp.php
3: .---------------------------------------------------------------------------.
4: | Software: PHPMailer - PHP email class |
5: | Version: 2.1 |
6: | Contact: via sourceforge.net support pages (also www.codeworxtech.com) |
7: | Info: http://phpmailer.sourceforge.net |
8: | Support: http://sourceforge.net/projects/phpmailer/ |
9: | ------------------------------------------------------------------------- |
10: | Author: Andy Prevost (project admininistrator) |
11: | Author: Brent R. Matzelle (original founder) |
12: | Copyright (c) 2004-2007, Andy Prevost. All Rights Reserved. |
13: | Copyright (c) 2001-2003, Brent R. Matzelle |
14: | ------------------------------------------------------------------------- |
15: | License: Distributed under the Lesser General Public License (LGPL) |
16: | http://www.gnu.org/copyleft/lesser.html |
17: | This program is distributed in the hope that it will be useful - WITHOUT |
18: | ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or |
19: | FITNESS FOR A PARTICULAR PURPOSE. |
20: | ------------------------------------------------------------------------- |
21: | We offer a number of paid services (www.codeworxtech.com): |
22: | - Web Hosting on highly optimized fast and secure servers |
23: | - Technology Consulting |
24: | - Oursourcing (highly qualified programmers and graphic designers) |
25: '---------------------------------------------------------------------------'
26:
27: /**
28: * SMTP is rfc 821 compliant and implements all the rfc 821 SMTP
29: * commands except TURN which will always return a not implemented
30: * error. SMTP also provides some utility methods for sending mail
31: * to an SMTP server.
32: * @package PHPMailer
33: * @author Chris Ryan
34: */
35:
36: class SMTP {
37: /**
38: * SMTP server port
39: * @var int
40: */
41: public $SMTP_PORT = 25;
42:
43: /**
44: * SMTP reply line ending
45: * @var string
46: */
47: public $CRLF = "\r\n";
48:
49: /**
50: * Sets whether debugging is turned on
51: * @var bool
52: */
53: public $do_debug; // the level of debug to perform
54:
55: /**
56: * Sets VERP use on/off (default is off)
57: * @var bool
58: */
59: public $do_verp = false;
60:
61: /**#@+
62: * @access private
63: */
64: private $smtp_conn; // the socket to the server
65: private $error; // error if any on the last call
66: private $helo_rply; // the reply the server sent to us for HELO
67: /**#@-*/
68:
69: /**
70: * Initialize the class so that the data is in a known state.
71: * @access public
72: * @return void
73: */
74: public function __construct() {
75: $this->smtp_conn = 0;
76: $this->error = null;
77: $this->helo_rply = null;
78:
79: $this->do_debug = 0;
80: }
81:
82: /*************************************************************
83: * CONNECTION FUNCTIONS *
84: ***********************************************************/
85:
86: /**
87: * Connect to the server specified on the port specified.
88: * If the port is not specified use the default SMTP_PORT.
89: * If tval is specified then a connection will try and be
90: * established with the server for that number of seconds.
91: * If tval is not specified the default is 30 seconds to
92: * try on the connection.
93: *
94: * SMTP CODE SUCCESS: 220
95: * SMTP CODE FAILURE: 421
96: * @access public
97: * @return bool
98: */
99: public function Connect($host,$port=0,$tval=30) {
100: /* set the error val to null so there is no confusion */
101: $this->error = null;
102:
103: /* make sure we are __not__ connected */
104: if($this->connected()) {
105: /* ok we are connected! what should we do?
106: * for now we will just give an error saying we
107: * are already connected
108: */
109: $this->error = array("error" => "Already connected to a server");
110: return false;
111: }
112:
113: if(empty($port)) {
114: $port = $this->SMTP_PORT;
115: }
116:
117: /* connect to the smtp server */
118: $this->smtp_conn = fsockopen($host, // the host of the server
119: $port, // the port to use
120: $errno, // error number if any
121: $errstr, // error message if any
122: $tval); // give up after ? secs
123: /* verify we connected properly */
124: if(empty($this->smtp_conn)) {
125: $this->error = array("error" => "Failed to connect to server",
126: "errno" => $errno,
127: "errstr" => $errstr);
128: if($this->do_debug >= 1) {
129: echo "SMTP -> ERROR: " . $this->error["error"] .
130: ": $errstr ($errno)" . $this->CRLF;
131: }
132: return false;
133: }
134:
135: /* sometimes the SMTP server takes a little longer to respond
136: * so we will give it a longer timeout for the first read
137: * - Windows still does not have support for this timeout function
138: */
139: if(substr(PHP_OS, 0, 3) != "WIN")
140: socket_set_timeout($this->smtp_conn, $tval, 0);
141:
142: /* get any announcement stuff */
143: $announce = $this->get_lines();
144:
145: /* set the timeout of any socket functions at 1/10 of a second */
146: //if(function_exists("socket_set_timeout"))
147: // socket_set_timeout($this->smtp_conn, 0, 100000);
148:
149: if($this->do_debug >= 2) {
150: echo "SMTP -> FROM SERVER:" . $this->CRLF . $announce;
151: }
152:
153: return true;
154: }
155:
156: /**
157: * Initiate a TSL communication with the server.
158: *
159: * SMTP CODE 220 Ready to start TLS
160: * SMTP CODE 501 Syntax error (no parameters allowed)
161: * SMTP CODE 454 TLS not available due to temporary reason
162: * @access public
163: * @return bool success
164: */
165: public function StartTLS() {
166: $this->error = null; # to avoid confusion
167:
168: if(!$this->connected()) {
169: $this->error = array("error" => "Called StartTLS() without being connected");
170: return false;
171: }
172:
173: fputs($this->smtp_conn,"STARTTLS" . $extra . $this->CRLF);
174:
175: $rply = $this->get_lines();
176: $code = substr($rply,0,3);
177:
178: if($this->do_debug >= 2) {
179: echo "SMTP -> FROM SERVER:" . $this->CRLF . $rply;
180: }
181:
182: if($code != 220) {
183: $this->error =
184: array("error" => "STARTTLS not accepted from server",
185: "smtp_code" => $code,
186: "smtp_msg" => substr($rply,4));
187: if($this->do_debug >= 1) {
188: echo "SMTP -> ERROR: " . $this->error["error"] . ": " . $rply . $this->CRLF;
189: }
190: return false;
191: }
192:
193: //Begin encrypted connection
194: if(!stream_socket_enable_crypto($this->smtp_conn, true, STREAM_CRYPTO_METHOD_TLS_CLIENT)) {
195: return false;
196: }
197:
198: return true;
199: }
200:
201: /**
202: * Performs SMTP authentication. Must be run after running the
203: * Hello() method. Returns true if successfully authenticated.
204: * @access public
205: * @return bool
206: */
207: public function Authenticate($username, $password) {
208: // Start authentication
209: fputs($this->smtp_conn,"AUTH LOGIN" . $this->CRLF);
210:
211: $rply = $this->get_lines();
212: $code = substr($rply,0,3);
213:
214: if($code != 334) {
215: $this->error =
216: array("error" => "AUTH not accepted from server",
217: "smtp_code" => $code,
218: "smtp_msg" => substr($rply,4));
219: if($this->do_debug >= 1) {
220: echo "SMTP -> ERROR: " . $this->error["error"] .
221: ": " . $rply . $this->CRLF;
222: }
223: return false;
224: }
225:
226: // Send encoded username
227: fputs($this->smtp_conn, base64_encode($username) . $this->CRLF);
228:
229: $rply = $this->get_lines();
230: $code = substr($rply,0,3);
231:
232: if($code != 334) {
233: $this->error =
234: array("error" => "Username not accepted from server",
235: "smtp_code" => $code,
236: "smtp_msg" => substr($rply,4));
237: if($this->do_debug >= 1) {
238: echo "SMTP -> ERROR: " . $this->error["error"] .
239: ": " . $rply . $this->CRLF;
240: }
241: return false;
242: }
243:
244: // Send encoded password
245: fputs($this->smtp_conn, base64_encode($password) . $this->CRLF);
246:
247: $rply = $this->get_lines();
248: $code = substr($rply,0,3);
249:
250: if($code != 235) {
251: $this->error =
252: array("error" => "Password not accepted from server",
253: "smtp_code" => $code,
254: "smtp_msg" => substr($rply,4));
255: if($this->do_debug >= 1) {
256: echo "SMTP -> ERROR: " . $this->error["error"] .
257: ": " . $rply . $this->CRLF;
258: }
259: return false;
260: }
261:
262: return true;
263: }
264:
265: /**
266: * Returns true if connected to a server otherwise false
267: * @access public
268: * @return bool
269: */
270: public function Connected() {
271: if(!empty($this->smtp_conn)) {
272: $sock_status = socket_get_status($this->smtp_conn);
273: if($sock_status["eof"]) {
274: // hmm this is an odd situation... the socket is
275: // valid but we are not connected anymore
276: if($this->do_debug >= 1) {
277: echo "SMTP -> NOTICE:" . $this->CRLF .
278: "EOF caught while checking if connected";
279: }
280: $this->Close();
281: return false;
282: }
283: return true; // everything looks good
284: }
285: return false;
286: }
287:
288: /**
289: * Closes the socket and cleans up the state of the class.
290: * It is not considered good to use this function without
291: * first trying to use QUIT.
292: * @access public
293: * @return void
294: */
295: public function Close() {
296: $this->error = null; // so there is no confusion
297: $this->helo_rply = null;
298: if(!empty($this->smtp_conn)) {
299: // close the connection and cleanup
300: fclose($this->smtp_conn);
301: $this->smtp_conn = 0;
302: }
303: }
304:
305: /***************************************************************
306: * SMTP COMMANDS *
307: *************************************************************/
308:
309: /**
310: * Issues a data command and sends the msg_data to the server
311: * finializing the mail transaction. $msg_data is the message
312: * that is to be send with the headers. Each header needs to be
313: * on a single line followed by a with the message headers
314: * and the message body being seperated by and additional .
315: *
316: * Implements rfc 821: DATA
317: *
318: * SMTP CODE INTERMEDIATE: 354
319: * [data]
320: * .
321: * SMTP CODE SUCCESS: 250
322: * SMTP CODE FAILURE: 552,554,451,452
323: * SMTP CODE FAILURE: 451,554
324: * SMTP CODE ERROR : 500,501,503,421
325: * @access public
326: * @return bool
327: */
328: public function Data($msg_data) {
329: $this->error = null; // so no confusion is caused
330:
331: if(!$this->connected()) {
332: $this->error = array(
333: "error" => "Called Data() without being connected");
334: return false;
335: }
336:
337: fputs($this->smtp_conn,"DATA" . $this->CRLF);
338:
339: $rply = $this->get_lines();
340: $code = substr($rply,0,3);
341:
342: if($this->do_debug >= 2) {
343: echo "SMTP -> FROM SERVER:" . $this->CRLF . $rply;
344: }
345:
346: if($code != 354) {
347: $this->error =
348: array("error" => "DATA command not accepted from server",
349: "smtp_code" => $code,
350: "smtp_msg" => substr($rply,4));
351: if($this->do_debug >= 1) {
352: echo "SMTP -> ERROR: " . $this->error["error"] .
353: ": " . $rply . $this->CRLF;
354: }
355: return false;
356: }
357:
358: /* the server is ready to accept data!
359: * according to rfc 821 we should not send more than 1000
360: * including the CRLF
361: * characters on a single line so we will break the data up
362: * into lines by \r and/or \n then if needed we will break
363: * each of those into smaller lines to fit within the limit.
364: * in addition we will be looking for lines that start with
365: * a period '.' and append and additional period '.' to that
366: * line. NOTE: this does not count towards are limit.
367: */
368:
369: // normalize the line breaks so we know the explode works
370: $msg_data = str_replace("\r\n","\n",$msg_data);
371: $msg_data = str_replace("\r","\n",$msg_data);
372: $lines = explode("\n",$msg_data);
373:
374: /* we need to find a good way to determine is headers are
375: * in the msg_data or if it is a straight msg body
376: * currently I am assuming rfc 822 definitions of msg headers
377: * and if the first field of the first line (':' sperated)
378: * does not contain a space then it _should_ be a header
379: * and we can process all lines before a blank "" line as
380: * headers.
381: */
382: $field = substr($lines[0],0,strpos($lines[0],":"));
383: $in_headers = false;
384: if(!empty($field) && !strstr($field," ")) {
385: $in_headers = true;
386: }
387:
388: $max_line_length = 998; // used below; set here for ease in change
389:
390: while(list(,$line) = @each($lines)) {
391: $lines_out = null;
392: if($line == "" && $in_headers) {
393: $in_headers = false;
394: }
395: // ok we need to break this line up into several smaller lines
396: while(strlen($line) > $max_line_length) {
397: $pos = strrpos(substr($line,0,$max_line_length)," ");
398:
399: // Patch to fix DOS attack
400: if(!$pos) {
401: $pos = $max_line_length - 1;
402: $lines_out[] = substr($line,0,$pos);
403: $line = substr($line,$pos);
404: } else {
405: $lines_out[] = substr($line,0,$pos);
406: $line = substr($line,$pos + 1);
407: }
408:
409: /* if we are processing headers we need to
410: * add a LWSP-char to the front of the new line
411: * rfc 822 on long msg headers
412: */
413: if($in_headers) {
414: $line = "\t" . $line;
415: }
416: }
417: $lines_out[] = $line;
418:
419: // now send the lines to the server
420: while(list(,$line_out) = @each($lines_out)) {
421: if(strlen($line_out) > 0)
422: {
423: if(substr($line_out, 0, 1) == ".") {
424: $line_out = "." . $line_out;
425: }
426: }
427: fputs($this->smtp_conn,$line_out . $this->CRLF);
428: }
429: }
430:
431: // ok all the message data has been sent so lets get this
432: // over with aleady
433: fputs($this->smtp_conn, $this->CRLF . "." . $this->CRLF);
434:
435: $rply = $this->get_lines();
436: $code = substr($rply,0,3);
437:
438: if($this->do_debug >= 2) {
439: echo "SMTP -> FROM SERVER:" . $this->CRLF . $rply;
440: }
441:
442: if($code != 250) {
443: $this->error =
444: array("error" => "DATA not accepted from server",
445: "smtp_code" => $code,
446: "smtp_msg" => substr($rply,4));
447: if($this->do_debug >= 1) {
448: echo "SMTP -> ERROR: " . $this->error["error"] .
449: ": " . $rply . $this->CRLF;
450: }
451: return false;
452: }
453: return true;
454: }
455:
456: /**
457: * Expand takes the name and asks the server to list all the
458: * people who are members of the _list_. Expand will return
459: * back and array of the result or false if an error occurs.
460: * Each value in the array returned has the format of:
461: * [ ]
462: * The definition of is defined in rfc 821
463: *
464: * Implements rfc 821: EXPN
465: *
466: * SMTP CODE SUCCESS: 250
467: * SMTP CODE FAILURE: 550
468: * SMTP CODE ERROR : 500,501,502,504,421
469: * @access public
470: * @return string array
471: */
472: public function Expand($name) {
473: $this->error = null; // so no confusion is caused
474:
475: if(!$this->connected()) {
476: $this->error = array(
477: "error" => "Called Expand() without being connected");
478: return false;
479: }
480:
481: fputs($this->smtp_conn,"EXPN " . $name . $this->CRLF);
482:
483: $rply = $this->get_lines();
484: $code = substr($rply,0,3);
485:
486: if($this->do_debug >= 2) {
487: echo "SMTP -> FROM SERVER:" . $this->CRLF . $rply;
488: }
489:
490: if($code != 250) {
491: $this->error =
492: array("error" => "EXPN not accepted from server",
493: "smtp_code" => $code,
494: "smtp_msg" => substr($rply,4));
495: if($this->do_debug >= 1) {
496: echo "SMTP -> ERROR: " . $this->error["error"] .
497: ": " . $rply . $this->CRLF;
498: }
499: return false;
500: }
501:
502: // parse the reply and place in our array to return to user
503: $entries = explode($this->CRLF,$rply);
504: while(list(,$l) = @each($entries)) {
505: $list[] = substr($l,4);
506: }
507:
508: return $list;
509: }
510:
511: /**
512: * Sends the HELO command to the smtp server.
513: * This makes sure that we and the server are in
514: * the same known state.
515: *
516: * Implements from rfc 821: HELO
517: *
518: * SMTP CODE SUCCESS: 250
519: * SMTP CODE ERROR : 500, 501, 504, 421
520: * @access public
521: * @return bool
522: */
523: public function Hello($host="") {
524: $this->error = null; // so no confusion is caused
525:
526: if(!$this->connected()) {
527: $this->error = array(
528: "error" => "Called Hello() without being connected");
529: return false;
530: }
531:
532: // if a hostname for the HELO was not specified determine
533: //a suitable one to send
534: if(empty($host)) {
535: // we need to determine some sort of appopiate default
536: // to send to the server
537: $host = "localhost";
538: }
539:
540: // Send extended hello first (RFC 2821)
541: if(!$this->SendHello("EHLO", $host))
542: {
543: if(!$this->SendHello("HELO", $host))
544: return false;
545: }
546:
547: return true;
548: }
549:
550: /**
551: * Sends a HELO/EHLO command.
552: * @access private
553: * @return bool
554: */
555: private function SendHello($hello, $host) {
556: fputs($this->smtp_conn, $hello . " " . $host . $this->CRLF);
557:
558: $rply = $this->get_lines();
559: $code = substr($rply,0,3);
560:
561: if($this->do_debug >= 2) {
562: echo "SMTP -> FROM SERVER: " . $this->CRLF . $rply;
563: }
564:
565: if($code != 250) {
566: $this->error =
567: array("error" => $hello . " not accepted from server",
568: "smtp_code" => $code,
569: "smtp_msg" => substr($rply,4));
570: if($this->do_debug >= 1) {
571: echo "SMTP -> ERROR: " . $this->error["error"] .
572: ": " . $rply . $this->CRLF;
573: }
574: return false;
575: }
576:
577: $this->helo_rply = $rply;
578:
579: return true;
580: }
581:
582: /**
583: * Gets help information on the keyword specified. If the keyword
584: * is not specified then returns generic help, ussually contianing
585: * A list of keywords that help is available on. This function
586: * returns the results back to the user. It is up to the user to
587: * handle the returned data. If an error occurs then false is
588: * returned with $this->error set appropiately.
589: *
590: * Implements rfc 821: HELP [ ]
591: *
592: * SMTP CODE SUCCESS: 211,214
593: * SMTP CODE ERROR : 500,501,502,504,421
594: * @access public
595: * @return string
596: */
597: public function Help($keyword="") {
598: $this->error = null; // to avoid confusion
599:
600: if(!$this->connected()) {
601: $this->error = array(
602: "error" => "Called Help() without being connected");
603: return false;
604: }
605:
606: $extra = "";
607: if(!empty($keyword)) {
608: $extra = " " . $keyword;
609: }
610:
611: fputs($this->smtp_conn,"HELP" . $extra . $this->CRLF);
612:
613: $rply = $this->get_lines();
614: $code = substr($rply,0,3);
615:
616: if($this->do_debug >= 2) {
617: echo "SMTP -> FROM SERVER:" . $this->CRLF . $rply;
618: }
619:
620: if($code != 211 && $code != 214) {
621: $this->error =
622: array("error" => "HELP not accepted from server",
623: "smtp_code" => $code,
624: "smtp_msg" => substr($rply,4));
625: if($this->do_debug >= 1) {
626: echo "SMTP -> ERROR: " . $this->error["error"] .
627: ": " . $rply . $this->CRLF;
628: }
629: return false;
630: }
631:
632: return $rply;
633: }
634:
635: /**
636: * Starts a mail transaction from the email address specified in
637: * $from. Returns true if successful or false otherwise. If True
638: * the mail transaction is started and then one or more Recipient
639: * commands may be called followed by a Data command.
640: *
641: * Implements rfc 821: MAIL FROM:
642: *
643: * SMTP CODE SUCCESS: 250
644: * SMTP CODE SUCCESS: 552,451,452
645: * SMTP CODE SUCCESS: 500,501,421
646: * @access public
647: * @return bool
648: */
649: public function Mail($from) {
650: $this->error = null; // so no confusion is caused
651:
652: if(!$this->connected()) {
653: $this->error = array(
654: "error" => "Called Mail() without being connected");
655: return false;
656: }
657:
658: $useVerp = ($this->do_verp ? "XVERP" : "");
659: fputs($this->smtp_conn,"MAIL FROM:<" . $from . ">" . $useVerp . $this->CRLF);
660:
661: $rply = $this->get_lines();
662: $code = substr($rply,0,3);
663:
664: if($this->do_debug >= 2) {
665: echo "SMTP -> FROM SERVER:" . $this->CRLF . $rply;
666: }
667:
668: if($code != 250) {
669: $this->error =
670: array("error" => "MAIL not accepted from server",
671: "smtp_code" => $code,
672: "smtp_msg" => substr($rply,4));
673: if($this->do_debug >= 1) {
674: echo "SMTP -> ERROR: " . $this->error["error"] .
675: ": " . $rply . $this->CRLF;
676: }
677: return false;
678: }
679: return true;
680: }
681:
682: /**
683: * Sends the command NOOP to the SMTP server.
684: *
685: * Implements from rfc 821: NOOP
686: *
687: * SMTP CODE SUCCESS: 250
688: * SMTP CODE ERROR : 500, 421
689: * @access public
690: * @return bool
691: */
692: public function Noop() {
693: $this->error = null; // so no confusion is caused
694:
695: if(!$this->connected()) {
696: $this->error = array(
697: "error" => "Called Noop() without being connected");
698: return false;
699: }
700:
701: fputs($this->smtp_conn,"NOOP" . $this->CRLF);
702:
703: $rply = $this->get_lines();
704: $code = substr($rply,0,3);
705:
706: if($this->do_debug >= 2) {
707: echo "SMTP -> FROM SERVER:" . $this->CRLF . $rply;
708: }
709:
710: if($code != 250) {
711: $this->error =
712: array("error" => "NOOP not accepted from server",
713: "smtp_code" => $code,
714: "smtp_msg" => substr($rply,4));
715: if($this->do_debug >= 1) {
716: echo "SMTP -> ERROR: " . $this->error["error"] .
717: ": " . $rply . $this->CRLF;
718: }
719: return false;
720: }
721: return true;
722: }
723:
724: /**
725: * Sends the quit command to the server and then closes the socket
726: * if there is no error or the $close_on_error argument is true.
727: *
728: * Implements from rfc 821: QUIT
729: *
730: * SMTP CODE SUCCESS: 221
731: * SMTP CODE ERROR : 500
732: * @access public
733: * @return bool
734: */
735: public function Quit($close_on_error=true) {
736: $this->error = null; // so there is no confusion
737:
738: if(!$this->connected()) {
739: $this->error = array(
740: "error" => "Called Quit() without being connected");
741: return false;
742: }
743:
744: // send the quit command to the server
745: fputs($this->smtp_conn,"quit" . $this->CRLF);
746:
747: // get any good-bye messages
748: $byemsg = $this->get_lines();
749:
750: if($this->do_debug >= 2) {
751: echo "SMTP -> FROM SERVER:" . $this->CRLF . $byemsg;
752: }
753:
754: $rval = true;
755: $e = null;
756:
757: $code = substr($byemsg,0,3);
758: if($code != 221) {
759: // use e as a tmp var cause Close will overwrite $this->error
760: $e = array("error" => "SMTP server rejected quit command",
761: "smtp_code" => $code,
762: "smtp_rply" => substr($byemsg,4));
763: $rval = false;
764: if($this->do_debug >= 1) {
765: echo "SMTP -> ERROR: " . $e["error"] . ": " .
766: $byemsg . $this->CRLF;
767: }
768: }
769:
770: if(empty($e) || $close_on_error) {
771: $this->Close();
772: }
773:
774: return $rval;
775: }
776:
777: /**
778: * Sends the command RCPT to the SMTP server with the TO: argument of $to.
779: * Returns true if the recipient was accepted false if it was rejected.
780: *
781: * Implements from rfc 821: RCPT TO:
782: *
783: * SMTP CODE SUCCESS: 250,251
784: * SMTP CODE FAILURE: 550,551,552,553,450,451,452
785: * SMTP CODE ERROR : 500,501,503,421
786: * @access public
787: * @return bool
788: */
789: public function Recipient($to) {
790: $this->error = null; // so no confusion is caused
791:
792: if(!$this->connected()) {
793: $this->error = array(
794: "error" => "Called Recipient() without being connected");
795: return false;
796: }
797:
798: fputs($this->smtp_conn,"RCPT TO:<" . $to . ">" . $this->CRLF);
799:
800: $rply = $this->get_lines();
801: $code = substr($rply,0,3);
802:
803: if($this->do_debug >= 2) {
804: echo "SMTP -> FROM SERVER:" . $this->CRLF . $rply;
805: }
806:
807: if($code != 250 && $code != 251) {
808: $this->error =
809: array("error" => "RCPT not accepted from server",
810: "smtp_code" => $code,
811: "smtp_msg" => substr($rply,4));
812: if($this->do_debug >= 1) {
813: echo "SMTP -> ERROR: " . $this->error["error"] .
814: ": " . $rply . $this->CRLF;
815: }
816: return false;
817: }
818: return true;
819: }
820:
821: /**
822: * Sends the RSET command to abort and transaction that is
823: * currently in progress. Returns true if successful false
824: * otherwise.
825: *
826: * Implements rfc 821: RSET
827: *
828: * SMTP CODE SUCCESS: 250
829: * SMTP CODE ERROR : 500,501,504,421
830: * @access public
831: * @return bool
832: */
833: public function Reset() {
834: $this->error = null; // so no confusion is caused
835:
836: if(!$this->connected()) {
837: $this->error = array(
838: "error" => "Called Reset() without being connected");
839: return false;
840: }
841:
842: fputs($this->smtp_conn,"RSET" . $this->CRLF);
843:
844: $rply = $this->get_lines();
845: $code = substr($rply,0,3);
846:
847: if($this->do_debug >= 2) {
848: echo "SMTP -> FROM SERVER:" . $this->CRLF . $rply;
849: }
850:
851: if($code != 250) {
852: $this->error =
853: array("error" => "RSET failed",
854: "smtp_code" => $code,
855: "smtp_msg" => substr($rply,4));
856: if($this->do_debug >= 1) {
857: echo "SMTP -> ERROR: " . $this->error["error"] .
858: ": " . $rply . $this->CRLF;
859: }
860: return false;
861: }
862:
863: return true;
864: }
865:
866: /**
867: * Starts a mail transaction from the email address specified in
868: * $from. Returns true if successful or false otherwise. If True
869: * the mail transaction is started and then one or more Recipient
870: * commands may be called followed by a Data command. This command
871: * will send the message to the users terminal if they are logged
872: * in.
873: *
874: * Implements rfc 821: SEND FROM:
875: *
876: * SMTP CODE SUCCESS: 250
877: * SMTP CODE SUCCESS: 552,451,452
878: * SMTP CODE SUCCESS: 500,501,502,421
879: * @access public
880: * @return bool
881: */
882: public function Send($from) {
883: $this->error = null; // so no confusion is caused
884:
885: if(!$this->connected()) {
886: $this->error = array(
887: "error" => "Called Send() without being connected");
888: return false;
889: }
890:
891: fputs($this->smtp_conn,"SEND FROM:" . $from . $this->CRLF);
892:
893: $rply = $this->get_lines();
894: $code = substr($rply,0,3);
895:
896: if($this->do_debug >= 2) {
897: echo "SMTP -> FROM SERVER:" . $this->CRLF . $rply;
898: }
899:
900: if($code != 250) {
901: $this->error =
902: array("error" => "SEND not accepted from server",
903: "smtp_code" => $code,
904: "smtp_msg" => substr($rply,4));
905: if($this->do_debug >= 1) {
906: echo "SMTP -> ERROR: " . $this->error["error"] .
907: ": " . $rply . $this->CRLF;
908: }
909: return false;
910: }
911: return true;
912: }
913:
914: /**
915: * Starts a mail transaction from the email address specified in
916: * $from. Returns true if successful or false otherwise. If True
917: * the mail transaction is started and then one or more Recipient
918: * commands may be called followed by a Data command. This command
919: * will send the message to the users terminal if they are logged
920: * in and send them an email.
921: *
922: * Implements rfc 821: SAML FROM:
923: *
924: * SMTP CODE SUCCESS: 250
925: * SMTP CODE SUCCESS: 552,451,452
926: * SMTP CODE SUCCESS: 500,501,502,421
927: * @access public
928: * @return bool
929: */
930: public function SendAndMail($from) {
931: $this->error = null; // so no confusion is caused
932:
933: if(!$this->connected()) {
934: $this->error = array(
935: "error" => "Called SendAndMail() without being connected");
936: return false;
937: }
938:
939: fputs($this->smtp_conn,"SAML FROM:" . $from . $this->CRLF);
940:
941: $rply = $this->get_lines();
942: $code = substr($rply,0,3);
943:
944: if($this->do_debug >= 2) {
945: echo "SMTP -> FROM SERVER:" . $this->CRLF . $rply;
946: }
947:
948: if($code != 250) {
949: $this->error =
950: array("error" => "SAML not accepted from server",
951: "smtp_code" => $code,
952: "smtp_msg" => substr($rply,4));
953: if($this->do_debug >= 1) {
954: echo "SMTP -> ERROR: " . $this->error["error"] .
955: ": " . $rply . $this->CRLF;
956: }
957: return false;
958: }
959: return true;
960: }
961:
962: /**
963: * Starts a mail transaction from the email address specified in
964: * $from. Returns true if successful or false otherwise. If True
965: * the mail transaction is started and then one or more Recipient
966: * commands may be called followed by a Data command. This command
967: * will send the message to the users terminal if they are logged
968: * in or mail it to them if they are not.
969: *
970: * Implements rfc 821: SOML FROM:
971: *
972: * SMTP CODE SUCCESS: 250
973: * SMTP CODE SUCCESS: 552,451,452
974: * SMTP CODE SUCCESS: 500,501,502,421
975: * @access public
976: * @return bool
977: */
978: public function SendOrMail($from) {
979: $this->error = null; // so no confusion is caused
980:
981: if(!$this->connected()) {
982: $this->error = array(
983: "error" => "Called SendOrMail() without being connected");
984: return false;
985: }
986:
987: fputs($this->smtp_conn,"SOML FROM:" . $from . $this->CRLF);
988:
989: $rply = $this->get_lines();
990: $code = substr($rply,0,3);
991:
992: if($this->do_debug >= 2) {
993: echo "SMTP -> FROM SERVER:" . $this->CRLF . $rply;
994: }
995:
996: if($code != 250) {
997: $this->error =
998: array("error" => "SOML not accepted from server",
999: "smtp_code" => $code,
1000: "smtp_msg" => substr($rply,4));
1001: if($this->do_debug >= 1) {
1002: echo "SMTP -> ERROR: " . $this->error["error"] .
1003: ": " . $rply . $this->CRLF;
1004: }
1005: return false;
1006: }
1007: return true;
1008: }
1009:
1010: /**
1011: * This is an optional command for SMTP that this class does not
1012: * support. This method is here to make the RFC821 Definition
1013: * complete for this class and __may__ be implimented in the future
1014: *
1015: * Implements from rfc 821: TURN
1016: *
1017: * SMTP CODE SUCCESS: 250
1018: * SMTP CODE FAILURE: 502
1019: * SMTP CODE ERROR : 500, 503
1020: * @access public
1021: * @return bool
1022: */
1023: public function Turn() {
1024: $this->error = array("error" => "This method, TURN, of the SMTP ".
1025: "is not implemented");
1026: if($this->do_debug >= 1) {
1027: echo "SMTP -> NOTICE: " . $this->error["error"] . $this->CRLF;
1028: }
1029: return false;
1030: }
1031:
1032: /**
1033: * Verifies that the name is recognized by the server.
1034: * Returns false if the name could not be verified otherwise
1035: * the response from the server is returned.
1036: *
1037: * Implements rfc 821: VRFY
1038: *
1039: * SMTP CODE SUCCESS: 250,251
1040: * SMTP CODE FAILURE: 550,551,553
1041: * SMTP CODE ERROR : 500,501,502,421
1042: * @access public
1043: * @return int
1044: */
1045: public function Verify($name) {
1046: $this->error = null; // so no confusion is caused
1047:
1048: if(!$this->connected()) {
1049: $this->error = array(
1050: "error" => "Called Verify() without being connected");
1051: return false;
1052: }
1053:
1054: fputs($this->smtp_conn,"VRFY " . $name . $this->CRLF);
1055:
1056: $rply = $this->get_lines();
1057: $code = substr($rply,0,3);
1058:
1059: if($this->do_debug >= 2) {
1060: echo "SMTP -> FROM SERVER:" . $this->CRLF . $rply;
1061: }
1062:
1063: if($code != 250 && $code != 251) {
1064: $this->error =
1065: array("error" => "VRFY failed on name '$name'",
1066: "smtp_code" => $code,
1067: "smtp_msg" => substr($rply,4));
1068: if($this->do_debug >= 1) {
1069: echo "SMTP -> ERROR: " . $this->error["error"] .
1070: ": " . $rply . $this->CRLF;
1071: }
1072: return false;
1073: }
1074: return $rply;
1075: }
1076:
1077: /*******************************************************************
1078: * INTERNAL FUNCTIONS *
1079: ******************************************************************/
1080:
1081: /**
1082: * Read in as many lines as possible
1083: * either before eof or socket timeout occurs on the operation.
1084: * With SMTP we can tell if we have more lines to read if the
1085: * 4th character is '-' symbol. If it is a space then we don't
1086: * need to read anything else.
1087: * @access private
1088: * @return string
1089: */
1090: private function get_lines() {
1091: $data = "";
1092: while($str = @fgets($this->smtp_conn,515)) {
1093: if($this->do_debug >= 4) {
1094: echo "SMTP -> get_lines(): \$data was \"$data\"" .
1095: $this->CRLF;
1096: echo "SMTP -> get_lines(): \$str is \"$str\"" .
1097: $this->CRLF;
1098: }
1099: $data .= $str;
1100: if($this->do_debug >= 4) {
1101: echo "SMTP -> get_lines(): \$data is \"$data\"" . $this->CRLF;
1102: }
1103: // if the 4th character is a space then we are done reading
1104: // so just break the loop
1105: if(substr($str,3,1) == " ") { break; }
1106: }
1107: return $data;
1108: }
1109:
1110: }
1111:
1112:
1113: ?>
1114: