Guest User

Untitled

a guest
Jun 6th, 2013
141
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 31.31 KB | None | 0 0
  1. <?php
  2. /*~ class.smtp.php
  3. .---------------------------------------------------------------------------.
  4. | Software: PHPMailer - PHP email class |
  5. | Version: 5.2.2 |
  6. | Site: https://code.google.com/a/apache-extras.org/p/phpmailer/ |
  7. | ------------------------------------------------------------------------- |
  8. | Admin: Jim Jagielski (project admininistrator) |
  9. | Authors: Andy Prevost (codeworxtech) [email protected] |
  10. | : Marcus Bointon (coolbru) [email protected] |
  11. | : Jim Jagielski (jimjag) [email protected] |
  12. | Founder: Brent R. Matzelle (original founder) |
  13. | Copyright (c) 2010-2012, Jim Jagielski. All Rights Reserved. |
  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. */
  24.  
  25. /**
  26. * PHPMailer - PHP SMTP email transport class
  27. * NOTE: Designed for use with PHP version 5 and up
  28. * @package PHPMailer
  29. * @author Andy Prevost
  30. * @author Marcus Bointon
  31. * @copyright 2004 - 2008 Andy Prevost
  32. * @author Jim Jagielski
  33. * @copyright 2010 - 2012 Jim Jagielski
  34. * @license http://www.gnu.org/copyleft/lesser.html Distributed under the Lesser General Public License (LGPL)
  35. */
  36.  
  37. /**
  38. * PHP RFC821 SMTP client
  39. *
  40. * Implements all the RFC 821 SMTP commands except TURN which will always return a not implemented error.
  41. * SMTP also provides some utility methods for sending mail to an SMTP server.
  42. * @author Chris Ryan
  43. * @package PHPMailer
  44. */
  45.  
  46. class SMTP {
  47. /**
  48. * SMTP server port
  49. * @var int
  50. */
  51. public $SMTP_PORT = 25;
  52.  
  53. /**
  54. * SMTP reply line ending (don't change)
  55. * @var string
  56. */
  57. public $CRLF = "\r\n";
  58.  
  59. /**
  60. * Sets whether debugging is turned on
  61. * @var bool
  62. */
  63. public $do_debug; // the level of debug to perform
  64.  
  65. /**
  66. * Sets the function/method to use for debugging output.
  67. * Right now we only honor "echo" or "error_log"
  68. * @var string
  69. */
  70. public $Debugoutput = "echo";
  71.  
  72. /**
  73. * Sets VERP use on/off (default is off)
  74. * @var bool
  75. */
  76. public $do_verp = false;
  77.  
  78. /**
  79. * Sets the SMTP timeout value for reads, in seconds
  80. * @var int
  81. */
  82. public $Timeout = 15;
  83.  
  84. /**
  85. * Sets the SMTP timelimit value for reads, in seconds
  86. * @var int
  87. */
  88. public $Timelimit = 30;
  89.  
  90. /**
  91. * Sets the SMTP PHPMailer Version number
  92. * @var string
  93. */
  94. public $Version = '5.2.2';
  95.  
  96. /////////////////////////////////////////////////
  97. // PROPERTIES, PRIVATE AND PROTECTED
  98. /////////////////////////////////////////////////
  99.  
  100. /**
  101. * @var resource The socket to the server
  102. */
  103. private $smtp_conn;
  104. /**
  105. * @var string Error message, if any, for the last call
  106. */
  107. private $error;
  108. /**
  109. * @var string The reply the server sent to us for HELO
  110. */
  111. private $helo_rply;
  112.  
  113. /**
  114. * Outputs debugging info via user-defined method
  115. * @param string $str
  116. */
  117. private function edebug($str) {
  118. if ($this->Debugoutput == "error_log") {
  119. error_log($str);
  120. } else {
  121. echo $str;
  122. }
  123. }
  124.  
  125. /**
  126. * Initialize the class so that the data is in a known state.
  127. * @access public
  128. * @return SMTP
  129. */
  130. public function __construct() {
  131. $this->smtp_conn = 0;
  132. $this->error = null;
  133. $this->helo_rply = null;
  134.  
  135. $this->do_debug = 0;
  136. }
  137.  
  138. /////////////////////////////////////////////////
  139. // CONNECTION FUNCTIONS
  140. /////////////////////////////////////////////////
  141.  
  142. /**
  143. * Connect to the server specified on the port specified.
  144. * If the port is not specified use the default SMTP_PORT.
  145. * If tval is specified then a connection will try and be
  146. * established with the server for that number of seconds.
  147. * If tval is not specified the default is 30 seconds to
  148. * try on the connection.
  149. *
  150. * SMTP CODE SUCCESS: 220
  151. * SMTP CODE FAILURE: 421
  152. * @access public
  153. * @param string $host
  154. * @param int $port
  155. * @param int $tval
  156. * @return bool
  157. */
  158. public function Connect($host, $port = 0, $tval = 30) {
  159. // set the error val to null so there is no confusion
  160. $this->error = null;
  161.  
  162. // make sure we are __not__ connected
  163. if($this->connected()) {
  164. // already connected, generate error
  165. $this->error = array("error" => "Already connected to a server");
  166. return false;
  167. }
  168.  
  169. if(empty($port)) {
  170. $port = $this->SMTP_PORT;
  171. }
  172.  
  173. // connect to the smtp server
  174. $this->smtp_conn = @fsockopen($host, // the host of the server
  175. $port, // the port to use
  176. $errno, // error number if any
  177. $errstr, // error message if any
  178. $tval); // give up after ? secs
  179. // verify we connected properly
  180. if(empty($this->smtp_conn)) {
  181. $this->error = array("error" => "Failed to connect to server",
  182. "errno" => $errno,
  183. "errstr" => $errstr);
  184. if($this->do_debug >= 1) {
  185. $this->edebug("SMTP -> ERROR: " . $this->error["error"] . ": $errstr ($errno)" . $this->CRLF . '<br />');
  186. }
  187. return false;
  188. }
  189.  
  190. // SMTP server can take longer to respond, give longer timeout for first read
  191. // Windows does not have support for this timeout function
  192. if(substr(PHP_OS, 0, 3) != "WIN") {
  193. $max = ini_get('max_execution_time');
  194. if ($max != 0 && $tval > $max) { // don't bother if unlimited
  195. @set_time_limit($tval);
  196. }
  197. stream_set_timeout($this->smtp_conn, $tval, 0);
  198. }
  199.  
  200. // get any announcement
  201. $announce = $this->get_lines();
  202.  
  203. if($this->do_debug >= 2) {
  204. $this->edebug("SMTP -> FROM SERVER:" . $announce . $this->CRLF . '<br />');
  205. }
  206.  
  207. return true;
  208. }
  209.  
  210. /**
  211. * Initiate a TLS communication with the server.
  212. *
  213. * SMTP CODE 220 Ready to start TLS
  214. * SMTP CODE 501 Syntax error (no parameters allowed)
  215. * SMTP CODE 454 TLS not available due to temporary reason
  216. * @access public
  217. * @return bool success
  218. */
  219. public function StartTLS() {
  220. $this->error = null; # to avoid confusion
  221.  
  222. if(!$this->connected()) {
  223. $this->error = array("error" => "Called StartTLS() without being connected");
  224. return false;
  225. }
  226.  
  227. fputs($this->smtp_conn,"STARTTLS" . $this->CRLF);
  228.  
  229. $rply = $this->get_lines();
  230. $code = substr($rply,0,3);
  231.  
  232. if($this->do_debug >= 2) {
  233. $this->edebug("SMTP -> FROM SERVER:" . $rply . $this->CRLF . '<br />');
  234. }
  235.  
  236. if($code != 220) {
  237. $this->error =
  238. array("error" => "STARTTLS not accepted from server",
  239. "smtp_code" => $code,
  240. "smtp_msg" => substr($rply,4));
  241. if($this->do_debug >= 1) {
  242. $this->edebug("SMTP -> ERROR: " . $this->error["error"] . ": " . $rply . $this->CRLF . '<br />');
  243. }
  244. return false;
  245. }
  246.  
  247. // Begin encrypted connection
  248. if(!stream_socket_enable_crypto($this->smtp_conn, true, STREAM_CRYPTO_METHOD_TLS_CLIENT)) {
  249. return false;
  250. }
  251.  
  252. return true;
  253. }
  254.  
  255. /**
  256. * Performs SMTP authentication. Must be run after running the
  257. * Hello() method. Returns true if successfully authenticated.
  258. * @access public
  259. * @param string $username
  260. * @param string $password
  261. * @param string $authtype
  262. * @param string $realm
  263. * @param string $workstation
  264. * @return bool
  265. */
  266. public function Authenticate($username, $password, $authtype='LOGIN', $realm='', $workstation='') {
  267. if (empty($authtype)) {
  268. $authtype = 'LOGIN';
  269. }
  270.  
  271. switch ($authtype) {
  272. case 'PLAIN':
  273. // Start authentication
  274. fputs($this->smtp_conn,"AUTH PLAIN" . $this->CRLF);
  275.  
  276. $rply = $this->get_lines();
  277. $code = substr($rply,0,3);
  278.  
  279. if($code != 334) {
  280. $this->error =
  281. array("error" => "AUTH not accepted from server",
  282. "smtp_code" => $code,
  283. "smtp_msg" => substr($rply,4));
  284. if($this->do_debug >= 1) {
  285. $this->edebug("SMTP -> ERROR: " . $this->error["error"] . ": " . $rply . $this->CRLF . '<br />');
  286. }
  287. return false;
  288. }
  289. // Send encoded username and password
  290. fputs($this->smtp_conn, base64_encode("\0".$username."\0".$password) . $this->CRLF);
  291.  
  292. $rply = $this->get_lines();
  293. $code = substr($rply,0,3);
  294.  
  295. if($code != 235) {
  296. $this->error =
  297. array("error" => "Authentication not accepted from server",
  298. "smtp_code" => $code,
  299. "smtp_msg" => substr($rply,4));
  300. if($this->do_debug >= 1) {
  301. $this->edebug("SMTP -> ERROR: " . $this->error["error"] . ": " . $rply . $this->CRLF . '<br />');
  302. }
  303. return false;
  304. }
  305. break;
  306. case 'LOGIN':
  307. // Start authentication
  308. fputs($this->smtp_conn,"AUTH LOGIN" . $this->CRLF);
  309.  
  310. $rply = $this->get_lines();
  311. $code = substr($rply,0,3);
  312.  
  313. if($code != 334) {
  314. $this->error =
  315. array("error" => "AUTH not accepted from server",
  316. "smtp_code" => $code,
  317. "smtp_msg" => substr($rply,4));
  318. if($this->do_debug >= 1) {
  319. $this->edebug("SMTP -> ERROR: " . $this->error["error"] . ": " . $rply . $this->CRLF . '<br />');
  320. }
  321. return false;
  322. }
  323.  
  324. // Send encoded username
  325. fputs($this->smtp_conn, base64_encode($username) . $this->CRLF);
  326.  
  327. $rply = $this->get_lines();
  328. $code = substr($rply,0,3);
  329.  
  330. if($code != 334) {
  331. $this->error =
  332. array("error" => "Username not accepted from server",
  333. "smtp_code" => $code,
  334. "smtp_msg" => substr($rply,4));
  335. if($this->do_debug >= 1) {
  336. $this->edebug("SMTP -> ERROR: " . $this->error["error"] . ": " . $rply . $this->CRLF . '<br />');
  337. }
  338. return false;
  339. }
  340.  
  341. // Send encoded password
  342. fputs($this->smtp_conn, base64_encode($password) . $this->CRLF);
  343.  
  344. $rply = $this->get_lines();
  345. $code = substr($rply,0,3);
  346.  
  347. if($code != 235) {
  348. $this->error =
  349. array("error" => "Password not accepted from server",
  350. "smtp_code" => $code,
  351. "smtp_msg" => substr($rply,4));
  352. if($this->do_debug >= 1) {
  353. $this->edebug("SMTP -> ERROR: " . $this->error["error"] . ": " . $rply . $this->CRLF . '<br />');
  354. }
  355. return false;
  356. }
  357. break;
  358. case 'NTLM':
  359. /*
  360. * ntlm_sasl_client.php
  361. ** Bundled with Permission
  362. **
  363. ** How to telnet in windows: http://technet.microsoft.com/en-us/library/aa995718%28EXCHG.65%29.aspx
  364. ** PROTOCOL Documentation http://curl.haxx.se/rfc/ntlm.html#ntlmSmtpAuthentication
  365. */
  366. require_once('ntlm_sasl_client.php');
  367. $temp = new stdClass();
  368. $ntlm_client = new ntlm_sasl_client_class;
  369. if(! $ntlm_client->Initialize($temp)){//let's test if every function its available
  370. $this->error = array("error" => $temp->error);
  371. if($this->do_debug >= 1) {
  372. $this->edebug("You need to enable some modules in your php.ini file: " . $this->error["error"] . $this->CRLF);
  373. }
  374. return false;
  375. }
  376. $msg1 = $ntlm_client->TypeMsg1($realm, $workstation);//msg1
  377.  
  378. fputs($this->smtp_conn,"AUTH NTLM " . base64_encode($msg1) . $this->CRLF);
  379.  
  380. $rply = $this->get_lines();
  381. $code = substr($rply,0,3);
  382.  
  383.  
  384. if($code != 334) {
  385. $this->error =
  386. array("error" => "AUTH not accepted from server",
  387. "smtp_code" => $code,
  388. "smtp_msg" => substr($rply,4));
  389. if($this->do_debug >= 1) {
  390. $this->edebug("SMTP -> ERROR: " . $this->error["error"] . ": " . $rply . $this->CRLF);
  391. }
  392. return false;
  393. }
  394.  
  395. $challange = substr($rply,3);//though 0 based, there is a white space after the 3 digit number....//msg2
  396. $challange = base64_decode($challange);
  397. $ntlm_res = $ntlm_client->NTLMResponse(substr($challange,24,8),$password);
  398. $msg3 = $ntlm_client->TypeMsg3($ntlm_res,$username,$realm,$workstation);//msg3
  399. // Send encoded username
  400. fputs($this->smtp_conn, base64_encode($msg3) . $this->CRLF);
  401.  
  402. $rply = $this->get_lines();
  403. $code = substr($rply,0,3);
  404.  
  405. if($code != 235) {
  406. $this->error =
  407. array("error" => "Could not authenticate",
  408. "smtp_code" => $code,
  409. "smtp_msg" => substr($rply,4));
  410. if($this->do_debug >= 1) {
  411. $this->edebug("SMTP -> ERROR: " . $this->error["error"] . ": " . $rply . $this->CRLF);
  412. }
  413. return false;
  414. }
  415. break;
  416. }
  417. return true;
  418. }
  419.  
  420. /**
  421. * Returns true if connected to a server otherwise false
  422. * @access public
  423. * @return bool
  424. */
  425. public function Connected() {
  426. if(!empty($this->smtp_conn)) {
  427. $sock_status = socket_get_status($this->smtp_conn);
  428. if($sock_status["eof"]) {
  429. // the socket is valid but we are not connected
  430. if($this->do_debug >= 1) {
  431. $this->edebug("SMTP -> NOTICE:" . $this->CRLF . "EOF caught while checking if connected");
  432. }
  433. $this->Close();
  434. return false;
  435. }
  436. return true; // everything looks good
  437. }
  438. return false;
  439. }
  440.  
  441. /**
  442. * Closes the socket and cleans up the state of the class.
  443. * It is not considered good to use this function without
  444. * first trying to use QUIT.
  445. * @access public
  446. * @return void
  447. */
  448. public function Close() {
  449. $this->error = null; // so there is no confusion
  450. $this->helo_rply = null;
  451. if(!empty($this->smtp_conn)) {
  452. // close the connection and cleanup
  453. fclose($this->smtp_conn);
  454. $this->smtp_conn = 0;
  455. }
  456. }
  457.  
  458. /////////////////////////////////////////////////
  459. // SMTP COMMANDS
  460. /////////////////////////////////////////////////
  461.  
  462. /**
  463. * Issues a data command and sends the msg_data to the server
  464. * finializing the mail transaction. $msg_data is the message
  465. * that is to be send with the headers. Each header needs to be
  466. * on a single line followed by a <CRLF> with the message headers
  467. * and the message body being seperated by and additional <CRLF>.
  468. *
  469. * Implements rfc 821: DATA <CRLF>
  470. *
  471. * SMTP CODE INTERMEDIATE: 354
  472. * [data]
  473. * <CRLF>.<CRLF>
  474. * SMTP CODE SUCCESS: 250
  475. * SMTP CODE FAILURE: 552,554,451,452
  476. * SMTP CODE FAILURE: 451,554
  477. * SMTP CODE ERROR : 500,501,503,421
  478. * @access public
  479. * @param string $msg_data
  480. * @return bool
  481. */
  482. public function Data($msg_data) {
  483. $this->error = null; // so no confusion is caused
  484.  
  485. if(!$this->connected()) {
  486. $this->error = array(
  487. "error" => "Called Data() without being connected");
  488. return false;
  489. }
  490.  
  491. fputs($this->smtp_conn,"DATA" . $this->CRLF);
  492.  
  493. $rply = $this->get_lines();
  494. $code = substr($rply,0,3);
  495.  
  496. if($this->do_debug >= 2) {
  497. $this->edebug("SMTP -> FROM SERVER:" . $rply . $this->CRLF . '<br />');
  498. }
  499.  
  500. if($code != 354) {
  501. $this->error =
  502. array("error" => "DATA command not accepted from server",
  503. "smtp_code" => $code,
  504. "smtp_msg" => substr($rply,4));
  505. if($this->do_debug >= 1) {
  506. $this->edebug("SMTP -> ERROR: " . $this->error["error"] . ": " . $rply . $this->CRLF . '<br />');
  507. }
  508. return false;
  509. }
  510.  
  511. /* the server is ready to accept data!
  512. * according to rfc 821 we should not send more than 1000
  513. * including the CRLF
  514. * characters on a single line so we will break the data up
  515. * into lines by \r and/or \n then if needed we will break
  516. * each of those into smaller lines to fit within the limit.
  517. * in addition we will be looking for lines that start with
  518. * a period '.' and append and additional period '.' to that
  519. * line. NOTE: this does not count towards limit.
  520. */
  521.  
  522. // normalize the line breaks so we know the explode works
  523. $msg_data = str_replace("\r\n","\n",$msg_data);
  524. $msg_data = str_replace("\r","\n",$msg_data);
  525. $lines = explode("\n",$msg_data);
  526.  
  527. /* we need to find a good way to determine is headers are
  528. * in the msg_data or if it is a straight msg body
  529. * currently I am assuming rfc 822 definitions of msg headers
  530. * and if the first field of the first line (':' sperated)
  531. * does not contain a space then it _should_ be a header
  532. * and we can process all lines before a blank "" line as
  533. * headers.
  534. */
  535.  
  536. $field = substr($lines[0],0,strpos($lines[0],":"));
  537. $in_headers = false;
  538. if(!empty($field) && !strstr($field," ")) {
  539. $in_headers = true;
  540. }
  541.  
  542. $max_line_length = 998; // used below; set here for ease in change
  543.  
  544. while(list(,$line) = @each($lines)) {
  545. $lines_out = null;
  546. if($line == "" && $in_headers) {
  547. $in_headers = false;
  548. }
  549. // ok we need to break this line up into several smaller lines
  550. while(strlen($line) > $max_line_length) {
  551. $pos = strrpos(substr($line,0,$max_line_length)," ");
  552.  
  553. // Patch to fix DOS attack
  554. if(!$pos) {
  555. $pos = $max_line_length - 1;
  556. $lines_out[] = substr($line,0,$pos);
  557. $line = substr($line,$pos);
  558. } else {
  559. $lines_out[] = substr($line,0,$pos);
  560. $line = substr($line,$pos + 1);
  561. }
  562.  
  563. /* if processing headers add a LWSP-char to the front of new line
  564. * rfc 822 on long msg headers
  565. */
  566. if($in_headers) {
  567. $line = "\t" . $line;
  568. }
  569. }
  570. $lines_out[] = $line;
  571.  
  572. // send the lines to the server
  573. while(list(,$line_out) = @each($lines_out)) {
  574. if(strlen($line_out) > 0)
  575. {
  576. if(substr($line_out, 0, 1) == ".") {
  577. $line_out = "." . $line_out;
  578. }
  579. }
  580. fputs($this->smtp_conn,$line_out . $this->CRLF);
  581. }
  582. }
  583.  
  584. // message data has been sent
  585. fputs($this->smtp_conn, $this->CRLF . "." . $this->CRLF);
  586.  
  587. $rply = $this->get_lines();
  588. $code = substr($rply,0,3);
  589.  
  590. if($this->do_debug >= 2) {
  591. $this->edebug("SMTP -> FROM SERVER:" . $rply . $this->CRLF . '<br />');
  592. }
  593.  
  594. if($code != 250) {
  595. $this->error =
  596. array("error" => "DATA not accepted from server",
  597. "smtp_code" => $code,
  598. "smtp_msg" => substr($rply,4));
  599. if($this->do_debug >= 1) {
  600. $this->edebug("SMTP -> ERROR: " . $this->error["error"] . ": " . $rply . $this->CRLF . '<br />');
  601. }
  602. return false;
  603. }
  604. return true;
  605. }
  606.  
  607. /**
  608. * Sends the HELO command to the smtp server.
  609. * This makes sure that we and the server are in
  610. * the same known state.
  611. *
  612. * Implements from rfc 821: HELO <SP> <domain> <CRLF>
  613. *
  614. * SMTP CODE SUCCESS: 250
  615. * SMTP CODE ERROR : 500, 501, 504, 421
  616. * @access public
  617. * @param string $host
  618. * @return bool
  619. */
  620. public function Hello($host = '') {
  621. $this->error = null; // so no confusion is caused
  622.  
  623. if(!$this->connected()) {
  624. $this->error = array(
  625. "error" => "Called Hello() without being connected");
  626. return false;
  627. }
  628.  
  629. // if hostname for HELO was not specified send default
  630. if(empty($host)) {
  631. // determine appropriate default to send to server
  632. $host = "localhost";
  633. }
  634.  
  635. // Send extended hello first (RFC 2821)
  636. if(!$this->SendHello("EHLO", $host)) {
  637. if(!$this->SendHello("HELO", $host)) {
  638. return false;
  639. }
  640. }
  641.  
  642. return true;
  643. }
  644.  
  645. /**
  646. * Sends a HELO/EHLO command.
  647. * @access private
  648. * @param string $hello
  649. * @param string $host
  650. * @return bool
  651. */
  652. private function SendHello($hello, $host) {
  653. fputs($this->smtp_conn, $hello . " " . $host . $this->CRLF);
  654.  
  655. $rply = $this->get_lines();
  656. $code = substr($rply,0,3);
  657.  
  658. if($this->do_debug >= 2) {
  659. $this->edebug("SMTP -> FROM SERVER: " . $rply . $this->CRLF . '<br />');
  660. }
  661.  
  662. if($code != 250) {
  663. $this->error =
  664. array("error" => $hello . " not accepted from server",
  665. "smtp_code" => $code,
  666. "smtp_msg" => substr($rply,4));
  667. if($this->do_debug >= 1) {
  668. $this->edebug("SMTP -> ERROR: " . $this->error["error"] . ": " . $rply . $this->CRLF . '<br />');
  669. }
  670. return false;
  671. }
  672.  
  673. $this->helo_rply = $rply;
  674.  
  675. return true;
  676. }
  677.  
  678. /**
  679. * Starts a mail transaction from the email address specified in
  680. * $from. Returns true if successful or false otherwise. If True
  681. * the mail transaction is started and then one or more Recipient
  682. * commands may be called followed by a Data command.
  683. *
  684. * Implements rfc 821: MAIL <SP> FROM:<reverse-path> <CRLF>
  685. *
  686. * SMTP CODE SUCCESS: 250
  687. * SMTP CODE SUCCESS: 552,451,452
  688. * SMTP CODE SUCCESS: 500,501,421
  689. * @access public
  690. * @param string $from
  691. * @return bool
  692. */
  693. public function Mail($from) {
  694. $this->error = null; // so no confusion is caused
  695.  
  696. if(!$this->connected()) {
  697. $this->error = array(
  698. "error" => "Called Mail() without being connected");
  699. return false;
  700. }
  701.  
  702. $useVerp = ($this->do_verp ? " XVERP" : "");
  703. fputs($this->smtp_conn,"MAIL FROM:<" . $from . ">" . $useVerp . $this->CRLF);
  704.  
  705. $rply = $this->get_lines();
  706. $code = substr($rply,0,3);
  707.  
  708. if($this->do_debug >= 2) {
  709. $this->edebug("SMTP -> FROM SERVER:" . $rply . $this->CRLF . '<br />');
  710. }
  711.  
  712. if($code != 250) {
  713. $this->error =
  714. array("error" => "MAIL not accepted from server",
  715. "smtp_code" => $code,
  716. "smtp_msg" => substr($rply,4));
  717. if($this->do_debug >= 1) {
  718. $this->edebug("SMTP -> ERROR: " . $this->error["error"] . ": " . $rply . $this->CRLF . '<br />');
  719. }
  720. return false;
  721. }
  722. return true;
  723. }
  724.  
  725. /**
  726. * Sends the quit command to the server and then closes the socket
  727. * if there is no error or the $close_on_error argument is true.
  728. *
  729. * Implements from rfc 821: QUIT <CRLF>
  730. *
  731. * SMTP CODE SUCCESS: 221
  732. * SMTP CODE ERROR : 500
  733. * @access public
  734. * @param bool $close_on_error
  735. * @return bool
  736. */
  737. public function Quit($close_on_error = true) {
  738. $this->error = null; // so there is no confusion
  739.  
  740. if(!$this->connected()) {
  741. $this->error = array(
  742. "error" => "Called Quit() without being connected");
  743. return false;
  744. }
  745.  
  746. // send the quit command to the server
  747. fputs($this->smtp_conn,"quit" . $this->CRLF);
  748.  
  749. // get any good-bye messages
  750. $byemsg = $this->get_lines();
  751.  
  752. if($this->do_debug >= 2) {
  753. $this->edebug("SMTP -> FROM SERVER:" . $byemsg . $this->CRLF . '<br />');
  754. }
  755.  
  756. $rval = true;
  757. $e = null;
  758.  
  759. $code = substr($byemsg,0,3);
  760. if($code != 221) {
  761. // use e as a tmp var cause Close will overwrite $this->error
  762. $e = array("error" => "SMTP server rejected quit command",
  763. "smtp_code" => $code,
  764. "smtp_rply" => substr($byemsg,4));
  765. $rval = false;
  766. if($this->do_debug >= 1) {
  767. $this->edebug("SMTP -> ERROR: " . $e["error"] . ": " . $byemsg . $this->CRLF . '<br />');
  768. }
  769. }
  770.  
  771. if(empty($e) || $close_on_error) {
  772. $this->Close();
  773. }
  774.  
  775. return $rval;
  776. }
  777.  
  778. /**
  779. * Sends the command RCPT to the SMTP server with the TO: argument of $to.
  780. * Returns true if the recipient was accepted false if it was rejected.
  781. *
  782. * Implements from rfc 821: RCPT <SP> TO:<forward-path> <CRLF>
  783. *
  784. * SMTP CODE SUCCESS: 250,251
  785. * SMTP CODE FAILURE: 550,551,552,553,450,451,452
  786. * SMTP CODE ERROR : 500,501,503,421
  787. * @access public
  788. * @param string $to
  789. * @return bool
  790. */
  791. public function Recipient($to) {
  792. $this->error = null; // so no confusion is caused
  793.  
  794. if(!$this->connected()) {
  795. $this->error = array(
  796. "error" => "Called Recipient() without being connected");
  797. return false;
  798. }
  799.  
  800. fputs($this->smtp_conn,"RCPT TO:<" . $to . ">" . $this->CRLF);
  801.  
  802. $rply = $this->get_lines();
  803. $code = substr($rply,0,3);
  804.  
  805. if($this->do_debug >= 2) {
  806. $this->edebug("SMTP -> FROM SERVER:" . $rply . $this->CRLF . '<br />');
  807. }
  808.  
  809. if($code != 250 && $code != 251) {
  810. $this->error =
  811. array("error" => "RCPT not accepted from server",
  812. "smtp_code" => $code,
  813. "smtp_msg" => substr($rply,4));
  814. if($this->do_debug >= 1) {
  815. $this->edebug("SMTP -> ERROR: " . $this->error["error"] . ": " . $rply . $this->CRLF . '<br />');
  816. }
  817. return false;
  818. }
  819. return true;
  820. }
  821.  
  822. /**
  823. * Sends the RSET command to abort and transaction that is
  824. * currently in progress. Returns true if successful false
  825. * otherwise.
  826. *
  827. * Implements rfc 821: RSET <CRLF>
  828. *
  829. * SMTP CODE SUCCESS: 250
  830. * SMTP CODE ERROR : 500,501,504,421
  831. * @access public
  832. * @return bool
  833. */
  834. public function Reset() {
  835. $this->error = null; // so no confusion is caused
  836.  
  837. if(!$this->connected()) {
  838. $this->error = array(
  839. "error" => "Called Reset() without being connected");
  840. return false;
  841. }
  842.  
  843. fputs($this->smtp_conn,"RSET" . $this->CRLF);
  844.  
  845. $rply = $this->get_lines();
  846. $code = substr($rply,0,3);
  847.  
  848. if($this->do_debug >= 2) {
  849. $this->edebug("SMTP -> FROM SERVER:" . $rply . $this->CRLF . '<br />');
  850. }
  851.  
  852. if($code != 250) {
  853. $this->error =
  854. array("error" => "RSET failed",
  855. "smtp_code" => $code,
  856. "smtp_msg" => substr($rply,4));
  857. if($this->do_debug >= 1) {
  858. $this->edebug("SMTP -> ERROR: " . $this->error["error"] . ": " . $rply . $this->CRLF . '<br />');
  859. }
  860. return false;
  861. }
  862.  
  863. return true;
  864. }
  865.  
  866. /**
  867. * Starts a mail transaction from the email address specified in
  868. * $from. Returns true if successful or false otherwise. If True
  869. * the mail transaction is started and then one or more Recipient
  870. * commands may be called followed by a Data command. This command
  871. * will send the message to the users terminal if they are logged
  872. * in and send them an email.
  873. *
  874. * Implements rfc 821: SAML <SP> FROM:<reverse-path> <CRLF>
  875. *
  876. * SMTP CODE SUCCESS: 250
  877. * SMTP CODE SUCCESS: 552,451,452
  878. * SMTP CODE SUCCESS: 500,501,502,421
  879. * @access public
  880. * @param string $from
  881. * @return bool
  882. */
  883. public function SendAndMail($from) {
  884. $this->error = null; // so no confusion is caused
  885.  
  886. if(!$this->connected()) {
  887. $this->error = array(
  888. "error" => "Called SendAndMail() without being connected");
  889. return false;
  890. }
  891.  
  892. fputs($this->smtp_conn,"SAML FROM:" . $from . $this->CRLF);
  893.  
  894. $rply = $this->get_lines();
  895. $code = substr($rply,0,3);
  896.  
  897. if($this->do_debug >= 2) {
  898. $this->edebug("SMTP -> FROM SERVER:" . $rply . $this->CRLF . '<br />');
  899. }
  900.  
  901. if($code != 250) {
  902. $this->error =
  903. array("error" => "SAML not accepted from server",
  904. "smtp_code" => $code,
  905. "smtp_msg" => substr($rply,4));
  906. if($this->do_debug >= 1) {
  907. $this->edebug("SMTP -> ERROR: " . $this->error["error"] . ": " . $rply . $this->CRLF . '<br />');
  908. }
  909. return false;
  910. }
  911. return true;
  912. }
  913.  
  914. /**
  915. * This is an optional command for SMTP that this class does not
  916. * support. This method is here to make the RFC821 Definition
  917. * complete for this class and __may__ be implimented in the future
  918. *
  919. * Implements from rfc 821: TURN <CRLF>
  920. *
  921. * SMTP CODE SUCCESS: 250
  922. * SMTP CODE FAILURE: 502
  923. * SMTP CODE ERROR : 500, 503
  924. * @access public
  925. * @return bool
  926. */
  927. public function Turn() {
  928. $this->error = array("error" => "This method, TURN, of the SMTP ".
  929. "is not implemented");
  930. if($this->do_debug >= 1) {
  931. $this->edebug("SMTP -> NOTICE: " . $this->error["error"] . $this->CRLF . '<br />');
  932. }
  933. return false;
  934. }
  935.  
  936. /**
  937. * Get the current error
  938. * @access public
  939. * @return array
  940. */
  941. public function getError() {
  942. return $this->error;
  943. }
  944.  
  945. /////////////////////////////////////////////////
  946. // INTERNAL FUNCTIONS
  947. /////////////////////////////////////////////////
  948.  
  949. /**
  950. * Read in as many lines as possible
  951. * either before eof or socket timeout occurs on the operation.
  952. * With SMTP we can tell if we have more lines to read if the
  953. * 4th character is '-' symbol. If it is a space then we don't
  954. * need to read anything else.
  955. * @access private
  956. * @return string
  957. */
  958. private function get_lines() {
  959. $data = "";
  960. $endtime = 0;
  961. /* If for some reason the fp is bad, don't inf loop */
  962. if (!is_resource($this->smtp_conn)) {
  963. return $data;
  964. }
  965. stream_set_timeout($this->smtp_conn, $this->Timeout);
  966. if ($this->Timelimit > 0) {
  967. $endtime = time() + $this->Timelimit;
  968. }
  969. while(is_resource($this->smtp_conn) && !feof($this->smtp_conn)) {
  970. $str = @fgets($this->smtp_conn,515);
  971. if($this->do_debug >= 4) {
  972. $this->edebug("SMTP -> get_lines(): \$data was \"$data\"" . $this->CRLF . '<br />');
  973. $this->edebug("SMTP -> get_lines(): \$str is \"$str\"" . $this->CRLF . '<br />');
  974. }
  975. $data .= $str;
  976. if($this->do_debug >= 4) {
  977. $this->edebug("SMTP -> get_lines(): \$data is \"$data\"" . $this->CRLF . '<br />');
  978. }
  979. // if 4th character is a space, we are done reading, break the loop
  980. if(substr($str,3,1) == " ") { break; }
  981. // Timed-out? Log and break
  982. $info = stream_get_meta_data($this->smtp_conn);
  983. if ($info['timed_out']) {
  984. if($this->do_debug >= 4) {
  985. $this->edebug("SMTP -> get_lines(): timed-out (" . $this->Timeout . " seconds) <br />");
  986. }
  987. break;
  988. }
  989. // Now check if reads took too long
  990. if ($endtime) {
  991. if (time() > $endtime) {
  992. if($this->do_debug >= 4) {
  993. $this->edebug("SMTP -> get_lines(): timelimit reached (" . $this->Timelimit . " seconds) <br />");
  994. }
  995. break;
  996. }
  997. }
  998. }
  999. return $data;
  1000. }
  1001.  
  1002. }
  1003. ?>
Add Comment
Please, Sign In to add comment