CakePHP
  • Documentation
    • Book
    • API
    • Videos
    • Reporting Security Issues
    • Privacy Policy
    • Logos & Trademarks
  • Business Solutions
  • Swag
  • Road Trip
  • Team
  • Community
    • Community
    • Get Involved
    • Issues (GitHub)
    • Bakery
    • Featured Resources
    • Training
    • Meetups
    • My CakePHP
    • CakeFest
    • Newsletter
    • Linkedin
    • YouTube
    • Facebook
    • Twitter
    • Mastodon
    • Help & Support
    • Forum
    • Stack Overflow
    • Slack
    • Paid Support
CakePHP

C CakePHP 2.6 API

  • Overview
  • Tree
  • Deprecated
  • Version:
    • 2.6
      • 4.2
      • 4.1
      • 4.0
      • 3.9
      • 3.8
      • 3.7
      • 3.6
      • 3.5
      • 3.4
      • 3.3
      • 3.2
      • 3.1
      • 3.0
      • 2.10
      • 2.9
      • 2.8
      • 2.7
      • 2.6
      • 2.5
      • 2.4
      • 2.3
      • 2.2
      • 2.1
      • 2.0
      • 1.3
      • 1.2

Packages

  • Cake
    • Cache
      • Engine
    • Configure
    • Console
      • Command
        • Task
    • Controller
      • Component
        • Acl
        • Auth
    • Core
    • Error
    • Event
    • I18n
    • Log
      • Engine
    • Model
      • Behavior
      • Datasource
        • Database
        • Session
      • Validator
    • Network
      • Email
      • Http
    • Routing
      • Filter
      • Route
    • TestSuite
      • Coverage
      • Fixture
      • Reporter
    • Utility
    • View
      • Helper

Classes

  • AbstractTransport
  • CakeEmail
  • DebugTransport
  • MailTransport
  • SmtpTransport
  1: <?php
  2: /**
  3:  * Send mail using SMTP protocol
  4:  *
  5:  * CakePHP(tm) : Rapid Development Framework (http://cakephp.org)
  6:  * Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org)
  7:  *
  8:  * Licensed under The MIT License
  9:  * For full copyright and license information, please see the LICENSE.txt
 10:  * Redistributions of files must retain the above copyright notice.
 11:  *
 12:  * @copyright     Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org)
 13:  * @link          http://cakephp.org CakePHP(tm) Project
 14:  * @package       Cake.Network.Email
 15:  * @since         CakePHP(tm) v 2.0.0
 16:  * @license       http://www.opensource.org/licenses/mit-license.php MIT License
 17:  */
 18: 
 19: App::uses('CakeSocket', 'Network');
 20: 
 21: /**
 22:  * Send mail using SMTP protocol
 23:  *
 24:  * @package       Cake.Network.Email
 25:  */
 26: class SmtpTransport extends AbstractTransport {
 27: 
 28: /**
 29:  * Socket to SMTP server
 30:  *
 31:  * @var CakeSocket
 32:  */
 33:     protected $_socket;
 34: 
 35: /**
 36:  * CakeEmail
 37:  *
 38:  * @var CakeEmail
 39:  */
 40:     protected $_cakeEmail;
 41: 
 42: /**
 43:  * Content of email to return
 44:  *
 45:  * @var string
 46:  */
 47:     protected $_content;
 48: 
 49: /**
 50:  * The response of the last sent SMTP command.
 51:  *
 52:  * @var array
 53:  */
 54:     protected $_lastResponse = array();
 55: 
 56: /**
 57:  * Returns the response of the last sent SMTP command.
 58:  *
 59:  * A response consists of one or more lines containing a response
 60:  * code and an optional response message text:
 61:  * ```
 62:  * array(
 63:  *     array(
 64:  *         'code' => '250',
 65:  *         'message' => 'mail.example.com'
 66:  *     ),
 67:  *     array(
 68:  *         'code' => '250',
 69:  *         'message' => 'PIPELINING'
 70:  *     ),
 71:  *     array(
 72:  *         'code' => '250',
 73:  *         'message' => '8BITMIME'
 74:  *     ),
 75:  *     // etc...
 76:  * )
 77:  * ```
 78:  *
 79:  * @return array
 80:  */
 81:     public function getLastResponse() {
 82:         return $this->_lastResponse;
 83:     }
 84: 
 85: /**
 86:  * Send mail
 87:  *
 88:  * @param CakeEmail $email CakeEmail
 89:  * @return array
 90:  * @throws SocketException
 91:  */
 92:     public function send(CakeEmail $email) {
 93:         $this->_cakeEmail = $email;
 94: 
 95:         $this->_connect();
 96:         $this->_auth();
 97:         $this->_sendRcpt();
 98:         $this->_sendData();
 99:         $this->_disconnect();
100: 
101:         return $this->_content;
102:     }
103: 
104: /**
105:  * Set the configuration
106:  *
107:  * @param array $config Configuration options.
108:  * @return array Returns configs
109:  */
110:     public function config($config = null) {
111:         if ($config === null) {
112:             return $this->_config;
113:         }
114:         $default = array(
115:             'host' => 'localhost',
116:             'port' => 25,
117:             'timeout' => 30,
118:             'username' => null,
119:             'password' => null,
120:             'client' => null,
121:             'tls' => false
122:         );
123:         $this->_config = array_merge($default, $this->_config, $config);
124:         return $this->_config;
125:     }
126: 
127: /**
128:  * Parses and stores the reponse lines in `'code' => 'message'` format.
129:  *
130:  * @param array $responseLines Response lines to parse.
131:  * @return void
132:  */
133:     protected function _bufferResponseLines(array $responseLines) {
134:         $response = array();
135:         foreach ($responseLines as $responseLine) {
136:             if (preg_match('/^(\d{3})(?:[ -]+(.*))?$/', $responseLine, $match)) {
137:                 $response[] = array(
138:                     'code' => $match[1],
139:                     'message' => isset($match[2]) ? $match[2] : null
140:                 );
141:             }
142:         }
143:         $this->_lastResponse = array_merge($this->_lastResponse, $response);
144:     }
145: 
146: /**
147:  * Connect to SMTP Server
148:  *
149:  * @return void
150:  * @throws SocketException
151:  */
152:     protected function _connect() {
153:         $this->_generateSocket();
154:         if (!$this->_socket->connect()) {
155:             throw new SocketException(__d('cake_dev', 'Unable to connect to SMTP server.'));
156:         }
157:         $this->_smtpSend(null, '220');
158: 
159:         if (isset($this->_config['client'])) {
160:             $host = $this->_config['client'];
161:         } elseif ($httpHost = env('HTTP_HOST')) {
162:             list($host) = explode(':', $httpHost);
163:         } else {
164:             $host = 'localhost';
165:         }
166: 
167:         try {
168:             $this->_smtpSend("EHLO {$host}", '250');
169:             if ($this->_config['tls']) {
170:                 $this->_smtpSend("STARTTLS", '220');
171:                 $this->_socket->enableCrypto('tls');
172:                 $this->_smtpSend("EHLO {$host}", '250');
173:             }
174:         } catch (SocketException $e) {
175:             if ($this->_config['tls']) {
176:                 throw new SocketException(__d('cake_dev', 'SMTP server did not accept the connection or trying to connect to non TLS SMTP server using TLS.'));
177:             }
178:             try {
179:                 $this->_smtpSend("HELO {$host}", '250');
180:             } catch (SocketException $e2) {
181:                 throw new SocketException(__d('cake_dev', 'SMTP server did not accept the connection.'));
182:             }
183:         }
184:     }
185: 
186: /**
187:  * Send authentication
188:  *
189:  * @return void
190:  * @throws SocketException
191:  */
192:     protected function _auth() {
193:         if (isset($this->_config['username']) && isset($this->_config['password'])) {
194:             $replyCode = $this->_smtpSend('AUTH LOGIN', '334|500|502|504');
195:             if ($replyCode == '334') {
196:                 try {
197:                     $this->_smtpSend(base64_encode($this->_config['username']), '334');
198:                 } catch (SocketException $e) {
199:                     throw new SocketException(__d('cake_dev', 'SMTP server did not accept the username.'));
200:                 }
201:                 try {
202:                     $this->_smtpSend(base64_encode($this->_config['password']), '235');
203:                 } catch (SocketException $e) {
204:                     throw new SocketException(__d('cake_dev', 'SMTP server did not accept the password.'));
205:                 }
206:             } elseif ($replyCode == '504') {
207:                 throw new SocketException(__d('cake_dev', 'SMTP authentication method not allowed, check if SMTP server requires TLS.'));
208:             } else {
209:                 throw new SocketException(__d('cake_dev', 'AUTH command not recognized or not implemented, SMTP server may not require authentication.'));
210:             }
211:         }
212:     }
213: 
214: /**
215:  * Prepares the `MAIL FROM` SMTP command.
216:  *
217:  * @param string $email The email address to send with the command.
218:  * @return string
219:  */
220:     protected function _prepareFromCmd($email) {
221:         return 'MAIL FROM:<' . $email . '>';
222:     }
223: 
224: /**
225:  * Prepares the `RCPT TO` SMTP command.
226:  *
227:  * @param string $email The email address to send with the command.
228:  * @return string
229:  */
230:     protected function _prepareRcptCmd($email) {
231:         return 'RCPT TO:<' . $email . '>';
232:     }
233: 
234: /**
235:  * Prepares the `from` email address.
236:  *
237:  * @return array
238:  */
239:     protected function _prepareFromAddress() {
240:         $from = $this->_cakeEmail->returnPath();
241:         if (empty($from)) {
242:             $from = $this->_cakeEmail->from();
243:         }
244:         return $from;
245:     }
246: 
247: /**
248:  * Prepares the recipient email addresses.
249:  *
250:  * @return array
251:  */
252:     protected function _prepareRecipientAddresses() {
253:         $to = $this->_cakeEmail->to();
254:         $cc = $this->_cakeEmail->cc();
255:         $bcc = $this->_cakeEmail->bcc();
256:         return array_merge(array_keys($to), array_keys($cc), array_keys($bcc));
257:     }
258: 
259: /**
260:  * Prepares the message headers.
261:  *
262:  * @return array
263:  */
264:     protected function _prepareMessageHeaders() {
265:         return $this->_cakeEmail->getHeaders(array('from', 'sender', 'replyTo', 'readReceipt', 'to', 'cc', 'subject'));
266:     }
267: 
268: /**
269:  * Prepares the message body.
270:  *
271:  * @return string
272:  */
273:     protected function _prepareMessage() {
274:         $lines = $this->_cakeEmail->message();
275:         $messages = array();
276:         foreach ($lines as $line) {
277:             if ((!empty($line)) && ($line[0] === '.')) {
278:                 $messages[] = '.' . $line;
279:             } else {
280:                 $messages[] = $line;
281:             }
282:         }
283:         return implode("\r\n", $messages);
284:     }
285: 
286: /**
287:  * Send emails
288:  *
289:  * @return void
290:  * @throws SocketException
291:  */
292:     protected function _sendRcpt() {
293:         $from = $this->_prepareFromAddress();
294:         $this->_smtpSend($this->_prepareFromCmd(key($from)));
295: 
296:         $emails = $this->_prepareRecipientAddresses();
297:         foreach ($emails as $email) {
298:             $this->_smtpSend($this->_prepareRcptCmd($email));
299:         }
300:     }
301: 
302: /**
303:  * Send Data
304:  *
305:  * @return void
306:  * @throws SocketException
307:  */
308:     protected function _sendData() {
309:         $this->_smtpSend('DATA', '354');
310: 
311:         $headers = $this->_headersToString($this->_prepareMessageHeaders());
312:         $message = $this->_prepareMessage();
313: 
314:         $this->_smtpSend($headers . "\r\n\r\n" . $message . "\r\n\r\n\r\n.");
315:         $this->_content = array('headers' => $headers, 'message' => $message);
316:     }
317: 
318: /**
319:  * Disconnect
320:  *
321:  * @return void
322:  * @throws SocketException
323:  */
324:     protected function _disconnect() {
325:         $this->_smtpSend('QUIT', false);
326:         $this->_socket->disconnect();
327:     }
328: 
329: /**
330:  * Helper method to generate socket
331:  *
332:  * @return void
333:  * @throws SocketException
334:  */
335:     protected function _generateSocket() {
336:         $this->_socket = new CakeSocket($this->_config);
337:     }
338: 
339: /**
340:  * Protected method for sending data to SMTP connection
341:  *
342:  * @param string $data data to be sent to SMTP server
343:  * @param string|bool $checkCode code to check for in server response, false to skip
344:  * @return void
345:  * @throws SocketException
346:  */
347:     protected function _smtpSend($data, $checkCode = '250') {
348:         $this->_lastResponse = array();
349: 
350:         if ($data !== null) {
351:             $this->_socket->write($data . "\r\n");
352:         }
353:         while ($checkCode !== false) {
354:             $response = '';
355:             $startTime = time();
356:             while (substr($response, -2) !== "\r\n" && ((time() - $startTime) < $this->_config['timeout'])) {
357:                 $response .= $this->_socket->read();
358:             }
359:             if (substr($response, -2) !== "\r\n") {
360:                 throw new SocketException(__d('cake_dev', 'SMTP timeout.'));
361:             }
362:             $responseLines = explode("\r\n", rtrim($response, "\r\n"));
363:             $response = end($responseLines);
364: 
365:             $this->_bufferResponseLines($responseLines);
366: 
367:             if (preg_match('/^(' . $checkCode . ')(.)/', $response, $code)) {
368:                 if ($code[2] === '-') {
369:                     continue;
370:                 }
371:                 return $code[1];
372:             }
373:             throw new SocketException(__d('cake_dev', 'SMTP Error: %s', $response));
374:         }
375:     }
376: 
377: }
378: 
OpenHub
Rackspace
Rackspace
  • Business Solutions
  • Showcase
  • Documentation
  • Book
  • API
  • Videos
  • Reporting Security Issues
  • Privacy Policy
  • Logos & Trademarks
  • Community
  • Get Involved
  • Issues (GitHub)
  • Bakery
  • Featured Resources
  • Training
  • Meetups
  • My CakePHP
  • CakeFest
  • Newsletter
  • Linkedin
  • YouTube
  • Facebook
  • Twitter
  • Mastodon
  • Help & Support
  • Forum
  • Stack Overflow
  • Slack
  • Paid Support

Generated using CakePHP API Docs