⚝
One Hat Cyber Team
⚝
Your IP:
216.73.216.72
Server IP:
41.128.143.86
Server:
Linux host.raqmix.cloud 6.8.0-1025-azure #30~22.04.1-Ubuntu SMP Wed Mar 12 15:28:20 UTC 2025 x86_64
Server Software:
Apache
PHP Version:
8.3.23
Buat File
|
Buat Folder
Eksekusi
Dir :
~
/
usr
/
share
/
psa-pear
/
pear
/
php
/
Horde
/
Edit File: Smtp.php
<?php /** * Copyright 2013-2017 Horde LLC (http://www.horde.org/) * * See the enclosed file COPYING for license information (LGPL). If you * did not receive this file, see http://www.horde.org/licenses/lgpl21. * * @category Horde * @copyright 2013-2017 Horde LLC * @license http://www.horde.org/licenses/lgpl21 LGPL 2.1 * @package Smtp */ /** * An interface to an SMTP server (RFC 5321). * * Implements the following SMTP-related RFCs: * <pre> * - RFC 1870/STD 10: Message Size Declaration * - RFC 1985: SMTP Service Extension for Remote Message Queue Starting * - RFC 2034: Enhanced-Status-Codes * - RFC 2195: CRAM-MD5 (SASL Authentication) * - RFC 2595/4616: TLS & PLAIN (SASL Authentication) * - RFC 2831: DIGEST-MD5 authentication mechanism (obsoleted by RFC 6331) * - RFC 2920/STD 60: Pipelining * - RFC 3030: SMTP Service Extensions for Transmission of Large and Binary * MIME Messages * - RFC 3207: Secure SMTP over TLS * - RFC 3463: Enhanced Mail System Status Codes * - RFC 4422: SASL Authentication (for DIGEST-MD5) * - RFC 4954: Authentication * - RFC 5321: Simple Mail Transfer Protocol * - RFC 6152/STD 71: 8bit-MIMEtransport * - RFC 6409/STD 72: Message Submission for Mail * - RFC 6531: Internationalized Email * * - XOAUTH2: https://developers.google.com/gmail/xoauth2_protocol * </pre> * * TODO: * <pre> * - RFC 1845: CHECKPOINT * - RFC 2852: DELIVERYBY * - RFC 3461: DSN * - RFC 3865: NO-SOLICITING * - RFC 3885: MTRK * - RFC 4141: CONPERM/CONNEG * - RFC 4405: SUBMITTER * - RFC 4468: BURL * - RFC 4865: FUTURERELEASE * - RFC 6710: MT-PRIORITY * - RFC 7293: RRVS * </pre> * * @author Michael Slusarz <slusarz@horde.org> * @category Horde * @copyright 2013-2017 Horde LLC * @license http://www.horde.org/licenses/lgpl21 LGPL 2.1 * @package Smtp * * @property-read boolean $data_8bit Does server support sending 8-bit MIME * data? * @property-read boolean $data_binary Does server support sending binary * MIME data? (@since 1.7.0) * @property-read boolean $data_intl Does server support sending * internationalized (UTF-8) header data? * (@since 1.6.0) * @property-read integer $size The maximum message size supported (in * bytes) or null if this cannot be determined. */ class Horde_Smtp implements Serializable { const CHUNK_DEFAULT = 1048576; /** * Connection to the SMTP server. * * @var Horde_Smtp_Connection */ protected $_connection; /** * The debug object. * * @var Horde_Smtp_Debug */ protected $_debug; /** * The hello command to use for extended SMTP support. * * @var string */ protected $_ehlo = 'EHLO'; /** * The list of ESMTP extensions. * If this value is null, we have not connected to server yet. * * @var array */ protected $_extensions = null; /** * Hash containing connection parameters. * * @var array */ protected $_params = array(); /** * List of required ESMTP extensions. * * @var array */ protected $_requiredExts = array(); /** * Constructor. * * @param array $params Configuration parameters: * - chunk_size: (integer) If CHUNKING is supported on the server, the * chunk size (in octets) to send. 0 will disable chunking. * @since 1.7.0 * - context: (array) Any context parameters passed to * stream_create_context(). @since 1.9.0 * - debug: (string) If set, will output debug information to the stream * provided. The value can be any PHP supported wrapper that * can be opened via fopen(). * DEFAULT: No debug output * - host: (string) The SMTP server. * DEFAULT: localhost * - localhost: (string) The hostname of the localhost. (since 1.9.0) * DEFAULT: Auto-determined. * - password: (mixed) The SMTP password or a Horde_Smtp_Password object * (since 1.1.0). * DEFAULT: NONE * - port: (string) The SMTP port. * DEFAULT: 587 (See RFC 6409/STD 72) * - secure: (string) Use SSL or TLS to connect. * DEFAULT: true (use 'tls' option, if available) * - false (No encryption) * - 'ssl' (Auto-detect SSL version) * - 'sslv2' (Force SSL version 2) * - 'sslv3' (Force SSL version 3) * - 'tls' (TLS; started via protocol-level negotation over * unencrypted channel; RECOMMENDED way of initiating secure * connection) * - 'tlsv1' (TLS direct version 1.x connection to server) [@since * 1.3.0] * - true (Use TLS, if available) [@since 1.2.0] * - timeout: (integer) Connection timeout, in seconds. * DEFAULT: 30 seconds * - username: (string) The SMTP username. * DEFAULT: NONE * - xoauth2_token: (string) If set, will authenticate via the XOAUTH2 * mechanism (if available) with this token. Either a * string or a Horde_Smtp_Password object (since 1.1.0). */ public function __construct(array $params = array()) { // Default values. $params = array_merge(array( 'chunk_size' => self::CHUNK_DEFAULT, 'context' => array(), 'host' => 'localhost', 'port' => 587, 'secure' => true, 'timeout' => 30 ), $params); foreach ($params as $key => $val) { $this->setParam($key, $val); } $this->_initOb(); } /** * Get encryption key. * * @deprecated * * @return string The encryption key. */ protected function _getEncryptKey() { if (is_callable($ekey = $this->getParam('password_encrypt'))) { return call_user_func($ekey); } throw new InvalidArgumentException('password_encrypt parameter is not a valid callback.'); } /** * Do initialization tasks. */ protected function _initOb() { register_shutdown_function(array($this, 'shutdown')); $this->_debug = ($debug = $this->getParam('debug')) ? new Horde_Smtp_Debug($debug) : new Horde_Support_Stub(); } /** * Shutdown actions. */ public function shutdown() { $this->logout(); } /** * This object can not be cloned. */ public function __clone() { throw new LogicException('Object cannot be cloned.'); } /** */ public function serialize() { return serialize($this->_params); } /** */ public function unserialize($data) { $this->_params = @unserialize($data); $this->_initOb(); } /** */ public function __get($name) { switch ($name) { case 'data_8bit': // RFC 6152 return $this->queryExtension('8BITMIME'); case 'data_binary': // RFC 3030 return $this->queryExtension('BINARYMIME'); case 'data_intl': // RFC 6531 return $this->queryExtension('SMTPUTF8'); case 'size': // RFC 1870 return $this->queryExtension('SIZE') ?: null; } } /** * Returns a value from the internal params array. * * @param string $key The param key. * * @return mixed The param value, or null if not found. */ public function getParam($key) { /* Passwords may be stored encrypted. */ switch ($key) { case 'password': case 'xoauth2_token': if (isset($this->_params[$key]) && ($this->_params[$key] instanceof Horde_Smtp_Password)) { return $this->_params[$key]->getPassword(); } // DEPRECATED if (($key == 'password') && !empty($this->_params['_passencrypt'])) { try { $secret = new Horde_Secret(); return $secret->read($this->_getEncryptKey(), $this->_params['password']); } catch (Exception $e) { return null; } } break; } return isset($this->_params[$key]) ? $this->_params[$key] : null; } /** * Sets a configuration parameter value. * * @param string $key The param key. * @param mixed $val The param value. */ public function setParam($key, $val) { switch ($key) { case 'password': if ($val instanceof Horde_Smtp_Password) { break; } // Encrypt password. DEPRECATED try { $encrypt_key = $this->_getEncryptKey(); if (strlen($encrypt_key)) { $secret = new Horde_Secret(); $val = $secret->write($encrypt_key, $val); $this->_params['_passencrypt'] = true; } } catch (Exception $e) {} break; } $this->_params[$key] = $val; } /** * Returns whether the SMTP server supports the given extension. * * @param string $ext The extension to query. * * @return mixed False if the server doesn't support the extension; * otherwise, the extension value (returns true if the * extension only supports existence). */ public function queryExtension($ext) { try { $this->login(); } catch (Horde_Smtp_Exception $e) { return false; } $ext = Horde_String::upper($ext); return isset($this->_extensions[$ext]) ? $this->_extensions[$ext] : false; } /** * Display if connection to the server has been secured via TLS or SSL. * * @return boolean True if the SMTP connection is secured. */ public function isSecureConnection() { return ($this->_connection && $this->_connection->secure); } /** * Connect/login to the SMTP server. * * @throws Horde_Smtp_Exception */ public function login() { if (!is_null($this->_extensions)) { return; } if (!$this->_connection) { try { $this->_connection = new Horde_Smtp_Connection( $this->getParam('host'), $this->getParam('port'), $this->getParam('timeout'), $this->getParam('secure'), $this->getParam('context'), array( 'debug' => $this->_debug ) ); } catch (Horde\Socket\Client\Exception $e) { $e2 = new Horde_Smtp_Exception( Horde_Smtp_Translation::r("Error connecting to SMTP server."), Horde_Smtp_Exception::SERVER_CONNECT ); $e2->details = $e->details; throw $e2; } $this->_debug->info(sprintf( 'Connection to: smtp://%s:%s', $this->getParam('host'), $this->getParam('port') )); // Get initial line (RFC 5321 [3.1]). $this->_getResponse(220, array( 'error' => 'logout' )); } $this->_hello(); if ($this->_startTls()) { $this->_extensions = null; $this->login(); return; } /* Check for required ESMTP extensions. */ foreach ($this->_requiredExts as $val) { if (!$this->queryExtension($val)) { throw new Horde_Smtp_Exception( sprintf( Horde_Smtp_Translation::r("Server does not support a necessary server extension: %s."), $val ), Horde_Smtp_Exception::LOGIN_MISSINGEXTENSION ); } } /* If we reached this point and don't have a secure connection, then * a secure connections is not available. */ if (!$this->isSecureConnection() && ($this->getParam('secure') === true)) { $this->setParam('secure', false); } if (!strlen($this->getParam('username')) || !($auth = $this->queryExtension('AUTH'))) { return; } $auth = array_flip(array_map('trim', explode(' ', $auth))); // XOAUTH2 if (isset($auth['XOAUTH2'])) { unset($auth['XOAUTH2']); if ($this->getParam('xoauth2_token')) { $auth = array('XOAUTH2' => true) + $auth; } } foreach (array_keys($auth) as $method) { try { $this->_auth($method); return; } catch (Horde_Smtp_Exception $e) {} } $this->logout(); throw new Horde_Smtp_Exception( Horde_Smtp_Translation::r("Server denied authentication."), Horde_Smtp_Exception::LOGIN_AUTHENTICATIONFAILED ); } /** * Logout from the SMTP server. */ public function logout() { if (!is_null($this->_extensions) && $this->_connection->connected) { try { // See RFC 5321 [4.1.1.10] $this->_connection->write('QUIT'); $this->_getResponse(221); } catch (Exception $e) {} $this->_connection->close(); } unset($this->_connection); $this->_extensions = null; } /** * Send a message. * * @param mixed $from The from address. Either a * Horde_Mail_Rfc822_Address object or a string. * @param mixed $to The to (recipient) addresses. Either a * Horde_Mail_Rfc822_List object, a string, or an * array of addresses. * @param mixed $data The data to send. Either a stream or a string. * * @return array If no receipients were successful, a * Horde_Smtp_Exception will be thrown. If at least one * recipient was successful, an array with the following * format is returned: (@since 1.5.0) * - KEYS: Recipient addresses ($to addresses). * - VALUES: Boolean true (if message was accepted for this recpieint) * or a Horde_Smtp_Exception (if messages was not accepted). * * @throws Horde_Smtp_Exception * @throws Horde_Smtp_Exception_Recipients * @throws InvalidArgumentException */ public function send($from, $to, $data, array $opts = array()) { $this->login(); if (!($from instanceof Horde_Mail_Rfc822_Address)) { $from = new Horde_Mail_Rfc822_Address($from); } /* Are EAI addresses present? */ $eai = $from->eai; if (!($to instanceof Horde_Mail_Rfc822_List)) { $to = new Horde_Mail_Rfc822_List($to); } if (!$eai) { foreach ($to->raw_addresses as $val) { if ($eai = $val->eai) { break; } } } /* RFC 6531: EAI */ if ($eai && !$this->data_intl) { throw new InvalidArgumentException( 'Server does not support sending internationalized header data.' ); } $stream = fopen('php://temp', 'r+'); stream_filter_register('horde_smtp_data', 'Horde_Smtp_Filter_Data'); $filter_data = stream_filter_append( $stream, 'horde_smtp_data', STREAM_FILTER_WRITE ); stream_filter_register('horde_smtp_body', 'Horde_Smtp_Filter_Body'); $filter_body_params = new stdClass; $filter_body = stream_filter_append( $stream, 'horde_smtp_body', STREAM_FILTER_WRITE, $filter_body_params ); if (is_resource($data)) { while (!feof($data)) { fwrite($stream, fread($data, 8192)); } } else { fwrite($stream, $data); } stream_filter_remove($filter_body); stream_filter_remove($filter_data); $size = ftell($stream); rewind($stream); $chunking = $this->queryExtension('CHUNKING'); $chunk_force = false; $chunk_size = $this->getParam('chunk_size'); /* Do body checks now, since if they fail it doesn't make sense to * do anything else. */ $body = null; if ($eai || ($filter_body_params->body === '8bit')) { /* RFC 6152[3]. RFC 6531[1.2] also requires at least 8BITMIME to * be available. */ $body = $this->data_8bit ? ' BODY=8BITMIME' : false; } /* Fallback to binarymime if 8bitmime is not available. */ if (($body === false) || ($filter_body_params->body === 'binary')) { // RFC 3030[3] if (!$this->data_binary) { switch ($filter_body_params->body) { case 'binary': throw new InvalidArgumentException( 'Server does not support binary message data.' ); default: throw new InvalidArgumentException( 'Server does not support 8-bit message data.' ); } } $body = ' BODY=BINARYMIME'; /* BINARYMIME requires CHUNKING. */ $chunking = $chunk_force = true; if (!$chunk_size) { $chunk_size = self::CHUNK_DEFAULT; } } if (is_null($body) && $this->_debug->active && $this->data_8bit) { /* Only output extended 7bit command if debug is active (it is * default and does not need to be explicitly declared). */ $body = ' BODY=7BIT'; } $mailcmd = 'MAIL FROM:<' . ($eai ? $from->bare_address : $from->bare_address_idn) . '>'; // RFC 1870[6] if ($this->queryExtension('SIZE')) { $mailcmd .= ' SIZE=' . intval($size); } // RFC 6531[3.4] if ($eai) { $mailcmd .= ' SMTPUTF8'; } if (!is_null($body)) { $mailcmd .= $body; } $recipients = $eai ? $to->bare_addresses : $to->bare_addresses_idn; $recip_cmds = array(); foreach ($recipients as $val) { $recip_cmds[$val] = 'RCPT TO:<' . $val . '>'; } if ($this->queryExtension('PIPELINING')) { $this->_connection->write( array_merge(array($mailcmd), array_values($recip_cmds)) ); try { $this->_getResponse(250); $error = null; } catch (Horde_Smtp_Exception $e) { $error = $e; } foreach ($recip_cmds as $key => $val) { try { $this->_getResponse(array(250, 251), array( 'exception' => 'Horde_Smtp_Exception_Recipients' )); } catch (Horde_Smtp_Exception_Recipients $e) { if (is_null($error)) { $error = $e; } if ($error instanceof Horde_Smtp_Exception_Recipients) { $error->recipients[] = $key; } } } /* Can't pipeline DATA since we want to throw an exception if * ANY of the recipients are bad. */ if (!is_null($error)) { $this->resetCmd(); throw $error; } } else { $this->_connection->write($mailcmd); $this->_getResponse(250, array( 'error' => 'reset' )); foreach ($recip_cmds as $key => $val) { $this->_connection->write($val); try { $this->_getResponse(array(250, 251), array( 'error' => 'reset', 'exception' => 'Horde_Smtp_Exception_Recipients' )); } catch (Horde_Smtp_Exception_Recipients $e) { $e->recipients[] = $key; throw $e; } } } /* CHUNKING support. RFC 3030[2] */ if ($chunking && $chunk_size && ($chunk_force || ($size > $chunk_size))) { while ($size) { $c = min($chunk_size, $size); $size -= $c; $this->_connection->write( 'BDAT ' . $c . ($size ? '' : ' LAST') ); $this->_connection->write($stream, $c); if ($size) { $this->_getResponse(250, array( 'error' => 'reset' )); } } } else { $this->_connection->write('DATA'); try { $this->_getResponse(354, array( 'error' => 'reset' )); } catch (Horde_Smtp_Exception $e) { fclose($stream); /* This is the place where a STARTTLS 530 error would occur. * If so, explicitly use STARTTLS and try again. */ switch ($e->getSmtpCode()) { case 530: if (!$this->isSecureConnection()) { $this->logout(); $this->setParam('secure', 'tls'); $this->send($from, $to, $data, $opts); return; } break; } throw $e; } $this->_connection->write($stream); $this->_connection->write('.'); } fclose($stream); return $this->_processData($recipients); } /** * Send a reset command. * * @throws Horde_Smtp_Exception */ public function resetCmd() { $this->login(); // See RFC 5321 [4.1.1.5]. // RSET only useful if we are already authenticated. if (!is_null($this->_extensions)) { $this->_connection->write('RSET'); $this->_getResponse(250); } } /** * Send a NOOP command. * * @throws Horde_Smtp_Exception */ public function noop() { $this->login(); // See RFC 5321 [4.1.1.9]. // NOOP only useful if we are already authenticated. if (!is_null($this->_extensions)) { $this->_connection->write('NOOP'); $this->_getResponse(250); } } /** * Send request to process the remote queue. * * @param string $host The specific host to request queue processing for. * * @throws Horde_Smtp_Exception */ public function processQueue($host = null) { $this->login(); if (!$this->queryExtension('ETRN')) { return; } if (is_null($host)) { $host = $this->_getHostname(); if ($host === false) { return; } } $this->_connection->write('ETRN ' . $host); $this->_getResponse(array(250, 251, 252, 253)); } /* Internal methods. */ /** * Send "Hello" command to the server. * * @throws Horde_Smtp_Exception */ protected function _hello() { $ehlo = $host = $this->_getHostname(); if ($host === false) { $ehlo = $_SERVER['SERVER_ADDR']; $host = 'localhost'; } $this->_connection->write($this->_ehlo . ' ' . $ehlo); try { $resp = $this->_getResponse(250); foreach ($resp as $val) { $tmp = explode(' ', $val, 2); $this->_extensions[$tmp[0]] = empty($tmp[1]) ? true : $tmp[1]; } } catch (Horde_Smtp_Exception $e) { switch ($e->getSmtpCode()) { case 502: // Old server - doesn't support EHLO $this->_connection->write('HELO ' . $host); try { $this->_getResponse(250); } catch (Horde_Smtp_Exception $e2) { $this->logout(); throw $e; } $this->_extensions = array(); break; default: $this->logout(); throw $e; } } } /** * Starts the TLS connection to the server, if necessary. See RFC 3207. * * @return boolean True if TLS was started. * * @throws Horde_Smtp_Exception */ protected function _startTls() { $secure = $this->getParam('secure'); if ($this->isSecureConnection() || (($secure !== true) && ($secure !== 'tls'))) { return false; } if (!$this->queryExtension('STARTTLS')) { if ($secure === true) { return false; } throw new Horde_Smtp_Exception( Horde_Smtp_Translation::r("Server does not support TLS connections."), Horde_Smtp_Exception::LOGIN_TLSFAILURE ); } $this->_connection->write('STARTTLS'); $this->_getResponse(220, array( 'error' => 'logout' )); if (!$this->_connection->startTls()) { $this->logout(); $e = new Horde_Smtp_Exception(); $e->setSmtpCode(454); throw $e; } $this->_debug->info('Successfully completed TLS negotiation.'); $this->setParam('secure', 'tls'); return true; } /** * Authenticate user to server for a given method. * * @param string $method Authentication method. * * @throws Horde_Smtp_Exception */ protected function _auth($method) { $user = $this->getParam('username'); $pass = $this->getParam('password'); $debug = sprintf("[AUTH Command - method: %s; username: %s]\n", $method, $user); switch ($method) { case 'CRAM-MD5': case 'CRAM-SHA1': case 'CRAM-SHA256': // RFC 2195: CRAM-MD5 // CRAM-SHA1 & CRAM-SHA256 supported by Courier SASL library $this->_connection->write('AUTH ' . $method); $resp = $this->_getResponse(334); $this->_debug->active = false; $this->_connection->write( base64_encode($user . ' ' . hash_hmac(Horde_String::lower(substr($method, 5)), base64_decode(reset($resp)), $pass, false)) ); $this->_debug->active = true; $this->_debug->raw($debug); break; case 'DIGEST-MD5': // RFC 2831/4422; obsoleted by RFC 6331 // Since this is obsolete, will only attempt if // Horde_Imap_Client is also present on the system. if (!class_exists('Horde_Imap_Client_Auth_DigestMD5')) { throw new Horde_Smtp_Exception('DIGEST-MD5 not supported'); } $this->_connection->write('AUTH ' . $method); $resp = $this->_getResponse(334); $this->_debug->active = false; $this->_connection->write( base64_encode(new Horde_Imap_Client_Auth_DigestMD5( $user, $pass, base64_decode(reset($resp)), $this->getParam('hostspec'), 'smtp' )) ); $this->_debug->active = true; $this->_debug->raw($debug); $this->_getResponse(334); $this->_connection->write(''); break; case 'LOGIN': $this->_connection->write('AUTH ' . $method); $this->_getResponse(334); $this->_connection->write(base64_encode($user)); $this->_getResponse(334); $this->_debug->active = false; $this->_connection->write(base64_encode($pass)); $this->_debug->active = true; $this->_debug->raw($debug); break; case 'PLAIN': // RFC 2595/4616 - PLAIN SASL mechanism $auth = base64_encode(implode("\0", array( $user, $user, $pass ))); $this->_debug->active = false; $this->_connection->write('AUTH ' . $method . ' ' . $auth); $this->_debug->active = true; $this->_debug->raw($debug); break; case 'XOAUTH2': // Google XOAUTH2 $this->_debug->active = false; $this->_connection->write( 'AUTH ' . $method . ' ' . $this->getParam('xoauth2_token') ); $this->_debug->active = true; $this->_debug->raw($debug); try { $this->_getResponse(235); return; } catch (Horde_Smtp_Exception $e) { switch ($e->getSmtpCode()) { case 334: $this->_connection->write(''); break; } } break; default: throw new Horde_Smtp_Exception(sprintf('Authentication method %s not supported', $method)); } $this->_getResponse(235); } /** * Gets a line from the incoming stream and parses it. * * @param mixed $code Expected reply code(s) (integer or array). * @param array $opts Additional options: * <pre> * - error: (string) On error, 'logout' or 'reset'? * - exception: (string) Throw an exception of this class on error. * </pre> * * @return array An array with the response text. * @throws Horde_Smtp_Exception */ protected function _getResponse($code, array $opts = array()) { $opts = array_merge(array( 'error' => null, 'exception' => 'Horde_Smtp_Exception' ), $opts); $text = array(); while ($read = $this->_connection->read()) { $read = trim(rtrim($read, "\r\n")); $replycode = intval(substr($read, 0, 3)); $text[] = ltrim(substr($read, 4)); if ($read[3] != '-') { break; } } if (!is_array($code)) { $code = array($code); } if (in_array($replycode, $code)) { return $text; } /* Check for enhanced status codes (RFC 2034). */ $details = reset($text); if (!is_null($this->_extensions) && $this->queryExtension('ENHANCEDSTATUSCODES')) { list($enhanced, $details) = explode(' ', $details, 2); if (!strpos($enhanced, '.')) { $details = $enhanced . ' ' . $details; $enhanced = null; } } else { $enhanced = null; } $e = new $opts['exception']($details); $e->details = $details; $e->setSmtpCode($replycode); if ($enhanced) { $e->setEnhancedSmtpCode($enhanced); } switch ($opts['error']) { case 'logout': $this->logout(); break; case 'reset': /* RFC 3207: If we see 530, no need to send reset command. */ if ($code != 530) { $this->resetCmd(); } break; } throw $e; } /** * Process the return from the DATA command. * * @see _send() * * @param array $recipients The list of message recipients. * * @return array See _send(). * @throws Horde_Smtp_Exception */ protected function _processData($recipients) { $this->_getResponse(250, array( 'error' => 'reset' )); return array_fill_keys($recipients, true); } /** * Return the local hostname. * * @return string Local hostname (null if it cannot be determined). */ protected function _getHostname() { return ($localhost = $this->getParam('localhost')) ? $localhost : gethostname(); } }
Simpan