PageRenderTime 53ms CodeModel.GetById 19ms RepoModel.GetById 0ms app.codeStats 1ms

/lib/phpmailer/class.smtp.php

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