<?php
 class vB_Mail_Transport_Legacy_Smtp extends vB_Mail_Transport_Legacy { protected $clientHost; protected $smtpHost; protected $smtpPort; protected $smtpUser; protected $smtpPass; protected $smtpSocket = null; protected $smtpReturn = 0; protected $smtpReturnMessage = ''; protected $secure = ''; public function __construct() { $vboptions = vB::getDatastore()->getValue('options'); $this->secure = $vboptions['smtp_tls']; if ($vboptions['smtp_tls'] == 1) { $this->secure = 'ssl'; } else if ($vboptions['smtp_tls'] === 0) { $this->secure = 'none'; } if ($vboptions['smtp_sender_host']) { $this->clientHost = $vboptions['smtp_sender_host']; } else { $this->clientHost = vB_String::parseUrl($vboptions['bburl'], PHP_URL_HOST); } $this->smtpHost = $vboptions['smtp_host']; $this->smtpPort = (!empty($vboptions['smtp_port']) ? intval($vboptions['smtp_port']) : 25); $this->smtpUser = $vboptions['smtp_user']; $this->smtpPass = $vboptions['smtp_pass']; $this->delimiter = "\r\n"; } private function logDebug(string $string) : void { $this->debug[] = $string; } private function errorMessage(string $msg) : never { if ($this->isDebug) { $this->logDebug($msg); } throw new Exception($msg); } public function send(array|string $to, string $subject, string $message, bool $isHtml, array $headers, array|string $replyto = '') : bool { if (!$this->prepareMail($to, $subject, $message, $isHtml, $headers, $replyto)) { return false; } if (!$this->toemail) { return false; } $this->smtpSocket = fsockopen(($this->secure == 'ssl' ? 'ssl://' : 'tcp://') . $this->smtpHost, $this->smtpPort, $errno, $errstr, 30); if ($this->smtpSocket) { if (!$this->sendMessage(false, 220)) { $this->errorMessage($this->smtpReturn . ' Unexpected response when connecting to SMTP server: ' . $this->smtpReturnMessage); } if (!$this->sendHello()) { $this->errorMessage($this->smtpReturn . ' Unexpected response from SMTP server during handshake: ' . $this->smtpReturnMessage); } if ($this->secure == 'tls' AND function_exists('stream_socket_enable_crypto')) { if ($this->sendMessage('STARTTLS', 220)) { if (!stream_socket_enable_crypto($this->smtpSocket, true, STREAM_CRYPTO_METHOD_TLS_CLIENT)) { $this->errorMessage('Unable to negotitate TLS handshake.'); } } $this->sendHello(); } if ($this->smtpUser AND $this->smtpPass) { if ($this->sendMessage('AUTH LOGIN', 334)) { if (!$this->sendMessage(base64_encode($this->smtpUser), 334) OR !$this->sendMessage(base64_encode($this->smtpPass), 235)) { $this->errorMessage($this->smtpReturn . ' Authorization to the SMTP server failed: ' . $this->smtpReturnMessage); } } } if (!$this->sendMessage('MAIL FROM:<' . $this->fromemail . '>', 250)) { $this->errorMessage($this->smtpReturn . ' Unexpected response from SMTP server during FROM address transmission: ' . $this->smtpReturnMessage); } $addresses = explode(',', $this->toemail); foreach ($addresses AS $address) { if (!$this->sendMessage('RCPT TO:<' . trim($address) . '>', 250)) { $this->errorMessage($this->smtpReturn . ' Unexpected response from SMTP server during TO address transmission: ' . $this->smtpReturnMessage); } } if ($this->sendMessage('DATA', 354)) { $this->sendMessage('Date: ' . gmdate('r'), false); $this->sendMessage('To: ' . $this->toemail, false); $this->sendMessage(trim($this->headers), false); $this->sendMessage('Subject: ' . $this->subject, false); $this->sendMessage("\r\n", false); $this->message = preg_replace('#^\.' . $this->delimiter . '#m', '..' . $this->delimiter, $this->message); $this->sendMessage($this->message, false); } else { $this->errorMessage($this->smtpReturn . ' Unexpected response from SMTP server during data transmission: ' . $this->smtpReturnMessage); } if (!$this->sendMessage('.', 250)) { $this->errorMessage($this->smtpReturn . ' Unexpected response from SMTP server when ending transmission: ' . $this->smtpReturnMessage); } $this->sendMessage('QUIT', 221); fclose($this->smtpSocket); return true; } else { $this->errorMessage('Unable to connect to SMTP server'); } } private function sendMessage($msg, $expectedResult = false) { $this->smtpReturnMessage = ''; if ($msg !== false AND !empty($msg)) { fputs($this->smtpSocket, $msg . "\r\n"); } if ($expectedResult !== false) { $result = ''; while ($line = @fgets($this->smtpSocket, 1024)) { $result .= "\n" . $line; if (preg_match('#^(\d{3}) #', $line, $matches)) { break; } } $this->smtpReturn = intval($matches[1]); $this->smtpReturnMessage = $result; return ($this->smtpReturn == $expectedResult); } return true; } private function sendHello() { if (!$this->smtpSocket) { return false; } if (!$this->sendMessage('EHLO ' . $this->clientHost, 250)) { if (!$this->sendMessage('HELO ' . $this->clientHost, 250)) { return false; } } return true; } } 