~ubuntu-branches/debian/experimental/php-nette/experimental

« back to all changes in this revision

Viewing changes to Nette-2.0.13/Nette/Mail/SmtpMailer.php

  • Committer: Package Import Robot
  • Author(s): David Prévot
  • Date: 2013-11-30 08:47:54 UTC
  • mfrom: (1.1.1)
  • Revision ID: package-import@ubuntu.com-20131130084754-4udf1xsu9085tnfc
Tags: 2.1.0~rc-1
* New upstream branch
* Update copyright

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
<?php
2
 
 
3
 
/**
4
 
 * This file is part of the Nette Framework (http://nette.org)
5
 
 *
6
 
 * Copyright (c) 2004 David Grudl (http://davidgrudl.com)
7
 
 *
8
 
 * For the full copyright and license information, please view
9
 
 * the file license.txt that was distributed with this source code.
10
 
 */
11
 
 
12
 
namespace Nette\Mail;
13
 
 
14
 
use Nette;
15
 
 
16
 
 
17
 
/**
18
 
 * Sends emails via the SMTP server.
19
 
 *
20
 
 * @author     David Grudl
21
 
 */
22
 
class SmtpMailer extends Nette\Object implements IMailer
23
 
{
24
 
        /** @var resource */
25
 
        private $connection;
26
 
 
27
 
        /** @var string */
28
 
        private $host;
29
 
 
30
 
        /** @var int */
31
 
        private $port;
32
 
 
33
 
        /** @var string */
34
 
        private $username;
35
 
 
36
 
        /** @var string */
37
 
        private $password;
38
 
 
39
 
        /** @var string ssl | tls | (empty) */
40
 
        private $secure;
41
 
 
42
 
        /** @var int */
43
 
        private $timeout;
44
 
 
45
 
 
46
 
        public function __construct(array $options = array())
47
 
        {
48
 
                if (isset($options['host'])) {
49
 
                        $this->host = $options['host'];
50
 
                        $this->port = isset($options['port']) ? (int) $options['port'] : NULL;
51
 
                } else {
52
 
                        $this->host = ini_get('SMTP');
53
 
                        $this->port = (int) ini_get('smtp_port');
54
 
                }
55
 
                $this->username = isset($options['username']) ? $options['username'] : '';
56
 
                $this->password = isset($options['password']) ? $options['password'] : '';
57
 
                $this->secure = isset($options['secure']) ? $options['secure'] : '';
58
 
                $this->timeout = isset($options['timeout']) ? (int) $options['timeout'] : 20;
59
 
                if (!$this->port) {
60
 
                        $this->port = $this->secure === 'ssl' ? 465 : 25;
61
 
                }
62
 
        }
63
 
 
64
 
 
65
 
        /**
66
 
         * Sends email.
67
 
         * @return void
68
 
         */
69
 
        public function send(Message $mail)
70
 
        {
71
 
                $mail = clone $mail;
72
 
 
73
 
                $this->connect();
74
 
 
75
 
                if (($from = $mail->getHeader('Return-Path'))
76
 
                        || ($from = key($mail->getHeader('From'))))
77
 
                {
78
 
                        $this->write("MAIL FROM:<$from>", 250);
79
 
                }
80
 
 
81
 
                foreach (array_merge(
82
 
                        (array) $mail->getHeader('To'),
83
 
                        (array) $mail->getHeader('Cc'),
84
 
                        (array) $mail->getHeader('Bcc')
85
 
                ) as $email => $name) {
86
 
                        $this->write("RCPT TO:<$email>", array(250, 251));
87
 
                }
88
 
 
89
 
                $mail->setHeader('Bcc', NULL);
90
 
                $data = $mail->generateMessage();
91
 
                $this->write('DATA', 354);
92
 
                $data = preg_replace('#^\.#m', '..', $data);
93
 
                $this->write($data);
94
 
                $this->write('.', 250);
95
 
 
96
 
                $this->write('QUIT', 221);
97
 
 
98
 
                $this->disconnect();
99
 
        }
100
 
 
101
 
 
102
 
        /**
103
 
         * Connects and authenticates to SMTP server.
104
 
         * @return void
105
 
         */
106
 
        private function connect()
107
 
        {
108
 
                $this->connection = @fsockopen( // intentionally @
109
 
                        ($this->secure === 'ssl' ? 'ssl://' : '') . $this->host,
110
 
                        $this->port, $errno, $error, $this->timeout
111
 
                );
112
 
                if (!$this->connection) {
113
 
                        throw new SmtpException($error, $errno);
114
 
                }
115
 
                stream_set_timeout($this->connection, $this->timeout, 0);
116
 
                $this->read(); // greeting
117
 
 
118
 
                $self = isset($_SERVER['HTTP_HOST']) && preg_match('#^[\w.-]+\z#', $_SERVER['HTTP_HOST']) ? $_SERVER['HTTP_HOST'] : 'localhost';
119
 
                $this->write("EHLO $self");
120
 
                if ((int) $this->read() !== 250) {
121
 
                        $this->write("HELO $self", 250);
122
 
                }
123
 
 
124
 
                if ($this->secure === 'tls') {
125
 
                        $this->write('STARTTLS', 220);
126
 
                        if (!stream_socket_enable_crypto($this->connection, TRUE, STREAM_CRYPTO_METHOD_TLS_CLIENT)) {
127
 
                                throw new SmtpException('Unable to connect via TLS.');
128
 
                        }
129
 
                        $this->write("EHLO $self", 250);
130
 
                }
131
 
 
132
 
                if ($this->username != NULL && $this->password != NULL) {
133
 
                        $this->write('AUTH LOGIN', 334);
134
 
                        $this->write(base64_encode($this->username), 334, 'username');
135
 
                        $this->write(base64_encode($this->password), 235, 'password');
136
 
                }
137
 
        }
138
 
 
139
 
 
140
 
        /**
141
 
         * Disconnects from SMTP server.
142
 
         * @return void
143
 
         */
144
 
        private function disconnect()
145
 
        {
146
 
                fclose($this->connection);
147
 
                $this->connection = NULL;
148
 
        }
149
 
 
150
 
 
151
 
        /**
152
 
         * Writes data to server and checks response.
153
 
         * @param  string
154
 
         * @param  int   response code
155
 
         * @param  string  error message
156
 
         * @return void
157
 
         */
158
 
        private function write($line, $expectedCode = NULL, $message = NULL)
159
 
        {
160
 
                fwrite($this->connection, $line . Message::EOL);
161
 
                if ($expectedCode && !in_array((int) $this->read(), (array) $expectedCode)) {
162
 
                        throw new SmtpException('SMTP server did not accept ' . ($message ? $message : $line));
163
 
                }
164
 
        }
165
 
 
166
 
 
167
 
        /**
168
 
         * Reads response from server.
169
 
         * @return string
170
 
         */
171
 
        private function read()
172
 
        {
173
 
                $s = '';
174
 
                while (($line = fgets($this->connection, 1e3)) != NULL) { // intentionally ==
175
 
                        $s .= $line;
176
 
                        if (substr($line, 3, 1) === ' ') {
177
 
                                break;
178
 
                        }
179
 
                }
180
 
                return $s;
181
 
        }
182
 
 
183
 
}
184
 
 
185
 
 
186
 
/**
187
 
 * SMTP mailer exception.
188
 
 *
189
 
 * @author     David Grudl
190
 
 */
191
 
class SmtpException extends \Exception
192
 
{
193
 
}