Initial commit
This commit is contained in:
@@ -0,0 +1,450 @@
|
||||
<?php
|
||||
|
||||
namespace FluentMail\App\Services\Mailer;
|
||||
|
||||
use Exception;
|
||||
use InvalidArgumentException;
|
||||
use FluentMail\App\Models\Logger;
|
||||
use FluentMail\Includes\Support\Arr;
|
||||
use FluentMail\Includes\Core\Application;
|
||||
use FluentMail\App\Services\Mailer\Manager;
|
||||
use FluentMail\App\Services\Mailer\ValidatorTrait;
|
||||
|
||||
class BaseHandler
|
||||
{
|
||||
use ValidatorTrait;
|
||||
|
||||
protected $app = null;
|
||||
|
||||
protected $params = [];
|
||||
|
||||
protected $manager = null;
|
||||
|
||||
protected $phpMailer = null;
|
||||
|
||||
protected $settings = [];
|
||||
|
||||
protected $attributes = [];
|
||||
|
||||
protected $response = null;
|
||||
|
||||
protected $existing_row_id = null;
|
||||
|
||||
public function __construct(?Application $app = null, ?Manager $manager = null)
|
||||
{
|
||||
$this->app = $app ?: fluentMail();
|
||||
$this->manager = $manager ?: fluentMail(Manager::class);
|
||||
}
|
||||
|
||||
public function setPhpMailer($phpMailer)
|
||||
{
|
||||
$this->phpMailer = $phpMailer;
|
||||
|
||||
if(!$this->phpMailer->CharSet) {
|
||||
$this->phpMailer->CharSet = 'UTF-8';
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function setSettings($settings)
|
||||
{
|
||||
|
||||
$this->settings = $settings;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
protected function preSend()
|
||||
{
|
||||
$this->attributes = [];
|
||||
|
||||
if ($this->isForced('from_name')) {
|
||||
$this->phpMailer->FromName = $this->getSetting('sender_name');
|
||||
}
|
||||
|
||||
if ($this->getSetting('return_path') == 'yes') {
|
||||
$this->phpMailer->Sender = $this->phpMailer->From;
|
||||
}
|
||||
|
||||
$this->attributes = $this->setAttributes();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
protected function isForced($key)
|
||||
{
|
||||
return $this->getSetting("force_{$key}") == 'yes';
|
||||
}
|
||||
|
||||
public function isForcedEmail()
|
||||
{
|
||||
return $this->getSetting("force_from_email") != 'no';
|
||||
}
|
||||
|
||||
public function isActive()
|
||||
{
|
||||
return $this->getSetting('is_active') == 'yes';
|
||||
}
|
||||
|
||||
protected function getDefaultParams()
|
||||
{
|
||||
$timeout = (int)ini_get('max_execution_time');
|
||||
|
||||
return [
|
||||
'timeout' => $timeout ?: 30,
|
||||
'httpversion' => '1.1',
|
||||
'blocking' => true,
|
||||
];
|
||||
}
|
||||
|
||||
protected function setAttributes()
|
||||
{
|
||||
$from = $this->setFrom();
|
||||
|
||||
$replyTos = $this->setRecipientsArray(array_values(
|
||||
$this->phpMailer->getReplyToAddresses()
|
||||
));
|
||||
|
||||
$contentType = $this->phpMailer->ContentType;
|
||||
|
||||
$customHeaders = $this->setFormattedCustomHeaders();
|
||||
|
||||
$recipients = [
|
||||
'to' => $this->setRecipientsArray($this->phpMailer->getToAddresses()),
|
||||
'cc' => $this->setRecipientsArray($this->phpMailer->getCcAddresses()),
|
||||
'bcc' => $this->setRecipientsArray($this->phpMailer->getBccAddresses())
|
||||
];
|
||||
|
||||
return array_merge($this->attributes, [
|
||||
'from' => $from,
|
||||
'to' => $recipients['to'],
|
||||
'subject' => $this->phpMailer->Subject,
|
||||
'message' => $this->phpMailer->Body,
|
||||
'alt_body' => $this->phpMailer->AltBody,
|
||||
'attachments' => $this->phpMailer->getAttachments(),
|
||||
'custom_headers' => $customHeaders,
|
||||
'headers' => [
|
||||
'reply-to' => $replyTos,
|
||||
'cc' => $recipients['cc'],
|
||||
'bcc' => $recipients['bcc'],
|
||||
'content-type' => $contentType
|
||||
]
|
||||
]);
|
||||
}
|
||||
|
||||
protected function setFrom()
|
||||
{
|
||||
$name = $this->getSetting('sender_name');
|
||||
$email = $this->getSetting('sender_email');
|
||||
$overrideName = $this->getSetting('force_from_name');
|
||||
|
||||
if ($name && ($overrideName == 'yes' || $this->phpMailer->FromName == 'WordPress')) {
|
||||
$this->attributes['sender_name'] = $name;
|
||||
$this->attributes['sender_email'] = $email;
|
||||
$from = $name . ' <' . $email . '>';
|
||||
} elseif ($this->phpMailer->FromName) {
|
||||
$this->attributes['sender_email'] = $email;
|
||||
$this->attributes['sender_name'] = $this->phpMailer->FromName;
|
||||
$from = $this->phpMailer->FromName . ' <' . $email . '>';
|
||||
} else {
|
||||
$from = $this->attributes['sender_email'] = $email;
|
||||
}
|
||||
|
||||
return $from;
|
||||
}
|
||||
|
||||
protected function setRecipientsArray($array)
|
||||
{
|
||||
$recipients = [];
|
||||
|
||||
foreach ($array as $key => $recipient) {
|
||||
$recipient = array_filter($recipient);
|
||||
|
||||
if (!$recipient) continue;
|
||||
|
||||
$recipients[$key] = [
|
||||
'email' => array_shift($recipient)
|
||||
];
|
||||
|
||||
if ($recipient) {
|
||||
$recipients[$key]['name'] = array_shift($recipient);
|
||||
}
|
||||
}
|
||||
|
||||
return $recipients;
|
||||
}
|
||||
|
||||
protected function setFormattedCustomHeaders()
|
||||
{
|
||||
$headers = [];
|
||||
|
||||
$customHeaders = $this->phpMailer->getCustomHeaders();
|
||||
|
||||
foreach ($customHeaders as $key => $header) {
|
||||
if ($header[0] == 'Return-Path') {
|
||||
if ($this->getSetting('options.return_path') == 'no') {
|
||||
if (!empty($header[1])) {
|
||||
$this->phpMailer->Sender = $header[1];
|
||||
}
|
||||
}
|
||||
unset($customHeaders[$key]);
|
||||
} else {
|
||||
$headers[] = [
|
||||
'key' => $header[0],
|
||||
'value' => $header[1]
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
$this->phpMailer->clearCustomHeaders();
|
||||
|
||||
foreach ($customHeaders as $customHeader) {
|
||||
$this->phpMailer->addCustomHeader($customHeader[0], $customHeader[1]);
|
||||
}
|
||||
|
||||
return $headers;
|
||||
}
|
||||
|
||||
public function getSetting($key = null, $default = null)
|
||||
{
|
||||
try {
|
||||
return $key ? Arr::get($this->settings, $key, $default) : $this->settings;
|
||||
} catch (Exception $e) {
|
||||
return $default;
|
||||
}
|
||||
}
|
||||
|
||||
protected function getParam($key = null, $default = null)
|
||||
{
|
||||
try {
|
||||
return $key ? Arr::get($this->attributes, $key, $default) : $this->attributes;
|
||||
} catch (Exception $e) {
|
||||
return $default;
|
||||
}
|
||||
}
|
||||
|
||||
protected function getHeader($key, $default = null)
|
||||
{
|
||||
try {
|
||||
return Arr::get(
|
||||
$this->attributes['headers'], $key, $default
|
||||
);
|
||||
} catch (Exception $e) {
|
||||
return $default;
|
||||
}
|
||||
}
|
||||
|
||||
public function getSubject()
|
||||
{
|
||||
$subject = '';
|
||||
|
||||
if (isset($this->attributes['subject'])) {
|
||||
$subject = $this->attributes['subject'];
|
||||
}
|
||||
|
||||
return $subject;
|
||||
}
|
||||
|
||||
protected function getExtraParams()
|
||||
{
|
||||
$this->attributes['extra']['provider'] = $this->getSetting('provider');
|
||||
|
||||
return $this->attributes['extra'];
|
||||
}
|
||||
|
||||
public function handleResponse($response)
|
||||
{
|
||||
if ( is_wp_error($response) ) {
|
||||
$code = $response->get_error_code();
|
||||
|
||||
if (!is_numeric($code)) {
|
||||
$code = 400;
|
||||
}
|
||||
|
||||
$message = $response->get_error_message();
|
||||
|
||||
$errorResponse = [
|
||||
'code' => $code,
|
||||
'message' => $message,
|
||||
'errors' => $response->get_error_data()
|
||||
];
|
||||
|
||||
$status = $this->processResponse($errorResponse, false);
|
||||
|
||||
if ( !$status ) {
|
||||
throw new \PHPMailer\PHPMailer\Exception($message, $code); // phpcs:ignore WordPress.Security.EscapeOutput.ExceptionNotEscaped
|
||||
} else {
|
||||
return $status;
|
||||
}
|
||||
|
||||
} else {
|
||||
return $this->processResponse($response, true);
|
||||
}
|
||||
}
|
||||
|
||||
public function processResponse($response, $status)
|
||||
{
|
||||
if ($this->shouldBeLogged($status)) {
|
||||
$data = [
|
||||
'to' => $this->serialize($this->attributes['to']),
|
||||
'from' => $this->attributes['from'],
|
||||
'subject' => sanitize_text_field($this->attributes['subject']),
|
||||
'body' => $this->attributes['message'],
|
||||
'attachments' => $this->serialize($this->attributes['attachments']),
|
||||
'status' => $status ? 'sent' : 'failed',
|
||||
'response' => $this->serialize($response),
|
||||
'headers' => $this->serialize($this->getParam('headers')),
|
||||
'extra' => $this->serialize($this->getExtraParams())
|
||||
];
|
||||
|
||||
if($this->existing_row_id) {
|
||||
$row = (new Logger())->find($this->existing_row_id);
|
||||
if($row) {
|
||||
$row['response'] = (array) $row['response'];
|
||||
if($status) {
|
||||
$row['response']['fallback'] = __('Sent using fallback connection ', 'fluent-smtp') . $this->attributes['from'];
|
||||
$row['response']['fallback_response'] = $response;
|
||||
} else {
|
||||
$row['response']['fallback'] = __('Tried to send using fallback but failed. ', 'fluent-smtp') . $this->attributes['from'];
|
||||
$row['response']['fallback_response'] = $response;
|
||||
}
|
||||
|
||||
$data['response'] = $this->serialize( $row['response']);
|
||||
$data['retries'] = $row['retries'] + 1;
|
||||
(new Logger())->updateLog($data, ['id' => $row['id']]);
|
||||
|
||||
if(!$status) {
|
||||
do_action('fluentmail_email_sending_failed_no_fallback', $row['id'], $this, $data);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
$logId = (new Logger)->add($data);
|
||||
if(!$status) {
|
||||
// We have to fire an action for this failed job
|
||||
$status = apply_filters('fluentmail_email_sending_failed', $status, $logId, $this, $data);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $status;
|
||||
}
|
||||
|
||||
protected function shouldBeLogged($status)
|
||||
{
|
||||
if($this->existing_row_id) {
|
||||
return true;
|
||||
}
|
||||
if (defined('FLUENTMAIL_LOG_OFF') && FLUENTMAIL_LOG_OFF) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!$status) {
|
||||
return true;
|
||||
}
|
||||
|
||||
$miscSettings = $this->manager->getConfig('misc');
|
||||
$isLogOn = $miscSettings['log_emails'] == 'yes';
|
||||
|
||||
return apply_filters('fluentmail_will_log_email', $isLogOn, $miscSettings, $this);
|
||||
}
|
||||
|
||||
protected function serialize(array $data)
|
||||
{
|
||||
foreach ($data as $key => $item) {
|
||||
|
||||
if (is_array($item)) {
|
||||
$this->serialize($item);
|
||||
}
|
||||
|
||||
if (is_object($item) || is_resource($item)) {
|
||||
throw new InvalidArgumentException(
|
||||
"Invalid Data: Array cannot contain an object or resource."
|
||||
);
|
||||
}
|
||||
|
||||
if (is_string($item)) {
|
||||
if (is_serialized($item)) {
|
||||
throw new InvalidArgumentException(
|
||||
"Invalid Data: Array cannot contain serialized data."
|
||||
);
|
||||
}
|
||||
|
||||
if (filter_var($item, FILTER_VALIDATE_EMAIL)) {
|
||||
$data[$key] = sanitize_email($item);
|
||||
} elseif (filter_var($item, FILTER_VALIDATE_URL)) {
|
||||
$data[$key] = esc_url_raw($item);
|
||||
} else {
|
||||
$data[$key] = sanitize_text_field($item);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return serialize($data);
|
||||
}
|
||||
|
||||
protected function fireWPMailFailedAction($data)
|
||||
{
|
||||
$code = is_numeric($data['code']) ? $data['code'] : 400;
|
||||
$code = strlen($code) < 3 ? 400 : $code;
|
||||
|
||||
$mail_error_data['phpmailer_exception_code'] = $code;
|
||||
$mail_error_data['errors'] = $data['errors'];
|
||||
|
||||
$error = new \WP_Error(
|
||||
$code, $data['message'], $mail_error_data
|
||||
);
|
||||
|
||||
$this->app->doAction('wp_mail_failed', $error);
|
||||
}
|
||||
|
||||
protected function updatedLog($id, $data)
|
||||
{
|
||||
try {
|
||||
$data['updated_at'] = current_time('mysql');
|
||||
(new Logger)->updateLog($data, ['id' => $id]);
|
||||
} catch (Exception $e) {
|
||||
error_log($e->getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
public function getValidSenders($connection)
|
||||
{
|
||||
return [$connection['sender_email']];
|
||||
}
|
||||
|
||||
public function checkConnection($connection)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
public function getConnectionInfo($connection)
|
||||
{
|
||||
return [
|
||||
'info' => (string) fluentMail('view')->make('admin.general_connection_info', [
|
||||
'connection' => $connection
|
||||
])
|
||||
];
|
||||
}
|
||||
|
||||
public function getPhpMailer()
|
||||
{
|
||||
return $this->phpMailer;
|
||||
}
|
||||
|
||||
public function setRowId($id)
|
||||
{
|
||||
$this->existing_row_id = $id;
|
||||
}
|
||||
|
||||
public function addNewSenderEmail($connection, $email)
|
||||
{
|
||||
return new \WP_Error('not_implemented', __('Not implemented', 'fluent-smtp'));
|
||||
}
|
||||
|
||||
public function removeSenderEmail($connection, $email)
|
||||
{
|
||||
return new \WP_Error('not_implemented', __('Not implemented', 'fluent-smtp'));
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user