Source for file smtpmx.php
Documentation is available at smtpmx.php
/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
* SMTP MX implementation of the PEAR Mail interface. Requires the Net_SMTP class.
* LICENSE: This source file is subject to version 3.0 of the PHP license
* that is available through the world-wide-web at the following URI:
* http://www.php.net/license/3_0.txt. If you did not receive a copy of
* the PHP License and are unable to obtain it through the web, please
* send a note to license@php.net so we can mail you a copy immediately.
* @author gERD Schaufelberger <gerd@php-tools.net>
* @copyright 1997-2005 The PHP Group
* @license http://www.php.net/license/3_0.txt PHP License 3.0
* @version CVS: $Id: smtpmx.php,v 1.2 2007/10/06 17:00:00 chagenbu Exp $
require_once 'Net/SMTP.php';
* SMTP MX implementation of the PEAR Mail interface. Requires the Net_SMTP class.
* @author gERD Schaufelberger <gerd@php-tools.net>
* @version $Revision: 1.2 $
* SMTP connection object.
* The port the SMTP server is on.
* @see getservicebyname()
* Hostname or domain that will be sent to the remote SMTP server in the
* SMTP connection timeout value. NULL indicates no timeout.
* use either PEAR:Net_DNS or getmxrr
* Whether to use VERP or not. If not a boolean, the string value
* will be used as the VERP separators.
* @var mixed boolean or string
* Whether to use VRFY or not.
* Switch to test mode - don't send emails for real
* Turn on Net_SMTP debugging?
* @var boolean $peardebug
* translate internal error identifier to PEAR-Error codes and human
* @todo as I need unique error-codes to identify what exactly went wrond
* I did not use intergers as it should be. Instead I added a "namespace"
* for each code. This avoids conflicts with error codes from different
* classes. How can I use unique error codes and stay conform with PEAR?
'not_connected' => array (
'msg' => 'Could not connect to any mail server ({HOST}) at port {PORT} to send mail to {RCPT}.'
'failed_vrfy_rcpt' => array (
'msg' => 'Recipient "{RCPT}" could not be veryfied.'
'failed_set_from' => array (
'msg' => 'Failed to set sender: {FROM}.'
'failed_set_rcpt' => array (
'msg' => 'Failed to set recipient: {RCPT}.'
'failed_send_data' => array (
'msg' => 'Failed to send mail to: {RCPT}.'
'msg' => 'No from address has be provided.'
'msg' => 'Failed to create Net_SMTP object.'
'msg' => 'No MX-record for {RCPT} found.'
'msg' => 'Could not start resolver! Install PEAR:Net_DNS or switch off "netdns"'
'msg' => 'RSET command failed, SMTP-connection corrupt.'
* Instantiates a new Mail_smtp:: object based on the parameters
* passed in. It looks for the following parameters:
* mailname The name of the local mail system (a valid hostname which matches the reverse lookup)
* port smtp-port - the default comes from getservicebyname() and should work fine
* timeout The SMTP connection timeout. Defaults to 30 seconds.
* vrfy Whether to use VRFY or not. Defaults to false.
* verp Whether to use VERP or not. Defaults to false.
* test Activate test mode? Defaults to false.
* debug Activate SMTP and Net_DNS debug mode? Defaults to false.
* netdns whether to use PEAR:Net_DNS or the PHP build in function getmxrr, default is true
* If a parameter is present in the $params array, it replaces the
* @param array Hash containing any parameters different from the
if (isset ($params['mailname'])) {
// try to find a valid mailname
if (isset ($params['port'])) {
$this->_port = $params['port'];
if (isset ($params['timeout'])) $this->timeout = $params['timeout'];
if (isset ($params['verp'])) $this->verp = $params['verp'];
if (isset ($params['test'])) $this->test = $params['test'];
if (isset ($params['peardebug'])) $this->test = $params['peardebug'];
if (isset ($params['netdns'])) $this->withNetDns = $params['netdns'];
* Constructor wrapper for PHP4
* @param array Hash containing any parameters different from the defaults
* Destructor implementation to ensure that we disconnect from any
* potentially-alive persistent SMTP connections.
$this->_smtp->disconnect ();
* Implements Mail::send() function using SMTP direct delivery
* @param mixed $recipients in RFC822 style or array
* @param array $headers The array of headers to send with the mail.
* @param string $body The full text of the message body,
* @return mixed Returns true on success, or a PEAR_Error
function send($recipients, $headers, $body)
return PEAR ::raiseError ('$headers must be an array');
$result = $this->_sanitizeHeaders ($headers);
if (is_a($result, 'PEAR_Error')) {
$headerElements = $this->prepareHeaders ($headers);
if (is_a($headerElements, 'PEAR_Error')) {
list ($from, $textHeaders) = $headerElements;
// use 'Return-Path' if possible
if (!empty ($headers['Return-Path'])) {
$from = $headers['Return-Path'];
return $this->_raiseError ('no_from');
$recipients = $this->parseRecipients ($recipients);
if (is_a($recipients, 'PEAR_Error')) {
foreach ($recipients as $rcpt) {
list ($user, $host) = explode('@', $rcpt);
$mx = $this->_getMx ($host);
if (is_a($mx, 'PEAR_Error')) {
$info = array ('rcpt' => $rcpt);
return $this->_raiseError ('no_mx', $info);
foreach ($mx as $mserver => $mpriority) {
$this->_smtp = new Net_SMTP ($mserver, $this->port, $this->mailname);
// configure the SMTP connection.
$this->_smtp->setDebug (true );
// attempt to connect to the configured SMTP server.
$res = $this->_smtp->connect ($this->timeout);
if (is_a($res, 'PEAR_Error')) {
// connection established
return $this->_raiseError ('not_connected', $info);
$res = $this->_smtp->vrfy ($rcpt);
if (is_a($res, 'PEAR_Error')) {
$info = array ('rcpt' => $rcpt);
return $this->_raiseError ('failed_vrfy_rcpt', $info);
$args['verp'] = $this->verp;
$res = $this->_smtp->mailFrom ($from, $args);
if (is_a($res, 'PEAR_Error')) {
$info = array ('from' => $from);
return $this->_raiseError ('failed_set_from', $info);
$res = $this->_smtp->rcptTo ($rcpt);
if (is_a($res, 'PEAR_Error')) {
$info = array ('rcpt' => $rcpt);
return $this->_raiseError ('failed_set_rcpt', $info);
// Don't send anything in test mode
$result = $this->_smtp->rset ();
$res = $this->_smtp->rset ();
if (is_a($res, 'PEAR_Error')) {
return $this->_raiseError ('failed_rset');
$this->_smtp->disconnect ();
$res = $this->_smtp->data (" $textHeaders\r\n$body" );
if (is_a($res, 'PEAR_Error')) {
$info = array ('rcpt' => $rcpt);
return $this->_raiseError ('failed_send_data', $info);
$this->_smtp->disconnect ();
* Recieve mx rexords for a spciefied host
* @param string $host mail host
$res = $this->_loadNetDns ();
if (is_a($res, 'PEAR_Error')) {
$response = $this->resolver->query ($host, 'MX');
foreach ($response->answer as $rr) {
$mx[$rr->exchange ] = $rr->preference;
if (!getmxrr($host, $mxHost, $mxWeight)) {
for ($i = 0; $i < count($mxHost); ++ $i) {
$mx[$mxHost[$i]] = $mxWeight[$i];
* initialize PEAR:Net_DNS_Resolver
* @return boolean true on success
if (!include_once 'Net/DNS.php') {
return $this->_raiseError ('no_resolver');
$this->resolver = new Net_DNS_Resolver ();
* raise standardized error
* include additional information in error message
* @param string $id maps error ids to codes and message
* @param array $info optional information in associative array
function _raiseError ($id, $info = array ())
// include info to messages
foreach ($info as $key => $value) {
return PEAR ::raiseError ($msg, $code);
Documentation generated on Fri, 15 May 2009 01:30:05 +0000 by phpDocumentor 1.4.2. PEAR Logo Copyright © PHP Group 2004.
|