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