1: <?php
2:
3: 4: 5: 6: 7: 8: 9: 10: 11:
12:
13:
14:
15: 16: 17: 18: 19: 20:
21: class NSmtpMailer extends NObject implements IMailer
22: {
23:
24: private $connection;
25:
26:
27: private $host;
28:
29:
30: private $port;
31:
32:
33: private $username;
34:
35:
36: private $password;
37:
38:
39: private $secure;
40:
41:
42: private $timeout;
43:
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: 67: 68: 69: 70:
71: public function send(NMail $mail)
72: {
73: $data = $mail->generateMessage();
74:
75: $this->connect();
76:
77: $from = $mail->getHeader('From');
78: if ($from) {
79: $from = array_keys($from);
80: $this->write("MAIL FROM:<$from[0]>", 250);
81: }
82:
83: foreach (array_merge(
84: (array) $mail->getHeader('To'),
85: (array) $mail->getHeader('Cc'),
86: (array) $mail->getHeader('Bcc')
87: ) as $email => $name) {
88: $this->write("RCPT TO:<$email>", array(250, 251));
89: }
90:
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: 104: 105: 106:
107: private function connect()
108: {
109: $this->connection = @fsockopen(
110: ($this->secure === 'ssl' ? 'ssl://' : '') . $this->host,
111: $this->port, $errno, $error, $this->timeout
112: );
113: if (!$this->connection) {
114: throw new NSmtpException($error, $errno);
115: }
116: stream_set_timeout($this->connection, $this->timeout, 0);
117: $this->read();
118:
119: $self = isset($_SERVER['SERVER_NAME']) ? $_SERVER['SERVER_NAME'] : 'localhost';
120: $this->write("EHLO $self");
121: if ((int) $this->read() !== 250) {
122: $this->write("HELO $self", 250);
123: }
124:
125: if ($this->secure === 'tls') {
126: $this->write('STARTTLS', 220);
127: if (!stream_socket_enable_crypto($this->connection, TRUE, STREAM_CRYPTO_METHOD_TLS_CLIENT)) {
128: throw new NSmtpException('Unable to connect via TLS.');
129: }
130: $this->write("EHLO $self", 250);
131: }
132:
133: if ($this->username != NULL && $this->password != NULL) {
134: $this->write('AUTH LOGIN', 334);
135: $this->write(base64_encode($this->username), 334, 'username');
136: $this->write(base64_encode($this->password), 235, 'password');
137: }
138: }
139:
140:
141:
142: 143: 144: 145:
146: private function disconnect()
147: {
148: fclose($this->connection);
149: $this->connection = NULL;
150: }
151:
152:
153:
154: 155: 156: 157: 158: 159: 160:
161: private function write($line, $expectedCode = NULL, $message = NULL)
162: {
163: fwrite($this->connection, $line . NMail::EOL);
164: if ($expectedCode && !in_array((int) $this->read(), (array) $expectedCode)) {
165: throw new NSmtpException('SMTP server did not accept ' . ($message ? $message : $line));
166: }
167: }
168:
169:
170:
171: 172: 173: 174:
175: private function read()
176: {
177: $s = '';
178: while (($line = fgets($this->connection, 1e3)) != NULL) {
179: $s .= $line;
180: if (substr($line, 3, 1) === ' ') {
181: break;
182: }
183: }
184: return $s;
185: }
186:
187: }
188:
189:
190:
191: 192: 193: 194: 195: 196:
197: class NSmtpException extends Exception
198: {
199: }
200: