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