File: 1.01.4b/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: