annotate sites/all/modules/smtp/phpmailer/class.smtp.php @ 9:830c812b520f

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