View source
<?php
namespace Drupal\phpmailer_smtp\Plugin\Mail;
use Drupal\Component\Utility\Html;
use Drupal\Core\Config\ConfigFactoryInterface;
use Drupal\Core\Logger\LoggerChannelFactoryInterface;
use Drupal\Core\Messenger\MessengerInterface;
use Drupal\Core\Mail\MailFormatHelper;
use Drupal\Core\Mail\MailInterface;
use Drupal\Core\Render\Markup;
use Drupal\Core\Plugin\ContainerFactoryPluginInterface;
use Drupal\Core\StringTranslation\StringTranslationTrait;
use Drupal\phpmailer_smtp\PluginManager\PhpmailerOauth2PluginManagerInterface;
use PHPMailer\PHPMailer\PHPMailer;
use PHPMailer\PHPMailer\Exception;
use Symfony\Component\DependencyInjection\ContainerInterface;
use PHPMailer\PHPMailer\OAuth;
class PhpMailerSmtp extends PHPMailer implements MailInterface, ContainerFactoryPluginInterface {
use StringTranslationTrait;
protected $configFactory;
protected $config;
public $AllowEmpty = TRUE;
public $drupalDebug = 0;
public $SMTPDebug = 2;
public $drupalDebugOutput = '';
protected $loggerFactory;
protected $messenger;
protected $phpmailerOauth2PluginManager;
public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition) {
return new static($container
->get('config.factory'), $container
->get('logger.factory'), $container
->get('messenger'), $container
->get('plugin.manager.phpmailer_oauth2'));
}
public function __construct(ConfigFactoryInterface $config, LoggerChannelFactoryInterface $logger_factory, MessengerInterface $messenger, PhpmailerOauth2PluginManagerInterface $plugin_manager) {
if (method_exists(get_parent_class($this), '__construct')) {
parent::__construct(TRUE);
}
$this->configFactory = $config;
$this->config = $config
->get('phpmailer_smtp.settings');
$this->loggerFactory = $logger_factory;
$this->messenger = $messenger;
$this->phpmailerOauth2PluginManager = $plugin_manager;
$this
->IsSMTP();
$this
->Reset();
$this->SMTPAutoTLS = FALSE;
$this->Host = $this->config
->get('smtp_host', '');
if ($backup = $this->config
->get('smtp_hostbackup', '')) {
$this->Host .= ';' . $backup;
}
$this->Port = $this->config
->get('smtp_port', '25');
$smtp_protocol = $this->config
->get('smtp_protocol', '');
$this->SMTPSecure = $smtp_protocol;
if (!empty($smtp_protocol)) {
$ssl_verify_peer = $this->config
->get('smtp_ssl_verify_peer');
$this->SMTPOptions['ssl']['verify_peer'] = isset($ssl_verify_peer) ? $ssl_verify_peer : 1;
$ssl_verify_peer_name = $this->config
->get('smtp_ssl_verify_peer_name');
$this->SMTPOptions['ssl']['verify_peer_name'] = isset($ssl_verify_peer_name) ? $ssl_verify_peer_name : 1;
$ssl_allow_self_signed = $this->config
->get('smtp_ssl_allow_self_signed');
$this->SMTPOptions['ssl']['allow_self_signed'] = isset($ssl_allow_self_signed) ? $ssl_allow_self_signed : 0;
}
if ($this->config
->get('smtp_authentication_type') === 'basic_auth') {
$this->Username = $this->config
->get('smtp_username', '');
$this->Password = $this->config
->get('smtp_password', '');
$this->SMTPAuth = (bool) ($this->Username != '' && $this->Password != '');
}
else {
$oauth2plugin = $this->phpmailerOauth2PluginManager
->createInstance($this->config
->get('smtp_authentication_type'));
$oauth_options = $oauth2plugin
->getAuthOptions();
$oauth = new OAuth($oauth_options);
$this
->setOAuth($oauth);
$this->AuthType = 'XOAUTH2';
$this->SMTPAuth = TRUE;
}
$this->SMTPKeepAlive = $this->config
->get('smtp_keepalive', 0);
$this->Timeout = $this->config
->get('smtp_timeout', 30);
$this->drupalDebug = $this->config
->get('smtp_debug', 0);
if ($this->drupalDebug > $this->SMTPDebug && \Drupal::currentUser()
->hasPermission('administer phpmailer smtp settings')) {
$this->SMTPDebug = $this->drupalDebug;
}
}
public function smtpSend($header, $body) {
if ($this->SMTPDebug) {
$this->drupalDebugOutput = '';
ob_start();
}
try {
$result = parent::SmtpSend($header, $body);
if (!$this->SMTPKeepAlive) {
$this
->SmtpClose();
}
} catch (Exception $exception) {
}
if ($this->SMTPDebug) {
if ($this->drupalDebug && ($this->drupalDebugOutput = ob_get_contents())) {
$this->messenger
->addMessage(Markup::create($this->drupalDebugOutput));
if ($this->config
->get('smtp_debug_log', 0)) {
$this->loggerFactory
->get('phpmailer_smtp')
->debug('Output of communication with SMTP server:<br /><pre>{output}</pre>', [
'output' => str_replace("<br>\n", "\n", Html::decodeEntities($this->drupalDebugOutput)),
]);
}
}
ob_end_clean();
}
$this
->reset();
if (isset($exception)) {
throw $exception;
}
return $result;
}
public function reset() {
$this
->clearAllRecipients();
$this
->clearReplyTos();
$this
->clearAttachments();
$this
->clearCustomHeaders();
$this->Priority = 3;
$this->CharSet = 'utf-8';
$this->ContentType = 'text/plain';
$this->Encoding = '8bit';
$from_name = $this->config
->get('smtp_fromname');
if ($from_name == '') {
$from_name = $this->configFactory
->get('system.site')
->get('name');
}
$this->FromName = $from_name;
$this->Sender = '';
$this->MessageID = '';
}
public function __destruct() {
if ($this->SMTPKeepAlive && isset($this->smtp->do_debug)) {
$this->smtp->do_debug = 0;
}
parent::__destruct();
}
public function setLanguage($langcode = 'en', $lang_path = 'language/') {
parent::SetLanguage('en');
$this->language = [
'authenticate' => $this
->t('SMTP error: Could not authenticate.'),
'connect_host' => $this
->t('SMTP error: Could not connect to host.'),
'data_not_accepted' => $this
->t('SMTP error: Data not accepted.'),
'smtp_connect_failed' => $this
->t('SMTP error: Could not connect to SMTP host.'),
'smtp_error' => $this
->t('SMTP server error:'),
'empty_message' => $this
->t('Message body empty'),
'encoding' => $this
->t('Unknown encoding:'),
'variable_set' => $this
->t('Cannot set or reset variable:'),
'file_access' => $this
->t('File error: Could not access file:'),
'file_open' => $this
->t('File error: Could not open file:'),
'from_failed' => $this
->t('The following From address failed:'),
'invalid_address' => $this
->t('Invalid address'),
'provide_address' => $this
->t('You must provide at least one recipient e-mail address.'),
'recipients_failed' => $this
->t('The following recipients failed:'),
] + $this->language;
return TRUE;
}
public static function rfcDate() {
$tz = date('Z');
$tzs = $tz < 0 ? '-' : '+';
$tz = abs($tz);
$tz = (int) ($tz / 3600) * 100 + $tz % 3600 / 60;
$result = sprintf("%s %s%04d", date('D, j M Y H:i:s'), $tzs, $tz);
return $result;
}
public function format(array $message) {
$message['body'] = implode("\n\n", $message['body']);
$message['body'] = MailFormatHelper::htmlToText($message['body']);
$message['body'] = MailFormatHelper::wrapMail($message['body']);
return $message;
}
public function mail(array $message) {
try {
$headers = array_change_key_case($message['headers']);
unset($message['headers']);
$from = $this
->parseAddresses($headers['from']);
$from = reset($from);
$this->From = $from['address'];
if ($from['name'] != '') {
$this->FromName = $from['name'];
}
unset($headers['from']);
$phpmailer_smtp_debug_email = $this->configFactory
->get('system.maintenance')
->get('phpmailer_smtp_debug_email');
if (empty($phpmailer_smtp_debug_email)) {
foreach ($this
->parseAddresses($message['to']) as $address) {
$this
->AddAddress($address['address'], $address['name']);
}
if (!empty($headers['cc'])) {
foreach ($this
->parseAddresses($headers['cc']) as $address) {
$this
->AddCC($address['address'], $address['name']);
}
}
if (!empty($headers['bcc'])) {
foreach ($this
->parseAddresses($headers['bcc']) as $address) {
$this
->AddBCC($address['address'], $address['name']);
}
}
}
else {
$this
->AddAddress($phpmailer_smtp_debug_email);
}
unset($headers['cc'], $headers['bcc']);
if (isset($headers['reply-to'])) {
foreach ($this
->parseAddresses($headers['reply-to']) as $address) {
$this
->AddReplyTo($address['address'], $address['name']);
}
unset($headers['reply-to']);
}
elseif ($this->config
->get('smtp_always_replyto')) {
$this
->AddReplyTo($from['address'], $from['name']);
}
if (isset($headers['content-type'])) {
$content_type = explode(';', $headers['content-type']);
$this->ContentType = trim(array_shift($content_type));
foreach ($content_type as $param) {
$param = explode('=', $param, 2);
$key = trim($param[0]);
if ($key == 'charset') {
$this->CharSet = trim($param[1]);
}
else {
$this->ContentType .= '; ' . $key . '=' . trim($param[1]);
}
}
unset($headers['content-type']);
}
$properties = [
'x-priority' => 'Priority',
'content-transfer-encoding' => 'Encoding',
'message-id' => 'MessageID',
];
foreach ($properties as $source => $property) {
if (isset($headers[$source])) {
$this->{$property} = $headers[$source];
unset($headers[$source]);
}
}
if (isset($headers['return-path'])) {
unset($headers['return-path']);
}
if (isset($headers['x-mailer'])) {
unset($headers['x-mailer']);
}
$envelopeSender = $this
->parseAddresses($message['from']);
$envelopeSender = reset($envelopeSender);
$this->Sender = $envelopeSender['address'];
$senderOption = $this->config
->get('smtp_envelope_sender_option');
if ($senderOption === 'site_mail') {
$this->Sender = $this->configFactory
->get('system.site')
->get('mail');
}
if ($senderOption === 'from_address') {
$this->Sender = $from['address'];
}
if ($senderOption === 'other') {
$this->Sender = $this->config
->get('smtp_envelope_sender');
}
if (!empty($this->config
->get('smtp_ehlo_host'))) {
$this->Hostname = $this->config
->get('smtp_ehlo_host');
}
unset($headers['mime-version']);
foreach ($headers as $key => $value) {
$this
->AddCustomHeader($key, $value);
}
$this->Subject = $message['subject'];
$this->Body = $message['body'];
return $this
->Send();
} catch (Exception $e) {
$output = $e
->getMessage();
$output .= " \n";
$arguments = [];
if ($this->drupalDebugOutput) {
$output .= '<p><strong>Server response:</strong></p>';
$output .= "<pre>\n@smtp_output\n</pre>";
$arguments += [
'@smtp_output' => str_replace("<br>\n", "\n", Html::decodeEntities($this->drupalDebugOutput)),
];
}
unset($message['params']);
$output .= "<p><strong>Subject:</strong> \n@subject\n</p>";
$arguments += [
'@subject' => $message['subject'],
];
unset($message['subject']);
$output .= '<p><strong>Body:</strong></p>';
$output .= "<pre>\n@body\n</pre>";
$arguments += [
'@body' => $message['body'],
];
unset($message['body']);
$output .= '<p><strong>Message:</strong></p>';
$output .= "<pre>\n@message\n</pre>";
$arguments += [
'@message' => var_export($message, TRUE),
];
$this->loggerFactory
->get('phpmailer_smtp')
->error($output, $arguments);
return FALSE;
}
}
}