| | |
| | | | program/include/rcube_smtp.php | |
| | | | | |
| | | | This file is part of the Roundcube Webmail client | |
| | | | Copyright (C) 2005-2010, Roundcube Dev. - Switzerland | |
| | | | Copyright (C) 2005-2010, The Roundcube Dev Team | |
| | | | Licensed under the GNU GPL | |
| | | | | |
| | | | PURPOSE: | |
| | |
| | | |
| | | // let plugins alter smtp connection config |
| | | $CONFIG = $RCMAIL->plugins->exec_hook('smtp_connect', array( |
| | | 'smtp_server' => $host ? $host : $RCMAIL->config->get('smtp_server'), |
| | | 'smtp_port' => $port ? $port : $RCMAIL->config->get('smtp_port', 25), |
| | | 'smtp_user' => $user ? $user : $RCMAIL->config->get('smtp_user'), |
| | | 'smtp_pass' => $pass ? $pass : $RCMAIL->config->get('smtp_pass'), |
| | | 'smtp_server' => $host ? $host : $RCMAIL->config->get('smtp_server'), |
| | | 'smtp_port' => $port ? $port : $RCMAIL->config->get('smtp_port', 25), |
| | | 'smtp_user' => $user ? $user : $RCMAIL->config->get('smtp_user'), |
| | | 'smtp_pass' => $pass ? $pass : $RCMAIL->config->get('smtp_pass'), |
| | | 'smtp_auth_cid' => $RCMAIL->config->get('smtp_auth_cid'), |
| | | 'smtp_auth_pw' => $RCMAIL->config->get('smtp_auth_pw'), |
| | | 'smtp_auth_type' => $RCMAIL->config->get('smtp_auth_type'), |
| | | 'smtp_helo_host' => $RCMAIL->config->get('smtp_helo_host'), |
| | | 'smtp_timeout' => $RCMAIL->config->get('smtp_timeout'), |
| | |
| | | $helo_host = 'localhost'; |
| | | |
| | | // IDNA Support |
| | | $smtp_host = idn_to_ascii($smtp_host); |
| | | $smtp_host = rcube_idn_to_ascii($smtp_host); |
| | | |
| | | $this->conn = new Net_SMTP($smtp_host, $smtp_port, $helo_host); |
| | | |
| | | if($RCMAIL->config->get('smtp_debug')) |
| | | if ($RCMAIL->config->get('smtp_debug')) |
| | | $this->conn->setDebug(true, array($this, 'debug_handler')); |
| | | |
| | | |
| | | // try to connect to server and exit on failure |
| | | $result = $this->conn->connect($smtp_timeout); |
| | | if (PEAR::isError($result)) |
| | | { |
| | | |
| | | if (PEAR::isError($result)) { |
| | | $this->response[] = "Connection failed: ".$result->getMessage(); |
| | | $this->error = array('label' => 'smtpconnerror', 'vars' => array('code' => $this->conn->_code)); |
| | | $this->conn = null; |
| | | return false; |
| | | } |
| | | |
| | | // workaround for timeout bug in Net_SMTP 1.5.[0-1] (#1487843) |
| | | if (method_exists($this->conn, 'setTimeout') |
| | | && ($timeout = ini_get('default_socket_timeout')) |
| | | ) { |
| | | $this->conn->setTimeout($timeout); |
| | | } |
| | | |
| | | $smtp_user = str_replace('%u', $_SESSION['username'], $CONFIG['smtp_user']); |
| | | $smtp_pass = str_replace('%p', $RCMAIL->decrypt($_SESSION['password']), $CONFIG['smtp_pass']); |
| | | $smtp_auth_type = empty($CONFIG['smtp_auth_type']) ? NULL : $CONFIG['smtp_auth_type']; |
| | | |
| | | if (!empty($CONFIG['smtp_auth_cid'])) { |
| | | $smtp_authz = $smtp_user; |
| | | $smtp_user = $CONFIG['smtp_auth_cid']; |
| | | $smtp_pass = $CONFIG['smtp_auth_pw']; |
| | | } |
| | | |
| | | // attempt to authenticate to the SMTP server |
| | | if ($smtp_user && $smtp_pass) |
| | | { |
| | | // IDNA Support |
| | | if (strpos($smtp_user, '@')) |
| | | $smtp_user = idn_to_ascii($smtp_user); |
| | | if (strpos($smtp_user, '@')) { |
| | | $smtp_user = rcube_idn_to_ascii($smtp_user); |
| | | } |
| | | |
| | | $result = $this->conn->auth($smtp_user, $smtp_pass, $smtp_auth_type, $use_tls); |
| | | $result = $this->conn->auth($smtp_user, $smtp_pass, $smtp_auth_type, $use_tls, $smtp_authz); |
| | | |
| | | if (PEAR::isError($result)) |
| | | { |
| | |
| | | * 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 mixed The full text of the message body, including any Mime parts |
| | | * or file handle |
| | | * @param array Delivery options (e.g. DSN request) |
| | | * |
| | | * @return bool Returns true on success, or false on error |
| | | */ |
| | | public function send_mail($from, $recipients, &$headers, &$body) |
| | | public function send_mail($from, $recipients, &$headers, &$body, $opts=null) |
| | | { |
| | | if (!is_object($this->conn)) |
| | | return false; |
| | |
| | | else |
| | | { |
| | | $this->reset(); |
| | | $this->response[] .= "Invalid message headers"; |
| | | $this->response[] = "Invalid message headers"; |
| | | return false; |
| | | } |
| | | |
| | |
| | | if (!isset($from)) |
| | | { |
| | | $this->reset(); |
| | | $this->response[] .= "No From address has been provided"; |
| | | $this->response[] = "No From address has been provided"; |
| | | return false; |
| | | } |
| | | |
| | | // RFC3461: Delivery Status Notification |
| | | if ($opts['dsn']) { |
| | | $exts = $this->conn->getServiceExtensions(); |
| | | |
| | | if (!isset($exts['DSN'])) { |
| | | $this->error = array('label' => 'smtpdsnerror'); |
| | | $this->response[] = "DSN not supported"; |
| | | return false; |
| | | } |
| | | |
| | | $from_params = 'RET=HDRS'; |
| | | $recipient_params = 'NOTIFY=SUCCESS,FAILURE'; |
| | | } |
| | | |
| | | // RFC2298.3: remove envelope sender address |
| | |
| | | } |
| | | |
| | | // set From: address |
| | | if (PEAR::isError($this->conn->mailFrom($from))) |
| | | if (PEAR::isError($this->conn->mailFrom($from, $from_params))) |
| | | { |
| | | $err = $this->conn->getResponse(); |
| | | $this->error = array('label' => 'smtpfromerror', 'vars' => array( |
| | | 'from' => $from, 'code' => $this->conn->_code, 'msg' => $err[1])); |
| | | $this->response[] .= "Failed to set sender '$from'"; |
| | | $this->response[] = "Failed to set sender '$from'"; |
| | | $this->reset(); |
| | | return false; |
| | | } |
| | |
| | | // set mail recipients |
| | | foreach ($recipients as $recipient) |
| | | { |
| | | if (PEAR::isError($this->conn->rcptTo($recipient))) { |
| | | if (PEAR::isError($this->conn->rcptTo($recipient, $recipient_params))) { |
| | | $err = $this->conn->getResponse(); |
| | | $this->error = array('label' => 'smtptoerror', 'vars' => array( |
| | | 'to' => $recipient, 'code' => $this->conn->_code, 'msg' => $err[1])); |
| | | $this->response[] .= "Failed to add recipient '$recipient'"; |
| | | $this->response[] = "Failed to add recipient '$recipient'"; |
| | | $this->reset(); |
| | | return false; |
| | | } |
| | |
| | | $msg = $result->getMessage(); |
| | | |
| | | $this->error = array('label' => 'smtperror', 'vars' => array('msg' => $msg)); |
| | | $this->response[] .= "Failed to send data"; |
| | | $this->response[] = "Failed to send data"; |
| | | $this->reset(); |
| | | return false; |
| | | } |
| | |
| | | // 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 = rcube_explode_quoted_string(',', $recipients); |
| | | |
| | | reset($recipients); |
| | | while (list($k, $recipient) = each($recipients)) |
| | | { |
| | | $a = explode(" ", $recipient); |
| | | $a = rcube_explode_quoted_string(' ', $recipient); |
| | | while (list($k2, $word) = each($a)) |
| | | { |
| | | if (strpos($word, "@") > 0 && $word[strlen($word)-1] != '"') |
| | |
| | | } |
| | | } |
| | | } |
| | | |
| | | return $addresses; |
| | | } |
| | | |