Namespaces

  • Nette
    • Application
      • Diagnostics
      • Responses
      • Routers
      • UI
    • Caching
      • Storages
    • ComponentModel
    • Config
      • Adapters
      • Extensions
    • Database
      • Diagnostics
      • Drivers
      • Reflection
      • Table
    • DI
      • Diagnostics
    • Diagnostics
    • Forms
      • Controls
      • Rendering
    • Http
    • Iterators
    • Latte
      • Macros
    • Loaders
    • Localization
    • Mail
    • Reflection
    • Security
      • Diagnostics
    • Templating
    • Utils
      • PhpGenerator
  • NetteModule
  • none

Classes

  • Message
  • MimePart
  • SendmailMailer
  • SmtpMailer

Interfaces

  • IMailer

Exceptions

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