*/ /** Allow to send mails by smtp */ class smtp { /** Debug mode */ public $debug = 0; /** The authentication user allow to send SMTP mails */ public $user = null; /** The authentication password allow to send SMTP mails */ public $password = null; /** The SMTP server name or IP */ public $server = "127.0.0.1"; /** The SMTP port */ public $port = 25; /** The SMTPS support by tunnelling the session in SSL transport */ public $ssl = false; /** The Timeout between the answer of the SMTP server. If the server don't * answer in this time, an exception is raised */ public $timeout = 10; /** Activate STARTTLS if needed. Allowed values : none, may, encrypt*/ public $starttls = "may"; /** The authentication methods in an array. Allowed : plain, login*/ public $authmethods = array ("plain", "login"); /** The socket of the connection */ private $smtpStream = null; /** Connect to the SMTP server */ public function connect () { if ($this->ssl) $this->server = "tls://$this->server"; $this->debug ("####SMTP Connection to $this->server:$this->port\n"); $this->smtpStream = @fsockopen ($this->server, $this->port, $errno, $errstr, $this->timeout); if ($this->smtpStream === false) throw new \Exception (sprintf (_("Can't connect to SMTP server : %s"), $errstr), 500); stream_set_timeout ($this->smtpStream, $this->timeout); // Wait for banner $banner = $this->getLine ("SMTP Banner"); // Send EHLO $features = $this->putLine ("EHLO ".gethostname ()."\r\n"); $features = explode ("\r\n", $features); if (in_array ("250-STARTTLS", $features)) { // Server supports STARTTLS if ($this->starttls === "may" || $this->starttls === "encrypt") { $this->putLine ("STARTTLS\r\n"); stream_socket_enable_crypto ($this->smtpStream, true, STREAM_CRYPTO_METHOD_TLS_CLIENT); } } elseif ($this->starttls === "encrypt") throw new \Exception (_("Server doesn't supports STARTTLS"), 500); if ($this->user !== null && $this->password !== null) { $auths = preg_grep ("#^250-AUTH #", $features); $auths = reset ($auths); if (strpos ($auths, "PLAIN") && in_array ("plain", $this->authmethods)) { // Send User and password AUTH PLAIN $this->putLine ("AUTH PLAIN ". base64_encode ($this->user.chr(0).$this->user.chr(0). $this->password)."\r\n"); } elseif (strpos ($auths, "LOGIN") && in_array ("login", $this->authmethods)) { // Send User and password AUTH LOGIN $this->putLine ("AUTH LOGIN ".base64_encode ($this->user)."\r\n"); $this->putLine (base64_encode ($this->password)."\r\n"); } else throw new \Exception ( _("No authentication method available for the server"), 500); } } /** Send the mail to the users * @param string $from The email address used for the from enveloppe * @param string|array $to the recipient of the email. Not displayed in the * email content * @param $completeMail The content of the email */ public function send ($from, $to, $completeMail) { if ($this->smtpStream === null) throw new \Exception ( _("Can't send email : not connected to SMTP server"), 500); if (is_string ($to)) $to = array ($to); $this->putLine ("MAIL FROM: $from\r\n"); foreach ($to as $t) $this->putLine ("RCPT TO: $t\r\n"); $this->putLine ("DATA\r\n"); if (substr ($completeMail, -2) !== "\r\n") $completeMail .= "\r\n"; $this->putLine ("$completeMail.\r\n"); } /** Disconnect from the SMTP server */ public function disconnect () { if ($this->smtpStream === null) throw new \Exception ( _("Can't send email : not connected to SMTP server"), 500); $this->putLine ("QUIT\r\n"); fclose ($this->smtpStream); } /** Reset the session to start a new mail in the same SMTP connection */ public function reset () { if ($this->smtpStream === null) throw new \Exception ( _("Can't send email : not connected to SMTP server"), 500); $this->putLine ("RSET\r\n"); } /** Send something to the SMTP server. Wait the acknoledgement line */ private function putLine ($data) { $this->debug ("> $data"); fwrite ($this->smtpStream, $data); return $this->getLine ($data); } /** Wait something from the server */ private function getLine ($message = "") { $this->debug ("Waiting for ".rtrim ($message)." answer\n", 2); $content = ""; while (1) { $line = stream_get_line ($this->smtpStream, 1024, "\r\n"); $meta = stream_get_meta_data ($this->smtpStream); if ($meta["timed_out"] !== FALSE) { $this->debug ("Timeout when waiting $message\n"); throw new \Exception ("Timeout when waiting $message", 500); } $content .= $line."\r\n"; if (substr ($line, 3, 1) === " ") break; } $this->debug ("< $content\n"); if (substr ($line, 0, 1) !== "2" && substr ($line, 0, 1) !== "3") { $this->debug ("Can't send mail : server answer : $line\n"); throw new \Exception ("Can't send mail : server answer : $line", 500); } return $content; } private function debug ($message, $priority = 1) { if ($this->debug == false) return; if ($priority > $this->debug) return; file_put_contents ("/tmp/debugsmtp", $message, FILE_APPEND); } }