Source for file class.smtp.php

Documentation is available at class.smtp.php

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

Documentation generated on Thu, 02 Apr 2009 17:51:29 -0400 by phpDocumentor 1.3.0RC3