@recaptime-dev's working patches + fork for Phorge, a community fork of Phabricator. (Upstream dev and stable branches are at upstream/main and upstream/stable respectively.) hq.recaptime.dev/wiki/Phorge
phorge phabricator
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

replace usage of each() with foreach() for smtp

Summary:
this replaces uses with warning suppression of each() (depreccated in
PHP7, removed in PHP8) with foreach

Test Plan: can verify that these chages do work (tested on my own install)

Reviewers: O1 Blessed Committers, #blessed_committers, dsadad, avivey, valerio.bozzolan

Reviewed By: O1 Blessed Committers, #blessed_committers, dsadad, avivey, valerio.bozzolan

Subscribers: avivey, Cigaryno, speck, tobiaswiese, valerio.bozzolan, Matthew

Differential Revision: https://we.phorge.it/D25059

authored by

MacFan4000 and committed by
Valerio Bozzolan
9623e667 66192a5b

+813 -813
+813 -813
externals/phpmailer/class.smtp.php
··· 1 - <?php 2 - /*~ class.smtp.php 3 - .---------------------------------------------------------------------------. 4 - | Software: PHPMailer - PHP email class | 5 - | Version: 5.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 - | Admin: Andy Prevost (project admininistrator) | 11 - | Authors: Andy Prevost (codeworxtech) codeworxtech@users.sourceforge.net | 12 - | : Marcus Bointon (coolbru) coolbru@users.sourceforge.net | 13 - | Founder: Brent R. Matzelle (original founder) | 14 - | Copyright (c) 2004-2009, Andy Prevost. All Rights Reserved. | 15 - | Copyright (c) 2001-2003, Brent R. Matzelle | 16 - | ------------------------------------------------------------------------- | 17 - | License: Distributed under the Lesser General Public License (LGPL) | 18 - | http://www.gnu.org/copyleft/lesser.html | 19 - | This program is distributed in the hope that it will be useful - WITHOUT | 20 - | ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | 21 - | FITNESS FOR A PARTICULAR PURPOSE. | 22 - | ------------------------------------------------------------------------- | 23 - | We offer a number of paid services (www.codeworxtech.com): | 24 - | - Web Hosting on highly optimized fast and secure servers | 25 - | - Technology Consulting | 26 - | - Oursourcing (highly qualified programmers and graphic designers) | 27 - '---------------------------------------------------------------------------' 28 - */ 29 - 30 - /** 31 - * PHPMailer - PHP SMTP email transport class 32 - * NOTE: Designed for use with PHP version 5 and up 33 - * @package PHPMailer 34 - * @author Andy Prevost 35 - * @author Marcus Bointon 36 - * @copyright 2004 - 2008 Andy Prevost 37 - * @license http://www.gnu.org/copyleft/lesser.html Distributed under the Lesser General Public License (LGPL) 38 - * @version $Id: class.smtp.php 444 2009-05-05 11:22:26Z coolbru $ 39 - */ 40 - 41 - /** 42 - * SMTP is rfc 821 compliant and implements all the rfc 821 SMTP 43 - * commands except TURN which will always return a not implemented 44 - * error. SMTP also provides some utility methods for sending mail 45 - * to an SMTP server. 46 - * original author: Chris Ryan 47 - */ 48 - 49 - class SMTP { 50 - /** 51 - * SMTP server port 52 - * @var int 53 - */ 54 - public $SMTP_PORT = 25; 55 - 56 - /** 57 - * SMTP reply line ending 58 - * @var string 59 - */ 60 - public $CRLF = "\r\n"; 61 - 62 - /** 63 - * Sets whether debugging is turned on 64 - * @var bool 65 - */ 66 - public $do_debug; // the level of debug to perform 67 - 68 - /** 69 - * Sets VERP use on/off (default is off) 70 - * @var bool 71 - */ 72 - public $do_verp = false; 73 - 74 - ///////////////////////////////////////////////// 75 - // PROPERTIES, PRIVATE AND PROTECTED 76 - ///////////////////////////////////////////////// 77 - 78 - private $smtp_conn; // the socket to the server 79 - private $error; // error if any on the last call 80 - private $helo_rply; // the reply the server sent to us for HELO 81 - 82 - /** 83 - * Initialize the class so that the data is in a known state. 84 - * @access public 85 - * @return void 86 - */ 87 - public function __construct() { 88 - $this->smtp_conn = 0; 89 - $this->error = null; 90 - $this->helo_rply = null; 91 - 92 - $this->do_debug = 0; 93 - } 94 - 95 - ///////////////////////////////////////////////// 96 - // CONNECTION FUNCTIONS 97 - ///////////////////////////////////////////////// 98 - 99 - /** 100 - * Connect to the server specified on the port specified. 101 - * If the port is not specified use the default SMTP_PORT. 102 - * If tval is specified then a connection will try and be 103 - * established with the server for that number of seconds. 104 - * If tval is not specified the default is 30 seconds to 105 - * try on the connection. 106 - * 107 - * SMTP CODE SUCCESS: 220 108 - * SMTP CODE FAILURE: 421 109 - * @access public 110 - * @return bool 111 - */ 112 - public function Connect($host, $port = 0, $tval = 30) { 113 - // set the error val to null so there is no confusion 114 - $this->error = null; 115 - 116 - // make sure we are __not__ connected 117 - if($this->connected()) { 118 - // already connected, generate error 119 - $this->error = array("error" => "Already connected to a server"); 120 - return false; 121 - } 122 - 123 - if(empty($port)) { 124 - $port = $this->SMTP_PORT; 125 - } 126 - 127 - // connect to the smtp server 128 - $this->smtp_conn = @fsockopen($host, // the host of the server 129 - $port, // the port to use 130 - $errno, // error number if any 131 - $errstr, // error message if any 132 - $tval); // give up after ? secs 133 - // verify we connected properly 134 - if(empty($this->smtp_conn)) { 135 - $this->error = array("error" => "Failed to connect to server", 136 - "errno" => $errno, 137 - "errstr" => $errstr); 138 - if($this->do_debug >= 1) { 139 - echo "SMTP -> ERROR: " . $this->error["error"] . ": $errstr ($errno)" . $this->CRLF . '<br />'; 140 - } 141 - return false; 142 - } 143 - 144 - // SMTP server can take longer to respond, give longer timeout for first read 145 - // Windows does not have support for this timeout function 146 - if(substr(PHP_OS, 0, 3) != "WIN") 147 - socket_set_timeout($this->smtp_conn, $tval, 0); 148 - 149 - // get any announcement 150 - $announce = $this->get_lines(); 151 - 152 - if($this->do_debug >= 2) { 153 - echo "SMTP -> FROM SERVER:" . $announce . $this->CRLF . '<br />'; 154 - } 155 - 156 - return true; 157 - } 158 - 159 - /** 160 - * Initiate a TLS communication with the server. 161 - * 162 - * SMTP CODE 220 Ready to start TLS 163 - * SMTP CODE 501 Syntax error (no parameters allowed) 164 - * SMTP CODE 454 TLS not available due to temporary reason 165 - * @access public 166 - * @return bool success 167 - */ 168 - public function StartTLS() { 169 - $this->error = null; # to avoid confusion 170 - 171 - if(!$this->connected()) { 172 - $this->error = array("error" => "Called StartTLS() without being connected"); 173 - return false; 174 - } 175 - 176 - fputs($this->smtp_conn,"STARTTLS" . $this->CRLF); 177 - 178 - $rply = $this->get_lines(); 179 - $code = substr($rply,0,3); 180 - 181 - if($this->do_debug >= 2) { 182 - echo "SMTP -> FROM SERVER:" . $rply . $this->CRLF . '<br />'; 183 - } 184 - 185 - if($code != 220) { 186 - $this->error = 187 - array("error" => "STARTTLS not accepted from server", 188 - "smtp_code" => $code, 189 - "smtp_msg" => substr($rply,4)); 190 - if($this->do_debug >= 1) { 191 - echo "SMTP -> ERROR: " . $this->error["error"] . ": " . $rply . $this->CRLF . '<br />'; 192 - } 193 - return false; 194 - } 195 - 196 - // Begin encrypted connection 197 - if(!stream_socket_enable_crypto($this->smtp_conn, true, STREAM_CRYPTO_METHOD_TLS_CLIENT)) { 198 - return false; 199 - } 200 - 201 - return true; 202 - } 203 - 204 - /** 205 - * Performs SMTP authentication. Must be run after running the 206 - * Hello() method. Returns true if successfully authenticated. 207 - * @access public 208 - * @return bool 209 - */ 210 - public function Authenticate($username, $password) { 211 - // Start authentication 212 - fputs($this->smtp_conn,"AUTH LOGIN" . $this->CRLF); 213 - 214 - $rply = $this->get_lines(); 215 - $code = substr($rply,0,3); 216 - 217 - if($code != 334) { 218 - $this->error = 219 - array("error" => "AUTH not accepted from server", 220 - "smtp_code" => $code, 221 - "smtp_msg" => substr($rply,4)); 222 - if($this->do_debug >= 1) { 223 - echo "SMTP -> ERROR: " . $this->error["error"] . ": " . $rply . $this->CRLF . '<br />'; 224 - } 225 - return false; 226 - } 227 - 228 - // Send encoded username 229 - fputs($this->smtp_conn, base64_encode($username) . $this->CRLF); 230 - 231 - $rply = $this->get_lines(); 232 - $code = substr($rply,0,3); 233 - 234 - if($code != 334) { 235 - $this->error = 236 - array("error" => "Username not accepted from server", 237 - "smtp_code" => $code, 238 - "smtp_msg" => substr($rply,4)); 239 - if($this->do_debug >= 1) { 240 - echo "SMTP -> ERROR: " . $this->error["error"] . ": " . $rply . $this->CRLF . '<br />'; 241 - } 242 - return false; 243 - } 244 - 245 - // Send encoded password 246 - fputs($this->smtp_conn, base64_encode($password) . $this->CRLF); 247 - 248 - $rply = $this->get_lines(); 249 - $code = substr($rply,0,3); 250 - 251 - if($code != 235) { 252 - $this->error = 253 - array("error" => "Password not accepted from server", 254 - "smtp_code" => $code, 255 - "smtp_msg" => substr($rply,4)); 256 - if($this->do_debug >= 1) { 257 - echo "SMTP -> ERROR: " . $this->error["error"] . ": " . $rply . $this->CRLF . '<br />'; 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 - // the socket is valid but we are not connected 275 - if($this->do_debug >= 1) { 276 - echo "SMTP -> NOTICE:" . $this->CRLF . "EOF caught while checking if connected"; 277 - } 278 - $this->Close(); 279 - return false; 280 - } 281 - return true; // everything looks good 282 - } 283 - return false; 284 - } 285 - 286 - /** 287 - * Closes the socket and cleans up the state of the class. 288 - * It is not considered good to use this function without 289 - * first trying to use QUIT. 290 - * @access public 291 - * @return void 292 - */ 293 - public function Close() { 294 - $this->error = null; // so there is no confusion 295 - $this->helo_rply = null; 296 - if(!empty($this->smtp_conn)) { 297 - // close the connection and cleanup 298 - fclose($this->smtp_conn); 299 - $this->smtp_conn = 0; 300 - } 301 - } 302 - 303 - ///////////////////////////////////////////////// 304 - // SMTP COMMANDS 305 - ///////////////////////////////////////////////// 306 - 307 - /** 308 - * Issues a data command and sends the msg_data to the server 309 - * finializing the mail transaction. $msg_data is the message 310 - * that is to be send with the headers. Each header needs to be 311 - * on a single line followed by a <CRLF> with the message headers 312 - * and the message body being seperated by and additional <CRLF>. 313 - * 314 - * Implements rfc 821: DATA <CRLF> 315 - * 316 - * SMTP CODE INTERMEDIATE: 354 317 - * [data] 318 - * <CRLF>.<CRLF> 319 - * SMTP CODE SUCCESS: 250 320 - * SMTP CODE FAILURE: 552,554,451,452 321 - * SMTP CODE FAILURE: 451,554 322 - * SMTP CODE ERROR : 500,501,503,421 323 - * @access public 324 - * @return bool 325 - */ 326 - public function Data($msg_data) { 327 - $this->error = null; // so no confusion is caused 328 - 329 - if(!$this->connected()) { 330 - $this->error = array( 331 - "error" => "Called Data() without being connected"); 332 - return false; 333 - } 334 - 335 - fputs($this->smtp_conn,"DATA" . $this->CRLF); 336 - 337 - $rply = $this->get_lines(); 338 - $code = substr($rply,0,3); 339 - 340 - if($this->do_debug >= 2) { 341 - echo "SMTP -> FROM SERVER:" . $rply . $this->CRLF . '<br />'; 342 - } 343 - 344 - if($code != 354) { 345 - $this->error = 346 - array("error" => "DATA command not accepted from server", 347 - "smtp_code" => $code, 348 - "smtp_msg" => substr($rply,4)); 349 - if($this->do_debug >= 1) { 350 - echo "SMTP -> ERROR: " . $this->error["error"] . ": " . $rply . $this->CRLF . '<br />'; 351 - } 352 - return false; 353 - } 354 - 355 - /* the server is ready to accept data! 356 - * according to rfc 821 we should not send more than 1000 357 - * including the CRLF 358 - * characters on a single line so we will break the data up 359 - * into lines by \r and/or \n then if needed we will break 360 - * each of those into smaller lines to fit within the limit. 361 - * in addition we will be looking for lines that start with 362 - * a period '.' and append and additional period '.' to that 363 - * line. NOTE: this does not count towards limit. 364 - */ 365 - 366 - // normalize the line breaks so we know the explode works 367 - $msg_data = str_replace("\r\n","\n",$msg_data); 368 - $msg_data = str_replace("\r","\n",$msg_data); 369 - $lines = explode("\n",$msg_data); 370 - 371 - /* we need to find a good way to determine is headers are 372 - * in the msg_data or if it is a straight msg body 373 - * currently I am assuming rfc 822 definitions of msg headers 374 - * and if the first field of the first line (':' sperated) 375 - * does not contain a space then it _should_ be a header 376 - * and we can process all lines before a blank "" line as 377 - * headers. 378 - */ 379 - 380 - $field = substr($lines[0],0,strpos($lines[0],":")); 381 - $in_headers = false; 382 - if(!empty($field) && !strstr($field," ")) { 383 - $in_headers = true; 384 - } 385 - 386 - $max_line_length = 998; // used below; set here for ease in change 387 - 388 - while(list(,$line) = @each($lines)) { 389 - $lines_out = null; 390 - if($line == "" && $in_headers) { 391 - $in_headers = false; 392 - } 393 - // ok we need to break this line up into several smaller lines 394 - while(strlen($line) > $max_line_length) { 395 - $pos = strrpos(substr($line,0,$max_line_length)," "); 396 - 397 - // Patch to fix DOS attack 398 - if(!$pos) { 399 - $pos = $max_line_length - 1; 400 - $lines_out[] = substr($line,0,$pos); 401 - $line = substr($line,$pos); 402 - } else { 403 - $lines_out[] = substr($line,0,$pos); 404 - $line = substr($line,$pos + 1); 405 - } 406 - 407 - /* if processing headers add a LWSP-char to the front of new line 408 - * rfc 822 on long msg headers 409 - */ 410 - if($in_headers) { 411 - $line = "\t" . $line; 412 - } 413 - } 414 - $lines_out[] = $line; 415 - 416 - // send the lines to the server 417 - while(list(,$line_out) = @each($lines_out)) { 418 - if(strlen($line_out) > 0) 419 - { 420 - if(substr($line_out, 0, 1) == ".") { 421 - $line_out = "." . $line_out; 422 - } 423 - } 424 - fputs($this->smtp_conn,$line_out . $this->CRLF); 425 - } 426 - } 427 - 428 - // message data has been sent 429 - fputs($this->smtp_conn, $this->CRLF . "." . $this->CRLF); 430 - 431 - $rply = $this->get_lines(); 432 - $code = substr($rply,0,3); 433 - 434 - if($this->do_debug >= 2) { 435 - echo "SMTP -> FROM SERVER:" . $rply . $this->CRLF . '<br />'; 436 - } 437 - 438 - if($code != 250) { 439 - $this->error = 440 - array("error" => "DATA not accepted from server", 441 - "smtp_code" => $code, 442 - "smtp_msg" => substr($rply,4)); 443 - if($this->do_debug >= 1) { 444 - echo "SMTP -> ERROR: " . $this->error["error"] . ": " . $rply . $this->CRLF . '<br />'; 445 - } 446 - return false; 447 - } 448 - return true; 449 - } 450 - 451 - /** 452 - * Sends the HELO command to the smtp server. 453 - * This makes sure that we and the server are in 454 - * the same known state. 455 - * 456 - * Implements from rfc 821: HELO <SP> <domain> <CRLF> 457 - * 458 - * SMTP CODE SUCCESS: 250 459 - * SMTP CODE ERROR : 500, 501, 504, 421 460 - * @access public 461 - * @return bool 462 - */ 463 - public function Hello($host = '') { 464 - $this->error = null; // so no confusion is caused 465 - 466 - if(!$this->connected()) { 467 - $this->error = array( 468 - "error" => "Called Hello() without being connected"); 469 - return false; 470 - } 471 - 472 - // if hostname for HELO was not specified send default 473 - if(empty($host)) { 474 - // determine appropriate default to send to server 475 - $host = "localhost"; 476 - } 477 - 478 - // Send extended hello first (RFC 2821) 479 - if(!$this->SendHello("EHLO", $host)) { 480 - if(!$this->SendHello("HELO", $host)) { 481 - return false; 482 - } 483 - } 484 - 485 - return true; 486 - } 487 - 488 - /** 489 - * Sends a HELO/EHLO command. 490 - * @access private 491 - * @return bool 492 - */ 493 - private function SendHello($hello, $host) { 494 - fputs($this->smtp_conn, $hello . " " . $host . $this->CRLF); 495 - 496 - $rply = $this->get_lines(); 497 - $code = substr($rply,0,3); 498 - 499 - if($this->do_debug >= 2) { 500 - echo "SMTP -> FROM SERVER: " . $rply . $this->CRLF . '<br />'; 501 - } 502 - 503 - if($code != 250) { 504 - $this->error = 505 - array("error" => $hello . " not accepted from server", 506 - "smtp_code" => $code, 507 - "smtp_msg" => substr($rply,4)); 508 - if($this->do_debug >= 1) { 509 - echo "SMTP -> ERROR: " . $this->error["error"] . ": " . $rply . $this->CRLF . '<br />'; 510 - } 511 - return false; 512 - } 513 - 514 - $this->helo_rply = $rply; 515 - 516 - return true; 517 - } 518 - 519 - /** 520 - * Starts a mail transaction from the email address specified in 521 - * $from. Returns true if successful or false otherwise. If True 522 - * the mail transaction is started and then one or more Recipient 523 - * commands may be called followed by a Data command. 524 - * 525 - * Implements rfc 821: MAIL <SP> FROM:<reverse-path> <CRLF> 526 - * 527 - * SMTP CODE SUCCESS: 250 528 - * SMTP CODE SUCCESS: 552,451,452 529 - * SMTP CODE SUCCESS: 500,501,421 530 - * @access public 531 - * @return bool 532 - */ 533 - public function Mail($from) { 534 - $this->error = null; // so no confusion is caused 535 - 536 - if(!$this->connected()) { 537 - $this->error = array( 538 - "error" => "Called Mail() without being connected"); 539 - return false; 540 - } 541 - 542 - $useVerp = ($this->do_verp ? "XVERP" : ""); 543 - fputs($this->smtp_conn,"MAIL FROM:<" . $from . ">" . $useVerp . $this->CRLF); 544 - 545 - $rply = $this->get_lines(); 546 - $code = substr($rply,0,3); 547 - 548 - if($this->do_debug >= 2) { 549 - echo "SMTP -> FROM SERVER:" . $rply . $this->CRLF . '<br />'; 550 - } 551 - 552 - if($code != 250) { 553 - $this->error = 554 - array("error" => "MAIL not accepted from server", 555 - "smtp_code" => $code, 556 - "smtp_msg" => substr($rply,4)); 557 - if($this->do_debug >= 1) { 558 - echo "SMTP -> ERROR: " . $this->error["error"] . ": " . $rply . $this->CRLF . '<br />'; 559 - } 560 - return false; 561 - } 562 - return true; 563 - } 564 - 565 - /** 566 - * Sends the quit command to the server and then closes the socket 567 - * if there is no error or the $close_on_error argument is true. 568 - * 569 - * Implements from rfc 821: QUIT <CRLF> 570 - * 571 - * SMTP CODE SUCCESS: 221 572 - * SMTP CODE ERROR : 500 573 - * @access public 574 - * @return bool 575 - */ 576 - public function Quit($close_on_error = true) { 577 - $this->error = null; // so there is no confusion 578 - 579 - if(!$this->connected()) { 580 - $this->error = array( 581 - "error" => "Called Quit() without being connected"); 582 - return false; 583 - } 584 - 585 - // send the quit command to the server 586 - fputs($this->smtp_conn,"quit" . $this->CRLF); 587 - 588 - // get any good-bye messages 589 - $byemsg = $this->get_lines(); 590 - 591 - if($this->do_debug >= 2) { 592 - echo "SMTP -> FROM SERVER:" . $byemsg . $this->CRLF . '<br />'; 593 - } 594 - 595 - $rval = true; 596 - $e = null; 597 - 598 - $code = substr($byemsg,0,3); 599 - if($code != 221) { 600 - // use e as a tmp var cause Close will overwrite $this->error 601 - $e = array("error" => "SMTP server rejected quit command", 602 - "smtp_code" => $code, 603 - "smtp_rply" => substr($byemsg,4)); 604 - $rval = false; 605 - if($this->do_debug >= 1) { 606 - echo "SMTP -> ERROR: " . $e["error"] . ": " . $byemsg . $this->CRLF . '<br />'; 607 - } 608 - } 609 - 610 - if(empty($e) || $close_on_error) { 611 - $this->Close(); 612 - } 613 - 614 - return $rval; 615 - } 616 - 617 - /** 618 - * Sends the command RCPT to the SMTP server with the TO: argument of $to. 619 - * Returns true if the recipient was accepted false if it was rejected. 620 - * 621 - * Implements from rfc 821: RCPT <SP> TO:<forward-path> <CRLF> 622 - * 623 - * SMTP CODE SUCCESS: 250,251 624 - * SMTP CODE FAILURE: 550,551,552,553,450,451,452 625 - * SMTP CODE ERROR : 500,501,503,421 626 - * @access public 627 - * @return bool 628 - */ 629 - public function Recipient($to) { 630 - $this->error = null; // so no confusion is caused 631 - 632 - if(!$this->connected()) { 633 - $this->error = array( 634 - "error" => "Called Recipient() without being connected"); 635 - return false; 636 - } 637 - 638 - fputs($this->smtp_conn,"RCPT TO:<" . $to . ">" . $this->CRLF); 639 - 640 - $rply = $this->get_lines(); 641 - $code = substr($rply,0,3); 642 - 643 - if($this->do_debug >= 2) { 644 - echo "SMTP -> FROM SERVER:" . $rply . $this->CRLF . '<br />'; 645 - } 646 - 647 - if($code != 250 && $code != 251) { 648 - $this->error = 649 - array("error" => "RCPT not accepted from server", 650 - "smtp_code" => $code, 651 - "smtp_msg" => substr($rply,4)); 652 - if($this->do_debug >= 1) { 653 - echo "SMTP -> ERROR: " . $this->error["error"] . ": " . $rply . $this->CRLF . '<br />'; 654 - } 655 - return false; 656 - } 657 - return true; 658 - } 659 - 660 - /** 661 - * Sends the RSET command to abort and transaction that is 662 - * currently in progress. Returns true if successful false 663 - * otherwise. 664 - * 665 - * Implements rfc 821: RSET <CRLF> 666 - * 667 - * SMTP CODE SUCCESS: 250 668 - * SMTP CODE ERROR : 500,501,504,421 669 - * @access public 670 - * @return bool 671 - */ 672 - public function Reset() { 673 - $this->error = null; // so no confusion is caused 674 - 675 - if(!$this->connected()) { 676 - $this->error = array( 677 - "error" => "Called Reset() without being connected"); 678 - return false; 679 - } 680 - 681 - fputs($this->smtp_conn,"RSET" . $this->CRLF); 682 - 683 - $rply = $this->get_lines(); 684 - $code = substr($rply,0,3); 685 - 686 - if($this->do_debug >= 2) { 687 - echo "SMTP -> FROM SERVER:" . $rply . $this->CRLF . '<br />'; 688 - } 689 - 690 - if($code != 250) { 691 - $this->error = 692 - array("error" => "RSET failed", 693 - "smtp_code" => $code, 694 - "smtp_msg" => substr($rply,4)); 695 - if($this->do_debug >= 1) { 696 - echo "SMTP -> ERROR: " . $this->error["error"] . ": " . $rply . $this->CRLF . '<br />'; 697 - } 698 - return false; 699 - } 700 - 701 - return true; 702 - } 703 - 704 - /** 705 - * Starts a mail transaction from the email address specified in 706 - * $from. Returns true if successful or false otherwise. If True 707 - * the mail transaction is started and then one or more Recipient 708 - * commands may be called followed by a Data command. This command 709 - * will send the message to the users terminal if they are logged 710 - * in and send them an email. 711 - * 712 - * Implements rfc 821: SAML <SP> FROM:<reverse-path> <CRLF> 713 - * 714 - * SMTP CODE SUCCESS: 250 715 - * SMTP CODE SUCCESS: 552,451,452 716 - * SMTP CODE SUCCESS: 500,501,502,421 717 - * @access public 718 - * @return bool 719 - */ 720 - public function SendAndMail($from) { 721 - $this->error = null; // so no confusion is caused 722 - 723 - if(!$this->connected()) { 724 - $this->error = array( 725 - "error" => "Called SendAndMail() without being connected"); 726 - return false; 727 - } 728 - 729 - fputs($this->smtp_conn,"SAML FROM:" . $from . $this->CRLF); 730 - 731 - $rply = $this->get_lines(); 732 - $code = substr($rply,0,3); 733 - 734 - if($this->do_debug >= 2) { 735 - echo "SMTP -> FROM SERVER:" . $rply . $this->CRLF . '<br />'; 736 - } 737 - 738 - if($code != 250) { 739 - $this->error = 740 - array("error" => "SAML not accepted from server", 741 - "smtp_code" => $code, 742 - "smtp_msg" => substr($rply,4)); 743 - if($this->do_debug >= 1) { 744 - echo "SMTP -> ERROR: " . $this->error["error"] . ": " . $rply . $this->CRLF . '<br />'; 745 - } 746 - return false; 747 - } 748 - return true; 749 - } 750 - 751 - /** 752 - * This is an optional command for SMTP that this class does not 753 - * support. This method is here to make the RFC821 Definition 754 - * complete for this class and __may__ be implimented in the future 755 - * 756 - * Implements from rfc 821: TURN <CRLF> 757 - * 758 - * SMTP CODE SUCCESS: 250 759 - * SMTP CODE FAILURE: 502 760 - * SMTP CODE ERROR : 500, 503 761 - * @access public 762 - * @return bool 763 - */ 764 - public function Turn() { 765 - $this->error = array("error" => "This method, TURN, of the SMTP ". 766 - "is not implemented"); 767 - if($this->do_debug >= 1) { 768 - echo "SMTP -> NOTICE: " . $this->error["error"] . $this->CRLF . '<br />'; 769 - } 770 - return false; 771 - } 772 - 773 - /** 774 - * Get the current error 775 - * @access public 776 - * @return array 777 - */ 778 - public function getError() { 779 - return $this->error; 780 - } 781 - 782 - ///////////////////////////////////////////////// 783 - // INTERNAL FUNCTIONS 784 - ///////////////////////////////////////////////// 785 - 786 - /** 787 - * Read in as many lines as possible 788 - * either before eof or socket timeout occurs on the operation. 789 - * With SMTP we can tell if we have more lines to read if the 790 - * 4th character is '-' symbol. If it is a space then we don't 791 - * need to read anything else. 792 - * @access private 793 - * @return string 794 - */ 795 - private function get_lines() { 796 - $data = ""; 797 - while($str = @fgets($this->smtp_conn,515)) { 798 - if($this->do_debug >= 4) { 799 - echo "SMTP -> get_lines(): \$data was \"$data\"" . $this->CRLF . '<br />'; 800 - echo "SMTP -> get_lines(): \$str is \"$str\"" . $this->CRLF . '<br />'; 801 - } 802 - $data .= $str; 803 - if($this->do_debug >= 4) { 804 - echo "SMTP -> get_lines(): \$data is \"$data\"" . $this->CRLF . '<br />'; 805 - } 806 - // if 4th character is a space, we are done reading, break the loop 807 - if(substr($str,3,1) == " ") { break; } 808 - } 809 - return $data; 810 - } 811 - 812 - } 813 - 1 + <?php 2 + /*~ class.smtp.php 3 + .---------------------------------------------------------------------------. 4 + | Software: PHPMailer - PHP email class | 5 + | Version: 5.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 + | Admin: Andy Prevost (project admininistrator) | 11 + | Authors: Andy Prevost (codeworxtech) codeworxtech@users.sourceforge.net | 12 + | : Marcus Bointon (coolbru) coolbru@users.sourceforge.net | 13 + | Founder: Brent R. Matzelle (original founder) | 14 + | Copyright (c) 2004-2009, Andy Prevost. All Rights Reserved. | 15 + | Copyright (c) 2001-2003, Brent R. Matzelle | 16 + | ------------------------------------------------------------------------- | 17 + | License: Distributed under the Lesser General Public License (LGPL) | 18 + | http://www.gnu.org/copyleft/lesser.html | 19 + | This program is distributed in the hope that it will be useful - WITHOUT | 20 + | ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | 21 + | FITNESS FOR A PARTICULAR PURPOSE. | 22 + | ------------------------------------------------------------------------- | 23 + | We offer a number of paid services (www.codeworxtech.com): | 24 + | - Web Hosting on highly optimized fast and secure servers | 25 + | - Technology Consulting | 26 + | - Oursourcing (highly qualified programmers and graphic designers) | 27 + '---------------------------------------------------------------------------' 28 + */ 29 + 30 + /** 31 + * PHPMailer - PHP SMTP email transport class 32 + * NOTE: Designed for use with PHP version 5 and up 33 + * @package PHPMailer 34 + * @author Andy Prevost 35 + * @author Marcus Bointon 36 + * @copyright 2004 - 2008 Andy Prevost 37 + * @license http://www.gnu.org/copyleft/lesser.html Distributed under the Lesser General Public License (LGPL) 38 + * @version $Id: class.smtp.php 444 2009-05-05 11:22:26Z coolbru $ 39 + */ 40 + 41 + /** 42 + * SMTP is rfc 821 compliant and implements all the rfc 821 SMTP 43 + * commands except TURN which will always return a not implemented 44 + * error. SMTP also provides some utility methods for sending mail 45 + * to an SMTP server. 46 + * original author: Chris Ryan 47 + */ 48 + 49 + class SMTP { 50 + /** 51 + * SMTP server port 52 + * @var int 53 + */ 54 + public $SMTP_PORT = 25; 55 + 56 + /** 57 + * SMTP reply line ending 58 + * @var string 59 + */ 60 + public $CRLF = "\r\n"; 61 + 62 + /** 63 + * Sets whether debugging is turned on 64 + * @var bool 65 + */ 66 + public $do_debug; // the level of debug to perform 67 + 68 + /** 69 + * Sets VERP use on/off (default is off) 70 + * @var bool 71 + */ 72 + public $do_verp = false; 73 + 74 + ///////////////////////////////////////////////// 75 + // PROPERTIES, PRIVATE AND PROTECTED 76 + ///////////////////////////////////////////////// 77 + 78 + private $smtp_conn; // the socket to the server 79 + private $error; // error if any on the last call 80 + private $helo_rply; // the reply the server sent to us for HELO 81 + 82 + /** 83 + * Initialize the class so that the data is in a known state. 84 + * @access public 85 + * @return void 86 + */ 87 + public function __construct() { 88 + $this->smtp_conn = 0; 89 + $this->error = null; 90 + $this->helo_rply = null; 91 + 92 + $this->do_debug = 0; 93 + } 94 + 95 + ///////////////////////////////////////////////// 96 + // CONNECTION FUNCTIONS 97 + ///////////////////////////////////////////////// 98 + 99 + /** 100 + * Connect to the server specified on the port specified. 101 + * If the port is not specified use the default SMTP_PORT. 102 + * If tval is specified then a connection will try and be 103 + * established with the server for that number of seconds. 104 + * If tval is not specified the default is 30 seconds to 105 + * try on the connection. 106 + * 107 + * SMTP CODE SUCCESS: 220 108 + * SMTP CODE FAILURE: 421 109 + * @access public 110 + * @return bool 111 + */ 112 + public function Connect($host, $port = 0, $tval = 30) { 113 + // set the error val to null so there is no confusion 114 + $this->error = null; 115 + 116 + // make sure we are __not__ connected 117 + if($this->connected()) { 118 + // already connected, generate error 119 + $this->error = array("error" => "Already connected to a server"); 120 + return false; 121 + } 122 + 123 + if(empty($port)) { 124 + $port = $this->SMTP_PORT; 125 + } 126 + 127 + // connect to the smtp server 128 + $this->smtp_conn = @fsockopen($host, // the host of the server 129 + $port, // the port to use 130 + $errno, // error number if any 131 + $errstr, // error message if any 132 + $tval); // give up after ? secs 133 + // verify we connected properly 134 + if(empty($this->smtp_conn)) { 135 + $this->error = array("error" => "Failed to connect to server", 136 + "errno" => $errno, 137 + "errstr" => $errstr); 138 + if($this->do_debug >= 1) { 139 + echo "SMTP -> ERROR: " . $this->error["error"] . ": $errstr ($errno)" . $this->CRLF . '<br />'; 140 + } 141 + return false; 142 + } 143 + 144 + // SMTP server can take longer to respond, give longer timeout for first read 145 + // Windows does not have support for this timeout function 146 + if(substr(PHP_OS, 0, 3) != "WIN") 147 + socket_set_timeout($this->smtp_conn, $tval, 0); 148 + 149 + // get any announcement 150 + $announce = $this->get_lines(); 151 + 152 + if($this->do_debug >= 2) { 153 + echo "SMTP -> FROM SERVER:" . $announce . $this->CRLF . '<br />'; 154 + } 155 + 156 + return true; 157 + } 158 + 159 + /** 160 + * Initiate a TLS communication with the server. 161 + * 162 + * SMTP CODE 220 Ready to start TLS 163 + * SMTP CODE 501 Syntax error (no parameters allowed) 164 + * SMTP CODE 454 TLS not available due to temporary reason 165 + * @access public 166 + * @return bool success 167 + */ 168 + public function StartTLS() { 169 + $this->error = null; # to avoid confusion 170 + 171 + if(!$this->connected()) { 172 + $this->error = array("error" => "Called StartTLS() without being connected"); 173 + return false; 174 + } 175 + 176 + fputs($this->smtp_conn,"STARTTLS" . $this->CRLF); 177 + 178 + $rply = $this->get_lines(); 179 + $code = substr($rply,0,3); 180 + 181 + if($this->do_debug >= 2) { 182 + echo "SMTP -> FROM SERVER:" . $rply . $this->CRLF . '<br />'; 183 + } 184 + 185 + if($code != 220) { 186 + $this->error = 187 + array("error" => "STARTTLS not accepted from server", 188 + "smtp_code" => $code, 189 + "smtp_msg" => substr($rply,4)); 190 + if($this->do_debug >= 1) { 191 + echo "SMTP -> ERROR: " . $this->error["error"] . ": " . $rply . $this->CRLF . '<br />'; 192 + } 193 + return false; 194 + } 195 + 196 + // Begin encrypted connection 197 + if(!stream_socket_enable_crypto($this->smtp_conn, true, STREAM_CRYPTO_METHOD_TLS_CLIENT)) { 198 + return false; 199 + } 200 + 201 + return true; 202 + } 203 + 204 + /** 205 + * Performs SMTP authentication. Must be run after running the 206 + * Hello() method. Returns true if successfully authenticated. 207 + * @access public 208 + * @return bool 209 + */ 210 + public function Authenticate($username, $password) { 211 + // Start authentication 212 + fputs($this->smtp_conn,"AUTH LOGIN" . $this->CRLF); 213 + 214 + $rply = $this->get_lines(); 215 + $code = substr($rply,0,3); 216 + 217 + if($code != 334) { 218 + $this->error = 219 + array("error" => "AUTH not accepted from server", 220 + "smtp_code" => $code, 221 + "smtp_msg" => substr($rply,4)); 222 + if($this->do_debug >= 1) { 223 + echo "SMTP -> ERROR: " . $this->error["error"] . ": " . $rply . $this->CRLF . '<br />'; 224 + } 225 + return false; 226 + } 227 + 228 + // Send encoded username 229 + fputs($this->smtp_conn, base64_encode($username) . $this->CRLF); 230 + 231 + $rply = $this->get_lines(); 232 + $code = substr($rply,0,3); 233 + 234 + if($code != 334) { 235 + $this->error = 236 + array("error" => "Username not accepted from server", 237 + "smtp_code" => $code, 238 + "smtp_msg" => substr($rply,4)); 239 + if($this->do_debug >= 1) { 240 + echo "SMTP -> ERROR: " . $this->error["error"] . ": " . $rply . $this->CRLF . '<br />'; 241 + } 242 + return false; 243 + } 244 + 245 + // Send encoded password 246 + fputs($this->smtp_conn, base64_encode($password) . $this->CRLF); 247 + 248 + $rply = $this->get_lines(); 249 + $code = substr($rply,0,3); 250 + 251 + if($code != 235) { 252 + $this->error = 253 + array("error" => "Password not accepted from server", 254 + "smtp_code" => $code, 255 + "smtp_msg" => substr($rply,4)); 256 + if($this->do_debug >= 1) { 257 + echo "SMTP -> ERROR: " . $this->error["error"] . ": " . $rply . $this->CRLF . '<br />'; 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 + // the socket is valid but we are not connected 275 + if($this->do_debug >= 1) { 276 + echo "SMTP -> NOTICE:" . $this->CRLF . "EOF caught while checking if connected"; 277 + } 278 + $this->Close(); 279 + return false; 280 + } 281 + return true; // everything looks good 282 + } 283 + return false; 284 + } 285 + 286 + /** 287 + * Closes the socket and cleans up the state of the class. 288 + * It is not considered good to use this function without 289 + * first trying to use QUIT. 290 + * @access public 291 + * @return void 292 + */ 293 + public function Close() { 294 + $this->error = null; // so there is no confusion 295 + $this->helo_rply = null; 296 + if(!empty($this->smtp_conn)) { 297 + // close the connection and cleanup 298 + fclose($this->smtp_conn); 299 + $this->smtp_conn = 0; 300 + } 301 + } 302 + 303 + ///////////////////////////////////////////////// 304 + // SMTP COMMANDS 305 + ///////////////////////////////////////////////// 306 + 307 + /** 308 + * Issues a data command and sends the msg_data to the server 309 + * finializing the mail transaction. $msg_data is the message 310 + * that is to be send with the headers. Each header needs to be 311 + * on a single line followed by a <CRLF> with the message headers 312 + * and the message body being seperated by and additional <CRLF>. 313 + * 314 + * Implements rfc 821: DATA <CRLF> 315 + * 316 + * SMTP CODE INTERMEDIATE: 354 317 + * [data] 318 + * <CRLF>.<CRLF> 319 + * SMTP CODE SUCCESS: 250 320 + * SMTP CODE FAILURE: 552,554,451,452 321 + * SMTP CODE FAILURE: 451,554 322 + * SMTP CODE ERROR : 500,501,503,421 323 + * @access public 324 + * @return bool 325 + */ 326 + public function Data($msg_data) { 327 + $this->error = null; // so no confusion is caused 328 + 329 + if(!$this->connected()) { 330 + $this->error = array( 331 + "error" => "Called Data() without being connected"); 332 + return false; 333 + } 334 + 335 + fputs($this->smtp_conn,"DATA" . $this->CRLF); 336 + 337 + $rply = $this->get_lines(); 338 + $code = substr($rply,0,3); 339 + 340 + if($this->do_debug >= 2) { 341 + echo "SMTP -> FROM SERVER:" . $rply . $this->CRLF . '<br />'; 342 + } 343 + 344 + if($code != 354) { 345 + $this->error = 346 + array("error" => "DATA command not accepted from server", 347 + "smtp_code" => $code, 348 + "smtp_msg" => substr($rply,4)); 349 + if($this->do_debug >= 1) { 350 + echo "SMTP -> ERROR: " . $this->error["error"] . ": " . $rply . $this->CRLF . '<br />'; 351 + } 352 + return false; 353 + } 354 + 355 + /* the server is ready to accept data! 356 + * according to rfc 821 we should not send more than 1000 357 + * including the CRLF 358 + * characters on a single line so we will break the data up 359 + * into lines by \r and/or \n then if needed we will break 360 + * each of those into smaller lines to fit within the limit. 361 + * in addition we will be looking for lines that start with 362 + * a period '.' and append and additional period '.' to that 363 + * line. NOTE: this does not count towards limit. 364 + */ 365 + 366 + // normalize the line breaks so we know the explode works 367 + $msg_data = str_replace("\r\n","\n",$msg_data); 368 + $msg_data = str_replace("\r","\n",$msg_data); 369 + $lines = explode("\n",$msg_data); 370 + 371 + /* we need to find a good way to determine is headers are 372 + * in the msg_data or if it is a straight msg body 373 + * currently I am assuming rfc 822 definitions of msg headers 374 + * and if the first field of the first line (':' sperated) 375 + * does not contain a space then it _should_ be a header 376 + * and we can process all lines before a blank "" line as 377 + * headers. 378 + */ 379 + 380 + $field = substr($lines[0],0,strpos($lines[0],":")); 381 + $in_headers = false; 382 + if(!empty($field) && !strstr($field," ")) { 383 + $in_headers = true; 384 + } 385 + 386 + $max_line_length = 998; // used below; set here for ease in change 387 + 388 + foreach($lines as $line) { 389 + $lines_out = null; 390 + if($line == "" && $in_headers) { 391 + $in_headers = false; 392 + } 393 + // ok we need to break this line up into several smaller lines 394 + while(strlen($line) > $max_line_length) { 395 + $pos = strrpos(substr($line,0,$max_line_length)," "); 396 + 397 + // Patch to fix DOS attack 398 + if(!$pos) { 399 + $pos = $max_line_length - 1; 400 + $lines_out[] = substr($line,0,$pos); 401 + $line = substr($line,$pos); 402 + } else { 403 + $lines_out[] = substr($line,0,$pos); 404 + $line = substr($line,$pos + 1); 405 + } 406 + 407 + /* if processing headers add a LWSP-char to the front of new line 408 + * rfc 822 on long msg headers 409 + */ 410 + if($in_headers) { 411 + $line = "\t" . $line; 412 + } 413 + } 414 + $lines_out[] = $line; 415 + 416 + // send the lines to the server 417 + foreach($lines_out as $line_out) { 418 + if(strlen($line_out) > 0) 419 + { 420 + if(substr($line_out, 0, 1) == ".") { 421 + $line_out = "." . $line_out; 422 + } 423 + } 424 + fputs($this->smtp_conn,$line_out . $this->CRLF); 425 + } 426 + } 427 + 428 + // message data has been sent 429 + fputs($this->smtp_conn, $this->CRLF . "." . $this->CRLF); 430 + 431 + $rply = $this->get_lines(); 432 + $code = substr($rply,0,3); 433 + 434 + if($this->do_debug >= 2) { 435 + echo "SMTP -> FROM SERVER:" . $rply . $this->CRLF . '<br />'; 436 + } 437 + 438 + if($code != 250) { 439 + $this->error = 440 + array("error" => "DATA not accepted from server", 441 + "smtp_code" => $code, 442 + "smtp_msg" => substr($rply,4)); 443 + if($this->do_debug >= 1) { 444 + echo "SMTP -> ERROR: " . $this->error["error"] . ": " . $rply . $this->CRLF . '<br />'; 445 + } 446 + return false; 447 + } 448 + return true; 449 + } 450 + 451 + /** 452 + * Sends the HELO command to the smtp server. 453 + * This makes sure that we and the server are in 454 + * the same known state. 455 + * 456 + * Implements from rfc 821: HELO <SP> <domain> <CRLF> 457 + * 458 + * SMTP CODE SUCCESS: 250 459 + * SMTP CODE ERROR : 500, 501, 504, 421 460 + * @access public 461 + * @return bool 462 + */ 463 + public function Hello($host = '') { 464 + $this->error = null; // so no confusion is caused 465 + 466 + if(!$this->connected()) { 467 + $this->error = array( 468 + "error" => "Called Hello() without being connected"); 469 + return false; 470 + } 471 + 472 + // if hostname for HELO was not specified send default 473 + if(empty($host)) { 474 + // determine appropriate default to send to server 475 + $host = "localhost"; 476 + } 477 + 478 + // Send extended hello first (RFC 2821) 479 + if(!$this->SendHello("EHLO", $host)) { 480 + if(!$this->SendHello("HELO", $host)) { 481 + return false; 482 + } 483 + } 484 + 485 + return true; 486 + } 487 + 488 + /** 489 + * Sends a HELO/EHLO command. 490 + * @access private 491 + * @return bool 492 + */ 493 + private function SendHello($hello, $host) { 494 + fputs($this->smtp_conn, $hello . " " . $host . $this->CRLF); 495 + 496 + $rply = $this->get_lines(); 497 + $code = substr($rply,0,3); 498 + 499 + if($this->do_debug >= 2) { 500 + echo "SMTP -> FROM SERVER: " . $rply . $this->CRLF . '<br />'; 501 + } 502 + 503 + if($code != 250) { 504 + $this->error = 505 + array("error" => $hello . " not accepted from server", 506 + "smtp_code" => $code, 507 + "smtp_msg" => substr($rply,4)); 508 + if($this->do_debug >= 1) { 509 + echo "SMTP -> ERROR: " . $this->error["error"] . ": " . $rply . $this->CRLF . '<br />'; 510 + } 511 + return false; 512 + } 513 + 514 + $this->helo_rply = $rply; 515 + 516 + return true; 517 + } 518 + 519 + /** 520 + * Starts a mail transaction from the email address specified in 521 + * $from. Returns true if successful or false otherwise. If True 522 + * the mail transaction is started and then one or more Recipient 523 + * commands may be called followed by a Data command. 524 + * 525 + * Implements rfc 821: MAIL <SP> FROM:<reverse-path> <CRLF> 526 + * 527 + * SMTP CODE SUCCESS: 250 528 + * SMTP CODE SUCCESS: 552,451,452 529 + * SMTP CODE SUCCESS: 500,501,421 530 + * @access public 531 + * @return bool 532 + */ 533 + public function Mail($from) { 534 + $this->error = null; // so no confusion is caused 535 + 536 + if(!$this->connected()) { 537 + $this->error = array( 538 + "error" => "Called Mail() without being connected"); 539 + return false; 540 + } 541 + 542 + $useVerp = ($this->do_verp ? "XVERP" : ""); 543 + fputs($this->smtp_conn,"MAIL FROM:<" . $from . ">" . $useVerp . $this->CRLF); 544 + 545 + $rply = $this->get_lines(); 546 + $code = substr($rply,0,3); 547 + 548 + if($this->do_debug >= 2) { 549 + echo "SMTP -> FROM SERVER:" . $rply . $this->CRLF . '<br />'; 550 + } 551 + 552 + if($code != 250) { 553 + $this->error = 554 + array("error" => "MAIL not accepted from server", 555 + "smtp_code" => $code, 556 + "smtp_msg" => substr($rply,4)); 557 + if($this->do_debug >= 1) { 558 + echo "SMTP -> ERROR: " . $this->error["error"] . ": " . $rply . $this->CRLF . '<br />'; 559 + } 560 + return false; 561 + } 562 + return true; 563 + } 564 + 565 + /** 566 + * Sends the quit command to the server and then closes the socket 567 + * if there is no error or the $close_on_error argument is true. 568 + * 569 + * Implements from rfc 821: QUIT <CRLF> 570 + * 571 + * SMTP CODE SUCCESS: 221 572 + * SMTP CODE ERROR : 500 573 + * @access public 574 + * @return bool 575 + */ 576 + public function Quit($close_on_error = true) { 577 + $this->error = null; // so there is no confusion 578 + 579 + if(!$this->connected()) { 580 + $this->error = array( 581 + "error" => "Called Quit() without being connected"); 582 + return false; 583 + } 584 + 585 + // send the quit command to the server 586 + fputs($this->smtp_conn,"quit" . $this->CRLF); 587 + 588 + // get any good-bye messages 589 + $byemsg = $this->get_lines(); 590 + 591 + if($this->do_debug >= 2) { 592 + echo "SMTP -> FROM SERVER:" . $byemsg . $this->CRLF . '<br />'; 593 + } 594 + 595 + $rval = true; 596 + $e = null; 597 + 598 + $code = substr($byemsg,0,3); 599 + if($code != 221) { 600 + // use e as a tmp var cause Close will overwrite $this->error 601 + $e = array("error" => "SMTP server rejected quit command", 602 + "smtp_code" => $code, 603 + "smtp_rply" => substr($byemsg,4)); 604 + $rval = false; 605 + if($this->do_debug >= 1) { 606 + echo "SMTP -> ERROR: " . $e["error"] . ": " . $byemsg . $this->CRLF . '<br />'; 607 + } 608 + } 609 + 610 + if(empty($e) || $close_on_error) { 611 + $this->Close(); 612 + } 613 + 614 + return $rval; 615 + } 616 + 617 + /** 618 + * Sends the command RCPT to the SMTP server with the TO: argument of $to. 619 + * Returns true if the recipient was accepted false if it was rejected. 620 + * 621 + * Implements from rfc 821: RCPT <SP> TO:<forward-path> <CRLF> 622 + * 623 + * SMTP CODE SUCCESS: 250,251 624 + * SMTP CODE FAILURE: 550,551,552,553,450,451,452 625 + * SMTP CODE ERROR : 500,501,503,421 626 + * @access public 627 + * @return bool 628 + */ 629 + public function Recipient($to) { 630 + $this->error = null; // so no confusion is caused 631 + 632 + if(!$this->connected()) { 633 + $this->error = array( 634 + "error" => "Called Recipient() without being connected"); 635 + return false; 636 + } 637 + 638 + fputs($this->smtp_conn,"RCPT TO:<" . $to . ">" . $this->CRLF); 639 + 640 + $rply = $this->get_lines(); 641 + $code = substr($rply,0,3); 642 + 643 + if($this->do_debug >= 2) { 644 + echo "SMTP -> FROM SERVER:" . $rply . $this->CRLF . '<br />'; 645 + } 646 + 647 + if($code != 250 && $code != 251) { 648 + $this->error = 649 + array("error" => "RCPT not accepted from server", 650 + "smtp_code" => $code, 651 + "smtp_msg" => substr($rply,4)); 652 + if($this->do_debug >= 1) { 653 + echo "SMTP -> ERROR: " . $this->error["error"] . ": " . $rply . $this->CRLF . '<br />'; 654 + } 655 + return false; 656 + } 657 + return true; 658 + } 659 + 660 + /** 661 + * Sends the RSET command to abort and transaction that is 662 + * currently in progress. Returns true if successful false 663 + * otherwise. 664 + * 665 + * Implements rfc 821: RSET <CRLF> 666 + * 667 + * SMTP CODE SUCCESS: 250 668 + * SMTP CODE ERROR : 500,501,504,421 669 + * @access public 670 + * @return bool 671 + */ 672 + public function Reset() { 673 + $this->error = null; // so no confusion is caused 674 + 675 + if(!$this->connected()) { 676 + $this->error = array( 677 + "error" => "Called Reset() without being connected"); 678 + return false; 679 + } 680 + 681 + fputs($this->smtp_conn,"RSET" . $this->CRLF); 682 + 683 + $rply = $this->get_lines(); 684 + $code = substr($rply,0,3); 685 + 686 + if($this->do_debug >= 2) { 687 + echo "SMTP -> FROM SERVER:" . $rply . $this->CRLF . '<br />'; 688 + } 689 + 690 + if($code != 250) { 691 + $this->error = 692 + array("error" => "RSET failed", 693 + "smtp_code" => $code, 694 + "smtp_msg" => substr($rply,4)); 695 + if($this->do_debug >= 1) { 696 + echo "SMTP -> ERROR: " . $this->error["error"] . ": " . $rply . $this->CRLF . '<br />'; 697 + } 698 + return false; 699 + } 700 + 701 + return true; 702 + } 703 + 704 + /** 705 + * Starts a mail transaction from the email address specified in 706 + * $from. Returns true if successful or false otherwise. If True 707 + * the mail transaction is started and then one or more Recipient 708 + * commands may be called followed by a Data command. This command 709 + * will send the message to the users terminal if they are logged 710 + * in and send them an email. 711 + * 712 + * Implements rfc 821: SAML <SP> FROM:<reverse-path> <CRLF> 713 + * 714 + * SMTP CODE SUCCESS: 250 715 + * SMTP CODE SUCCESS: 552,451,452 716 + * SMTP CODE SUCCESS: 500,501,502,421 717 + * @access public 718 + * @return bool 719 + */ 720 + public function SendAndMail($from) { 721 + $this->error = null; // so no confusion is caused 722 + 723 + if(!$this->connected()) { 724 + $this->error = array( 725 + "error" => "Called SendAndMail() without being connected"); 726 + return false; 727 + } 728 + 729 + fputs($this->smtp_conn,"SAML FROM:" . $from . $this->CRLF); 730 + 731 + $rply = $this->get_lines(); 732 + $code = substr($rply,0,3); 733 + 734 + if($this->do_debug >= 2) { 735 + echo "SMTP -> FROM SERVER:" . $rply . $this->CRLF . '<br />'; 736 + } 737 + 738 + if($code != 250) { 739 + $this->error = 740 + array("error" => "SAML not accepted from server", 741 + "smtp_code" => $code, 742 + "smtp_msg" => substr($rply,4)); 743 + if($this->do_debug >= 1) { 744 + echo "SMTP -> ERROR: " . $this->error["error"] . ": " . $rply . $this->CRLF . '<br />'; 745 + } 746 + return false; 747 + } 748 + return true; 749 + } 750 + 751 + /** 752 + * This is an optional command for SMTP that this class does not 753 + * support. This method is here to make the RFC821 Definition 754 + * complete for this class and __may__ be implimented in the future 755 + * 756 + * Implements from rfc 821: TURN <CRLF> 757 + * 758 + * SMTP CODE SUCCESS: 250 759 + * SMTP CODE FAILURE: 502 760 + * SMTP CODE ERROR : 500, 503 761 + * @access public 762 + * @return bool 763 + */ 764 + public function Turn() { 765 + $this->error = array("error" => "This method, TURN, of the SMTP ". 766 + "is not implemented"); 767 + if($this->do_debug >= 1) { 768 + echo "SMTP -> NOTICE: " . $this->error["error"] . $this->CRLF . '<br />'; 769 + } 770 + return false; 771 + } 772 + 773 + /** 774 + * Get the current error 775 + * @access public 776 + * @return array 777 + */ 778 + public function getError() { 779 + return $this->error; 780 + } 781 + 782 + ///////////////////////////////////////////////// 783 + // INTERNAL FUNCTIONS 784 + ///////////////////////////////////////////////// 785 + 786 + /** 787 + * Read in as many lines as possible 788 + * either before eof or socket timeout occurs on the operation. 789 + * With SMTP we can tell if we have more lines to read if the 790 + * 4th character is '-' symbol. If it is a space then we don't 791 + * need to read anything else. 792 + * @access private 793 + * @return string 794 + */ 795 + private function get_lines() { 796 + $data = ""; 797 + while($str = @fgets($this->smtp_conn,515)) { 798 + if($this->do_debug >= 4) { 799 + echo "SMTP -> get_lines(): \$data was \"$data\"" . $this->CRLF . '<br />'; 800 + echo "SMTP -> get_lines(): \$str is \"$str\"" . $this->CRLF . '<br />'; 801 + } 802 + $data .= $str; 803 + if($this->do_debug >= 4) { 804 + echo "SMTP -> get_lines(): \$data is \"$data\"" . $this->CRLF . '<br />'; 805 + } 806 + // if 4th character is a space, we are done reading, break the loop 807 + if(substr($str,3,1) == " ") { break; } 808 + } 809 + return $data; 810 + } 811 + 812 + } 813 + 814 814 ?>