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.7 API

  • Overview
  • Tree
  • Deprecated
  • Version:
    • 2.7
      • 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:             'ssl_allow_self_signed' => false
123:         );
124:         $this->_config = array_merge($default, $this->_config, $config);
125:         return $this->_config;
126:     }
127: 
128: /**
129:  * Parses and stores the reponse lines in `'code' => 'message'` format.
130:  *
131:  * @param array $responseLines Response lines to parse.
132:  * @return void
133:  */
134:     protected function _bufferResponseLines(array $responseLines) {
135:         $response = array();
136:         foreach ($responseLines as $responseLine) {
137:             if (preg_match('/^(\d{3})(?:[ -]+(.*))?$/', $responseLine, $match)) {
138:                 $response[] = array(
139:                     'code' => $match[1],
140:                     'message' => isset($match[2]) ? $match[2] : null
141:                 );
142:             }
143:         }
144:         $this->_lastResponse = array_merge($this->_lastResponse, $response);
145:     }
146: 
147: /**
148:  * Connect to SMTP Server
149:  *
150:  * @return void
151:  * @throws SocketException
152:  */
153:     protected function _connect() {
154:         $this->_generateSocket();
155:         if (!$this->_socket->connect()) {
156:             throw new SocketException(__d('cake_dev', 'Unable to connect to SMTP server.'));
157:         }
158:         $this->_smtpSend(null, '220');
159: 
160:         if (isset($this->_config['client'])) {
161:             $host = $this->_config['client'];
162:         } elseif ($httpHost = env('HTTP_HOST')) {
163:             list($host) = explode(':', $httpHost);
164:         } else {
165:             $host = 'localhost';
166:         }
167: 
168:         try {
169:             $this->_smtpSend("EHLO {$host}", '250');
170:             if ($this->_config['tls']) {
171:                 $this->_smtpSend("STARTTLS", '220');
172:                 $this->_socket->enableCrypto('tls');
173:                 $this->_smtpSend("EHLO {$host}", '250');
174:             }
175:         } catch (SocketException $e) {
176:             if ($this->_config['tls']) {
177:                 throw new SocketException(__d('cake_dev', 'SMTP server did not accept the connection or trying to connect to non TLS SMTP server using TLS.'));
178:             }
179:             try {
180:                 $this->_smtpSend("HELO {$host}", '250');
181:             } catch (SocketException $e2) {
182:                 throw new SocketException(__d('cake_dev', 'SMTP server did not accept the connection.'));
183:             }
184:         }
185:     }
186: 
187: /**
188:  * Send authentication
189:  *
190:  * @return void
191:  * @throws SocketException
192:  */
193:     protected function _auth() {
194:         if (isset($this->_config['username']) && isset($this->_config['password'])) {
195:             $replyCode = $this->_smtpSend('AUTH LOGIN', '334|500|502|504');
196:             if ($replyCode == '334') {
197:                 try {
198:                     $this->_smtpSend(base64_encode($this->_config['username']), '334');
199:                 } catch (SocketException $e) {
200:                     throw new SocketException(__d('cake_dev', 'SMTP server did not accept the username.'));
201:                 }
202:                 try {
203:                     $this->_smtpSend(base64_encode($this->_config['password']), '235');
204:                 } catch (SocketException $e) {
205:                     throw new SocketException(__d('cake_dev', 'SMTP server did not accept the password.'));
206:                 }
207:             } elseif ($replyCode == '504') {
208:                 throw new SocketException(__d('cake_dev', 'SMTP authentication method not allowed, check if SMTP server requires TLS.'));
209:             } else {
210:                 throw new SocketException(__d('cake_dev', 'AUTH command not recognized or not implemented, SMTP server may not require authentication.'));
211:             }
212:         }
213:     }
214: 
215: /**
216:  * Prepares the `MAIL FROM` SMTP command.
217:  *
218:  * @param string $email The email address to send with the command.
219:  * @return string
220:  */
221:     protected function _prepareFromCmd($email) {
222:         return 'MAIL FROM:<' . $email . '>';
223:     }
224: 
225: /**
226:  * Prepares the `RCPT TO` SMTP command.
227:  *
228:  * @param string $email The email address to send with the command.
229:  * @return string
230:  */
231:     protected function _prepareRcptCmd($email) {
232:         return 'RCPT TO:<' . $email . '>';
233:     }
234: 
235: /**
236:  * Prepares the `from` email address.
237:  *
238:  * @return array
239:  */
240:     protected function _prepareFromAddress() {
241:         $from = $this->_cakeEmail->returnPath();
242:         if (empty($from)) {
243:             $from = $this->_cakeEmail->from();
244:         }
245:         return $from;
246:     }
247: 
248: /**
249:  * Prepares the recipient email addresses.
250:  *
251:  * @return array
252:  */
253:     protected function _prepareRecipientAddresses() {
254:         $to = $this->_cakeEmail->to();
255:         $cc = $this->_cakeEmail->cc();
256:         $bcc = $this->_cakeEmail->bcc();
257:         return array_merge(array_keys($to), array_keys($cc), array_keys($bcc));
258:     }
259: 
260: /**
261:  * Prepares the message headers.
262:  *
263:  * @return array
264:  */
265:     protected function _prepareMessageHeaders() {
266:         return $this->_cakeEmail->getHeaders(array('from', 'sender', 'replyTo', 'readReceipt', 'to', 'cc', 'subject'));
267:     }
268: 
269: /**
270:  * Prepares the message body.
271:  *
272:  * @return string
273:  */
274:     protected function _prepareMessage() {
275:         $lines = $this->_cakeEmail->message();
276:         $messages = array();
277:         foreach ($lines as $line) {
278:             if ((!empty($line)) && ($line[0] === '.')) {
279:                 $messages[] = '.' . $line;
280:             } else {
281:                 $messages[] = $line;
282:             }
283:         }
284:         return implode("\r\n", $messages);
285:     }
286: 
287: /**
288:  * Send emails
289:  *
290:  * @return void
291:  * @throws SocketException
292:  */
293:     protected function _sendRcpt() {
294:         $from = $this->_prepareFromAddress();
295:         $this->_smtpSend($this->_prepareFromCmd(key($from)));
296: 
297:         $emails = $this->_prepareRecipientAddresses();
298:         foreach ($emails as $email) {
299:             $this->_smtpSend($this->_prepareRcptCmd($email));
300:         }
301:     }
302: 
303: /**
304:  * Send Data
305:  *
306:  * @return void
307:  * @throws SocketException
308:  */
309:     protected function _sendData() {
310:         $this->_smtpSend('DATA', '354');
311: 
312:         $headers = $this->_headersToString($this->_prepareMessageHeaders());
313:         $message = $this->_prepareMessage();
314: 
315:         $this->_smtpSend($headers . "\r\n\r\n" . $message . "\r\n\r\n\r\n.");
316:         $this->_content = array('headers' => $headers, 'message' => $message);
317:     }
318: 
319: /**
320:  * Disconnect
321:  *
322:  * @return void
323:  * @throws SocketException
324:  */
325:     protected function _disconnect() {
326:         $this->_smtpSend('QUIT', false);
327:         $this->_socket->disconnect();
328:     }
329: 
330: /**
331:  * Helper method to generate socket
332:  *
333:  * @return void
334:  * @throws SocketException
335:  */
336:     protected function _generateSocket() {
337:         $this->_socket = new CakeSocket($this->_config);
338:     }
339: 
340: /**
341:  * Protected method for sending data to SMTP connection
342:  *
343:  * @param string|null $data Data to be sent to SMTP server
344:  * @param string|bool $checkCode Code to check for in server response, false to skip
345:  * @return string|null The matched code, or null if nothing matched
346:  * @throws SocketException
347:  */
348:     protected function _smtpSend($data, $checkCode = '250') {
349:         $this->_lastResponse = array();
350: 
351:         if ($data !== null) {
352:             $this->_socket->write($data . "\r\n");
353:         }
354:         while ($checkCode !== false) {
355:             $response = '';
356:             $startTime = time();
357:             while (substr($response, -2) !== "\r\n" && ((time() - $startTime) < $this->_config['timeout'])) {
358:                 $response .= $this->_socket->read();
359:             }
360:             if (substr($response, -2) !== "\r\n") {
361:                 throw new SocketException(__d('cake_dev', 'SMTP timeout.'));
362:             }
363:             $responseLines = explode("\r\n", rtrim($response, "\r\n"));
364:             $response = end($responseLines);
365: 
366:             $this->_bufferResponseLines($responseLines);
367: 
368:             if (preg_match('/^(' . $checkCode . ')(.)/', $response, $code)) {
369:                 if ($code[2] === '-') {
370:                     continue;
371:                 }
372:                 return $code[1];
373:             }
374:             throw new SocketException(__d('cake_dev', 'SMTP Error: %s', $response));
375:         }
376:     }
377: 
378: }
379: 
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