[ Index ] |
PHP Cross Reference of MyBB |
[Summary view] [Print] [Text view]
1 <?php 2 /** 3 * MyBB 1.6 4 * Copyright 2010 MyBB Group, All Rights Reserved 5 * 6 * Website: http://mybb.com 7 * License: http://mybb.com/about/license 8 * 9 * $Id$ 10 */ 11 12 // Disallow direct access to this file for security reasons 13 if(!defined("IN_MYBB")) 14 { 15 die("Direct initialization of this file is not allowed.<br /><br />Please make sure IN_MYBB is defined."); 16 } 17 18 /** 19 * SMTP mail handler class. 20 */ 21 22 if(!defined('MYBB_SSL')) 23 { 24 define('MYBB_SSL', 1); 25 } 26 27 if(!defined('MYBB_TLS')) 28 { 29 define('MYBB_TLS', 2); 30 } 31 32 class SmtpMail extends MailHandler 33 { 34 /** 35 * The SMTP connection. 36 * 37 * @var resource 38 */ 39 public $connection; 40 41 /** 42 * SMTP username. 43 * 44 * @var string 45 */ 46 public $username = ''; 47 48 /** 49 * SMTP password. 50 * 51 * @var string 52 */ 53 public $password = ''; 54 55 /** 56 * Hello string sent to the smtp server with either HELO or EHLO. 57 * 58 * @var string 59 */ 60 public $helo = 'localhost'; 61 62 /** 63 * User authenticated or not. 64 * 65 * @var boolean 66 */ 67 public $authenticated = false; 68 69 /** 70 * How long before timeout. 71 * 72 * @var integer 73 */ 74 public $timeout = 5; 75 76 /** 77 * SMTP status. 78 * 79 * @var integer 80 */ 81 public $status = 0; 82 83 /** 84 * SMTP default port. 85 * 86 * @var integer 87 */ 88 public $port = 25; 89 90 /** 91 * SMTP default secure port. 92 * 93 * @var integer 94 */ 95 public $secure_port = 465; 96 97 /** 98 * SMTP host. 99 * 100 * @var string 101 */ 102 public $host = ''; 103 104 /** 105 * The last received response from the SMTP server. 106 * 107 * @var string 108 */ 109 public $data = ''; 110 111 /** 112 * The last received response code from the SMTP server. 113 * 114 * @var string 115 */ 116 public $code = 0; 117 118 /** 119 * The last received error message from the SMTP server. 120 * 121 * @var string 122 */ 123 public $last_error = ''; 124 125 /** 126 * Are we keeping the connection to the SMTP server alive? 127 * 128 * @var boolean 129 */ 130 public $keep_alive = false; 131 132 /** 133 * Whether to use TLS encryption. 134 * 135 * @var boolean 136 */ 137 public $use_tls = false; 138 139 function __construct() 140 { 141 global $mybb; 142 143 $protocol = ''; 144 switch($mybb->settings['secure_smtp']) 145 { 146 case MYBB_SSL: 147 $protocol = 'ssl://'; 148 break; 149 case MYBB_TLS: 150 $this->use_tls = true; 151 break; 152 } 153 154 if(empty($mybb->settings['smtp_host'])) 155 { 156 $this->host = @ini_get('SMTP'); 157 } 158 else 159 { 160 $this->host = $mybb->settings['smtp_host']; 161 } 162 163 $this->helo = $this->host; 164 165 $this->host = $protocol . $this->host; 166 167 if(empty($mybb->settings['smtp_port']) && !empty($protocol) && !@ini_get('smtp_port')) 168 { 169 $this->port = $this->secure_port; 170 } 171 else if(empty($mybb->settings['smtp_port']) && @ini_get('smtp_port')) 172 { 173 $this->port = @ini_get('smtp_port'); 174 } 175 else if(!empty($mybb->settings['smtp_port'])) 176 { 177 $this->port = $mybb->settings['smtp_port']; 178 } 179 180 $this->password = $mybb->settings['smtp_pass']; 181 $this->username = $mybb->settings['smtp_user']; 182 } 183 184 /** 185 * Sends the email. 186 * 187 * @return true/false whether or not the email got sent or not. 188 */ 189 function send() 190 { 191 global $lang, $mybb; 192 193 if(!$this->connected()) 194 { 195 if(!$this->connect()) 196 { 197 $this->close(); 198 } 199 } 200 201 if($this->connected()) 202 { 203 if(!$this->send_data('MAIL FROM:<'.$this->from.'>', '250')) 204 { 205 $this->fatal_error("The mail server does not understand the MAIL FROM command. Reason: ".$this->get_error()); 206 return false; 207 } 208 209 // Loop through recipients 210 $emails = explode(',', $this->to); 211 foreach($emails as $to) 212 { 213 $to = trim($to); 214 if(!$this->send_data('RCPT TO:<'.$to.'>', '250')) 215 { 216 $this->fatal_error("The mail server does not understand the RCPT TO command. Reason: ".$this->get_error()); 217 return false; 218 } 219 } 220 221 if($this->send_data('DATA', '354')) 222 { 223 $this->send_data('Date: ' . gmdate('r')); 224 $this->send_data('To: ' . $this->to); 225 226 $this->send_data('Subject: ' . $this->subject); 227 228 // Only send additional headers if we've got any 229 if(trim($this->headers)) 230 { 231 $this->send_data(trim($this->headers)); 232 } 233 234 $this->send_data(""); 235 236 // Queue the actual message 237 $this->message = str_replace("\n.", "\n..", $this->message); 238 $this->send_data($this->message); 239 } 240 else 241 { 242 $this->fatal_error("The mail server did not understand the DATA command"); 243 return false; 244 } 245 246 $this->send_data('.', '250'); 247 248 if(!$this->keep_alive) 249 { 250 $this->close(); 251 } 252 return true; 253 } 254 else 255 { 256 return false; 257 } 258 } 259 260 /** 261 * Connect to the SMTP server. 262 * 263 * @return boolean True if connection was successful 264 */ 265 function connect() 266 { 267 global $lang, $mybb; 268 269 $this->connection = @fsockopen($this->host, $this->port, $error_number, $error_string, $this->timeout); 270 271 // DIRECTORY_SEPARATOR checks if running windows 272 if(function_exists('stream_set_timeout') && DIRECTORY_SEPARATOR != '\\') 273 { 274 @stream_set_timeout($this->connection, $this->timeout, 0); 275 } 276 277 if(is_resource($this->connection)) 278 { 279 $this->status = 1; 280 $this->get_data(); 281 if(!$this->check_status('220')) 282 { 283 $this->fatal_error("The mail server is not ready, it did not respond with a 220 status message."); 284 return false; 285 } 286 287 if($this->use_tls || (!empty($this->username) && !empty($this->password))) 288 { 289 $helo = 'EHLO'; 290 } 291 else 292 { 293 $helo = 'HELO'; 294 } 295 296 $data = $this->send_data("{$helo} {$this->helo}", '250'); 297 if(!$data) 298 { 299 $this->fatal_error("The server did not understand the {$helo} command"); 300 return false; 301 } 302 303 if($this->use_tls && preg_match("#250( |-)STARTTLS#mi", $data)) 304 { 305 if(!$this->send_data('STARTTLS', '220')) 306 { 307 $this->fatal_error("The server did not understand the STARTTLS command. Reason: ".$this->get_error()); 308 return false; 309 } 310 if(!@stream_socket_enable_crypto($this->connection, true, STREAM_CRYPTO_METHOD_TLS_CLIENT)) 311 { 312 $this->fatal_error("Failed to start TLS encryption"); 313 return false; 314 } 315 // Resend EHLO to get updated service list 316 $data = $this->send_data("{$helo} {$this->helo}", '250'); 317 if(!$data) 318 { 319 $this->fatal_error("The server did not understand the EHLO command"); 320 return false; 321 } 322 } 323 324 if(!empty($this->username) && !empty($this->password)) 325 { 326 preg_match("#250( |-)AUTH( |=)(.+)$#mi", $data, $matches); 327 if(!$this->auth($matches[3])) 328 { 329 return false; 330 } 331 } 332 return true; 333 } 334 else 335 { 336 $this->fatal_error("Unable to connect to the mail server with the given details. Reason: {$error_number}: {$error_string}"); 337 return false; 338 } 339 } 340 341 /** 342 * Authenticate against the SMTP server. 343 * 344 * @param string A list of authentication methods supported by the server 345 * @return boolean True on success 346 */ 347 function auth($auth_methods) 348 { 349 global $lang, $mybb; 350 351 $auth_methods = explode(" ", trim($auth_methods)); 352 353 if(in_array("LOGIN", $auth_methods)) 354 { 355 if(!$this->send_data("AUTH LOGIN", 334)) 356 { 357 if($this->code == 503) 358 { 359 return true; 360 } 361 $this->fatal_error("The SMTP server did not respond correctly to the AUTH LOGIN command"); 362 return false; 363 } 364 365 if(!$this->send_data(base64_encode($this->username), '334')) 366 { 367 $this->fatal_error("The SMTP server rejected the supplied SMTP username. Reason: ".$this->get_error()); 368 return false; 369 } 370 371 if(!$this->send_data(base64_encode($this->password), '235')) 372 { 373 $this->fatal_error("The SMTP server rejected the supplied SMTP password. Reason: ".$this->get_error()); 374 return false; 375 } 376 } 377 else if(in_array("PLAIN", $auth_methods)) 378 { 379 if(!$this->send_data("AUTH PLAIN", '334')) 380 { 381 if($this->code == 503) 382 { 383 return true; 384 } 385 $this->fatal_error("The SMTP server did not respond correctly to the AUTH PLAIN command"); 386 return false; 387 } 388 $auth = base64_encode(chr(0).$this->username.chr(0).$this->password); 389 if(!$this->send_data($auth, 235)) 390 { 391 $this->fatal_error("The SMTP server rejected the supplied login username and password. Reason: ".$this->get_error()); 392 return false; 393 } 394 } 395 else 396 { 397 $this->fatal_error("The SMTP server does not support any of the AUTH methods that MyBB supports"); 398 return false; 399 } 400 401 // Still here, we're authenticated 402 return true; 403 } 404 405 /** 406 * Fetch data from the SMTP server. 407 * 408 * @return string The data from the SMTP server 409 */ 410 function get_data() 411 { 412 $string = ''; 413 414 while((($line = fgets($this->connection, 515)) !== false)) 415 { 416 $string .= $line; 417 if(substr($line, 3, 1) == ' ') 418 { 419 break; 420 } 421 } 422 $string = trim($string); 423 $this->data = $string; 424 $this->code = substr($this->data, 0, 3); 425 return $string; 426 } 427 428 /** 429 * Check if we're currently connected to an SMTP server 430 * 431 * @return boolean true if connected 432 */ 433 function connected() 434 { 435 if($this->status == 1) 436 { 437 return true; 438 } 439 return false; 440 } 441 442 /** 443 * Send data through to the SMTP server. 444 * 445 * @param string The data to be sent 446 * @param int The response code expected back from the server (if we have one) 447 * @return boolean True on success 448 */ 449 function send_data($data, $status_num = false) 450 { 451 if($this->connected()) 452 { 453 if(fwrite($this->connection, $data."\r\n")) 454 { 455 if($status_num != false) 456 { 457 $rec = $this->get_data(); 458 if($this->check_status($status_num)) 459 { 460 return $rec; 461 } 462 else 463 { 464 $this->set_error($rec); 465 return false; 466 } 467 } 468 return true; 469 } 470 else 471 { 472 $this->fatal_error("Unable to send the data to the SMTP server"); 473 return false; 474 } 475 } 476 return false; 477 } 478 479 /** 480 * Checks if the received status code matches the one we expect. 481 * 482 * @param int The status code we expected back from the server 483 * @param boolean True if it matches 484 */ 485 function check_status($status_num) 486 { 487 if($this->code == $status_num) 488 { 489 return $this->data; 490 } 491 else 492 { 493 return false; 494 } 495 } 496 497 /** 498 * Close the connection to the SMTP server. 499 */ 500 function close() 501 { 502 if($this->status == 1) 503 { 504 $this->send_data('QUIT'); 505 fclose($this->connection); 506 $this->status = 0; 507 } 508 } 509 510 /** 511 * Get the last error message response from the SMTP server 512 * 513 * @return string The error message response from the SMTP server 514 */ 515 function get_error() 516 { 517 if(!$this->last_error) 518 { 519 $this->last_error = "N/A"; 520 } 521 522 return $this->last_error; 523 } 524 525 /** 526 * Set the last error message response from the SMTP server 527 * 528 * @param string The error message response 529 */ 530 function set_error($error) 531 { 532 $this->last_error = $error; 533 } 534 } 535 ?>
title
Description
Body
title
Description
Body
title
Description
Body
title
Body
Generated: Tue Oct 8 19:19:50 2013 | Cross-referenced by PHPXref 0.7.1 |