Added the zend framework 2 library, the path is specified in line no.26 in zend_modul...
[openemr.git] / interface / modules / zend_modules / library / Zend / Mail / Protocol / Smtp.php
blob6e31b3767de6cb96d13365e9f44cd04e3f18120c
1 <?php
2 /**
3 * Zend Framework (http://framework.zend.com/)
5 * @link http://github.com/zendframework/zf2 for the canonical source repository
6 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
7 * @license http://framework.zend.com/license/new-bsd New BSD License
8 */
10 namespace Zend\Mail\Protocol;
12 /**
13 * SMTP implementation of Zend\Mail\Protocol\AbstractProtocol
15 * Minimum implementation according to RFC2821: EHLO, MAIL FROM, RCPT TO, DATA, RSET, NOOP, QUIT
17 class Smtp extends AbstractProtocol
19 /**
20 * The transport method for the socket
22 * @var string
24 protected $transport = 'tcp';
27 /**
28 * Indicates that a session is requested to be secure
30 * @var string
32 protected $secure;
35 /**
36 * Indicates an smtp session has been started by the HELO command
38 * @var bool
40 protected $sess = false;
43 /**
44 * Indicates an smtp AUTH has been issued and authenticated
46 * @var bool
48 protected $auth = false;
51 /**
52 * Indicates a MAIL command has been issued
54 * @var bool
56 protected $mail = false;
59 /**
60 * Indicates one or more RCTP commands have been issued
62 * @var bool
64 protected $rcpt = false;
67 /**
68 * Indicates that DATA has been issued and sent
70 * @var bool
72 protected $data = null;
75 /**
76 * Constructor.
78 * The first argument may be an array of all options. If so, it must include
79 * the 'host' and 'port' keys in order to ensure that all required values
80 * are present.
82 * @param string|array $host
83 * @param null|int $port
84 * @param null|array $config
85 * @throws Exception\InvalidArgumentException
87 public function __construct($host = '127.0.0.1', $port = null, array $config = null)
89 // Did we receive a configuration array?
90 if (is_array($host)) {
91 // Merge config array with principal array, if provided
92 if (is_array($config)) {
93 $config = array_replace_recursive($host, $config);
94 } else {
95 $config = $host;
98 // Look for a host key; if none found, use default value
99 if (isset($config['host'])) {
100 $host = $config['host'];
101 } else {
102 $host = '127.0.0.1';
105 // Look for a port key; if none found, use default value
106 if (isset($config['port'])) {
107 $port = $config['port'];
108 } else {
109 $port = null;
113 // If we don't have a config array, initialize it
114 if (null === $config) {
115 $config = array();
118 if (isset($config['ssl'])) {
119 switch (strtolower($config['ssl'])) {
120 case 'tls':
121 $this->secure = 'tls';
122 break;
124 case 'ssl':
125 $this->transport = 'ssl';
126 $this->secure = 'ssl';
127 if ($port == null) {
128 $port = 465;
130 break;
132 default:
133 throw new Exception\InvalidArgumentException($config['ssl'] . ' is unsupported SSL type');
134 break;
138 // If no port has been specified then check the master PHP ini file. Defaults to 25 if the ini setting is null.
139 if ($port == null) {
140 if (($port = ini_get('smtp_port')) == '') {
141 $port = 25;
145 parent::__construct($host, $port);
150 * Connect to the server with the parameters given in the constructor.
152 * @return bool
154 public function connect()
156 return $this->_connect($this->transport . '://' . $this->host . ':' . $this->port);
161 * Initiate HELO/EHLO sequence and set flag to indicate valid smtp session
163 * @param string $host The client hostname or IP address (default: 127.0.0.1)
164 * @throws Exception\RuntimeException
166 public function helo($host = '127.0.0.1')
168 // Respect RFC 2821 and disallow HELO attempts if session is already initiated.
169 if ($this->sess === true) {
170 throw new Exception\RuntimeException('Cannot issue HELO to existing session');
173 // Validate client hostname
174 if (!$this->validHost->isValid($host)) {
175 throw new Exception\RuntimeException(implode(', ', $this->validHost->getMessages()));
178 // Initiate helo sequence
179 $this->_expect(220, 300); // Timeout set for 5 minutes as per RFC 2821 4.5.3.2
180 $this->_ehlo($host);
182 // If a TLS session is required, commence negotiation
183 if ($this->secure == 'tls') {
184 $this->_send('STARTTLS');
185 $this->_expect(220, 180);
186 if (!stream_socket_enable_crypto($this->socket, true, STREAM_CRYPTO_METHOD_TLS_CLIENT)) {
187 throw new Exception\RuntimeException('Unable to connect via TLS');
189 $this->_ehlo($host);
192 $this->_startSession();
193 $this->auth();
197 * Returns the perceived session status
199 * @return bool
201 public function hasSession()
203 return $this->sess;
207 * Send EHLO or HELO depending on capabilities of smtp host
209 * @param string $host The client hostname or IP address (default: 127.0.0.1)
210 * @throws \Exception|Exception\ExceptionInterface
212 protected function _ehlo($host)
214 // Support for older, less-compliant remote servers. Tries multiple attempts of EHLO or HELO.
215 try {
216 $this->_send('EHLO ' . $host);
217 $this->_expect(250, 300); // Timeout set for 5 minutes as per RFC 2821 4.5.3.2
218 } catch (Exception\ExceptionInterface $e) {
219 $this->_send('HELO ' . $host);
220 $this->_expect(250, 300); // Timeout set for 5 minutes as per RFC 2821 4.5.3.2
221 } catch (\Exception $e) {
222 throw $e;
228 * Issues MAIL command
230 * @param string $from Sender mailbox
231 * @throws Exception\RuntimeException
233 public function mail($from)
235 if ($this->sess !== true) {
236 throw new Exception\RuntimeException('A valid session has not been started');
239 $this->_send('MAIL FROM:<' . $from . '>');
240 $this->_expect(250, 300); // Timeout set for 5 minutes as per RFC 2821 4.5.3.2
242 // Set mail to true, clear recipients and any existing data flags as per 4.1.1.2 of RFC 2821
243 $this->mail = true;
244 $this->rcpt = false;
245 $this->data = false;
250 * Issues RCPT command
252 * @param string $to Receiver(s) mailbox
253 * @throws Exception\RuntimeException
255 public function rcpt($to)
258 if ($this->mail !== true) {
259 throw new Exception\RuntimeException('No sender reverse path has been supplied');
262 // Set rcpt to true, as per 4.1.1.3 of RFC 2821
263 $this->_send('RCPT TO:<' . $to . '>');
264 $this->_expect(array(250, 251), 300); // Timeout set for 5 minutes as per RFC 2821 4.5.3.2
265 $this->rcpt = true;
270 * Issues DATA command
272 * @param string $data
273 * @throws Exception\RuntimeException
275 public function data($data)
277 // Ensure recipients have been set
278 if ($this->rcpt !== true) { // Per RFC 2821 3.3 (page 18)
279 throw new Exception\RuntimeException('No recipient forward path has been supplied');
282 $this->_send('DATA');
283 $this->_expect(354, 120); // Timeout set for 2 minutes as per RFC 2821 4.5.3.2
285 foreach (explode(self::EOL, $data) as $line) {
286 if (strpos($line, '.') === 0) {
287 // Escape lines prefixed with a '.'
288 $line = '.' . $line;
290 $this->_send($line);
293 $this->_send('.');
294 $this->_expect(250, 600); // Timeout set for 10 minutes as per RFC 2821 4.5.3.2
295 $this->data = true;
300 * Issues the RSET command end validates answer
302 * Can be used to restore a clean smtp communication state when a transaction has been cancelled or commencing a new transaction.
305 public function rset()
307 $this->_send('RSET');
308 // MS ESMTP doesn't follow RFC, see [ZF-1377]
309 $this->_expect(array(250, 220));
311 $this->mail = false;
312 $this->rcpt = false;
313 $this->data = false;
318 * Issues the NOOP command end validates answer
320 * Not used by Zend\Mail, could be used to keep a connection alive or check if it is still open.
323 public function noop()
325 $this->_send('NOOP');
326 $this->_expect(250, 300); // Timeout set for 5 minutes as per RFC 2821 4.5.3.2
331 * Issues the VRFY command end validates answer
333 * Not used by Zend\Mail.
335 * @param string $user User Name or eMail to verify
337 public function vrfy($user)
339 $this->_send('VRFY ' . $user);
340 $this->_expect(array(250, 251, 252), 300); // Timeout set for 5 minutes as per RFC 2821 4.5.3.2
345 * Issues the QUIT command and clears the current session
348 public function quit()
350 if ($this->sess) {
351 $this->auth = false;
352 $this->_send('QUIT');
353 $this->_expect(221, 300); // Timeout set for 5 minutes as per RFC 2821 4.5.3.2
354 $this->_stopSession();
360 * Default authentication method
362 * This default method is implemented by AUTH adapters to properly authenticate to a remote host.
364 * @throws Exception\RuntimeException
366 public function auth()
368 if ($this->auth === true) {
369 throw new Exception\RuntimeException('Already authenticated for this session');
375 * Closes connection
378 public function disconnect()
380 $this->_disconnect();
384 * Disconnect from remote host and free resource
386 protected function _disconnect()
388 // Make sure the session gets closed
389 $this->quit();
390 parent::_disconnect();
394 * Start mail session
397 protected function _startSession()
399 $this->sess = true;
404 * Stop mail session
407 protected function _stopSession()
409 $this->sess = false;