1ee5c0205SAndreas Gohr<?php 2ee5c0205SAndreas Gohr/***************************************************\ 3ee5c0205SAndreas Gohr * 4ee5c0205SAndreas Gohr * Mailer (https://github.com/txthinking/Mailer) 5ee5c0205SAndreas Gohr * 6ee5c0205SAndreas Gohr * A lightweight PHP SMTP mail sender. 7ee5c0205SAndreas Gohr * Implement RFC0821, RFC0822, RFC1869, RFC2045, RFC2821 8ee5c0205SAndreas Gohr * 9ee5c0205SAndreas Gohr * Support html body, don't worry that the receiver's 10ee5c0205SAndreas Gohr * mail client can't support html, because Mailer will 11ee5c0205SAndreas Gohr * send both text/plain and text/html body, so if the 12ee5c0205SAndreas Gohr * mail client can't support html, it will display the 13ee5c0205SAndreas Gohr * text/plain body. 14ee5c0205SAndreas Gohr * 15ee5c0205SAndreas Gohr * Create Date 2012-07-25. 16ee5c0205SAndreas Gohr * Under the MIT license. 17ee5c0205SAndreas Gohr * 18ee5c0205SAndreas Gohr \***************************************************/ 19ee5c0205SAndreas Gohr 20ee5c0205SAndreas Gohrnamespace Tx\Mailer; 21ee5c0205SAndreas Gohr 22ee5c0205SAndreas Gohruse Psr\Log\LoggerInterface; 23ee5c0205SAndreas Gohruse Tx\Mailer\Exceptions\CodeException; 24ee5c0205SAndreas Gohruse Tx\Mailer\Exceptions\CryptoException; 25ee5c0205SAndreas Gohruse Tx\Mailer\Exceptions\SMTPException; 26ee5c0205SAndreas Gohr 27ee5c0205SAndreas Gohrclass SMTP 28ee5c0205SAndreas Gohr{ 29ee5c0205SAndreas Gohr /** 30ee5c0205SAndreas Gohr * smtp socket 31ee5c0205SAndreas Gohr */ 32ee5c0205SAndreas Gohr protected $smtp; 33ee5c0205SAndreas Gohr 34ee5c0205SAndreas Gohr /** 35ee5c0205SAndreas Gohr * smtp server 36ee5c0205SAndreas Gohr */ 37ee5c0205SAndreas Gohr protected $host; 38ee5c0205SAndreas Gohr 39ee5c0205SAndreas Gohr /** 40ee5c0205SAndreas Gohr * smtp server port 41ee5c0205SAndreas Gohr */ 42ee5c0205SAndreas Gohr protected $port; 43ee5c0205SAndreas Gohr 44ee5c0205SAndreas Gohr /** 45ee5c0205SAndreas Gohr * smtp secure ssl tls tlsv1.0 tlsv1.1 tlsv1.2 46ee5c0205SAndreas Gohr */ 47ee5c0205SAndreas Gohr protected $secure; 48ee5c0205SAndreas Gohr 49ee5c0205SAndreas Gohr /** 50*28d0809aSAndreas Gohr * smtp allow insecure ssl 51*28d0809aSAndreas Gohr */ 52*28d0809aSAndreas Gohr protected $allowInsecure; 53*28d0809aSAndreas Gohr 54*28d0809aSAndreas Gohr /** 55ee5c0205SAndreas Gohr * EHLO message 56ee5c0205SAndreas Gohr */ 57ee5c0205SAndreas Gohr protected $ehlo; 58ee5c0205SAndreas Gohr 59ee5c0205SAndreas Gohr /** 60ee5c0205SAndreas Gohr * smtp username 61ee5c0205SAndreas Gohr */ 62ee5c0205SAndreas Gohr protected $username; 63ee5c0205SAndreas Gohr 64ee5c0205SAndreas Gohr /** 65ee5c0205SAndreas Gohr * smtp password 66ee5c0205SAndreas Gohr */ 67ee5c0205SAndreas Gohr protected $password; 68ee5c0205SAndreas Gohr 69ee5c0205SAndreas Gohr /** 70ee5c0205SAndreas Gohr * oauth access token 71ee5c0205SAndreas Gohr */ 72ee5c0205SAndreas Gohr protected $oauthToken; 73ee5c0205SAndreas Gohr 74ee5c0205SAndreas Gohr /** 75ee5c0205SAndreas Gohr * $this->CRLF 76ee5c0205SAndreas Gohr * @var string 77ee5c0205SAndreas Gohr */ 78ee5c0205SAndreas Gohr protected $CRLF = "\r\n"; 79ee5c0205SAndreas Gohr 80ee5c0205SAndreas Gohr /** 81ee5c0205SAndreas Gohr * @var Message 82ee5c0205SAndreas Gohr */ 83ee5c0205SAndreas Gohr protected $message; 84ee5c0205SAndreas Gohr 85ee5c0205SAndreas Gohr /** 86ee5c0205SAndreas Gohr * @var LoggerInterface - Used to make things prettier than self::$logger 87ee5c0205SAndreas Gohr */ 88ee5c0205SAndreas Gohr protected $logger; 89ee5c0205SAndreas Gohr 90ee5c0205SAndreas Gohr /** 91ee5c0205SAndreas Gohr * Stack of all commands issued to SMTP 92ee5c0205SAndreas Gohr * @var array 93ee5c0205SAndreas Gohr */ 94ee5c0205SAndreas Gohr protected $commandStack = array(); 95ee5c0205SAndreas Gohr 96ee5c0205SAndreas Gohr /** 97ee5c0205SAndreas Gohr * Stack of all results issued to SMTP 98ee5c0205SAndreas Gohr * @var array 99ee5c0205SAndreas Gohr */ 100ee5c0205SAndreas Gohr protected $resultStack = array(); 101ee5c0205SAndreas Gohr 102ee5c0205SAndreas Gohr public function __construct(LoggerInterface $logger=null) 103ee5c0205SAndreas Gohr { 104ee5c0205SAndreas Gohr $this->logger = $logger; 105ee5c0205SAndreas Gohr } 106ee5c0205SAndreas Gohr 107ee5c0205SAndreas Gohr /** 108ee5c0205SAndreas Gohr * set server and port 109ee5c0205SAndreas Gohr * @param string $host server 110ee5c0205SAndreas Gohr * @param int $port port 111*28d0809aSAndreas Gohr * @param string $secure ssl tls 112*28d0809aSAndreas Gohr * @param bool $allowInsecure skip certificate verification? 113ee5c0205SAndreas Gohr * @return $this 114ee5c0205SAndreas Gohr */ 115*28d0809aSAndreas Gohr public function setServer($host, $port, $secure=null, $allowInsecure=null) 116ee5c0205SAndreas Gohr { 117ee5c0205SAndreas Gohr $this->host = $host; 118ee5c0205SAndreas Gohr $this->port = $port; 119ee5c0205SAndreas Gohr $this->secure = $secure; 120*28d0809aSAndreas Gohr $this->allowInsecure = (bool) $allowInsecure; 121ee5c0205SAndreas Gohr if(!$this->ehlo) $this->ehlo = $host; 122ee5c0205SAndreas Gohr $this->logger && $this->logger->debug("Set: the server"); 123ee5c0205SAndreas Gohr return $this; 124ee5c0205SAndreas Gohr } 125ee5c0205SAndreas Gohr 126ee5c0205SAndreas Gohr /** 127ee5c0205SAndreas Gohr * auth login with server 128ee5c0205SAndreas Gohr * @param string $username 129ee5c0205SAndreas Gohr * @param string $password 130ee5c0205SAndreas Gohr * @return $this 131ee5c0205SAndreas Gohr */ 132ee5c0205SAndreas Gohr public function setAuth($username, $password) 133ee5c0205SAndreas Gohr { 134ee5c0205SAndreas Gohr $this->username = $username; 135ee5c0205SAndreas Gohr $this->password = $password; 136ee5c0205SAndreas Gohr $this->logger && $this->logger->debug("Set: the auth login"); 137ee5c0205SAndreas Gohr return $this; 138ee5c0205SAndreas Gohr } 139ee5c0205SAndreas Gohr 140ee5c0205SAndreas Gohr /** 141ee5c0205SAndreas Gohr * auth oauthbearer with server 142ee5c0205SAndreas Gohr * @param string $accessToken 143ee5c0205SAndreas Gohr * @return $this 144ee5c0205SAndreas Gohr */ 145ee5c0205SAndreas Gohr public function setOAuth($accessToken) 146ee5c0205SAndreas Gohr { 147ee5c0205SAndreas Gohr $this->oauthToken = $accessToken; 148ee5c0205SAndreas Gohr $this->logger && $this->logger->debug("Set: the auth oauthbearer"); 149ee5c0205SAndreas Gohr return $this; 150ee5c0205SAndreas Gohr } 151ee5c0205SAndreas Gohr 152ee5c0205SAndreas Gohr /** 153ee5c0205SAndreas Gohr * set the EHLO message 154ee5c0205SAndreas Gohr * @param $ehlo 155ee5c0205SAndreas Gohr * @return $this 156ee5c0205SAndreas Gohr */ 157ee5c0205SAndreas Gohr public function setEhlo($ehlo) 158ee5c0205SAndreas Gohr { 159ee5c0205SAndreas Gohr $this->ehlo = $ehlo; 160ee5c0205SAndreas Gohr return $this; 161ee5c0205SAndreas Gohr } 162ee5c0205SAndreas Gohr 163ee5c0205SAndreas Gohr /** 164ee5c0205SAndreas Gohr * Send the message 165ee5c0205SAndreas Gohr * 166ee5c0205SAndreas Gohr * @param Message $message 167ee5c0205SAndreas Gohr * @return bool 168ee5c0205SAndreas Gohr * @throws CodeException 169ee5c0205SAndreas Gohr * @throws CryptoException 170ee5c0205SAndreas Gohr * @throws SMTPException 171ee5c0205SAndreas Gohr */ 172ee5c0205SAndreas Gohr public function send(Message $message) 173ee5c0205SAndreas Gohr { 174ee5c0205SAndreas Gohr $this->logger && $this->logger->debug('Set: a message will be sent'); 175ee5c0205SAndreas Gohr $this->message = $message; 176ee5c0205SAndreas Gohr $this->connect() 177ee5c0205SAndreas Gohr ->ehlo(); 178ee5c0205SAndreas Gohr 179ee5c0205SAndreas Gohr if ($this->secure === 'tls' || $this->secure === 'tlsv1.0' || $this->secure === 'tlsv1.1' | $this->secure === 'tlsv1.2') { 180ee5c0205SAndreas Gohr $this->starttls() 181ee5c0205SAndreas Gohr ->ehlo(); 182ee5c0205SAndreas Gohr } 183ee5c0205SAndreas Gohr 184ee5c0205SAndreas Gohr if ($this->username !== null || $this->password !== null) { 185ee5c0205SAndreas Gohr $this->authLogin(); 186ee5c0205SAndreas Gohr } elseif ($this->oauthToken !== null) { 187ee5c0205SAndreas Gohr $this->authOAuthBearer(); 188ee5c0205SAndreas Gohr } 189ee5c0205SAndreas Gohr $this->mailFrom() 190ee5c0205SAndreas Gohr ->rcptTo() 191ee5c0205SAndreas Gohr ->data() 192ee5c0205SAndreas Gohr ->quit(); 193ee5c0205SAndreas Gohr return fclose($this->smtp); 194ee5c0205SAndreas Gohr } 195ee5c0205SAndreas Gohr 196ee5c0205SAndreas Gohr /** 197ee5c0205SAndreas Gohr * connect the server 198ee5c0205SAndreas Gohr * SUCCESS 220 199ee5c0205SAndreas Gohr * @return $this 200ee5c0205SAndreas Gohr * @throws CodeException 201ee5c0205SAndreas Gohr * @throws SMTPException 202ee5c0205SAndreas Gohr */ 203ee5c0205SAndreas Gohr protected function connect() 204ee5c0205SAndreas Gohr { 205ee5c0205SAndreas Gohr $this->logger && $this->logger->debug("Connecting to {$this->host} at {$this->port}"); 206ee5c0205SAndreas Gohr $host = ($this->secure == 'ssl') ? 'ssl://' . $this->host : $this->host; 207*28d0809aSAndreas Gohr // Create connection 208*28d0809aSAndreas Gohr $context = stream_context_create([]); 209*28d0809aSAndreas Gohr if ($this->allowInsecure) { 210*28d0809aSAndreas Gohr $context = stream_context_create([ 211*28d0809aSAndreas Gohr 'ssl' => [ 212*28d0809aSAndreas Gohr 'security_level' => 0, 213*28d0809aSAndreas Gohr 'verify_peer' => false, 214*28d0809aSAndreas Gohr 'verify_peer_name' => false 215*28d0809aSAndreas Gohr ] 216*28d0809aSAndreas Gohr ]); 217*28d0809aSAndreas Gohr } 218*28d0809aSAndreas Gohr $this->smtp = @stream_socket_client( 219*28d0809aSAndreas Gohr $host.':'.$this->port, 220*28d0809aSAndreas Gohr $error_code, 221*28d0809aSAndreas Gohr $error_message, 222*28d0809aSAndreas Gohr ini_get('default_socket_timeout'), 223*28d0809aSAndreas Gohr STREAM_CLIENT_CONNECT, 224*28d0809aSAndreas Gohr $context 225*28d0809aSAndreas Gohr ); 226ee5c0205SAndreas Gohr if (!$this->smtp){ 227*28d0809aSAndreas Gohr throw new SMTPException("Could not open SMTP Port to $host:{$this->port}"); 228ee5c0205SAndreas Gohr } 229ee5c0205SAndreas Gohr $code = $this->getCode(); 230ee5c0205SAndreas Gohr if ($code !== '220'){ 231ee5c0205SAndreas Gohr throw new CodeException('220', $code, array_pop($this->resultStack)); 232ee5c0205SAndreas Gohr } 233ee5c0205SAndreas Gohr return $this; 234ee5c0205SAndreas Gohr } 235ee5c0205SAndreas Gohr 236ee5c0205SAndreas Gohr /** 237ee5c0205SAndreas Gohr * SMTP STARTTLS 238ee5c0205SAndreas Gohr * SUCCESS 220 239ee5c0205SAndreas Gohr * @return $this 240ee5c0205SAndreas Gohr * @throws CodeException 241ee5c0205SAndreas Gohr * @throws CryptoException 242ee5c0205SAndreas Gohr * @throws SMTPException 243ee5c0205SAndreas Gohr */ 244ee5c0205SAndreas Gohr protected function starttls() 245ee5c0205SAndreas Gohr { 246ee5c0205SAndreas Gohr $in = "STARTTLS" . $this->CRLF; 247ee5c0205SAndreas Gohr $code = $this->pushStack($in); 248ee5c0205SAndreas Gohr if ($code !== '220'){ 249ee5c0205SAndreas Gohr throw new CodeException('220', $code, array_pop($this->resultStack)); 250ee5c0205SAndreas Gohr } 251ee5c0205SAndreas Gohr 252ee5c0205SAndreas Gohr if ($this->secure !== 'tls' && version_compare(phpversion(), '5.6.0', '<')) { 253ee5c0205SAndreas Gohr throw new CryptoException('Crypto type expected PHP 5.6 or greater'); 254ee5c0205SAndreas Gohr } 255ee5c0205SAndreas Gohr 256*28d0809aSAndreas Gohr if ($this->allowInsecure) { 257*28d0809aSAndreas Gohr stream_context_set_option($this->smtp, 'ssl', 'verify_peer', false); 258*28d0809aSAndreas Gohr stream_context_set_option($this->smtp, 'ssl', 'verify_peer_name', false); 259*28d0809aSAndreas Gohr stream_context_set_option($this->smtp, 'ssl', 'allow_self_signed', true); 260ee5c0205SAndreas Gohr } 261ee5c0205SAndreas Gohr 262*28d0809aSAndreas Gohr if(!\stream_socket_enable_crypto($this->smtp, true, STREAM_CRYPTO_METHOD_ANY_CLIENT)) { 263ee5c0205SAndreas Gohr throw new CryptoException("Start TLS failed to enable crypto"); 264ee5c0205SAndreas Gohr } 265ee5c0205SAndreas Gohr return $this; 266ee5c0205SAndreas Gohr } 267ee5c0205SAndreas Gohr 268ee5c0205SAndreas Gohr /** 269ee5c0205SAndreas Gohr * SMTP EHLO 270ee5c0205SAndreas Gohr * SUCCESS 250 271ee5c0205SAndreas Gohr * @return $this 272ee5c0205SAndreas Gohr * @throws CodeException 273ee5c0205SAndreas Gohr * @throws SMTPException 274ee5c0205SAndreas Gohr */ 275ee5c0205SAndreas Gohr protected function ehlo() 276ee5c0205SAndreas Gohr { 277ee5c0205SAndreas Gohr $in = "EHLO " . $this->ehlo . $this->CRLF; 278ee5c0205SAndreas Gohr $code = $this->pushStack($in); 279ee5c0205SAndreas Gohr if ($code !== '250'){ 280ee5c0205SAndreas Gohr throw new CodeException('250', $code, array_pop($this->resultStack)); 281ee5c0205SAndreas Gohr } 282ee5c0205SAndreas Gohr return $this; 283ee5c0205SAndreas Gohr } 284ee5c0205SAndreas Gohr 285ee5c0205SAndreas Gohr /** 286ee5c0205SAndreas Gohr * SMTP AUTH LOGIN 287ee5c0205SAndreas Gohr * SUCCESS 334 288ee5c0205SAndreas Gohr * SUCCESS 334 289ee5c0205SAndreas Gohr * SUCCESS 235 290ee5c0205SAndreas Gohr * @return $this 291ee5c0205SAndreas Gohr * @throws CodeException 292ee5c0205SAndreas Gohr * @throws SMTPException 293ee5c0205SAndreas Gohr */ 294ee5c0205SAndreas Gohr protected function authLogin() 295ee5c0205SAndreas Gohr { 296ee5c0205SAndreas Gohr $in = "AUTH LOGIN" . $this->CRLF; 297ee5c0205SAndreas Gohr $code = $this->pushStack($in); 298ee5c0205SAndreas Gohr if ($code !== '334'){ 299ee5c0205SAndreas Gohr throw new CodeException('334', $code, array_pop($this->resultStack)); 300ee5c0205SAndreas Gohr } 301ee5c0205SAndreas Gohr $in = base64_encode($this->username) . $this->CRLF; 302ee5c0205SAndreas Gohr $code = $this->pushStack($in); 303ee5c0205SAndreas Gohr if ($code !== '334'){ 304ee5c0205SAndreas Gohr throw new CodeException('334', $code, array_pop($this->resultStack)); 305ee5c0205SAndreas Gohr } 306ee5c0205SAndreas Gohr $in = base64_encode($this->password) . $this->CRLF; 307ee5c0205SAndreas Gohr $code = $this->pushStack($in); 308ee5c0205SAndreas Gohr if ($code !== '235'){ 309ee5c0205SAndreas Gohr throw new CodeException('235', $code, array_pop($this->resultStack)); 310ee5c0205SAndreas Gohr } 311ee5c0205SAndreas Gohr return $this; 312ee5c0205SAndreas Gohr } 313ee5c0205SAndreas Gohr 314ee5c0205SAndreas Gohr /** 315ee5c0205SAndreas Gohr * SMTP AUTH OAUTHBEARER 316ee5c0205SAndreas Gohr * SUCCESS 235 317ee5c0205SAndreas Gohr * @return $this 318ee5c0205SAndreas Gohr * @throws CodeException 319ee5c0205SAndreas Gohr * @throws SMTPException 320ee5c0205SAndreas Gohr */ 321ee5c0205SAndreas Gohr protected function authOAuthBearer() 322ee5c0205SAndreas Gohr { 323ee5c0205SAndreas Gohr $authStr = sprintf("n,a=%s,%shost=%s%sport=%s%sauth=Bearer %s%s%s", 324ee5c0205SAndreas Gohr $this->message->getFromEmail(), 325ee5c0205SAndreas Gohr chr(1), 326ee5c0205SAndreas Gohr $this->host, 327ee5c0205SAndreas Gohr chr(1), 328ee5c0205SAndreas Gohr $this->port, 329ee5c0205SAndreas Gohr chr(1), 330ee5c0205SAndreas Gohr $this->oauthToken, 331ee5c0205SAndreas Gohr chr(1), 332ee5c0205SAndreas Gohr chr(1) 333ee5c0205SAndreas Gohr ); 334ee5c0205SAndreas Gohr $authStr = base64_encode($authStr); 335ee5c0205SAndreas Gohr $in = "AUTH OAUTHBEARER $authStr" . $this->CRLF; 336ee5c0205SAndreas Gohr $code = $this->pushStack($in); 337ee5c0205SAndreas Gohr if ($code !== '235'){ 338ee5c0205SAndreas Gohr throw new CodeException('235', $code, array_pop($this->resultStack)); 339ee5c0205SAndreas Gohr } 340ee5c0205SAndreas Gohr return $this; 341ee5c0205SAndreas Gohr } 342ee5c0205SAndreas Gohr 343ee5c0205SAndreas Gohr /** 344ee5c0205SAndreas Gohr * SMTP AUTH XOAUTH2 345ee5c0205SAndreas Gohr * SUCCESS 235 346ee5c0205SAndreas Gohr * @return $this 347ee5c0205SAndreas Gohr * @throws CodeException 348ee5c0205SAndreas Gohr * @throws SMTPException 349ee5c0205SAndreas Gohr */ 350ee5c0205SAndreas Gohr protected function authXOAuth2() 351ee5c0205SAndreas Gohr { 352ee5c0205SAndreas Gohr $authStr = sprintf("user=%s%sauth=Bearer %s%s%s", 353ee5c0205SAndreas Gohr $this->message->getFromEmail(), 354ee5c0205SAndreas Gohr chr(1), 355ee5c0205SAndreas Gohr $this->oauthToken, 356ee5c0205SAndreas Gohr chr(1), 357ee5c0205SAndreas Gohr chr(1) 358ee5c0205SAndreas Gohr ); 359ee5c0205SAndreas Gohr $authStr = base64_encode($authStr); 360ee5c0205SAndreas Gohr $in = "AUTH XOAUTH2 $authStr" . $this->CRLF; 361ee5c0205SAndreas Gohr $code = $this->pushStack($in); 362ee5c0205SAndreas Gohr if ($code !== '235'){ 363ee5c0205SAndreas Gohr throw new CodeException('235', $code, array_pop($this->resultStack)); 364ee5c0205SAndreas Gohr } 365ee5c0205SAndreas Gohr return $this; 366ee5c0205SAndreas Gohr } 367ee5c0205SAndreas Gohr 368ee5c0205SAndreas Gohr /** 369ee5c0205SAndreas Gohr * SMTP MAIL FROM 370ee5c0205SAndreas Gohr * SUCCESS 250 371ee5c0205SAndreas Gohr * @return $this 372ee5c0205SAndreas Gohr * @throws CodeException 373ee5c0205SAndreas Gohr * @throws SMTPException 374ee5c0205SAndreas Gohr */ 375ee5c0205SAndreas Gohr protected function mailFrom() 376ee5c0205SAndreas Gohr { 377ee5c0205SAndreas Gohr $in = "MAIL FROM:<{$this->message->getFromEmail()}>" . $this->CRLF; 378ee5c0205SAndreas Gohr $code = $this->pushStack($in); 379ee5c0205SAndreas Gohr if ($code !== '250') { 380ee5c0205SAndreas Gohr throw new CodeException('250', $code, array_pop($this->resultStack)); 381ee5c0205SAndreas Gohr } 382ee5c0205SAndreas Gohr return $this; 383ee5c0205SAndreas Gohr } 384ee5c0205SAndreas Gohr 385ee5c0205SAndreas Gohr /** 386ee5c0205SAndreas Gohr * SMTP RCPT TO 387ee5c0205SAndreas Gohr * SUCCESS 250 388ee5c0205SAndreas Gohr * @return $this 389ee5c0205SAndreas Gohr * @throws CodeException 390ee5c0205SAndreas Gohr * @throws SMTPException 391ee5c0205SAndreas Gohr */ 392ee5c0205SAndreas Gohr protected function rcptTo() 393ee5c0205SAndreas Gohr { 394ee5c0205SAndreas Gohr $to = array_merge( 395ee5c0205SAndreas Gohr $this->message->getTo(), 396ee5c0205SAndreas Gohr $this->message->getCc(), 397ee5c0205SAndreas Gohr $this->message->getBcc() 398ee5c0205SAndreas Gohr ); 399ee5c0205SAndreas Gohr foreach ($to as $toEmail=>$_) { 400ee5c0205SAndreas Gohr $in = "RCPT TO:<" . $toEmail . ">" . $this->CRLF; 401ee5c0205SAndreas Gohr $code = $this->pushStack($in); 402ee5c0205SAndreas Gohr if ($code !== '250') { 403ee5c0205SAndreas Gohr throw new CodeException('250', $code, array_pop($this->resultStack)); 404ee5c0205SAndreas Gohr } 405ee5c0205SAndreas Gohr } 406ee5c0205SAndreas Gohr return $this; 407ee5c0205SAndreas Gohr } 408ee5c0205SAndreas Gohr 409ee5c0205SAndreas Gohr /** 410ee5c0205SAndreas Gohr * SMTP DATA 411ee5c0205SAndreas Gohr * SUCCESS 354 412ee5c0205SAndreas Gohr * SUCCESS 250 413ee5c0205SAndreas Gohr * @return $this 414ee5c0205SAndreas Gohr * @throws CodeException 415ee5c0205SAndreas Gohr * @throws SMTPException 416ee5c0205SAndreas Gohr */ 417ee5c0205SAndreas Gohr protected function data() 418ee5c0205SAndreas Gohr { 419ee5c0205SAndreas Gohr $in = "DATA" . $this->CRLF; 420ee5c0205SAndreas Gohr $code = $this->pushStack($in); 421ee5c0205SAndreas Gohr if ($code !== '354') { 422ee5c0205SAndreas Gohr throw new CodeException('354', $code, array_pop($this->resultStack)); 423ee5c0205SAndreas Gohr } 424ee5c0205SAndreas Gohr $in = $this->message->toString(); 425ee5c0205SAndreas Gohr $code = $this->pushStack($in); 426ee5c0205SAndreas Gohr if ($code !== '250'){ 427ee5c0205SAndreas Gohr throw new CodeException('250', $code, array_pop($this->resultStack)); 428ee5c0205SAndreas Gohr } 429ee5c0205SAndreas Gohr return $this; 430ee5c0205SAndreas Gohr } 431ee5c0205SAndreas Gohr 432ee5c0205SAndreas Gohr /** 433ee5c0205SAndreas Gohr * SMTP QUIT 434ee5c0205SAndreas Gohr * SUCCESS 221 435ee5c0205SAndreas Gohr * @return $this 436ee5c0205SAndreas Gohr * @throws CodeException 437ee5c0205SAndreas Gohr * @throws SMTPException 438ee5c0205SAndreas Gohr */ 439ee5c0205SAndreas Gohr protected function quit() 440ee5c0205SAndreas Gohr { 441ee5c0205SAndreas Gohr $in = "QUIT" . $this->CRLF; 442ee5c0205SAndreas Gohr $code = $this->pushStack($in); 443ee5c0205SAndreas Gohr if ($code !== '221'){ 444ee5c0205SAndreas Gohr throw new CodeException('221', $code, array_pop($this->resultStack)); 445ee5c0205SAndreas Gohr } 446ee5c0205SAndreas Gohr return $this; 447ee5c0205SAndreas Gohr } 448ee5c0205SAndreas Gohr 449ee5c0205SAndreas Gohr protected function pushStack($string) 450ee5c0205SAndreas Gohr { 451ee5c0205SAndreas Gohr $this->commandStack[] = $string; 452ee5c0205SAndreas Gohr fputs($this->smtp, $string, strlen($string)); 453ee5c0205SAndreas Gohr $this->logger && $this->logger->debug('Sent: '. $string); 454ee5c0205SAndreas Gohr return $this->getCode(); 455ee5c0205SAndreas Gohr } 456ee5c0205SAndreas Gohr 457ee5c0205SAndreas Gohr /** 458ee5c0205SAndreas Gohr * get smtp response code 459ee5c0205SAndreas Gohr * once time has three digital and a space 460ee5c0205SAndreas Gohr * @return string 461ee5c0205SAndreas Gohr * @throws SMTPException 462ee5c0205SAndreas Gohr */ 463ee5c0205SAndreas Gohr protected function getCode() 464ee5c0205SAndreas Gohr { 465ee5c0205SAndreas Gohr while ($str = fgets($this->smtp, 515)) { 466ee5c0205SAndreas Gohr $this->logger && $this->logger->debug("Got: ". $str); 467ee5c0205SAndreas Gohr $this->resultStack[] = $str; 468ee5c0205SAndreas Gohr if(substr($str,3,1) == " ") { 469ee5c0205SAndreas Gohr $code = substr($str,0,3); 470ee5c0205SAndreas Gohr return $code; 471ee5c0205SAndreas Gohr } 472ee5c0205SAndreas Gohr } 473ee5c0205SAndreas Gohr throw new SMTPException("SMTP Server did not respond with anything I recognized"); 474ee5c0205SAndreas Gohr } 475ee5c0205SAndreas Gohr 476ee5c0205SAndreas Gohr} 477ee5c0205SAndreas Gohr 478