summaryrefslogtreecommitdiff
path: root/program
diff options
context:
space:
mode:
Diffstat (limited to 'program')
-rw-r--r--program/include/rcube_smtp.inc324
-rw-r--r--program/lib/Mail/mime.php2
-rw-r--r--program/lib/smtp.inc351
-rw-r--r--program/steps/mail/sendmail.inc37
4 files changed, 343 insertions, 371 deletions
diff --git a/program/include/rcube_smtp.inc b/program/include/rcube_smtp.inc
new file mode 100644
index 000000000..9f1932703
--- /dev/null
+++ b/program/include/rcube_smtp.inc
@@ -0,0 +1,324 @@
+<?
+
+/*
+ +-----------------------------------------------------------------------+
+ | program/include/rcube_smtp.inc |
+ | |
+ | This file is part of the RoundCube Webmail client |
+ | Copyright (C) 2005, RoundCube Dev. - Switzerland |
+ | Licensed under the GNU GPL |
+ | |
+ | PURPOSE: |
+ | Provide SMTP functionality using socket connections |
+ | |
+ +-----------------------------------------------------------------------+
+ | Author: Thomas Bruederli <roundcube@gmail.com> |
+ +-----------------------------------------------------------------------+
+
+ $Id$
+
+*/
+
+
+// include required PEAR classes
+require_once('Net/SMTP.php');
+
+
+// define headers delimiter
+define('SMTP_MIME_CRLF', "\r\n");
+
+$SMTP_CONN = null;
+
+/**
+ * Function for sending mail using SMTP.
+ *
+ * @param string Sender e-Mail address
+ *
+ * @param mixed Either a comma-seperated list of recipients
+ * (RFC822 compliant), or an array of recipients,
+ * each RFC822 valid. This may contain recipients not
+ * specified in the headers, for Bcc:, resending
+ * messages, etc.
+ *
+ * @param mixed The message headers to send with the mail
+ * Either as an associative array or a finally
+ * formatted string
+ *
+ * @param string The full text of the message body, including any Mime parts, etc.
+ *
+ * @return bool Returns TRUE on success, or FALSE on error
+ * @access public
+ */
+function smtp_mail($from, $recipients, $headers, $body)
+ {
+ global $SMTP_CONN, $CONFIG, $SMTP_ERROR;
+ $smtp_timeout = null;
+ $smtp_port = is_numeric($CONFIG['smtp_port']) ? $CONFIG['smtp_port'] : 25;
+
+ // create Net_SMTP object and connect to server
+ if (!is_object($smtp_conn))
+ {
+ $SMTP_CONN = new Net_SMTP($CONFIG['smtp_server'], $smtp_port, 'localhost');
+
+ // set debugging
+ if ($CONFIG['debug_level'] & 8)
+ $SMTP_CONN->setDebug(TRUE);
+
+
+ // try to connect to server and exit on failure
+ if (PEAR::isError($SMTP_CONN->connect($smtp_timeout)))
+ {
+ $SMTP_CONN = null;
+ $SMTP_ERROR .= "Connection failed\n";
+ return FALSE;
+ }
+
+
+ // attempt to authenticate to the SMTP server
+ if ($CONFIG['smtp_user'] && $CONFIG['smtp_pass'])
+ {
+ if (PEAR::isError($SMTP_CONN->auth($CONFIG['smtp_user'], $CONFIG['smtp_pass'])))
+ {
+ smtp_reset();
+ $SMTP_ERROR .= "authentication failure\n";
+ return FALSE;
+ }
+ }
+ }
+
+
+ // prepare message headers as string
+ if (is_array($headers))
+ {
+ $headerElements = smtp_prepare_headers($headers);
+ if (!$headerElements)
+ {
+ smtp_reset();
+ return FALSE;
+ }
+
+ list($from, $text_headers) = $headerElements;
+ }
+ else if (is_string($headers))
+ $text_headers = $headers;
+ else
+ {
+ smtp_reset();
+ $SMTP_ERROR .= "Invalid message headers\n";
+ return FALSE;
+ }
+
+ // exit if no from address is given
+ if (!isset($from))
+ {
+ smtp_reset();
+ $SMTP_ERROR .= "No From address has been provided\n";
+ return FALSE;
+ }
+
+
+ // set From: address
+ if (PEAR::isError($SMTP_CONN->mailFrom($from)))
+ {
+ smtp_reset();
+ $SMTP_ERROR .= "Failed to set sender '$from'\n";
+ return FALSE;
+ }
+
+
+ // prepare list of recipients
+ $recipients = smtp_parse_rfc822($recipients);
+ if (PEAR::isError($recipients))
+ {
+ smtp_reset();
+ return FALSE;
+ }
+
+
+ // set mail recipients
+ foreach ($recipients as $recipient)
+ {
+ if (PEAR::isError($SMTP_CONN->rcptTo($recipient)))
+ {
+ smtp_reset();
+ $SMTP_ERROR .= "Failed to add recipient '$recipient'\n";
+ return FALSE;
+ }
+ }
+
+
+ // Send the message's headers and the body as SMTP data.
+ if (PEAR::isError($SMTP_CONN->data("$text_headers\r\n$body")))
+ {
+ smtp_reset();
+ $SMTP_ERROR .= "Failed to send data\n";
+ return FALSE;
+ }
+
+
+ return TRUE;
+ }
+
+
+
+/**
+ * Reset the global SMTP connection
+ * @access public
+ */
+function smtp_reset()
+ {
+ global $SMTP_CONN;
+
+ if (is_object($SMTP_CONN))
+ {
+ $SMTP_CONN->rset();
+ smtp_disconnect();
+ }
+ }
+
+
+
+/**
+ * Disconnect the global SMTP connection and destroy object
+ * @access public
+ */
+function smtp_disconnect()
+ {
+ global $SMTP_CONN;
+
+ if (is_object($SMTP_CONN))
+ {
+ $SMTP_CONN->disconnect();
+ $SMTP_CONN = null;
+ }
+ }
+
+
+/**
+ * Take an array of mail headers and return a string containing
+ * text usable in sending a message.
+ *
+ * @param array $headers The array of headers to prepare, in an associative
+ * array, where the array key is the header name (ie,
+ * 'Subject'), and the array value is the header
+ * value (ie, 'test'). The header produced from those
+ * values would be 'Subject: test'.
+ *
+ * @return mixed Returns false if it encounters a bad address,
+ * otherwise returns an array containing two
+ * elements: Any From: address found in the headers,
+ * and the plain text version of the headers.
+ * @access private
+ */
+function smtp_prepare_headers($headers)
+ {
+ $lines = array();
+ $from = null;
+
+ foreach ($headers as $key => $value)
+ {
+ if (strcasecmp($key, 'From') === 0)
+ {
+ $addresses = smtp_parse_rfc822($value);
+
+ if (is_array($addresses))
+ $from = $addresses[0];
+
+ // Reject envelope From: addresses with spaces.
+ if (strstr($from, ' '))
+ return FALSE;
+
+
+ $lines[] = $key . ': ' . $value;
+ }
+ else if (strcasecmp($key, 'Received') === 0)
+ {
+ $received = array();
+ if (is_array($value))
+ {
+ foreach ($value as $line)
+ $received[] = $key . ': ' . $line;
+ }
+ else
+ {
+ $received[] = $key . ': ' . $value;
+ }
+
+ // Put Received: headers at the top. Spam detectors often
+ // flag messages with Received: headers after the Subject:
+ // as spam.
+ $lines = array_merge($received, $lines);
+ }
+
+ else
+ {
+ // If $value is an array (i.e., a list of addresses), convert
+ // it to a comma-delimited string of its elements (addresses).
+ if (is_array($value))
+ $value = implode(', ', $value);
+
+ $lines[] = $key . ': ' . $value;
+ }
+ }
+
+ return array($from, join(SMTP_MIME_CRLF, $lines) . SMTP_MIME_CRLF);
+ }
+
+
+
+/**
+ * Take a set of recipients and parse them, returning an array of
+ * bare addresses (forward paths) that can be passed to sendmail
+ * or an smtp server with the rcpt to: command.
+ *
+ * @param mixed Either a comma-seperated list of recipients
+ * (RFC822 compliant), or an array of recipients,
+ * each RFC822 valid.
+ *
+ * @return array An array of forward paths (bare addresses).
+ * @access private
+ */
+function smtp_parse_rfc822($recipients)
+ {
+ // if we're passed an array, assume addresses are valid and implode them before parsing.
+ if (is_array($recipients))
+ $recipients = implode(', ', $recipients);
+
+ $addresses = array();
+ $recipients = smtp_explode_quoted_str(",", $recipients);
+
+ reset($recipients);
+ while (list($k, $recipient) = each($recipients))
+ {
+ $a = explode(" ", $recipient);
+ while (list($k2, $word) = each($a))
+ {
+ if ((strpos($word, "@") > 0) && (strpos($word, "\"")===false))
+ {
+ $word = ereg_replace('^<|>$', '', trim($word));
+ if (in_array($word, $addresses)===false)
+ array_push($addresses, $word);
+ }
+ }
+ }
+ return $addresses;
+ }
+
+
+function smtp_explode_quoted_str($delimiter, $string)
+ {
+ $quotes=explode("\"", $string);
+ while ( list($key, $val) = each($quotes))
+ if (($key % 2) == 1)
+ $quotes[$key] = str_replace($delimiter, "_!@!_", $quotes[$key]);
+ $string=implode("\"", $quotes);
+
+ $result=explode($delimiter, $string);
+ while (list($key, $val) = each($result))
+ $result[$key] = str_replace("_!@!_", $delimiter, $result[$key]);
+
+ return $result;
+ }
+
+
+?>
diff --git a/program/lib/Mail/mime.php b/program/lib/Mail/mime.php
index 48bd5f5c0..6b3a992b0 100644
--- a/program/lib/Mail/mime.php
+++ b/program/lib/Mail/mime.php
@@ -119,7 +119,7 @@ class Mail_mime
$this->_build_params = array(
'text_encoding' => '7bit',
'html_encoding' => 'quoted-printable',
- 'header_encoding' => 'quoted-printable',
+ 'head_encoding' => 'quoted-printable',
'7bit_wrap' => 998,
'html_charset' => 'ISO-8859-1',
'text_charset' => 'ISO-8859-1',
diff --git a/program/lib/smtp.inc b/program/lib/smtp.inc
deleted file mode 100644
index ebff9d263..000000000
--- a/program/lib/smtp.inc
+++ /dev/null
@@ -1,351 +0,0 @@
-<?php
-/////////////////////////////////////////////////////////
-//
-// include/smtp.inc
-//
-// (C)Copyright 2002 Ryo Chijiiwa <Ryo@IlohaMail.org>
-//
-// This file is part of IlohaMail.
-// IlohaMail is free software released under the GPL
-// license. See enclosed file COPYING for details,
-// or see http://www.fsf.org/copyleft/gpl.html
-//
-/////////////////////////////////////////////////////////
-
-/********************************************************
-
- AUTHOR: Ryo Chijiiwa <ryo@ilohamail.org>
- FILE: include/smtp.php
- PURPOSE:
- Provide SMTP functionality using pure PHP.
- PRE-CONDITIONS:
- The functions here require a SMTP server configured to allow relaying.
- POST-CONDITIONS:
- The following global variables are returned:
- $smtp_errornum - error number, 0 if successful
- $smtp_error - error message(s)
- $SMTP_TYPE - Optional
- COMMENTS:
- The optional $smtp_message_file can be used for sending extremely large
- messages. Storing large messages in a variable will consume whatever
- amount of memory required, which may be more than is available if dealing
- with messages with large attachments. By storing them in a file, it becomes
- possible to read/send bits at a time, drastically reducing memory useage.
-
- This library only provides bare-bones SMTP functionality. It is up to the
- parent code to form valid RFC822 (MIME) messages.
-
-********************************************************/
-
- //set some global constants
- if (strcasecmp($SMTP_TYPE, "courier")==0){
- $SMTP_REPLY_DELIM = "-";
- $SMTP_DATA_REPLY = 250;
- }else{
- $SMTP_REPLY_DELIM = " ";
- $SMTP_DATA_REPLY = 354;
- }
-
- /* fgets replacement that's multi-line aware */
- function smtp_get_response($fp, $len){
- $end = false;
- do{
- $line = chop(fgets($fp, 5120));
- // echo "SMTP:".$line."<br>\n"; flush();
- if ((strlen($line)==3) || ($line[3]==' ')) $end = true;
- }while(!$end);
-
- return $line;
- }
-
-
- function smtp_check_reply($reply){
- global $smtp_error;
- global $SMTP_REPLY_DELIM;
-
- $a = explode($SMTP_REPLY_DELIM, chop($reply));
-
- if (count($a) >= 1){
-
- if ($a[0]==250||$a[0]==354) return true;
- else{
- $smtp_error .= $reply."\n";
- }
- }else{
- $smtp_error .= "Invalid SMTP response line: $reply\n";
- }
-
- return false;
- }
-
-
- function smtp_split($str){
- $result = array();
- $pos = strpos($str, " ");
- if ($pos===false){
- $result[0] = $str;
- }else{
- $result[0] = substr($str, 0, $pos);
- $result[1] = substr($str, $pos+1);
- }
-
- return $result;
- }
-
-
- function smtp_ehlo(&$conn, $host){
- $result = "";
- fputs($conn, "EHLO $host\r\n");
- //echo "Sent: EHLO $host\n"; flush();
- do{
- $line = fgets($conn, 2048);
- //echo "Got: $line"; flush();
- $a = explode(" ", $line);
- if ($a[0]=="250-AUTH") $result .= substr($line, 9);
- }while(!is_numeric($a[0]));
-
- if ($a[0]==250) return $result;
- else return $a[0];
-
- }
-
-
- function smtp_auth_login(&$conn, $user, $pass){
- $auth["username"] = base64_encode($user);
- $auth["password"] = base64_encode($pass);
-
- fputs($conn, "AUTH LOGIN\r\n");
-
- //echo "Sent: AUTH LOGIN\n"; flush();
-
- //get first line
- $line = smtp_get_response($conn, 1024);
- //echo "AUTH_LOGIN << $line"; flush();
- $parts = smtp_split($line);
- //valid reply?
- if (($parts[0]!=334) || (empty($parts[1]))) return false;
- //send data
- $prompt = eregi_replace("[^a-z]", "", strtolower(base64_decode($parts[1])));
- fputs($conn, $auth[$prompt]."\r\n");
- //echo "AUT_LOGIN >> ".$auth[$prompt]."\n"; flush();
-
- //get second line
- $line = smtp_get_response($conn, 1024);
- //echo "AUTH_LOGIN << $line"; flush();
- $parts = smtp_split($line);
- //valid reply?
- if (($parts[0]!=334) || (empty($parts[1]))) return false;
- $prompt = eregi_replace("[^a-z]", "", strtolower(base64_decode($parts[1])));
- fputs($conn, $auth[$prompt]."\r\n");
- //echo "AUT_LOGIN >> ".$auth[$prompt]."\n"; flush();
-
- $line = smtp_get_response($conn, 1024);
- //echo "AUTH_LOGIN << $line"; flush();
- $parts = smtp_split($line);
- return ($parts[0]==235);
- }
-
-
- function smtp_connect($host, $port, $user, $pass){
- global $smtp_errornum;
- global $smtp_error;
-
- //auth user?
- global $SMTP_USER, $SMTP_PASSWORD;
- if ((!empty($SMTP_USER)) && (!empty($SMTP_PASSWORD))){
- $user = $SMTP_USER;
- $pass = $SMTP_PASSWORD;
- }
-
- // echo "User: $user<br>\n";
-
- //figure out auth mode
- global $AUTH_MODE;
- $auth_mode = $AUTH_MODE["smtp"];
- if (empty($auth_mode)) $auth_mode = "none";
- if (empty($user) || empty($pass)) $auth_mode = "none";
-
- // echo "authmode: $auth_mode<br>\n"; flush();
-
- //initialize defaults
- if (empty($host)) $host = "localhost";
- if (empty($port)) $port = 25;
-
- // echo "Connecting to $host:$port<br>\n"; flush();
-
- //connect to SMTP server
- $conn = fsockopen($host, $port);
-
- if (!$conn){
- //echo "fsockopen failed\n";
- $smtp_error = "Couldn't connect to $host:$port<br>\n";
- return false;
- }
-
- //read greeting
- $greeting = smtp_get_response($conn, 1024);
-
- // echo "Connected: $greeting<br>\n"; flush();
-
- if (($auth_mode=="check") || ($auth_mode=="auth")){
- // echo "Trying EHLO<br>\n"; flush();
- $auth_modes = smtp_ehlo($conn, $_SERVER["SERVER_NAME"]);
- // echo "smtp_ehlo returned: $auth_modes<br>\n"; flush();
- if ($auth_modes===false){
- $smtp_error = "EHLO failed\n";
- $conn = false;
- }else if (stristr($auth_modes, "LOGIN")!==false){
- echo "trying AUTH LOGIN\n"; flush();
- if (!smtp_auth_login($conn, $user, $pass)){
- //echo "CONN: AUTH_LOGIN failed\n"; flush();
- $conn = false;
- }
- //echo "Conn after LOGIN: $conn<br>\n"; flush();
- }
- }else{
- fputs($conn, "HELO ".$_SERVER["SERVER_NAME"]."\r\n");
- $line = smtp_get_response($conn, 1024);
- if (!smtp_check_reply($line)){
- $conn = false;
- $smtp_error .= $line."\n";
- }
- // echo "after HELO: $conn<br>\n"; flush();
- }
-
- return $conn;
- }
-
-
- function smtp_close($conn){
- fclose($conn);
- }
-
-
- function smtp_mail($conn, $from, $recipients, $message, $is_file){
- global $smtp_errornum;
- global $smtp_error;
- global $SMTP_DATA_REPLY;
-
- //check recipients and sender addresses
- if ((count($recipients)==0) || (!is_array($recipients))){
- $smtp_errornum = -1;
- $smtp_error .= "Recipients list is empty\n";
- return false;
- }
- if (empty($from)){
- $smtp_errornum = -2;
- $smtp_error .= "From address unspecified\n";
- return false;
- }
-
- if (!$conn){
- $smtp_errornum = -3;
- $smtp_error .= "Invalid connection\n";
- }
-
- if (!ereg("^<", $from)) $from = "<".$from;
- if (!ereg(">$", $from)) $from = $from.">";
-
- //send MAIL FROM command
- $command = "MAIL FROM: $from\r\n";
- // echo nl2br(htmlspecialchars($command));
- fputs($conn, $command);
-
- if (smtp_check_reply(smtp_get_response($conn, 1024))){
- //send RCPT TO commands, count valid recipients
- $num_recipients = 0;
- while ( list($k, $recipient) = each($recipients) ){
- $command = "RCPT TO: $recipient\r\n";
- fputs($conn, $command);
- $reply = smtp_check_reply(smtp_get_response($conn, 1024));
- if ($reply) $num_recipients++;
- else $smtp_error .= $reply."\n";
- }
-
- //error out if no valid recipiets
- if ($num_recipients == 0){
- $smtp_errornum = -1;
- $smtp_error .= "No valid recipients\n";
- return false;
- }
-
- //send DATA command
- fputs($conn, "DATA\r\n");
- $reply = chop(smtp_get_response($conn, 1024));
- $a = explode(" ", $reply);
-
- //error out if DATA command ill received
- if ($a[0]!=$SMTP_DATA_REPLY){
- $smtp_errornum = -4;
- $smtp_error .= $reply;
- return false;
- }
- //send data
- if ($is_file){
- //if message file, open file
- $fp = false;
- if (file_exists(realpath($message))) $fp = fopen($message, "rb");
- if (!$fp)
- {
- $smtp_errornum = -4;
- $smtp_error .= "Invlid message file\n";
- return false;
- }
-
- //send file
- while(!feof($fp)){
- $buffer = chop(fgets($fp, 4096), "\r\n");
- fputs($conn, $buffer."\r\n");
- }
- fclose($fp);
- fputs($conn, "\r\n.\r\n");
-
- return smtp_check_reply(smtp_get_response($conn, 1024));
- }else{
- //else, send message
- $message = str_replace("\r\n", "\n", $message);
- $message = str_replace("\n", "\r\n", $message);
- $message = str_replace("\r\n.\r\n", "\r\n..\r\n", $message);
- fputs($conn, $message);
- fputs($conn, "\r\n.\r\n");
-
- return smtp_check_reply(smtp_get_response($conn, 1024));
- }
- }
-
- return false;
- }
-
-
- function smtp_ExplodeQuotedString($delimiter, $string){
- $quotes=explode("\"", $string);
- while ( list($key, $val) = each($quotes))
- if (($key % 2) == 1)
- $quotes[$key] = str_replace($delimiter, "_!@!_", $quotes[$key]);
- $string=implode("\"", $quotes);
-
- $result=explode($delimiter, $string);
- while ( list($key, $val) = each($result) )
- $result[$key] = str_replace("_!@!_", $delimiter, $result[$key]);
-
- return $result;
- }
-
-
- function smtp_expand($str){
- $addresses = array();
- $recipients = smtp_ExplodeQuotedString(",", $str);
- reset($recipients);
- while ( list($k, $recipient) = each($recipients) ){
- $a = explode(" ", $recipient);
- while ( list($k2, $word) = each($a) ){
- if ((strpos($word, "@") > 0) && (strpos($word, "\"")===false)){
- if (!ereg("^<", $word)) $word = "<".$word;
- if (!ereg(">$", $word)) $word = $word.">";
- if (in_array($word, $addresses)===false) array_push($addresses, $word);
- }
- }
- }
- return $addresses;
- }
-?> \ No newline at end of file
diff --git a/program/steps/mail/sendmail.inc b/program/steps/mail/sendmail.inc
index e33593139..2172accc8 100644
--- a/program/steps/mail/sendmail.inc
+++ b/program/steps/mail/sendmail.inc
@@ -21,7 +21,8 @@
*/
-require_once('lib/smtp.inc');
+//require_once('lib/smtp.inc');
+require_once('include/rcube_smtp.inc');
require_once('Mail/mime.php');
@@ -155,30 +156,28 @@ $msg_subject = $headers['Subject'];
// send thru SMTP server using cusotm SMTP library
if ($CONFIG['smtp_server'])
{
- // connect to SMTP server
- $smtp_conn = smtp_connect($CONFIG['smtp_server'], '25', $CONFIG['smtp_user'], $CONFIG['smtp_pass']);
-
- if ($smtp_conn)
- {
- // generate list of recipients
- $recipients = $mailto.', '.$headers['Cc'].', '.$headers['Bcc'];
- $a_recipients = smtp_expand($recipients);
-
- // generate message headers
- $header_str = $MAIL_MIME->txtHeaders($headers);
-
- // send message
- $sent = smtp_mail($smtp_conn, $from, $a_recipients, $header_str."\r\n".$msg_body, FALSE);
- }
-
+ // generate list of recipients
+ $a_recipients = array($mailto);
+
+ if (strlen($headers['Cc']))
+ $a_recipients[] = $headers['Cc'];
+ if (strlen($headers['Bcc']))
+ $a_recipients[] = $headers['Bcc'];
+
+ // generate message headers
+ $header_str = $MAIL_MIME->txtHeaders($headers);
+
+ // send message
+ $sent = smtp_mail($from, $a_recipients, $header_str, $msg_body);
+
// log error
- if (!$smtp_conn || !$sent)
+ if (!$sent)
{
raise_error(array('code' => 800,
'type' => 'smtp',
'line' => __LINE__,
'file' => __FILE__,
- 'message' => "Connection failed: $smtp_error"), TRUE, FALSE);
+ 'message' => "SMTP error: $SMTP_ERROR"), TRUE, FALSE);
}
}