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'));
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,58 @@
|
||||
<?php
|
||||
|
||||
namespace FluentMail\App\Services\Mailer;
|
||||
|
||||
use FluentMail\App\Models\Logger;
|
||||
use FluentMail\App\Services\Mailer\Providers\Factory;
|
||||
use FluentMail\App\Services\Mailer\Providers\DefaultMail\Handler as PHPMailer;
|
||||
|
||||
class FluentPHPMailer
|
||||
{
|
||||
protected $app = null;
|
||||
|
||||
protected $phpMailer = null;
|
||||
|
||||
public function __construct($phpMailer)
|
||||
{
|
||||
$this->app = fluentMail();
|
||||
|
||||
$this->phpMailer = $phpMailer;
|
||||
}
|
||||
|
||||
public function send()
|
||||
{
|
||||
if ($driver = fluentMailGetProvider($this->phpMailer->From)) {
|
||||
if ($forceFromEmail = $driver->getSetting('force_from_email_id')) {
|
||||
$this->phpMailer->From = $forceFromEmail;
|
||||
}
|
||||
return $driver->setPhpMailer($this->phpMailer)->send();
|
||||
}
|
||||
|
||||
return $this->phpMailer->send();
|
||||
}
|
||||
|
||||
public function sendViaFallback($rowId)
|
||||
{
|
||||
$driver = fluentMailGetProvider($this->phpMailer->From);
|
||||
if($driver) {
|
||||
$driver->setRowId($rowId);
|
||||
return $driver->setPhpMailer($this->phpMailer)->send();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public function __get($key)
|
||||
{
|
||||
return $this->phpMailer->{$key};
|
||||
}
|
||||
|
||||
public function __set($key, $value)
|
||||
{
|
||||
$this->phpMailer->{$key} = $value;
|
||||
}
|
||||
|
||||
public function __call($method, $params)
|
||||
{
|
||||
return call_user_func_array([$this->phpMailer, $method], $params);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,103 @@
|
||||
<?php
|
||||
|
||||
namespace FluentMail\App\Services\Mailer;
|
||||
|
||||
use FluentMail\App\Models\Logger;
|
||||
use FluentMail\App\Models\Settings;
|
||||
use FluentMail\Includes\Support\Arr;
|
||||
use FluentMail\Includes\Core\Application;
|
||||
use FluentMail\Includes\Support\ValidationException;
|
||||
use FluentMail\App\Services\Mailer\Providers\Factory;
|
||||
|
||||
class Manager
|
||||
{
|
||||
protected $app = null;
|
||||
|
||||
protected static $config = [];
|
||||
|
||||
protected static $settings = [];
|
||||
|
||||
protected static $resolved = [];
|
||||
|
||||
protected static $wpConfigSettings = [];
|
||||
|
||||
public function __construct(?Application $app = null)
|
||||
{
|
||||
$this->app = $app ?: fluentMail();
|
||||
|
||||
$this->initialize();
|
||||
}
|
||||
|
||||
protected function initialize()
|
||||
{
|
||||
$this->loadConfigAndSettings();
|
||||
|
||||
$this->app->addCustomFilter('active_driver', [$this, 'activeDriver']);
|
||||
}
|
||||
|
||||
protected function loadConfigAndSettings()
|
||||
{
|
||||
static::$config = require(__DIR__ . '/Providers/config.php');
|
||||
|
||||
static::$settings = (new Settings)->getSettings();
|
||||
|
||||
$this->mergeConfigAndSettings();
|
||||
}
|
||||
|
||||
protected function mergeConfigAndSettings()
|
||||
{
|
||||
$databaseSettings = $this->getSettings();
|
||||
|
||||
Arr::set(static::$config, 'mappings', Arr::get($databaseSettings, 'mappings'));
|
||||
Arr::set(static::$config, 'connections', Arr::get($databaseSettings, 'connections'));
|
||||
|
||||
if (isset($databaseSettings['misc'])) {
|
||||
Arr::set(static::$config, "misc", array_merge(
|
||||
static::$config['misc'], $databaseSettings['misc']
|
||||
));
|
||||
}
|
||||
|
||||
foreach (static::$config['providers'] as $key => $provider) {
|
||||
try {
|
||||
$optionKey = "providers.{$key}.options";
|
||||
|
||||
$options = array_merge(
|
||||
$provider['options'],
|
||||
Arr::get($databaseSettings, $optionKey, [])
|
||||
);
|
||||
|
||||
Arr::set(static::$config, $optionKey, $options);
|
||||
|
||||
} catch (ValidationException $e) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public function getMailerConfigAndSettings()
|
||||
{
|
||||
return static::$config;
|
||||
}
|
||||
|
||||
public function getConfig($key = null, $default = null)
|
||||
{
|
||||
return $key ? Arr::get(static::$config, $key, $default) : static::$config;
|
||||
}
|
||||
|
||||
public function getSettings($key = null, $default = null)
|
||||
{
|
||||
return $key ? Arr::get(static::$settings, $key, $default) : static::$settings;
|
||||
}
|
||||
|
||||
public function getWPConfig($key = null, $default = null)
|
||||
{
|
||||
return $key ? Arr::get(
|
||||
static::$wpConfigSettings, $key, $default
|
||||
) : static::$wpConfigSettings;
|
||||
}
|
||||
|
||||
public function activeDriver($phpMailer)
|
||||
{
|
||||
return fluentMailgetConnection($phpMailer->From);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,354 @@
|
||||
<?php
|
||||
|
||||
namespace FluentMail\App\Services\Mailer\Providers\AmazonSes;
|
||||
|
||||
use FluentMail\App\Models\Settings;
|
||||
use FluentMail\App\Services\Mailer\BaseHandler;
|
||||
use FluentMail\Includes\Support\Arr;
|
||||
|
||||
class Handler extends BaseHandler
|
||||
{
|
||||
use ValidatorTrait;
|
||||
|
||||
protected $client = null;
|
||||
|
||||
const RAW_REQUEST = true;
|
||||
|
||||
const TRIGGER_ERROR = false;
|
||||
|
||||
public function send()
|
||||
{
|
||||
if ($this->preSend() && $this->phpMailer->preSend()) {
|
||||
$this->client = new SimpleEmailServiceMessage;
|
||||
return $this->postSend();
|
||||
}
|
||||
|
||||
return $this->handleResponse(new \WP_Error(422, __('Something went wrong!', 'fluent-smtp'), []));
|
||||
}
|
||||
|
||||
public function postSend()
|
||||
{
|
||||
$mime = chunk_split(base64_encode($this->phpMailer->getSentMIMEMessage()), 76, "\n");
|
||||
|
||||
$connectionSettings = $this->filterConnectionVars($this->getSetting());
|
||||
|
||||
$ses = fluentMailSesConnection($connectionSettings);
|
||||
|
||||
$this->response = $ses->sendRawEmail($mime);
|
||||
|
||||
return $this->handleResponse($this->response);
|
||||
}
|
||||
|
||||
protected function getFrom()
|
||||
{
|
||||
return $this->getParam('from');
|
||||
}
|
||||
|
||||
public function getVerifiedEmails()
|
||||
{
|
||||
return (new Settings)->getVerifiedEmails();
|
||||
}
|
||||
|
||||
protected function getReplyTo()
|
||||
{
|
||||
$replyTo = $this->getRecipients(
|
||||
$this->getParam('headers.reply-to')
|
||||
);
|
||||
|
||||
if (is_array($replyTo)) {
|
||||
$replyTo = reset($replyTo);
|
||||
}
|
||||
|
||||
return $replyTo;
|
||||
}
|
||||
|
||||
protected function getTo()
|
||||
{
|
||||
return $this->getRecipients($this->getParam('to'));
|
||||
}
|
||||
|
||||
protected function getCarbonCopy()
|
||||
{
|
||||
return $this->getRecipients($this->getParam('headers.cc'));
|
||||
}
|
||||
|
||||
protected function getBlindCarbonCopy()
|
||||
{
|
||||
return $this->getRecipients($this->getParam('headers.bcc'));
|
||||
}
|
||||
|
||||
protected function getRecipients($recipients)
|
||||
{
|
||||
$array = array_map(function ($recipient) {
|
||||
return isset($recipient['name'])
|
||||
? $recipient['name'] . ' <' . $recipient['email'] . '>'
|
||||
: $recipient['email'];
|
||||
}, $recipients);
|
||||
|
||||
return implode(', ', $array);
|
||||
}
|
||||
|
||||
protected function getBody()
|
||||
{
|
||||
return [
|
||||
$this->phpMailer->AltBody,
|
||||
$this->phpMailer->Body
|
||||
];
|
||||
}
|
||||
|
||||
protected function getAttachments()
|
||||
{
|
||||
$attachments = [];
|
||||
|
||||
foreach ($this->getParam('attachments') as $attachment) {
|
||||
$file = false;
|
||||
|
||||
try {
|
||||
if (is_file($attachment[0]) && is_readable($attachment[0])) {
|
||||
$fileName = basename($attachment[0]);
|
||||
$file = file_get_contents($attachment[0]);
|
||||
$mimeType = mime_content_type($attachment[0]);
|
||||
$filetype = str_replace(';', '', trim($mimeType));
|
||||
}
|
||||
} catch (\Exception $e) {
|
||||
$file = false;
|
||||
}
|
||||
|
||||
if ($file === false) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$attachments[] = [
|
||||
'type' => $filetype,
|
||||
'name' => $fileName,
|
||||
'content' => $file
|
||||
];
|
||||
}
|
||||
|
||||
return $attachments;
|
||||
}
|
||||
|
||||
protected function getCustomEmailHeaders()
|
||||
{
|
||||
$customHeaders = [
|
||||
'X-Mailer' => 'Amazon-SES'
|
||||
];
|
||||
|
||||
$headers = [];
|
||||
foreach ($customHeaders as $key => $header) {
|
||||
$headers[] = $key . ':' . $header;
|
||||
}
|
||||
|
||||
return $headers;
|
||||
}
|
||||
|
||||
protected function getRegion()
|
||||
{
|
||||
return 'email.' . $this->getSetting('region') . '.amazonaws.com';
|
||||
}
|
||||
|
||||
public function getValidSenders($config)
|
||||
{
|
||||
$config = $this->filterConnectionVars($config);
|
||||
|
||||
$senders = $this->getSendersFromMappingsAndApi($config);
|
||||
|
||||
return $senders['all_senders'];
|
||||
}
|
||||
|
||||
public function getValidSendingIdentities($config)
|
||||
{
|
||||
$config = $this->filterConnectionVars($config);
|
||||
$region = 'email.' . $config['region'] . '.amazonaws.com';
|
||||
|
||||
$ses = new SimpleEmailService(
|
||||
$config['access_key'],
|
||||
$config['secret_key'],
|
||||
$region,
|
||||
static::TRIGGER_ERROR
|
||||
);
|
||||
|
||||
$validSenders = $ses->listVerifiedEmailAddresses();
|
||||
$addresses = [];
|
||||
|
||||
if (is_wp_error($validSenders)) {
|
||||
return [
|
||||
'emails' => [$config['sender_email']],
|
||||
'verified_domain' => ''
|
||||
];
|
||||
}
|
||||
|
||||
if ($validSenders && isset($validSenders['Addresses'])) {
|
||||
$addresses = $validSenders['Addresses'];
|
||||
}
|
||||
|
||||
$primaryEmail = $config['sender_email'];
|
||||
$domainArray = explode('@', $primaryEmail);
|
||||
$domainName = $domainArray[1];
|
||||
|
||||
if (apply_filters('fluent_mail_ses_primary_domain_only', true)) {
|
||||
$addresses = array_filter($addresses, function ($email) use ($domainName) {
|
||||
return !!strpos($email, $domainName);
|
||||
});
|
||||
$addresses = array_values($addresses);
|
||||
}
|
||||
|
||||
return [
|
||||
'emails' => apply_filters('fluentsmtp_ses_valid_senders', $addresses, $config),
|
||||
'verified_domain' => in_array($domainName, $validSenders['domains']) ? $domainName : ''
|
||||
];
|
||||
}
|
||||
|
||||
public function getConnectionInfo($connection)
|
||||
{
|
||||
$connection = $this->filterConnectionVars($connection);
|
||||
|
||||
$stats = $this->getStats($connection);
|
||||
$error = '';
|
||||
if (is_wp_error($stats)) {
|
||||
$error = $stats->get_error_message();
|
||||
$stats = [];
|
||||
}
|
||||
|
||||
$validSenders = $this->getSendersFromMappingsAndApi($connection);
|
||||
|
||||
$info = (string)fluentMail('view')->make('admin.ses_connection_info', [
|
||||
'connection' => $connection,
|
||||
'valid_senders' => $validSenders['all_senders'],
|
||||
'stats' => $stats,
|
||||
'error' => $error
|
||||
]);
|
||||
|
||||
return [
|
||||
'info' => $info,
|
||||
'verificationSettings' => [
|
||||
'connection_name' => 'Amazon SES',
|
||||
'all_senders' => $validSenders['all_senders'],
|
||||
'verified_senders' => $validSenders['verified_senders'],
|
||||
'verified_domain' => $validSenders['verified_domain']
|
||||
]
|
||||
];
|
||||
}
|
||||
|
||||
public function addNewSenderEmail($connection, $email)
|
||||
{
|
||||
$connection = $this->filterConnectionVars($connection);
|
||||
$validSenders = $this->getValidSendingIdentities($connection);
|
||||
|
||||
$emailDomain = explode('@', $email);
|
||||
$emailDomain = $emailDomain[1];
|
||||
|
||||
if ($emailDomain != $validSenders['verified_domain']) {
|
||||
return new \WP_Error(422, __('Invalid email address! Please use a verified domain.', 'fluent-smtp'));
|
||||
}
|
||||
|
||||
$settings = fluentMailGetSettings();
|
||||
$mappings = Arr::get($settings, 'mappings', []);
|
||||
|
||||
if (isset($mappings[$email])) {
|
||||
return new \WP_Error(422, __('Email address already exists with another connection. Please choose a different email.', 'fluent-smtp'));
|
||||
}
|
||||
|
||||
$settings = get_option('fluentmail-settings');
|
||||
|
||||
$settings['mappings'][$email] = md5($connection['sender_email']);
|
||||
|
||||
update_option('fluentmail-settings', $settings);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public function removeSenderEmail($connection, $email)
|
||||
{
|
||||
$connection = $this->filterConnectionVars($connection);
|
||||
$validSenders = $this->getValidSendingIdentities($connection);
|
||||
|
||||
$emailDomain = explode('@', $email);
|
||||
$emailDomain = $emailDomain[1];
|
||||
|
||||
if ($emailDomain != $validSenders['verified_domain']) {
|
||||
return new \WP_Error(422, __('Invalid email address! Please use a verified domain.', 'fluent-smtp'));
|
||||
}
|
||||
|
||||
if (in_array($email, $validSenders['emails'])) {
|
||||
return new \WP_Error(422, __('Sorry! you can not remove this email from this connection', 'fluent-smtp'));
|
||||
}
|
||||
|
||||
$settings = fluentMailGetSettings();
|
||||
$mappings = Arr::get($settings, 'mappings', []);
|
||||
|
||||
if (!isset($mappings[$email])) {
|
||||
return new \WP_Error(422, __('Email does not exists. Please try again.', 'fluent-smtp'));
|
||||
}
|
||||
|
||||
// check if the it's the same email or not
|
||||
if ($mappings[$email] != md5($connection['sender_email'])) {
|
||||
return new \WP_Error(422, __('Email does not exists. Please try again.', 'fluent-smtp'));
|
||||
}
|
||||
|
||||
$settings = get_option('fluentmail-settings');
|
||||
|
||||
unset($settings['mappings'][$email]);
|
||||
|
||||
update_option('fluentmail-settings', $settings);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
private function getStats($config)
|
||||
{
|
||||
$region = 'email.' . $config['region'] . '.amazonaws.com';
|
||||
|
||||
$ses = new SimpleEmailService(
|
||||
$config['access_key'],
|
||||
$config['secret_key'],
|
||||
$region,
|
||||
static::TRIGGER_ERROR
|
||||
);
|
||||
|
||||
return $ses->getSendQuota();
|
||||
}
|
||||
|
||||
private function filterConnectionVars($connection)
|
||||
{
|
||||
if ($connection['key_store'] == 'wp_config') {
|
||||
$connection['access_key'] = defined('FLUENTMAIL_AWS_ACCESS_KEY_ID') ? FLUENTMAIL_AWS_ACCESS_KEY_ID : '';
|
||||
$connection['secret_key'] = defined('FLUENTMAIL_AWS_SECRET_ACCESS_KEY') ? FLUENTMAIL_AWS_SECRET_ACCESS_KEY : '';
|
||||
}
|
||||
|
||||
return $connection;
|
||||
}
|
||||
|
||||
private function getSendersFromMappingsAndApi($connection)
|
||||
{
|
||||
$validSenders = $this->getValidSendingIdentities($connection);
|
||||
$verifiedDomain = Arr::get($validSenders, 'verified_domain', '');
|
||||
if ($verifiedDomain) {
|
||||
$settings = fluentMailGetSettings();
|
||||
$mappings = Arr::get($settings, 'mappings', []);
|
||||
|
||||
$mapKey = md5($connection['sender_email']);
|
||||
$mapSenders = array_filter($mappings, function ($key) use ($mapKey) {
|
||||
return $key == $mapKey;
|
||||
});
|
||||
|
||||
$mapSenders[$connection['sender_email']] = true;
|
||||
|
||||
foreach ($validSenders['emails'] as $email) {
|
||||
$mapSenders[$email] = $email;
|
||||
}
|
||||
|
||||
$mapSenders = array_keys($mapSenders);
|
||||
|
||||
} else {
|
||||
$mapSenders = $validSenders['emails'];
|
||||
}
|
||||
|
||||
return [
|
||||
'all_senders' => $mapSenders,
|
||||
'verified_senders' => $validSenders['emails'],
|
||||
'verified_domain' => $verifiedDomain
|
||||
];
|
||||
}
|
||||
}
|
||||
+685
@@ -0,0 +1,685 @@
|
||||
<?php
|
||||
|
||||
namespace FluentMail\App\Services\Mailer\Providers\AmazonSes;
|
||||
|
||||
/**
|
||||
*
|
||||
* Copyright (c) 2014, Daniel Zahariev.
|
||||
* Copyright (c) 2011, Dan Myers.
|
||||
* Parts copyright (c) 2008, Donovan Schonknecht.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* - Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
* - Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* This is a modified BSD license (the third clause has been removed).
|
||||
* The BSD license may be found here:
|
||||
* http://www.opensource.org/licenses/bsd-license.php
|
||||
*
|
||||
* Amazon Simple Email Service is a trademark of Amazon.com, Inc. or its affiliates.
|
||||
*
|
||||
* SimpleEmailService is based on Donovan Schonknecht's Amazon S3 PHP class, found here:
|
||||
* http://undesigned.org.za/2007/10/22/amazon-s3-php-class
|
||||
*
|
||||
* @copyright 2014 Daniel Zahariev
|
||||
* @copyright 2011 Dan Myers
|
||||
* @copyright 2008 Donovan Schonknecht
|
||||
*/
|
||||
|
||||
/**
|
||||
* SimpleEmailService PHP class
|
||||
*
|
||||
* @link https://github.com/daniel-zahariev/php-aws-ses
|
||||
* @package AmazonSimpleEmailService
|
||||
* @version v0.9.1
|
||||
*/
|
||||
class SimpleEmailService
|
||||
{
|
||||
/**
|
||||
* @link(AWS SES regions, http://docs.aws.amazon.com/ses/latest/DeveloperGuide/regions.html)
|
||||
*/
|
||||
const AWS_US_EAST_1 = 'email.us-east-1.amazonaws.com';
|
||||
const AWS_US_WEST_2 = 'email.us-west-2.amazonaws.com';
|
||||
const AWS_EU_WEST1 = 'email.eu-west-1.amazonaws.com';
|
||||
|
||||
const REQUEST_SIGNATURE_V3 = 'v3';
|
||||
const REQUEST_SIGNATURE_V4 = 'v4';
|
||||
|
||||
/**
|
||||
* AWS SES Target host of region
|
||||
*/
|
||||
protected $__host;
|
||||
|
||||
/**
|
||||
* AWS SES Access key
|
||||
*/
|
||||
protected $__accessKey;
|
||||
|
||||
/**
|
||||
* AWS Secret key
|
||||
*/
|
||||
protected $__secretKey;
|
||||
|
||||
/**
|
||||
* Enable/disable
|
||||
*/
|
||||
protected $__trigger_errors;
|
||||
|
||||
/**
|
||||
* Controls the reuse of CURL hander for sending a bulk of messages
|
||||
* @deprecated
|
||||
*/
|
||||
protected $__bulk_sending_mode = false;
|
||||
|
||||
/**
|
||||
* Optionally reusable SimpleEmailServiceRequest instance
|
||||
*/
|
||||
protected $__ses_request = null;
|
||||
|
||||
/**
|
||||
* Controls CURLOPT_SSL_VERIFYHOST setting for SimpleEmailServiceRequest's curl handler
|
||||
*/
|
||||
protected $__verifyHost = true;
|
||||
|
||||
/**
|
||||
* Controls CURLOPT_SSL_VERIFYPEER setting for SimpleEmailServiceRequest's curl handler
|
||||
*/
|
||||
protected $__verifyPeer = true;
|
||||
|
||||
/**
|
||||
* @var string HTTP Request signature version
|
||||
*/
|
||||
protected $__requestSignatureVersion;
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* @param string $accessKey Access key
|
||||
* @param string $secretKey Secret key
|
||||
* @param string $host Amazon Host through which to send the emails
|
||||
* @param boolean $trigger_errors Trigger PHP errors when AWS SES API returns an error
|
||||
* @param string $requestSignatureVersion Version of the request signature
|
||||
*/
|
||||
public function __construct($accessKey = null, $secretKey = null, $host = self::AWS_US_EAST_1, $trigger_errors = true, $requestSignatureVersion = self::REQUEST_SIGNATURE_V4)
|
||||
{
|
||||
if ($accessKey !== null && $secretKey !== null) {
|
||||
$this->setAuth($accessKey, $secretKey);
|
||||
}
|
||||
$this->__host = $host;
|
||||
$this->__trigger_errors = $trigger_errors;
|
||||
$this->__requestSignatureVersion = $requestSignatureVersion;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the request signature version
|
||||
*
|
||||
* @param string $requestSignatureVersion
|
||||
* @return SimpleEmailService $this
|
||||
*/
|
||||
public function setRequestSignatureVersion($requestSignatureVersion)
|
||||
{
|
||||
$this->__requestSignatureVersion = $requestSignatureVersion;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function getRequestSignatureVersion()
|
||||
{
|
||||
return $this->__requestSignatureVersion;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set AWS access key and secret key
|
||||
*
|
||||
* @param string $accessKey Access key
|
||||
* @param string $secretKey Secret key
|
||||
* @return SimpleEmailService $this
|
||||
*/
|
||||
public function setAuth($accessKey, $secretKey)
|
||||
{
|
||||
$this->__accessKey = $accessKey;
|
||||
$this->__secretKey = $secretKey;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set AWS Host
|
||||
* @param string $host AWS Host
|
||||
*/
|
||||
public function setHost($host = self::AWS_US_EAST_1)
|
||||
{
|
||||
$this->__host = $host;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated
|
||||
*/
|
||||
public function enableVerifyHost($enable = true)
|
||||
{
|
||||
$this->__verifyHost = (bool)$enable;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated
|
||||
*/
|
||||
public function enableVerifyPeer($enable = true)
|
||||
{
|
||||
$this->__verifyPeer = (bool)$enable;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated
|
||||
*/
|
||||
public function verifyHost()
|
||||
{
|
||||
return $this->__verifyHost;
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated
|
||||
*/
|
||||
public function verifyPeer()
|
||||
{
|
||||
return $this->__verifyPeer;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Get AWS target host
|
||||
* @return boolean
|
||||
*/
|
||||
public function getHost()
|
||||
{
|
||||
return $this->__host;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get AWS SES auth access key
|
||||
* @return string
|
||||
*/
|
||||
public function getAccessKey()
|
||||
{
|
||||
return $this->__accessKey;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get AWS SES auth secret key
|
||||
* @return string
|
||||
*/
|
||||
public function getSecretKey()
|
||||
{
|
||||
return $this->__secretKey;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the verify peer CURL mode
|
||||
* @return boolean
|
||||
*/
|
||||
public function getVerifyPeer()
|
||||
{
|
||||
return $this->__verifyPeer;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the verify host CURL mode
|
||||
* @return boolean
|
||||
*/
|
||||
public function getVerifyHost()
|
||||
{
|
||||
return $this->__verifyHost;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get bulk email sending mode
|
||||
* @return boolean
|
||||
* @deprecated
|
||||
*/
|
||||
public function getBulkMode()
|
||||
{
|
||||
return $this->__bulk_sending_mode;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Enable/disable CURLOPT_SSL_VERIFYHOST for SimpleEmailServiceRequest's curl handler
|
||||
* verifyHost and verifyPeer determine whether curl verifies ssl certificates.
|
||||
* It may be necessary to disable these checks on certain systems.
|
||||
* These only have an effect if SSL is enabled.
|
||||
*
|
||||
* @param boolean $enable New status for the mode
|
||||
* @return SimpleEmailService $this
|
||||
*/
|
||||
public function setVerifyHost($enable = true)
|
||||
{
|
||||
$this->__verifyHost = (bool)$enable;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Enable/disable CURLOPT_SSL_VERIFYPEER for SimpleEmailServiceRequest's curl handler
|
||||
* verifyHost and verifyPeer determine whether curl verifies ssl certificates.
|
||||
* It may be necessary to disable these checks on certain systems.
|
||||
* These only have an effect if SSL is enabled.
|
||||
*
|
||||
* @param boolean $enable New status for the mode
|
||||
* @return SimpleEmailService $this
|
||||
*/
|
||||
public function setVerifyPeer($enable = true)
|
||||
{
|
||||
$this->__verifyPeer = (bool)$enable;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Enable/disable bulk email sending mode
|
||||
*
|
||||
* @param boolean $enable New status for the mode
|
||||
* @return SimpleEmailService $this
|
||||
* @deprecated
|
||||
*/
|
||||
public function setBulkMode($enable = true)
|
||||
{
|
||||
$this->__bulk_sending_mode = (bool)$enable;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Lists the email addresses that have been verified and can be used as the 'From' address
|
||||
*
|
||||
* @return array|\WP_Error An array containing two items: a list of verified email addresses, and the request id.
|
||||
*/
|
||||
public function listVerifiedEmailAddresses()
|
||||
{
|
||||
$ses_request = $this->getRequestHandler('GET');
|
||||
$ses_request->setParameter('Action', 'ListIdentities');
|
||||
|
||||
$ses_response = $ses_request->getResponse();
|
||||
|
||||
if ($ses_response->error === false && $ses_response->code !== 200) {
|
||||
$ses_response->error = array('code' => $ses_response->code, 'message' => 'Unexpected HTTP status');
|
||||
}
|
||||
if ($ses_response->error !== false) {
|
||||
return new \WP_Error($ses_response->code, $this->getErrorMessage('ListIdentities', $ses_response->error), $ses_response->error);
|
||||
}
|
||||
|
||||
$response = array();
|
||||
if (!isset($ses_response->body)) {
|
||||
return $response;
|
||||
}
|
||||
|
||||
$domains = array();
|
||||
$addresses = array();
|
||||
foreach ($ses_response->body->ListIdentitiesResult->Identities->member as $address) {
|
||||
if (is_email($address)) {
|
||||
$addresses[] = (string)$address;
|
||||
} else {
|
||||
$domains[] = (string)$address;
|
||||
}
|
||||
}
|
||||
|
||||
$response['Addresses'] = $addresses;
|
||||
$response['domains'] = $domains;
|
||||
$response['RequestId'] = (string)$ses_response->body->ResponseMetadata->RequestId;
|
||||
|
||||
return $response;
|
||||
}
|
||||
|
||||
/**
|
||||
* Requests verification of the provided email address, so it can be used
|
||||
* as the 'From' address when sending emails through SimpleEmailService.
|
||||
*
|
||||
* After submitting this request, you should receive a verification email
|
||||
* from Amazon at the specified address containing instructions to follow.
|
||||
*
|
||||
* @param string $email The email address to get verified
|
||||
* @return array The request id for this request.
|
||||
*/
|
||||
public function verifyEmailAddress($email)
|
||||
{
|
||||
$ses_request = $this->getRequestHandler('POST');
|
||||
$ses_request->setParameter('Action', 'VerifyEmailAddress');
|
||||
$ses_request->setParameter('EmailAddress', $email);
|
||||
|
||||
$ses_response = $ses_request->getResponse();
|
||||
if ($ses_response->error === false && $ses_response->code !== 200) {
|
||||
$ses_response->error = array('code' => $ses_response->code, 'message' => 'Unexpected HTTP status');
|
||||
}
|
||||
if ($ses_response->error !== false) {
|
||||
$this->__triggerError('verifyEmailAddress', $ses_response->error);
|
||||
return false;
|
||||
}
|
||||
|
||||
$response['RequestId'] = (string)$ses_response->body->ResponseMetadata->RequestId;
|
||||
return $response;
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes the specified email address from the list of verified addresses.
|
||||
*
|
||||
* @param string $email The email address to remove
|
||||
* @return array The request id for this request.
|
||||
*/
|
||||
public function deleteVerifiedEmailAddress($email)
|
||||
{
|
||||
$ses_request = $this->getRequestHandler('DELETE');
|
||||
$ses_request->setParameter('Action', 'DeleteVerifiedEmailAddress');
|
||||
$ses_request->setParameter('EmailAddress', $email);
|
||||
|
||||
$ses_response = $ses_request->getResponse();
|
||||
if ($ses_response->error === false && $ses_response->code !== 200) {
|
||||
$ses_response->error = array('code' => $ses_response->code, 'message' => 'Unexpected HTTP status');
|
||||
}
|
||||
if ($ses_response->error !== false) {
|
||||
$this->__triggerError('deleteVerifiedEmailAddress', $ses_response->error);
|
||||
return false;
|
||||
}
|
||||
|
||||
$response['RequestId'] = (string)$ses_response->body->ResponseMetadata->RequestId;
|
||||
return $response;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves information on the current activity limits for this account.
|
||||
* See http://docs.amazonwebservices.com/ses/latest/APIReference/API_GetSendQuota.html
|
||||
*
|
||||
* @return array|\WP_Error An array containing information on this account's activity limits.
|
||||
*/
|
||||
public function getSendQuota()
|
||||
{
|
||||
$ses_request = $this->getRequestHandler('GET');
|
||||
$ses_request->setParameter('Action', 'GetSendQuota');
|
||||
|
||||
$ses_response = $ses_request->getResponse();
|
||||
|
||||
if ($ses_response->error === false && $ses_response->code !== 200) {
|
||||
$ses_response->error = array('code' => $ses_response->code, 'message' => 'Unexpected HTTP status');
|
||||
}
|
||||
if ($ses_response->error !== false) {
|
||||
return new \WP_Error($ses_response->code, $this->getErrorMessage('getSendQuota', $ses_response->error), $ses_response->error);
|
||||
}
|
||||
|
||||
$response = array();
|
||||
if (!isset($ses_response->body)) {
|
||||
return $response;
|
||||
}
|
||||
|
||||
$response['Max24HourSend'] = (string)$ses_response->body->GetSendQuotaResult->Max24HourSend;
|
||||
$response['MaxSendRate'] = (string)$ses_response->body->GetSendQuotaResult->MaxSendRate;
|
||||
$response['SentLast24Hours'] = (string)$ses_response->body->GetSendQuotaResult->SentLast24Hours;
|
||||
$response['RequestId'] = (string)$ses_response->body->ResponseMetadata->RequestId;
|
||||
|
||||
return $response;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves statistics for the last two weeks of activity on this account.
|
||||
* See http://docs.amazonwebservices.com/ses/latest/APIReference/API_GetSendStatistics.html
|
||||
*
|
||||
* @return array An array of activity statistics. Each array item covers a 15-minute period.
|
||||
*/
|
||||
public function getSendStatistics()
|
||||
{
|
||||
$ses_request = $this->getRequestHandler('GET');
|
||||
$ses_request->setParameter('Action', 'GetSendStatistics');
|
||||
|
||||
$ses_response = $ses_request->getResponse();
|
||||
if ($ses_response->error === false && $ses_response->code !== 200) {
|
||||
$ses_response->error = array('code' => $ses_response->code, 'message' => 'Unexpected HTTP status');
|
||||
}
|
||||
if ($ses_response->error !== false) {
|
||||
$this->__triggerError('getSendStatistics', $ses_response->error);
|
||||
return false;
|
||||
}
|
||||
|
||||
$response = array();
|
||||
if (!isset($ses_response->body)) {
|
||||
return $response;
|
||||
}
|
||||
|
||||
$datapoints = array();
|
||||
foreach ($ses_response->body->GetSendStatisticsResult->SendDataPoints->member as $datapoint) {
|
||||
$p = array();
|
||||
$p['Bounces'] = (string)$datapoint->Bounces;
|
||||
$p['Complaints'] = (string)$datapoint->Complaints;
|
||||
$p['DeliveryAttempts'] = (string)$datapoint->DeliveryAttempts;
|
||||
$p['Rejects'] = (string)$datapoint->Rejects;
|
||||
$p['Timestamp'] = (string)$datapoint->Timestamp;
|
||||
|
||||
$datapoints[] = $p;
|
||||
}
|
||||
|
||||
$response['SendDataPoints'] = $datapoints;
|
||||
$response['RequestId'] = (string)$ses_response->body->ResponseMetadata->RequestId;
|
||||
|
||||
return $response;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Given a SimpleEmailServiceMessage object, submits the message to the service for sending.
|
||||
*
|
||||
* @param SimpleEmailServiceMessage $sesMessage An instance of the message class
|
||||
* @param boolean $use_raw_request If this is true or there are attachments to the email `SendRawEmail` call will be used
|
||||
* @param boolean $trigger_error Optionally overwrite the class setting for triggering an error (with type check to true/false)
|
||||
* @return array An array containing the unique identifier for this message and a separate request id.
|
||||
* Returns false if the provided message is missing any required fields.
|
||||
* @link(AWS SES Response formats, http://docs.aws.amazon.com/ses/latest/DeveloperGuide/query-interface-responses.html)
|
||||
*/
|
||||
public function sendEmail($sesMessage, $use_raw_request = false, $trigger_error = null)
|
||||
{
|
||||
if (!$sesMessage->validate()) {
|
||||
$this->__triggerError('sendEmail', 'Message failed validation.');
|
||||
return false;
|
||||
}
|
||||
|
||||
$ses_request = $this->getRequestHandler('POST');
|
||||
$action = !empty($sesMessage->attachments) || $use_raw_request ? 'SendRawEmail' : 'SendEmail';
|
||||
$ses_request->setParameter('Action', $action);
|
||||
|
||||
// Works with both calls
|
||||
if (!is_null($sesMessage->configuration_set)) {
|
||||
$ses_request->setParameter('ConfigurationSetName', $sesMessage->configuration_set);
|
||||
}
|
||||
|
||||
if ($action == 'SendRawEmail') {
|
||||
// https://docs.aws.amazon.com/ses/latest/APIReference/API_SendRawEmail.html
|
||||
$ses_request->setParameter('RawMessage.Data', $sesMessage->mime);
|
||||
} else {
|
||||
$i = 1;
|
||||
foreach ($sesMessage->to as $to) {
|
||||
$ses_request->setParameter('Destination.ToAddresses.member.' . $i, $sesMessage->encodeRecipients($to));
|
||||
$i++;
|
||||
}
|
||||
|
||||
if (is_array($sesMessage->cc)) {
|
||||
$i = 1;
|
||||
foreach ($sesMessage->cc as $cc) {
|
||||
$ses_request->setParameter('Destination.CcAddresses.member.' . $i, $sesMessage->encodeRecipients($cc));
|
||||
$i++;
|
||||
}
|
||||
}
|
||||
|
||||
if (is_array($sesMessage->bcc)) {
|
||||
$i = 1;
|
||||
foreach ($sesMessage->bcc as $bcc) {
|
||||
$ses_request->setParameter('Destination.BccAddresses.member.' . $i, $sesMessage->encodeRecipients($bcc));
|
||||
$i++;
|
||||
}
|
||||
}
|
||||
|
||||
if (is_array($sesMessage->replyto)) {
|
||||
$i = 1;
|
||||
foreach ($sesMessage->replyto as $replyto) {
|
||||
$ses_request->setParameter('ReplyToAddresses.member.' . $i, $sesMessage->encodeRecipients($replyto));
|
||||
$i++;
|
||||
}
|
||||
}
|
||||
|
||||
$ses_request->setParameter('Source', $sesMessage->encodeRecipients($sesMessage->from));
|
||||
|
||||
if ($sesMessage->returnpath != null) {
|
||||
$ses_request->setParameter('ReturnPath', $sesMessage->returnpath);
|
||||
}
|
||||
|
||||
if ($sesMessage->subject != null && strlen($sesMessage->subject) > 0) {
|
||||
$ses_request->setParameter('Message.Subject.Data', $sesMessage->subject);
|
||||
if ($sesMessage->subjectCharset != null && strlen($sesMessage->subjectCharset) > 0) {
|
||||
$ses_request->setParameter('Message.Subject.Charset', $sesMessage->subjectCharset);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if ($sesMessage->messagetext != null && strlen($sesMessage->messagetext) > 0) {
|
||||
$ses_request->setParameter('Message.Body.Text.Data', $sesMessage->messagetext);
|
||||
if ($sesMessage->messageTextCharset != null && strlen($sesMessage->messageTextCharset) > 0) {
|
||||
$ses_request->setParameter('Message.Body.Text.Charset', $sesMessage->messageTextCharset);
|
||||
}
|
||||
}
|
||||
|
||||
if ($sesMessage->messagehtml != null && strlen($sesMessage->messagehtml) > 0) {
|
||||
$ses_request->setParameter('Message.Body.Html.Data', $sesMessage->messagehtml);
|
||||
if ($sesMessage->messageHtmlCharset != null && strlen($sesMessage->messageHtmlCharset) > 0) {
|
||||
$ses_request->setParameter('Message.Body.Html.Charset', $sesMessage->messageHtmlCharset);
|
||||
}
|
||||
}
|
||||
|
||||
$i = 1;
|
||||
foreach ($sesMessage->message_tags as $key => $value) {
|
||||
$ses_request->setParameter('Tags.member.' . $i . '.Name', $key);
|
||||
$ses_request->setParameter('Tags.member.' . $i . '.Value', $value);
|
||||
$i++;
|
||||
}
|
||||
}
|
||||
|
||||
$ses_response = $ses_request->getResponse();
|
||||
if ($ses_response->error === false && $ses_response->code !== 200) {
|
||||
$response = array(
|
||||
'code' => $ses_response->code,
|
||||
'error' => array('Error' => array('message' => 'Unexpected HTTP status')),
|
||||
);
|
||||
return $response;
|
||||
}
|
||||
if ($ses_response->error !== false) {
|
||||
if (($this->__trigger_errors && ($trigger_error !== false)) || $trigger_error === true) {
|
||||
$this->__triggerError('sendEmail', $ses_response->error);
|
||||
return false;
|
||||
}
|
||||
return $ses_response;
|
||||
}
|
||||
|
||||
$response = array(
|
||||
'MessageId' => (string)$ses_response->body->{"{$action}Result"}->MessageId,
|
||||
'RequestId' => (string)$ses_response->body->ResponseMetadata->RequestId,
|
||||
);
|
||||
return $response;
|
||||
}
|
||||
|
||||
|
||||
public function sendRawEmail($sesMessage)
|
||||
{
|
||||
$ses_request = $this->getRequestHandler('POST');
|
||||
$ses_request->setParameter('Action', 'SendRawEmail');
|
||||
|
||||
// https://docs.aws.amazon.com/ses/latest/APIReference/API_SendRawEmail.html
|
||||
$ses_request->setParameter('RawMessage.Data', $sesMessage);
|
||||
|
||||
$ses_response = $ses_request->getResponse();
|
||||
if (($ses_response->error === false && $ses_response->code !== 200) || $ses_response->error !== false) {
|
||||
return new \WP_Error($ses_response->code, $this->getErrorMessage('sendRawEmail', $ses_response->error), $ses_response->error);
|
||||
}
|
||||
|
||||
return array(
|
||||
'MessageId' => (string)$ses_response->body->SendRawEmailResult->MessageId,
|
||||
'RequestId' => (string)$ses_response->body->ResponseMetadata->RequestId,
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Trigger an error message
|
||||
*
|
||||
* {@internal Used by member functions to output errors}
|
||||
* @param string $functionname The name of the function that failed
|
||||
* @param array $error Array containing error information
|
||||
* @return void
|
||||
*/
|
||||
public function __triggerError($functionname, $error)
|
||||
{
|
||||
trigger_error($this->getErrorMessage($functionname, $error), E_USER_WARNING); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
|
||||
}
|
||||
|
||||
public function getErrorMessage($functionname, $error)
|
||||
{
|
||||
if ($error == false) {
|
||||
return sprintf("SimpleEmailService::%s(): Encountered an error, but no description given", $functionname);
|
||||
} else if (isset($error['curl']) && $error['curl']) {
|
||||
return sprintf("SimpleEmailService::%s(): %s %s", $functionname, $error['code'], $error['message']);
|
||||
} else if (isset($error['Error'])) {
|
||||
$e = $error['Error'];
|
||||
return sprintf("SimpleEmailService::%s(): %s - %s: %s\nRequest Id: %s\n", $functionname, $e['Type'], $e['Code'], $e['Message'], $error['RequestId']);
|
||||
}
|
||||
|
||||
return sprintf("SimpleEmailService::%s(): Encountered an error: %s", $functionname, $error);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set SES Request
|
||||
*
|
||||
* @param SimpleEmailServiceRequest|null $ses_request description
|
||||
* @return SimpleEmailService $this
|
||||
*/
|
||||
public function setRequestHandler($ses_request = null)
|
||||
{
|
||||
if (!is_null($ses_request)) {
|
||||
$ses_request->setSES($this);
|
||||
}
|
||||
|
||||
$this->__ses_request = $ses_request;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get SES Request
|
||||
*
|
||||
* @param string $verb HTTP Verb: GET, POST, DELETE
|
||||
* @return SimpleEmailServiceRequest SES Request
|
||||
*/
|
||||
public function getRequestHandler($verb)
|
||||
{
|
||||
if (empty($this->__ses_request)) {
|
||||
$this->__ses_request = new SimpleEmailServiceRequest($this, $verb);
|
||||
} else {
|
||||
$this->__ses_request->setVerb($verb);
|
||||
}
|
||||
|
||||
return $this->__ses_request;
|
||||
}
|
||||
}
|
||||
+640
@@ -0,0 +1,640 @@
|
||||
<?php
|
||||
|
||||
namespace FluentMail\App\Services\Mailer\Providers\AmazonSes;
|
||||
|
||||
/**
|
||||
* SimpleEmailServiceMessage PHP class
|
||||
*
|
||||
* @link https://github.com/daniel-zahariev/php-aws-ses
|
||||
* @package AmazonSimpleEmailService
|
||||
* @version v0.9.1
|
||||
*/
|
||||
final class SimpleEmailServiceMessage {
|
||||
|
||||
// these are public for convenience only
|
||||
// these are not to be used outside of the SimpleEmailService class!
|
||||
public $to, $cc, $bcc, $replyto, $recipientsCharset;
|
||||
public $from, $returnpath;
|
||||
public $subject, $messagetext, $messagehtml;
|
||||
public $subjectCharset, $messageTextCharset, $messageHtmlCharset;
|
||||
public $attachments, $customHeaders, $configuration_set, $message_tags;
|
||||
public $is_clean, $raw_message;
|
||||
public $mime;
|
||||
|
||||
public function __construct() {
|
||||
$this->to = array();
|
||||
$this->cc = array();
|
||||
$this->bcc = array();
|
||||
$this->replyto = array();
|
||||
$this->recipientsCharset = 'UTF-8';
|
||||
|
||||
$this->from = null;
|
||||
$this->returnpath = null;
|
||||
|
||||
$this->subject = null;
|
||||
$this->messagetext = null;
|
||||
$this->messagehtml = null;
|
||||
|
||||
$this->subjectCharset = 'UTF-8';
|
||||
$this->messageTextCharset = 'UTF-8';
|
||||
$this->messageHtmlCharset = 'UTF-8';
|
||||
|
||||
$this->attachments = array();
|
||||
$this->customHeaders = array();
|
||||
$this->configuration_set = null;
|
||||
$this->message_tags = array();
|
||||
|
||||
$this->is_clean = true;
|
||||
$this->raw_message = null;
|
||||
}
|
||||
|
||||
/**
|
||||
* addTo, addCC, addBCC, and addReplyTo have the following behavior:
|
||||
* If a single address is passed, it is appended to the current list of addresses.
|
||||
* If an array of addresses is passed, that array is merged into the current list.
|
||||
*
|
||||
* @return SimpleEmailServiceMessage $this
|
||||
* @link http://docs.aws.amazon.com/ses/latest/APIReference/API_Destination.html
|
||||
*/
|
||||
public function addTo($to) {
|
||||
if (!is_array($to)) {
|
||||
$this->to[] = $to;
|
||||
} else {
|
||||
$this->to = array_unique(array_merge($this->to, $to));
|
||||
}
|
||||
|
||||
$this->is_clean = false;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return SimpleEmailServiceMessage $this
|
||||
*/
|
||||
public function setTo($to) {
|
||||
$this->to = (array) $to;
|
||||
|
||||
$this->is_clean = false;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Clear the To: email address(es) for the message
|
||||
*
|
||||
* @return SimpleEmailServiceMessage $this
|
||||
*/
|
||||
public function clearTo() {
|
||||
$this->to = array();
|
||||
|
||||
$this->is_clean = false;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return SimpleEmailServiceMessage $this
|
||||
* @see addTo()
|
||||
*/
|
||||
public function addCC($cc) {
|
||||
if (!is_array($cc)) {
|
||||
$this->cc[] = $cc;
|
||||
} else {
|
||||
$this->cc = array_merge($this->cc, $cc);
|
||||
}
|
||||
|
||||
$this->is_clean = false;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Clear the CC: email address(es) for the message
|
||||
*
|
||||
* @return SimpleEmailServiceMessage $this
|
||||
*/
|
||||
public function clearCC() {
|
||||
$this->cc = array();
|
||||
|
||||
$this->is_clean = false;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return SimpleEmailServiceMessage $this
|
||||
* @see addTo()
|
||||
*/
|
||||
public function addBCC($bcc) {
|
||||
if (!is_array($bcc)) {
|
||||
$this->bcc[] = $bcc;
|
||||
} else {
|
||||
$this->bcc = array_merge($this->bcc, $bcc);
|
||||
}
|
||||
|
||||
$this->is_clean = false;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Clear the BCC: email address(es) for the message
|
||||
*
|
||||
* @return SimpleEmailServiceMessage $this
|
||||
*/
|
||||
public function clearBCC() {
|
||||
$this->bcc = array();
|
||||
|
||||
$this->is_clean = false;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return SimpleEmailServiceMessage $this
|
||||
* @see addTo()
|
||||
*/
|
||||
public function addReplyTo($replyto) {
|
||||
if (!is_array($replyto)) {
|
||||
$this->replyto[] = $replyto;
|
||||
} else {
|
||||
$this->replyto = array_merge($this->replyto, $replyto);
|
||||
}
|
||||
|
||||
$this->is_clean = false;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Clear the Reply-To: email address(es) for the message
|
||||
*
|
||||
* @return SimpleEmailServiceMessage $this
|
||||
*/
|
||||
public function clearReplyTo() {
|
||||
$this->replyto = array();
|
||||
|
||||
$this->is_clean = false;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Clear all of the message recipients in one go
|
||||
*
|
||||
* @return SimpleEmailServiceMessage $this
|
||||
* @uses clearTo()
|
||||
* @uses clearCC()
|
||||
* @uses clearBCC()
|
||||
* @uses clearReplyTo()
|
||||
*/
|
||||
public function clearRecipients() {
|
||||
$this->clearTo();
|
||||
$this->clearCC();
|
||||
$this->clearBCC();
|
||||
$this->clearReplyTo();
|
||||
|
||||
$this->is_clean = false;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return SimpleEmailServiceMessage $this
|
||||
*/
|
||||
public function setFrom($from) {
|
||||
$this->from = $from;
|
||||
|
||||
$this->is_clean = false;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return SimpleEmailServiceMessage $this
|
||||
*/
|
||||
public function setReturnPath($returnpath) {
|
||||
$this->returnpath = $returnpath;
|
||||
|
||||
$this->is_clean = false;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return SimpleEmailServiceMessage $this
|
||||
*/
|
||||
public function setRecipientsCharset($charset) {
|
||||
$this->recipientsCharset = $charset;
|
||||
|
||||
$this->is_clean = false;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return SimpleEmailServiceMessage $this
|
||||
*/
|
||||
public function setSubject($subject) {
|
||||
$this->subject = $subject;
|
||||
|
||||
$this->is_clean = false;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return SimpleEmailServiceMessage $this
|
||||
*/
|
||||
public function setSubjectCharset($charset) {
|
||||
$this->subjectCharset = $charset;
|
||||
|
||||
$this->is_clean = false;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return SimpleEmailServiceMessage $this
|
||||
* @link http://docs.aws.amazon.com/ses/latest/APIReference/API_Message.html
|
||||
*/
|
||||
public function setMessageFromString($text, $html = null) {
|
||||
$this->messagetext = $text;
|
||||
$this->messagehtml = $html;
|
||||
|
||||
$this->is_clean = false;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return SimpleEmailServiceMessage $this
|
||||
*/
|
||||
public function setMessageFromFile($textfile, $htmlfile = null) {
|
||||
if (file_exists($textfile) && is_file($textfile) && is_readable($textfile)) {
|
||||
$this->messagetext = file_get_contents($textfile);
|
||||
} else {
|
||||
$this->messagetext = null;
|
||||
}
|
||||
if (file_exists($htmlfile) && is_file($htmlfile) && is_readable($htmlfile)) {
|
||||
$this->messagehtml = file_get_contents($htmlfile);
|
||||
} else {
|
||||
$this->messagehtml = null;
|
||||
}
|
||||
|
||||
$this->is_clean = false;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return SimpleEmailServiceMessage $this
|
||||
*/
|
||||
public function setMessageFromURL($texturl, $htmlurl = null) {
|
||||
if ($texturl !== null) {
|
||||
$this->messagetext = file_get_contents($texturl);
|
||||
} else {
|
||||
$this->messagetext = null;
|
||||
}
|
||||
if ($htmlurl !== null) {
|
||||
$this->messagehtml = file_get_contents($htmlurl);
|
||||
} else {
|
||||
$this->messagehtml = null;
|
||||
}
|
||||
|
||||
$this->is_clean = false;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return SimpleEmailServiceMessage $this
|
||||
*/
|
||||
public function setMessageCharset($textCharset, $htmlCharset = null) {
|
||||
$this->messageTextCharset = $textCharset;
|
||||
$this->messageHtmlCharset = $htmlCharset;
|
||||
|
||||
$this->is_clean = false;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return SimpleEmailServiceMessage $this
|
||||
*/
|
||||
public function setConfigurationSet($configuration_set = null) {
|
||||
$this->configuration_set = $configuration_set;
|
||||
|
||||
$this->is_clean = false;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array $message_tags
|
||||
*/
|
||||
public function getMessageTags() {
|
||||
return $this->message_tags;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return null|mixed $message_tag
|
||||
*/
|
||||
public function getMessageTag($key) {
|
||||
return isset($this->message_tags[$key]) ? $this->message_tags[$key] : null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add Message tag
|
||||
*
|
||||
* Both key and value can contain only ASCII letters (a-z, A-Z), numbers (0-9), underscores (_), or dashes (-) and be less than 256 characters.
|
||||
*
|
||||
* @param string $key
|
||||
* @param mixed $value
|
||||
* @return SimpleEmailServiceMessage $this
|
||||
* @link https://docs.aws.amazon.com/ses/latest/DeveloperGuide/event-publishing-send-email.html
|
||||
* @link https://docs.aws.amazon.com/ses/latest/APIReference/API_MessageTag.html
|
||||
*/
|
||||
public function setMessageTag($key, $value) {
|
||||
$this->message_tags[$key] = $value;
|
||||
|
||||
$this->is_clean = false;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $key The key of the tag to be removed
|
||||
* @return SimpleEmailServiceMessage $this
|
||||
*/
|
||||
public function removeMessageTag($key) {
|
||||
unset($this->message_tags[$key]);
|
||||
|
||||
$this->is_clean = false;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $message_tags
|
||||
* @return SimpleEmailServiceMessage $this
|
||||
*/
|
||||
public function setMessageTags($message_tags = array()) {
|
||||
$this->message_tags = array_merge($this->message_tags, $message_tags);
|
||||
|
||||
$this->is_clean = false;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return SimpleEmailServiceMessage $this
|
||||
*/
|
||||
public function removeMessageTags() {
|
||||
$this->message_tags = array();
|
||||
|
||||
$this->is_clean = false;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add custom header - this works only with SendRawEmail
|
||||
*
|
||||
* @param string $header Your custom header
|
||||
* @return SimpleEmailServiceMessage $this
|
||||
* @link( Restrictions on headers, http://docs.aws.amazon.com/ses/latest/DeveloperGuide/header-fields.html)
|
||||
*/
|
||||
public function addCustomHeader($header) {
|
||||
$this->customHeaders[] = $header;
|
||||
|
||||
$this->is_clean = false;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add email attachment by directly passing the content
|
||||
*
|
||||
* @param string $name The name of the file attachment as it will appear in the email
|
||||
* @param string $data The contents of the attachment file
|
||||
* @param string $mimeType Specify custom MIME type
|
||||
* @param string $contentId Content ID of the attachment for inclusion in the mail message
|
||||
* @param string $attachmentType Attachment type: attachment or inline
|
||||
* @return SimpleEmailServiceMessage $this
|
||||
*/
|
||||
public function addAttachmentFromData($name, $data, $mimeType = 'application/octet-stream', $contentId = null, $attachmentType = 'attachment') {
|
||||
$this->attachments[$name] = array(
|
||||
'name' => $name,
|
||||
'mimeType' => $mimeType,
|
||||
'data' => $data,
|
||||
'contentId' => $contentId,
|
||||
'attachmentType' => ($attachmentType == 'inline' ? 'inline; filename="' . $name . '"' : $attachmentType),
|
||||
);
|
||||
|
||||
$this->is_clean = false;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add email attachment by passing file path
|
||||
*
|
||||
* @param string $name The name of the file attachment as it will appear in the email
|
||||
* @param string $path Path to the attachment file
|
||||
* @param string $mimeType Specify custom MIME type
|
||||
* @param string $contentId Content ID of the attachment for inclusion in the mail message
|
||||
* @param string $attachmentType Attachment type: attachment or inline
|
||||
* @return boolean Status of the operation
|
||||
*/
|
||||
public function addAttachmentFromFile($name, $path, $mimeType = 'application/octet-stream', $contentId = null, $attachmentType = 'attachment') {
|
||||
if (file_exists($path) && is_file($path) && is_readable($path)) {
|
||||
$this->addAttachmentFromData($name, file_get_contents($path), $mimeType, $contentId, $attachmentType);
|
||||
return true;
|
||||
}
|
||||
|
||||
$this->is_clean = false;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add email attachment by passing file path
|
||||
*
|
||||
* @param string $name The name of the file attachment as it will appear in the email
|
||||
* @param string $url URL to the attachment file
|
||||
* @param string $mimeType Specify custom MIME type
|
||||
* @param string $contentId Content ID of the attachment for inclusion in the mail message
|
||||
* @param string $attachmentType Attachment type: attachment or inline
|
||||
* @return boolean Status of the operation
|
||||
*/
|
||||
public function addAttachmentFromUrl($name, $url, $mimeType = 'application/octet-stream', $contentId = null, $attachmentType = 'attachment') {
|
||||
$data = file_get_contents($url);
|
||||
if ($data !== false) {
|
||||
$this->addAttachmentFromData($name, $data, $mimeType, $contentId, $attachmentType);
|
||||
return true;
|
||||
}
|
||||
|
||||
$this->is_clean = false;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the existence of attached inline messages
|
||||
*
|
||||
* @return boolean
|
||||
*/
|
||||
public function hasInlineAttachments() {
|
||||
foreach ($this->attachments as $attachment) {
|
||||
if ($attachment['attachmentType'] != 'attachment') {
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the raw mail message
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getRawMessage($encode = true) {
|
||||
if ($this->is_clean && !is_null($this->raw_message) && $encode) {
|
||||
return $this->raw_message;
|
||||
}
|
||||
|
||||
$this->is_clean = true;
|
||||
|
||||
$boundary = uniqid(rand(), true);
|
||||
$raw_message = count($this->customHeaders) > 0 ? join("\n", $this->customHeaders) . "\n" : '';
|
||||
|
||||
if (!empty($this->message_tags)) {
|
||||
$message_tags = array();
|
||||
foreach ($this->message_tags as $key => $value) {
|
||||
$message_tags[] = "{$key}={$value}";
|
||||
}
|
||||
|
||||
$raw_message .= 'X-SES-MESSAGE-TAGS: ' . join(', ', $message_tags) . "\n";
|
||||
}
|
||||
|
||||
if (!is_null($this->configuration_set)) {
|
||||
$raw_message .= 'X-SES-CONFIGURATION-SET: ' . $this->configuration_set . "\n";
|
||||
}
|
||||
|
||||
$raw_message .= count($this->to) > 0 ? 'To: ' . $this->encodeRecipients($this->to) . "\n" : '';
|
||||
$raw_message .= 'From: ' . $this->encodeRecipients($this->from) . "\n";
|
||||
if (!empty($this->replyto)) {
|
||||
$raw_message .= 'Reply-To: ' . $this->encodeRecipients($this->replyto) . "\n";
|
||||
}
|
||||
|
||||
if (!empty($this->cc)) {
|
||||
$raw_message .= 'CC: ' . $this->encodeRecipients($this->cc) . "\n";
|
||||
}
|
||||
if (!empty($this->bcc)) {
|
||||
$raw_message .= 'BCC: ' . $this->encodeRecipients($this->bcc) . "\n";
|
||||
}
|
||||
|
||||
if ($this->subject != null && strlen($this->subject) > 0) {
|
||||
$raw_message .= 'Subject: =?' . $this->subjectCharset . '?B?' . base64_encode($this->subject) . "?=\n";
|
||||
}
|
||||
|
||||
$raw_message .= 'MIME-Version: 1.0' . "\n";
|
||||
$raw_message .= 'Content-type: ' . ($this->hasInlineAttachments() ? 'multipart/related' : 'Multipart/Mixed') . '; boundary="' . $boundary . '"' . "\n";
|
||||
$raw_message .= "\n--{$boundary}\n";
|
||||
$raw_message .= 'Content-type: Multipart/Alternative; boundary="alt-' . $boundary . '"' . "\n";
|
||||
|
||||
if ($this->messagetext != null && strlen($this->messagetext) > 0) {
|
||||
$charset = empty($this->messageTextCharset) ? '' : "; charset=\"{$this->messageTextCharset}\"";
|
||||
$raw_message .= "\n--alt-{$boundary}\n";
|
||||
$raw_message .= 'Content-Type: text/plain' . $charset . "\n\n";
|
||||
$raw_message .= $this->messagetext . "\n";
|
||||
}
|
||||
|
||||
|
||||
if ($this->messagehtml != null && strlen($this->messagehtml) > 0) {
|
||||
$charset = empty($this->messageHtmlCharset) ? '' : "; charset=\"{$this->messageHtmlCharset}\"";
|
||||
$raw_message .= "\n--alt-{$boundary}\n";
|
||||
$raw_message .= 'Content-Type: text/html' . $charset . "\n\n";
|
||||
$raw_message .= $this->messagehtml . "\n";
|
||||
}
|
||||
$raw_message .= "\n--alt-{$boundary}--\n";
|
||||
|
||||
foreach ($this->attachments as $attachment) {
|
||||
$raw_message .= "\n--{$boundary}\n";
|
||||
$raw_message .= 'Content-Type: ' . $attachment['mimeType'] . '; name="' . $attachment['name'] . '"' . "\n";
|
||||
$raw_message .= 'Content-Disposition: ' . $attachment['attachmentType'] . "\n";
|
||||
if (!empty($attachment['contentId'])) {
|
||||
$raw_message .= 'Content-ID: ' . $attachment['contentId'] . '' . "\n";
|
||||
}
|
||||
$raw_message .= 'Content-Transfer-Encoding: base64' . "\n";
|
||||
$raw_message .= "\n" . chunk_split(base64_encode($attachment['data']), 76, "\n") . "\n";
|
||||
}
|
||||
|
||||
$raw_message .= "\n--{$boundary}--\n";
|
||||
|
||||
if (!$encode) {
|
||||
return $raw_message;
|
||||
}
|
||||
|
||||
$this->raw_message = base64_encode($raw_message);
|
||||
|
||||
return $this->raw_message;
|
||||
}
|
||||
|
||||
/**
|
||||
* Encode recipient with the specified charset in `recipientsCharset`
|
||||
*
|
||||
* @return string Encoded recipients joined with comma
|
||||
*/
|
||||
public function encodeRecipients($recipient) {
|
||||
if (is_array($recipient)) {
|
||||
return join(', ', array_map(array($this, 'encodeRecipients'), $recipient));
|
||||
}
|
||||
|
||||
if (preg_match("/(.*)<(.*)>/", $recipient, $regs)) {
|
||||
$recipient = '=?' . $this->recipientsCharset . '?B?' . base64_encode($regs[1]) . '?= <' . $regs[2] . '>';
|
||||
}
|
||||
|
||||
return $recipient;
|
||||
}
|
||||
|
||||
/**
|
||||
* Validates whether the message object has sufficient information to submit a request to SES.
|
||||
*
|
||||
* This does not guarantee the message will arrive, nor that the request will succeed;
|
||||
* instead, it makes sure that no required fields are missing.
|
||||
*
|
||||
* This is used internally before attempting a SendEmail or SendRawEmail request,
|
||||
* but it can be used outside of this file if verification is desired.
|
||||
* May be useful if e.g. the data is being populated from a form; developers can generally
|
||||
* use this function to verify completeness instead of writing custom logic.
|
||||
*
|
||||
* @return boolean
|
||||
*/
|
||||
public function validate() {
|
||||
// at least one destination is required
|
||||
if (count($this->to) == 0 && count($this->cc) == 0 && count($this->bcc) == 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// sender is required
|
||||
if ($this->from == null || strlen($this->from) == 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// subject is required
|
||||
if (($this->subject == null || strlen($this->subject) == 0)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// message is required
|
||||
if ((empty($this->messagetext) || strlen((string) $this->messagetext) == 0)
|
||||
&& (empty($this->messagehtml) || strlen((string) $this->messagehtml) == 0)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
+376
@@ -0,0 +1,376 @@
|
||||
<?php
|
||||
|
||||
namespace FluentMail\App\Services\Mailer\Providers\AmazonSes;
|
||||
|
||||
/**
|
||||
* SimpleEmailServiceRequest PHP class
|
||||
*
|
||||
* @link https://github.com/daniel-zahariev/php-aws-ses
|
||||
* @package AmazonSimpleEmailService
|
||||
* @version v0.9.1
|
||||
*/
|
||||
class SimpleEmailServiceRequest
|
||||
{
|
||||
private $ses, $verb, $parameters = array();
|
||||
|
||||
// CURL request handler that can be reused
|
||||
protected $curl_handler = null;
|
||||
|
||||
// Holds the response from calling AWS's API
|
||||
protected $response;
|
||||
|
||||
//
|
||||
public static $curlOptions = array();
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* @param SimpleEmailService $ses The SimpleEmailService object making this request
|
||||
* @param string $verb HTTP verb
|
||||
* @return void
|
||||
*/
|
||||
public function __construct($ses = null, $verb = 'GET') {
|
||||
$this->ses = $ses;
|
||||
$this->verb = $verb;
|
||||
$this->response = (object) array('body' => '', 'code' => 0, 'error' => false);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Set SES class
|
||||
*
|
||||
* @param SimpleEmailService $ses
|
||||
* @return SimpleEmailServiceRequest $this
|
||||
*/
|
||||
public function setSES(SimpleEmailService $ses) {
|
||||
$this->ses = $ses;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set HTTP method
|
||||
*
|
||||
* @param string $verb
|
||||
* @return SimpleEmailServiceRequest $this
|
||||
*/
|
||||
public function setVerb($verb) {
|
||||
$this->verb = $verb;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set request parameter
|
||||
*
|
||||
* @param string $key Key
|
||||
* @param string $value Value
|
||||
* @param boolean $replace Whether to replace the key if it already exists (default true)
|
||||
* @return SimpleEmailServiceRequest $this
|
||||
*/
|
||||
public function setParameter($key, $value, $replace = true) {
|
||||
if(!$replace && isset($this->parameters[$key])) {
|
||||
$temp = (array)($this->parameters[$key]);
|
||||
$temp[] = $value;
|
||||
$this->parameters[$key] = $temp;
|
||||
} else {
|
||||
$this->parameters[$key] = $value;
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the params for the request
|
||||
*
|
||||
* @return array $params
|
||||
*/
|
||||
public function getParametersEncoded() {
|
||||
$params = array();
|
||||
|
||||
foreach ($this->parameters as $var => $value) {
|
||||
if(is_array($value)) {
|
||||
foreach($value as $v) {
|
||||
$params[] = $var.'='.$this->__customUrlEncode($v);
|
||||
}
|
||||
} else {
|
||||
$params[] = $var.'='.$this->__customUrlEncode($value);
|
||||
}
|
||||
}
|
||||
|
||||
sort($params, SORT_STRING);
|
||||
|
||||
return $params;
|
||||
}
|
||||
|
||||
/**
|
||||
* Clear the request parameters
|
||||
* @return SimpleEmailServiceRequest $this
|
||||
*/
|
||||
public function clearParameters() {
|
||||
$this->parameters = array();
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Instantiate and setup CURL handler for sending requests.
|
||||
* Instance is cashed in `$this->curl_handler`
|
||||
*
|
||||
* @return resource $curl_handler
|
||||
*/
|
||||
protected function getCurlHandler() {
|
||||
if (!empty($this->curl_handler))
|
||||
return $this->curl_handler;
|
||||
|
||||
$curl = curl_init();
|
||||
curl_setopt($curl, CURLOPT_USERAGENT, 'SimpleEmailService/php');
|
||||
|
||||
curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, ($this->ses->verifyHost() ? 2 : 0));
|
||||
curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, ($this->ses->verifyPeer() ? 1 : 0));
|
||||
curl_setopt($curl, CURLOPT_HEADER, false);
|
||||
curl_setopt($curl, CURLOPT_RETURNTRANSFER, false);
|
||||
curl_setopt($curl, CURLOPT_WRITEFUNCTION, array(&$this, '__responseWriteCallback'));
|
||||
curl_setopt($curl, CURLOPT_FOLLOWLOCATION, true);
|
||||
|
||||
foreach(self::$curlOptions as $option => $value) {
|
||||
curl_setopt($curl, $option, $value);
|
||||
}
|
||||
|
||||
$this->curl_handler = $curl;
|
||||
|
||||
return $this->curl_handler;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the response
|
||||
*
|
||||
* @return object | false
|
||||
*/
|
||||
public function getResponse() {
|
||||
|
||||
$url = 'https://'.$this->ses->getHost().'/';
|
||||
$query = implode('&', $this->getParametersEncoded());
|
||||
$headers = $this->getHeaders($query);
|
||||
|
||||
$curl_handler = $this->getCurlHandler();
|
||||
curl_setopt($curl_handler, CURLOPT_CUSTOMREQUEST, $this->verb);
|
||||
|
||||
// Request types
|
||||
switch ($this->verb) {
|
||||
case 'GET':
|
||||
case 'DELETE':
|
||||
$url .= '?'.$query;
|
||||
break;
|
||||
|
||||
case 'POST':
|
||||
curl_setopt($curl_handler, CURLOPT_POSTFIELDS, $query);
|
||||
$headers[] = 'Content-Type: application/x-www-form-urlencoded';
|
||||
break;
|
||||
}
|
||||
curl_setopt($curl_handler, CURLOPT_HTTPHEADER, $headers);
|
||||
curl_setopt($curl_handler, CURLOPT_URL, $url);
|
||||
|
||||
|
||||
// Execute, grab errors
|
||||
if (curl_exec($curl_handler)) {
|
||||
$this->response->code = curl_getinfo($curl_handler, CURLINFO_HTTP_CODE);
|
||||
} else {
|
||||
$this->response->error = array(
|
||||
'curl' => true,
|
||||
'code' => curl_errno($curl_handler),
|
||||
'message' => curl_error($curl_handler),
|
||||
);
|
||||
}
|
||||
|
||||
// cleanup for reusing the current instance for multiple requests
|
||||
curl_setopt($curl_handler, CURLOPT_POSTFIELDS, '');
|
||||
$this->parameters = array();
|
||||
|
||||
// Parse body into XML
|
||||
if ($this->response->error === false && !empty($this->response->body)) {
|
||||
$this->response->body = simplexml_load_string($this->response->body);
|
||||
|
||||
// Grab SES errors
|
||||
if (!in_array($this->response->code, array(200, 201, 202, 204))
|
||||
&& isset($this->response->body->Error)) {
|
||||
$error = $this->response->body->Error;
|
||||
$output = array();
|
||||
$output['curl'] = false;
|
||||
$output['Error'] = array();
|
||||
$output['Error']['Type'] = (string)$error->Type;
|
||||
$output['Error']['Code'] = (string)$error->Code;
|
||||
$output['Error']['Message'] = (string)$error->Message;
|
||||
$output['RequestId'] = (string)$this->response->body->RequestId;
|
||||
|
||||
$this->response->error = $output;
|
||||
unset($this->response->body);
|
||||
}
|
||||
}
|
||||
|
||||
$response = $this->response;
|
||||
$this->response = (object) array('body' => '', 'code' => 0, 'error' => false);
|
||||
|
||||
return $response;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get request headers
|
||||
* @param string $query
|
||||
* @return array
|
||||
*/
|
||||
protected function getHeaders($query) {
|
||||
$headers = array();
|
||||
|
||||
if ($this->ses->getRequestSignatureVersion() == SimpleEmailService::REQUEST_SIGNATURE_V4) {
|
||||
$date = (new \DateTime('now', new \DateTimeZone('UTC')))->format('Ymd\THis\Z');
|
||||
$headers[] = 'X-Amz-Date: ' . $date;
|
||||
$headers[] = 'Host: ' . $this->ses->getHost();
|
||||
$headers[] = 'Authorization: ' . $this->__getAuthHeaderV4($date, $query);
|
||||
|
||||
} else {
|
||||
// must be in format 'Sun, 06 Nov 1994 08:49:37 GMT'
|
||||
$date = gmdate('D, d M Y H:i:s e');
|
||||
$auth = 'AWS3-HTTPS AWSAccessKeyId='.$this->ses->getAccessKey();
|
||||
$auth .= ',Algorithm=HmacSHA256,Signature='.$this->__getSignature($date);
|
||||
|
||||
$headers[] = 'Date: ' . $date;
|
||||
$headers[] = 'Host: ' . $this->ses->getHost();
|
||||
$headers[] = 'X-Amzn-Authorization: ' . $auth;
|
||||
}
|
||||
|
||||
return $headers;
|
||||
}
|
||||
|
||||
/**
|
||||
* Destroy any leftover handlers
|
||||
*/
|
||||
public function __destruct() {
|
||||
if (!empty($this->curl_handler))
|
||||
@curl_close($this->curl_handler);
|
||||
}
|
||||
|
||||
/**
|
||||
* CURL write callback
|
||||
*
|
||||
* @param resource $curl CURL resource
|
||||
* @param string $data Data
|
||||
* @return integer
|
||||
*/
|
||||
private function __responseWriteCallback($curl, $data) {
|
||||
if (!isset($this->response->body)) {
|
||||
$this->response->body = $data;
|
||||
} else {
|
||||
$this->response->body .= $data;
|
||||
}
|
||||
|
||||
return strlen($data);
|
||||
}
|
||||
|
||||
/**
|
||||
* Contributed by afx114
|
||||
* URL encode the parameters as per http://docs.amazonwebservices.com/AWSECommerceService/latest/DG/index.html?Query_QueryAuth.html
|
||||
* PHP's rawurlencode() follows RFC 1738, not RFC 3986 as required by Amazon. The only difference is the tilde (~), so convert it back after rawurlencode
|
||||
* See: http://www.morganney.com/blog/API/AWS-Product-Advertising-API-Requires-a-Signed-Request.php
|
||||
*
|
||||
* @param string $var String to encode
|
||||
* @return string
|
||||
*/
|
||||
private function __customUrlEncode($var) {
|
||||
return str_replace('%7E', '~', rawurlencode($var));
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate the auth string using Hmac-SHA256
|
||||
*
|
||||
* @internal Used by SimpleEmailServiceRequest::getResponse()
|
||||
* @param string $string String to sign
|
||||
* @return string
|
||||
*/
|
||||
private function __getSignature($string) {
|
||||
return base64_encode(hash_hmac('sha256', $string, $this->ses->getSecretKey(), true));
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $key
|
||||
* @param string $dateStamp
|
||||
* @param string $regionName
|
||||
* @param string $serviceName
|
||||
* @param string $algo
|
||||
* @return string
|
||||
*/
|
||||
private function __getSigningKey($key, $dateStamp, $regionName, $serviceName, $algo) {
|
||||
$kDate = hash_hmac($algo, $dateStamp, 'AWS4' . $key, true);
|
||||
$kRegion = hash_hmac($algo, $regionName, $kDate, true);
|
||||
$kService = hash_hmac($algo, $serviceName, $kRegion, true);
|
||||
|
||||
return hash_hmac($algo,'aws4_request', $kService, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Implementation of AWS Signature Version 4
|
||||
* @see https://docs.aws.amazon.com/general/latest/gr/sigv4_signing.html
|
||||
* @param string $amz_datetime
|
||||
* @param string $query
|
||||
* @return string
|
||||
*/
|
||||
private function __getAuthHeaderV4($amz_datetime, $query) {
|
||||
$amz_date = substr($amz_datetime, 0, 8);
|
||||
$algo = 'sha256';
|
||||
$aws_algo = 'AWS4-HMAC-' . strtoupper($algo);
|
||||
|
||||
$host_parts = explode('.', $this->ses->getHost());
|
||||
$service = $host_parts[0];
|
||||
$region = $host_parts[1];
|
||||
|
||||
$canonical_uri = '/';
|
||||
if($this->verb === 'POST') {
|
||||
$canonical_querystring = '';
|
||||
$payload_data = $query;
|
||||
} else {
|
||||
$canonical_querystring = $query;
|
||||
$payload_data = '';
|
||||
}
|
||||
|
||||
// ************* TASK 1: CREATE A CANONICAL REQUEST *************
|
||||
$canonical_headers_list = [
|
||||
'host:' . $this->ses->getHost(),
|
||||
'x-amz-date:' . $amz_datetime
|
||||
];
|
||||
|
||||
$canonical_headers = implode("\n", $canonical_headers_list) . "\n";
|
||||
$signed_headers = 'host;x-amz-date';
|
||||
$payload_hash = hash($algo, $payload_data, false);
|
||||
|
||||
$canonical_request = implode("\n", array(
|
||||
$this->verb,
|
||||
$canonical_uri,
|
||||
$canonical_querystring,
|
||||
$canonical_headers,
|
||||
$signed_headers,
|
||||
$payload_hash
|
||||
));
|
||||
|
||||
// ************* TASK 2: CREATE THE STRING TO SIGN*************
|
||||
$credential_scope = $amz_date. '/' . $region . '/' . $service . '/' . 'aws4_request';
|
||||
$string_to_sign = implode("\n", array(
|
||||
$aws_algo,
|
||||
$amz_datetime,
|
||||
$credential_scope,
|
||||
hash($algo, $canonical_request, false)
|
||||
));
|
||||
|
||||
// ************* TASK 3: CALCULATE THE SIGNATURE *************
|
||||
// Create the signing key using the function defined above.
|
||||
$signing_key = $this->__getSigningKey($this->ses->getSecretKey(), $amz_date, $region, $service, $algo);
|
||||
|
||||
// Sign the string_to_sign using the signing_key
|
||||
$signature = hash_hmac($algo, $string_to_sign, $signing_key, false);
|
||||
|
||||
// ************* TASK 4: ADD SIGNING INFORMATION TO THE REQUEST *************
|
||||
return $aws_algo . ' ' . implode(', ', array(
|
||||
'Credential=' . $this->ses->getAccessKey() . '/' . $credential_scope,
|
||||
'SignedHeaders=' . $signed_headers ,
|
||||
'Signature=' . $signature
|
||||
));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,79 @@
|
||||
<?php
|
||||
|
||||
namespace FluentMail\App\Services\Mailer\Providers\AmazonSes;
|
||||
|
||||
use FluentMail\App\Models\Settings;
|
||||
use FluentMail\Includes\Support\Arr;
|
||||
use FluentMail\Includes\Support\ValidationException;
|
||||
use FluentMail\App\Services\Mailer\Providers\AmazonSes\SimpleEmailService;
|
||||
|
||||
class Validator
|
||||
{
|
||||
protected $errors = null;
|
||||
|
||||
protected $provider = null;
|
||||
|
||||
public function __construct($provider, $errors)
|
||||
{
|
||||
$this->errors = $errors;
|
||||
$this->provider = $provider;
|
||||
}
|
||||
|
||||
public function validate()
|
||||
{
|
||||
|
||||
$data = fluentMail('request')->except(['action', 'nonce']);
|
||||
|
||||
$inputs = Arr::only(
|
||||
$data['provider']['options'], ['access_key', 'secret_key', 'region']
|
||||
);
|
||||
|
||||
$ses = new SimpleEmailService(
|
||||
$inputs['access_key'],
|
||||
$inputs['secret_key'],
|
||||
'email.' . $inputs['region'] . '.amazonaws.com',
|
||||
false
|
||||
);
|
||||
|
||||
$result = $ses->listVerifiedEmailAddresses();
|
||||
|
||||
if (is_wp_error($result)) {
|
||||
throw new ValidationException(wp_kses_post($result->get_error_message()), 400);
|
||||
}
|
||||
|
||||
if ($result) {
|
||||
$senderEmail = Arr::get(
|
||||
$data, 'provider.options.sender_email'
|
||||
);
|
||||
|
||||
if (!in_array($senderEmail, $result['Addresses'])) {
|
||||
throw new \Exception(esc_html__('The from email is not verified', 'fluent-smtp'), 400);
|
||||
}
|
||||
|
||||
fluentMail(Settings::class)->saveVerifiedEmails($result['Addresses']);
|
||||
}
|
||||
}
|
||||
|
||||
public function errorHandler($errno, $errstr, $errfile, $errline, $errcontext)
|
||||
{
|
||||
if (isset($errcontext['e'])) {
|
||||
$message = $errcontext['e']['Message'];
|
||||
} else {
|
||||
$message = $errcontext['error']['message'];
|
||||
}
|
||||
|
||||
$newException = new ValidationException(
|
||||
'', $errno, null, array_merge(
|
||||
$this->errors, [
|
||||
'sender_email' => [
|
||||
$errcontext['functionname'] => $message
|
||||
]
|
||||
]
|
||||
)
|
||||
);
|
||||
|
||||
restore_error_handler();
|
||||
|
||||
throw $newException;
|
||||
}
|
||||
}
|
||||
+61
@@ -0,0 +1,61 @@
|
||||
<?php
|
||||
|
||||
namespace FluentMail\App\Services\Mailer\Providers\AmazonSes;
|
||||
|
||||
use FluentMail\Includes\Support\Arr;
|
||||
use FluentMail\App\Services\Mailer\ValidatorTrait as BaseValidatorTrait;
|
||||
|
||||
trait ValidatorTrait
|
||||
{
|
||||
use BaseValidatorTrait;
|
||||
|
||||
public function validateProviderInformation($connection)
|
||||
{
|
||||
$errors = [];
|
||||
|
||||
$keyStoreType = $connection['key_store'];
|
||||
|
||||
if ($keyStoreType == 'db') {
|
||||
if (!Arr::get($connection, 'access_key')) {
|
||||
$errors['access_key']['required'] = __('Access key is required.', 'fluent-smtp');
|
||||
}
|
||||
|
||||
if (!Arr::get($connection, 'secret_key')) {
|
||||
$errors['secret_key']['required'] = __('Secret key is required.', 'fluent-smtp');
|
||||
}
|
||||
} else if ($keyStoreType == 'wp_config') {
|
||||
if (!defined('FLUENTMAIL_AWS_ACCESS_KEY_ID') || !FLUENTMAIL_AWS_ACCESS_KEY_ID) {
|
||||
$errors['access_key']['required'] = __('Please define FLUENTMAIL_AWS_ACCESS_KEY_ID in wp-config.php file.', 'fluent-smtp');
|
||||
}
|
||||
|
||||
if (!defined('FLUENTMAIL_AWS_SECRET_ACCESS_KEY') || !FLUENTMAIL_AWS_SECRET_ACCESS_KEY) {
|
||||
$errors['secret_key']['required'] = __('Please define FLUENTMAIL_AWS_SECRET_ACCESS_KEY in wp-config.php file.', 'fluent-smtp');
|
||||
}
|
||||
}
|
||||
|
||||
if ($errors) {
|
||||
$this->throwValidationException($errors);
|
||||
}
|
||||
}
|
||||
|
||||
public function checkConnection($connection)
|
||||
{
|
||||
$connection = $this->filterConnectionVars($connection);
|
||||
$region = 'email.' . $connection['region'] . '.amazonaws.com';
|
||||
|
||||
$ses = new SimpleEmailService(
|
||||
$connection['access_key'],
|
||||
$connection['secret_key'],
|
||||
$region,
|
||||
true
|
||||
);
|
||||
|
||||
$lists = $ses->listVerifiedEmailAddresses();
|
||||
|
||||
if (is_wp_error($lists)) {
|
||||
$this->throwValidationException(['api_error' => $lists->get_error_message()]);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
<?php
|
||||
|
||||
namespace FluentMail\App\Services\Mailer\Providers\DefaultMail;
|
||||
|
||||
use Exception;
|
||||
use FluentMail\App\Services\Mailer\BaseHandler;
|
||||
|
||||
class Handler extends BaseHandler
|
||||
{
|
||||
public function send()
|
||||
{
|
||||
if ($this->preSend()) {
|
||||
return $this->postSend();
|
||||
}
|
||||
|
||||
return $this->handleResponse(new \WP_Error(422, __('Something went wrong!', 'fluent-smtp'), []) );
|
||||
}
|
||||
|
||||
protected function postSend()
|
||||
{
|
||||
try {
|
||||
$this->phpMailer->send();
|
||||
return $this->handleSuccess();
|
||||
} catch(Exception $e) {
|
||||
return $this->handleFailure($e);
|
||||
}
|
||||
}
|
||||
|
||||
protected function handleSuccess()
|
||||
{
|
||||
$data = [
|
||||
'code' => 200,
|
||||
'message' => 'OK'
|
||||
];
|
||||
|
||||
return $this->processResponse($data, true);
|
||||
}
|
||||
|
||||
protected function handleFailure($exception)
|
||||
{
|
||||
$error = new \WP_Error($exception->getCode(), $exception->getMessage(), []);
|
||||
return $this->handleResponse($error);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,337 @@
|
||||
<?php
|
||||
|
||||
namespace FluentMail\App\Services\Mailer\Providers\ElasticMail;
|
||||
|
||||
use FluentMail\Includes\Support\Arr;
|
||||
use FluentMail\App\Services\Mailer\BaseHandler;
|
||||
|
||||
class Handler extends BaseHandler
|
||||
{
|
||||
use ValidatorTrait;
|
||||
|
||||
protected $boundary = '';
|
||||
|
||||
protected $postbody = [];
|
||||
|
||||
protected $url = 'https://api.elasticemail.com/v2/';
|
||||
|
||||
public function send()
|
||||
{
|
||||
if ($this->preSend()) {
|
||||
return $this->postSend();
|
||||
}
|
||||
|
||||
return $this->handleResponse(new \WP_Error(422, __('Something went wrong!', 'fluent-smtp'), []));
|
||||
}
|
||||
|
||||
public function postSend()
|
||||
{
|
||||
$this->boundary = hash('sha256', uniqid('', true));
|
||||
$this->postbody = [];
|
||||
|
||||
$replyTo = $this->getReplyTo();
|
||||
|
||||
$postData = [
|
||||
'subject' => $this->getSubject(),
|
||||
'from' => $this->getParam('sender_email'),
|
||||
'fromName' => $this->getParam('sender_name'),
|
||||
'replyTo' => Arr::get($replyTo, 'email'),
|
||||
'replyToName' => Arr::get($replyTo, 'name'),
|
||||
'msgTo' => $this->getToFormatted(),
|
||||
'msgCC' => $this->getCcFormatted(), // with ; separated or null
|
||||
'msgBcc' => $this->getBccFormatted(), // with ; separated or null
|
||||
'bodyHtml' => '',
|
||||
'bodyText' => '',
|
||||
'charset' => $this->phpMailer->CharSet,
|
||||
'encodingType' => 0,
|
||||
'isTransactional' => ($this->getSetting('mail_type') == 'transactional') ? true : false
|
||||
];
|
||||
|
||||
if ($this->phpMailer->ContentType == 'text/html') {
|
||||
$postData['bodyHtml'] = $this->getBody();
|
||||
} else if ($this->phpMailer->ContentType == 'multipart/alternative') {
|
||||
$postData['bodyHtml'] = $this->getBody();
|
||||
$postData['bodyText'] = $this->phpMailer->AltBody;
|
||||
} else {
|
||||
$postData['bodyText'] = $this->getBody();
|
||||
}
|
||||
|
||||
foreach ($this->getParam('custom_headers') as $header) {
|
||||
$key = trim($header['key']);
|
||||
$postData['headers_' . $key] = $key . ': ' . trim($header['value']);
|
||||
}
|
||||
|
||||
$this->parseAllPostData($postData);
|
||||
$this->setAttachments();
|
||||
$this->postbody[] = '--' . $this->boundary . '--';
|
||||
|
||||
$actualData = implode('', $this->postbody);
|
||||
|
||||
try {
|
||||
$response = wp_remote_post($this->url . 'email/send?apikey=' . $this->getSetting('api_key'), array(
|
||||
'method' => 'POST',
|
||||
'headers' => array(
|
||||
'content-type' => 'multipart/form-data; boundary=' . $this->boundary
|
||||
),
|
||||
'body' => $actualData
|
||||
)
|
||||
);
|
||||
|
||||
if (is_wp_error($response)) {
|
||||
$returnResponse = new \WP_Error($response->get_error_code(), $response->get_error_message(), $response->get_error_messages());
|
||||
} else {
|
||||
$responseBody = wp_remote_retrieve_body($response);
|
||||
$responseBody = \json_decode($responseBody, true);
|
||||
|
||||
if (!$responseBody['success']) {
|
||||
$returnResponse = new \WP_Error('api_error', $responseBody['error'], $responseBody);
|
||||
} else {
|
||||
$returnResponse = [
|
||||
'code' => 200,
|
||||
'message' => $responseBody
|
||||
];
|
||||
}
|
||||
}
|
||||
} catch (\Exception $exception) {
|
||||
$returnResponse = new \WP_Error($exception->getCode(), $exception->getMessage(), []);
|
||||
}
|
||||
|
||||
$this->response = $returnResponse;
|
||||
|
||||
return $this->handleResponse($this->response);
|
||||
}
|
||||
|
||||
protected function parseAllPostData($data)
|
||||
{
|
||||
foreach ($data as $key => $item) {
|
||||
if (empty($item)) {
|
||||
continue;
|
||||
}
|
||||
if (is_array($item)) {
|
||||
$this->parseAllPostData($item);
|
||||
} else {
|
||||
$this->postbody[] = '--' . $this->boundary . "\r\n" . 'Content-Disposition: form-data; name=' . $key . "\r\n\r\n" . $item . "\r\n";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected function getFrom()
|
||||
{
|
||||
$from = [
|
||||
'email' => $this->getParam('sender_email')
|
||||
];
|
||||
|
||||
if ($name = $this->getParam('sender_name')) {
|
||||
$from['name'] = $name;
|
||||
}
|
||||
|
||||
return $from;
|
||||
}
|
||||
|
||||
protected function getReplyTo()
|
||||
{
|
||||
if ($replyTo = $this->getParam('headers.reply-to')) {
|
||||
return reset($replyTo);
|
||||
}
|
||||
return [
|
||||
'name' => '',
|
||||
'email' => ''
|
||||
];
|
||||
}
|
||||
|
||||
protected function getCcFormatted()
|
||||
{
|
||||
$ccs = $this->getCarbonCopy();
|
||||
if (!$ccs) {
|
||||
return null;
|
||||
}
|
||||
|
||||
$ccs = array_filter($ccs);
|
||||
|
||||
$toFormatted = [];
|
||||
foreach ($ccs as $toEmail) {
|
||||
if (!empty($toEmail['name'])) {
|
||||
$string = $toEmail['name'] . ' <' . $toEmail['email'] . '>';
|
||||
} else {
|
||||
$string = $toEmail['email'];
|
||||
}
|
||||
$toFormatted[] = $string;
|
||||
}
|
||||
|
||||
$toFormatted = array_filter($toFormatted);
|
||||
|
||||
return implode(';', $toFormatted);
|
||||
}
|
||||
|
||||
protected function getBccFormatted()
|
||||
{
|
||||
$ccs = $this->getBlindCarbonCopy();
|
||||
if (!$ccs) {
|
||||
return null;
|
||||
}
|
||||
|
||||
$ccs = array_filter($ccs);
|
||||
|
||||
$toFormatted = [];
|
||||
foreach ($ccs as $toEmail) {
|
||||
if (!empty($toEmail['name'])) {
|
||||
$string = $toEmail['name'] . ' <' . $toEmail['email'] . '>';
|
||||
} else {
|
||||
$string = $toEmail['email'];
|
||||
}
|
||||
$toFormatted[] = $string;
|
||||
}
|
||||
|
||||
$toFormatted = array_filter($toFormatted);
|
||||
|
||||
return implode(';', $toFormatted);
|
||||
}
|
||||
|
||||
protected function getToFormatted()
|
||||
{
|
||||
$to = $this->getParam('to');
|
||||
$toFormatted = [];
|
||||
|
||||
foreach ($to as $toEmail) {
|
||||
if (!empty($toEmail['name'])) {
|
||||
$string = $toEmail['name'] . ' <' . $toEmail['email'] . '>';
|
||||
} else {
|
||||
$string = $toEmail['email'];
|
||||
}
|
||||
$toFormatted[] = $string;
|
||||
}
|
||||
|
||||
$toFormatted = array_filter($toFormatted);
|
||||
|
||||
return implode(';', $toFormatted);
|
||||
}
|
||||
|
||||
protected function getCarbonCopy()
|
||||
{
|
||||
return $this->getParam('headers.cc');
|
||||
}
|
||||
|
||||
protected function getBlindCarbonCopy()
|
||||
{
|
||||
return $this->getParam('headers.bcc');
|
||||
}
|
||||
|
||||
protected function getBody()
|
||||
{
|
||||
return $this->getParam('message');
|
||||
}
|
||||
|
||||
protected function setAttachments()
|
||||
{
|
||||
$rawAttachments = $this->getParam('attachments');
|
||||
|
||||
if (empty($rawAttachments) === true) {
|
||||
return false;
|
||||
}
|
||||
|
||||
foreach ($rawAttachments as $i => $attpath) {
|
||||
if (empty($attpath) === true) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!is_readable($attpath[0]) || !is_file($attpath[0])) {
|
||||
continue;
|
||||
}
|
||||
|
||||
//Extracting the file name
|
||||
$filenameonly = explode(DIRECTORY_SEPARATOR, $attpath[0]);
|
||||
$fname = end($filenameonly);
|
||||
|
||||
$mimeType = 'application/octet-stream'; // Default
|
||||
if (function_exists('mime_content_type')) {
|
||||
$detectedMime = mime_content_type($attpath[0]);
|
||||
if ($detectedMime !== false) {
|
||||
$mimeType = $detectedMime;
|
||||
}
|
||||
} elseif (function_exists('finfo_file')) {
|
||||
$finfo = finfo_open(FILEINFO_MIME_TYPE);
|
||||
$detectedMime = finfo_file($finfo, $attpath[0]);
|
||||
finfo_close($finfo);
|
||||
if ($detectedMime !== false) {
|
||||
$mimeType = $detectedMime;
|
||||
}
|
||||
}
|
||||
|
||||
// Add boundary and headers for attachment
|
||||
$this->postbody[] = '--' . $this->boundary . "\r\n";
|
||||
$this->postbody[] = 'Content-Disposition: form-data; name="attachments' . ($i + 1) . '"; filename="' . $fname . '"' . "\r\n";
|
||||
$this->postbody[] = 'Content-Type: ' . $mimeType . "\r\n";
|
||||
$this->postbody[] = "\r\n";
|
||||
|
||||
$handle = fopen($attpath[0], "rb");
|
||||
if ($handle) {
|
||||
$fileContent = '';
|
||||
while (($buffer = fread($handle, 8192)) !== false && $buffer !== '') {
|
||||
$fileContent .= $buffer;
|
||||
}
|
||||
fclose($handle);
|
||||
|
||||
$this->postbody[] = $fileContent . "\r\n";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected function getCustomEmailHeaders()
|
||||
{
|
||||
return [];
|
||||
}
|
||||
|
||||
protected function getRequestHeaders()
|
||||
{
|
||||
return [
|
||||
'Content-Type' => 'application/json',
|
||||
'X-ElasticEmail-ApiKey' => $this->getSetting('api_key')
|
||||
];
|
||||
}
|
||||
|
||||
public function setSettings($settings)
|
||||
{
|
||||
if ($settings['key_store'] == 'wp_config') {
|
||||
$settings['api_key'] = defined('FLUENTMAIL_ELASTICMAIL_API_KEY') ? FLUENTMAIL_ELASTICMAIL_API_KEY : '';
|
||||
}
|
||||
|
||||
$this->settings = $settings;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function checkConnection($connection)
|
||||
{
|
||||
$this->setSettings($connection);
|
||||
$request = wp_remote_get($this->url . 'account/profileoverview', [
|
||||
'body' => [
|
||||
'apikey' => $this->getSetting('api_key')
|
||||
]
|
||||
]);
|
||||
|
||||
if (is_wp_error($request)) {
|
||||
$this->throwValidationException([
|
||||
'api_key' => [
|
||||
'required' => $request->get_error_message()
|
||||
]
|
||||
]);
|
||||
}
|
||||
|
||||
$response = json_decode(wp_remote_retrieve_body($request), true);
|
||||
|
||||
if (!$response || empty($response['success'])) {
|
||||
$error = 'API Key is invalid';
|
||||
if (!empty($response['error'])) {
|
||||
$error = $response['error'];
|
||||
}
|
||||
|
||||
$this->throwValidationException([
|
||||
'api_key' => [
|
||||
'required' => $error
|
||||
]
|
||||
]);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
+31
@@ -0,0 +1,31 @@
|
||||
<?php
|
||||
|
||||
namespace FluentMail\App\Services\Mailer\Providers\ElasticMail;
|
||||
|
||||
use FluentMail\Includes\Support\Arr;
|
||||
use FluentMail\App\Services\Mailer\ValidatorTrait as BaseValidatorTrait;
|
||||
|
||||
trait ValidatorTrait
|
||||
{
|
||||
use BaseValidatorTrait;
|
||||
|
||||
public function validateProviderInformation($connection)
|
||||
{
|
||||
$errors = [];
|
||||
$keyStoreType = $connection['key_store'];
|
||||
|
||||
if($keyStoreType == 'db') {
|
||||
if (! Arr::get($connection, 'api_key')) {
|
||||
$errors['api_key']['required'] = __('Api key is required.', 'fluent-smtp');
|
||||
}
|
||||
} else if($keyStoreType == 'wp_config') {
|
||||
if(!defined('FLUENTMAIL_ELASTICMAIL_API_KEY') || !FLUENTMAIL_ELASTICMAIL_API_KEY) {
|
||||
$errors['api_key']['required'] = __('Please define FLUENTMAIL_ELASTICMAIL_API_KEY in wp-config.php file.', 'fluent-smtp');
|
||||
}
|
||||
}
|
||||
|
||||
if ($errors) {
|
||||
$this->throwValidationException($errors);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,53 @@
|
||||
<?php
|
||||
|
||||
namespace FluentMail\App\Services\Mailer\Providers;
|
||||
|
||||
use InvalidArgumentException;
|
||||
use FluentMail\App\Models\Settings;
|
||||
use FluentMail\Includes\Core\Application;
|
||||
|
||||
class Factory
|
||||
{
|
||||
protected $app = null;
|
||||
|
||||
protected $settings = null;
|
||||
|
||||
public function __construct(Application $app, Settings $settings)
|
||||
{
|
||||
$this->app = $app;
|
||||
|
||||
$this->settings = $settings;
|
||||
}
|
||||
|
||||
public function make($provider)
|
||||
{
|
||||
return $this->app->make($provider);
|
||||
}
|
||||
|
||||
public function get($email)
|
||||
{
|
||||
if (!($conn = $this->settings->getConnection($email))) {
|
||||
$conn = $this->getDefaultProvider();
|
||||
}
|
||||
|
||||
if ($conn) {
|
||||
$settings = array_merge($conn['provider_settings'], [
|
||||
'title' => $conn['title']
|
||||
]);
|
||||
|
||||
return $this->make(
|
||||
$conn['provider_settings']['provider']
|
||||
)->setSettings($settings);
|
||||
}
|
||||
|
||||
|
||||
throw new InvalidArgumentException(
|
||||
esc_html__('There is no matching provider found by email: ', 'fluent-smtp') . $email // phpcs:ignore WordPress.Security.EscapeOutput.ExceptionNotEscaped
|
||||
);
|
||||
}
|
||||
|
||||
public function getDefaultProvider()
|
||||
{
|
||||
return fluentMailDefaultConnection();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,334 @@
|
||||
<?php
|
||||
|
||||
namespace FluentMail\App\Services\Mailer\Providers\Gmail;
|
||||
|
||||
use FluentMail\App\Models\Settings;
|
||||
use FluentMail\Includes\Support\Arr;
|
||||
use FluentMail\App\Services\Mailer\BaseHandler;
|
||||
|
||||
class Handler extends BaseHandler
|
||||
{
|
||||
|
||||
public function send()
|
||||
{
|
||||
if ($this->preSend() && $this->phpMailer->preSend()) {
|
||||
return $this->postSend();
|
||||
}
|
||||
|
||||
return $this->handleResponse(new \WP_Error(422, __('Something went wrong!', 'fluent-smtp'), []));
|
||||
}
|
||||
|
||||
protected function postSend()
|
||||
{
|
||||
try {
|
||||
$returnResponse = $this->sendViaApi();
|
||||
} catch (\Exception $e) {
|
||||
$returnResponse = new \WP_Error(422, $e->getMessage(), []);
|
||||
}
|
||||
|
||||
$this->response = $returnResponse;
|
||||
|
||||
return $this->handleResponse($this->response);
|
||||
}
|
||||
|
||||
public function setSettings($settings)
|
||||
{
|
||||
if (Arr::get($settings, 'key_store') == 'wp_config') {
|
||||
$settings['client_id'] = defined('FLUENTMAIL_GMAIL_CLIENT_ID') ? FLUENTMAIL_GMAIL_CLIENT_ID : '';
|
||||
$settings['client_secret'] = defined('FLUENTMAIL_GMAIL_CLIENT_SECRET') ? FLUENTMAIL_GMAIL_CLIENT_SECRET : '';
|
||||
}
|
||||
|
||||
$this->settings = $settings;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
private function sendViaApi()
|
||||
{
|
||||
if (!class_exists('\FluentSmtpLib\Google\Service\Gmail\Message')) {
|
||||
require_once FLUENTMAIL_PLUGIN_PATH . 'includes/libs/google-api-client/build/vendor/autoload.php';
|
||||
}
|
||||
|
||||
$message = $this->phpMailer->getSentMIMEMessage();
|
||||
|
||||
$data = $this->getSetting();
|
||||
|
||||
$googleApiMessage = new \FluentSmtpLib\Google\Service\Gmail\Message();
|
||||
|
||||
$file_size = strlen($message);
|
||||
$googleClient = $this->getApiClient($data);
|
||||
|
||||
if (is_wp_error($googleClient)) {
|
||||
return $googleClient;
|
||||
}
|
||||
|
||||
$googleService = new \FluentSmtpLib\Google\Service\Gmail($googleClient);
|
||||
|
||||
$result = array();
|
||||
try {
|
||||
$googleClient->setDefer(true);
|
||||
$result = $googleService->users_messages->send('me', $googleApiMessage, array('uploadType' => 'resumable'));
|
||||
|
||||
$chunkSizeBytes = 1 * 1024 * 1024;
|
||||
|
||||
// create mediafile upload
|
||||
$media = new \FluentSmtpLib\Google\Http\MediaFileUpload(
|
||||
$googleClient,
|
||||
$result,
|
||||
'message/rfc822',
|
||||
$message,
|
||||
true,
|
||||
$chunkSizeBytes
|
||||
);
|
||||
$media->setFileSize($file_size);
|
||||
|
||||
$status = false;
|
||||
while (!$status) {
|
||||
$status = $media->nextChunk();
|
||||
}
|
||||
$result = false;
|
||||
|
||||
// Reset to the client to execute requests immediately in the future.
|
||||
$googleClient->setDefer(false);
|
||||
|
||||
$googleMessageId = $status->getId();
|
||||
|
||||
} catch (\Exception $e) {
|
||||
$errorMessage = $e->getMessage();
|
||||
return new \WP_Error(422, $errorMessage, []);
|
||||
}
|
||||
|
||||
return array(
|
||||
'MessageId' => $googleMessageId,
|
||||
);
|
||||
}
|
||||
|
||||
public function validateProviderInformation($connection)
|
||||
{
|
||||
$errors = [];
|
||||
|
||||
$keyStoreType = $connection['key_store'];
|
||||
|
||||
$clientId = Arr::get($connection, 'client_id');
|
||||
$clientSecret = Arr::get($connection, 'client_secret');
|
||||
|
||||
if ($keyStoreType == 'db') {
|
||||
if (!$clientId) {
|
||||
$errors['client_id']['required'] = __('Application Client ID is required.', 'fluent-smtp');
|
||||
}
|
||||
|
||||
if (!$clientSecret) {
|
||||
$errors['client_secret']['required'] = __('Application Client Secret key is required.', 'fluent-smtp');
|
||||
}
|
||||
} else if ($keyStoreType == 'wp_config') {
|
||||
if (!defined('FLUENTMAIL_GMAIL_CLIENT_ID') || !FLUENTMAIL_GMAIL_CLIENT_ID) {
|
||||
$errors['client_id']['required'] = __('Please define FLUENTMAIL_GMAIL_CLIENT_ID in wp-config.php file.', 'fluent-smtp');
|
||||
} else {
|
||||
$clientId = FLUENTMAIL_GMAIL_CLIENT_ID;
|
||||
}
|
||||
|
||||
if (!defined('FLUENTMAIL_GMAIL_CLIENT_SECRET') || !FLUENTMAIL_GMAIL_CLIENT_SECRET) {
|
||||
$errors['client_secret']['required'] = __('Please define FLUENTMAIL_GMAIL_CLIENT_SECRET in wp-config.php file.', 'fluent-smtp');
|
||||
} else {
|
||||
$clientSecret = FLUENTMAIL_GMAIL_CLIENT_SECRET;
|
||||
}
|
||||
}
|
||||
|
||||
if ($errors) {
|
||||
$this->throwValidationException($errors);
|
||||
}
|
||||
|
||||
$accessToken = Arr::get($connection, 'access_token');
|
||||
$authToken = Arr::get($connection, 'auth_token');
|
||||
|
||||
if (!$accessToken && $authToken) {
|
||||
// this is new, We have to generate the tokens
|
||||
$body = [
|
||||
'code' => $authToken,
|
||||
'grant_type' => 'authorization_code',
|
||||
'redirect_uri' => apply_filters('fluentsmtp_gapi_callback', 'https://fluentsmtp.com/gapi/'), // 'urn:ietf:wg:oauth:2.0:oob'
|
||||
'client_id' => $clientId,
|
||||
'client_secret' => $clientSecret
|
||||
];
|
||||
$tokens = $this->makeRequest('https://accounts.google.com/o/oauth2/token', $body, 'POST');
|
||||
if (is_wp_error($tokens)) {
|
||||
$errors['auth_token']['required'] = $tokens->get_error_message();
|
||||
} else {
|
||||
add_filter('fluentmail_saving_connection_data', function ($con, $provider) use ($connection, $tokens) {
|
||||
|
||||
if ($provider != 'gmail') {
|
||||
return $con;
|
||||
}
|
||||
|
||||
if (Arr::get($con, 'connection.sender_email') != $connection['sender_email']) {
|
||||
return $con;
|
||||
}
|
||||
|
||||
$con['connection']['refresh_token'] = $tokens['refresh_token'];
|
||||
$con['connection']['access_token'] = $tokens['access_token'];
|
||||
$con['connection']['auth_token'] = '';
|
||||
$con['connection']['expire_stamp'] = time() + $tokens['expires_in'];
|
||||
$con['connection']['expires_in'] = $tokens['expires_in'];
|
||||
$con['connection']['version'] = 2;
|
||||
return $con;
|
||||
}, 10, 2);
|
||||
}
|
||||
} else if (!$authToken && !$accessToken) {
|
||||
$errors['auth_token']['required'] = __('Please Provide Auth Token.', 'fluent-smtp');
|
||||
}
|
||||
|
||||
if ($errors) {
|
||||
$this->throwValidationException($errors);
|
||||
}
|
||||
}
|
||||
|
||||
private function makeRequest($url, $bodyArgs, $type = 'GET', $headers = false)
|
||||
{
|
||||
if (!$headers) {
|
||||
$headers = array(
|
||||
'Content-Type' => 'application/http',
|
||||
'Content-Transfer-Encoding' => 'binary',
|
||||
'MIME-Version' => '1.0',
|
||||
);
|
||||
}
|
||||
|
||||
$args = [
|
||||
'headers' => $headers
|
||||
];
|
||||
if ($bodyArgs) {
|
||||
$args['body'] = json_encode($bodyArgs);
|
||||
}
|
||||
|
||||
|
||||
$args['method'] = $type;
|
||||
$request = wp_remote_request($url, $args);
|
||||
|
||||
if (is_wp_error($request)) {
|
||||
$message = $request->get_error_message();
|
||||
return new \WP_Error(422, $message);
|
||||
}
|
||||
|
||||
$body = json_decode(wp_remote_retrieve_body($request), true);
|
||||
|
||||
if (!empty($body['error'])) {
|
||||
$error = 'Unknown Error';
|
||||
if (isset($body['error_description'])) {
|
||||
$error = $body['error_description'];
|
||||
} else if (!empty($body['error']['message'])) {
|
||||
$error = $body['error']['message'];
|
||||
}
|
||||
return new \WP_Error(422, $error);
|
||||
}
|
||||
|
||||
return $body;
|
||||
}
|
||||
|
||||
private function saveNewTokens($existingData, $tokens)
|
||||
{
|
||||
if (empty($tokens['access_token']) || empty($tokens['refresh_token'])) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$senderEmail = $existingData['sender_email'];
|
||||
|
||||
$existingData['access_token'] = $tokens['access_token'];
|
||||
$existingData['refresh_token'] = $tokens['refresh_token'];
|
||||
$existingData['expire_stamp'] = $tokens['expires_in'] + time();
|
||||
$existingData['expires_in'] = $tokens['expires_in'];
|
||||
|
||||
(new Settings())->updateConnection($senderEmail, $existingData);
|
||||
fluentMailGetProvider($senderEmail, true); // we are clearing the static cache here
|
||||
wp_schedule_single_event($existingData['expire_stamp'] - 360, 'fluentsmtp_renew_gmail_token');
|
||||
return true;
|
||||
}
|
||||
|
||||
private function getApiClient($data)
|
||||
{
|
||||
$senderEmail = $data['sender_email'];
|
||||
|
||||
static $cachedServices = [];
|
||||
if (isset($cachedServices[$senderEmail])) {
|
||||
return $cachedServices[$senderEmail];
|
||||
}
|
||||
|
||||
if (!class_exists('\FluentSmtpLib\Google\Client')) {
|
||||
require_once FLUENTMAIL_PLUGIN_PATH . 'includes/libs/google-api-client/build/vendor/autoload.php';
|
||||
}
|
||||
|
||||
$client = new \FluentSmtpLib\Google\Client();
|
||||
$client->setClientId($data['client_id']);
|
||||
$client->setClientSecret($data['client_secret']);
|
||||
$client->addScope("https://www.googleapis.com/auth/gmail.compose");
|
||||
$client->setAccessType('offline');
|
||||
$client->setApprovalPrompt('force');
|
||||
|
||||
$tokens = [
|
||||
'access_token' => $data['access_token'],
|
||||
'refresh_token' => $data['refresh_token'],
|
||||
'expires_in' => $data['expire_stamp'] - time()
|
||||
];
|
||||
|
||||
$client->setAccessToken($tokens);
|
||||
|
||||
// check if expired or will be expired in 5 minutes
|
||||
if (($data['expire_stamp'] - 300) < time()) {
|
||||
$newTokens = $client->refreshToken($data['refresh_token']);
|
||||
|
||||
$result = $this->saveNewTokens($data, $newTokens);
|
||||
|
||||
if (!$result) {
|
||||
$errorDescription = Arr::get($newTokens, 'error_description');
|
||||
if (!$errorDescription) {
|
||||
$errorDescription = __('Failed to renew token with Gmail Api', 'fluent-smtp');
|
||||
}
|
||||
|
||||
return new \WP_Error('api_error', $errorDescription);
|
||||
}
|
||||
|
||||
$client->setAccessToken($newTokens);
|
||||
}
|
||||
|
||||
$cachedServices[$senderEmail] = $client;
|
||||
|
||||
return $cachedServices[$senderEmail];
|
||||
}
|
||||
|
||||
public function getConnectionInfo($connection)
|
||||
{
|
||||
if (Arr::get($connection, 'key_store') == 'wp_config') {
|
||||
$connection['client_id'] = defined('FLUENTMAIL_GMAIL_CLIENT_ID') ? FLUENTMAIL_GMAIL_CLIENT_ID : '';
|
||||
$connection['client_secret'] = defined('FLUENTMAIL_GMAIL_CLIENT_SECRET') ? FLUENTMAIL_GMAIL_CLIENT_SECRET : '';
|
||||
}
|
||||
|
||||
if (!class_exists('\FluentSmtpLib\Google\Client')) {
|
||||
require_once FLUENTMAIL_PLUGIN_PATH . 'includes/libs/google-api-client/build/vendor/autoload.php';
|
||||
}
|
||||
|
||||
$client = $this->getApiClient($connection);
|
||||
|
||||
if (is_wp_error($client)) {
|
||||
return '<p style="color: red; text-align: center; font-size: 18px;">ERROR: ' . $connection->get_error_message() . '</p>';
|
||||
}
|
||||
|
||||
$info = fluentMailgetConnection($connection['sender_email']);
|
||||
|
||||
$connection = $info->getSetting();
|
||||
|
||||
$extraRow = [
|
||||
'title' => __('Token Validity', 'fluent-smtp'),
|
||||
'content' => 'Valid (' . (int)(($connection['expire_stamp'] - time()) / 60) . 'minutes)'
|
||||
];
|
||||
|
||||
if (($connection['expire_stamp']) < time()) {
|
||||
$extraRow['content'] = __('Invalid. Please re-authenticate', 'fluent-smtp');
|
||||
}
|
||||
|
||||
$connection['extra_rows'] = [$extraRow];
|
||||
|
||||
return [
|
||||
'info' => (string)fluentMail('view')->make('admin.general_connection_info', [
|
||||
'connection' => $connection
|
||||
])
|
||||
];
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,248 @@
|
||||
<?php
|
||||
|
||||
namespace FluentMail\App\Services\Mailer\Providers\Mailgun;
|
||||
|
||||
use FluentMail\Includes\Support\Arr;
|
||||
use FluentMail\App\Services\Mailer\BaseHandler;
|
||||
|
||||
class Handler extends BaseHandler
|
||||
{
|
||||
use ValidatorTrait;
|
||||
|
||||
protected $emailSentCode = 200;
|
||||
|
||||
protected $url = null;
|
||||
|
||||
const API_BASE_US = 'https://api.mailgun.net/v3/';
|
||||
|
||||
const API_BASE_EU = 'https://api.eu.mailgun.net/v3/';
|
||||
|
||||
public function send()
|
||||
{
|
||||
if ($this->preSend()) {
|
||||
$this->setUrl();
|
||||
return $this->postSend();
|
||||
}
|
||||
|
||||
return $this->handleResponse(new \WP_Error(422, __('Something went wrong!', 'fluent-smtp'), []));
|
||||
}
|
||||
|
||||
protected function setUrl()
|
||||
{
|
||||
$url = $this->getSetting('region') == 'eu' ? self::API_BASE_EU : self::API_BASE_US;
|
||||
|
||||
$url .= sanitize_text_field($this->getSetting('domain_name') . '/messages');
|
||||
|
||||
return $this->url = $url;
|
||||
}
|
||||
|
||||
public function postSend()
|
||||
{
|
||||
$content_type = $this->getHeader('content-type');
|
||||
$body = [
|
||||
'from' => $this->getFrom(),
|
||||
'subject' => $this->getSubject(),
|
||||
'h:X-Mailer' => 'FluentMail - Mailgun',
|
||||
'h:Content-Type' => $content_type
|
||||
];
|
||||
|
||||
if (stripos($content_type, 'html') === false) {
|
||||
$body['text'] = $this->getBody();
|
||||
} else if ($content_type == 'multipart/alternative') {
|
||||
$body['html'] = $this->getBody();
|
||||
$body['text'] = $this->phpMailer->AltBody;
|
||||
} else {
|
||||
$body['html'] = $this->getBody();
|
||||
}
|
||||
|
||||
if ($replyTo = $this->getReplyTo()) {
|
||||
$body['h:Reply-To'] = $replyTo;
|
||||
}
|
||||
|
||||
$recipients = [
|
||||
'to' => $this->getTo(),
|
||||
'cc' => $this->getCarbonCopy(),
|
||||
'bcc' => $this->getBlindCarbonCopy()
|
||||
];
|
||||
|
||||
if ($recipients = array_filter($recipients)) {
|
||||
$body = array_merge($body, $recipients);
|
||||
}
|
||||
|
||||
foreach ($this->getParam('custom_headers') as $header) {
|
||||
$key = trim($header['key']);
|
||||
$body['h:' . $key] = trim($header['value']);
|
||||
}
|
||||
|
||||
$params = [
|
||||
'body' => $body,
|
||||
'headers' => $this->getRequestHeaders()
|
||||
];
|
||||
|
||||
$params = array_merge($params, $this->getDefaultParams());
|
||||
|
||||
if (!empty($this->attributes['attachments'])) {
|
||||
$params = $this->getAttachments($params);
|
||||
}
|
||||
|
||||
$response = wp_safe_remote_post($this->url, $params);
|
||||
|
||||
if (is_wp_error($response)) {
|
||||
$returnResponse = new \WP_Error($response->get_error_code(), $response->get_error_message(), $response->get_error_messages());
|
||||
} else {
|
||||
$responseBody = wp_remote_retrieve_body($response);
|
||||
$responseCode = wp_remote_retrieve_response_code($response);
|
||||
|
||||
$isOKCode = $responseCode == $this->emailSentCode;
|
||||
|
||||
if ($isOKCode) {
|
||||
$responseBody = \json_decode($responseBody, true);
|
||||
}
|
||||
|
||||
if ($isOKCode && isset($responseBody['id'])) {
|
||||
$returnResponse = [
|
||||
'id' => Arr::get($responseBody, 'id'),
|
||||
'message' => Arr::get($responseBody, 'message')
|
||||
];
|
||||
} else {
|
||||
$returnResponse = new \WP_Error($responseCode, __('Mailgun API Error', 'fluent-smtp'), $responseBody);
|
||||
}
|
||||
}
|
||||
|
||||
$this->response = $returnResponse;
|
||||
|
||||
return $this->handleResponse($this->response);
|
||||
}
|
||||
|
||||
public function setSettings($settings)
|
||||
{
|
||||
if ($settings['key_store'] == 'wp_config') {
|
||||
$settings['api_key'] = defined('FLUENTMAIL_MAILGUN_API_KEY') ? FLUENTMAIL_MAILGUN_API_KEY : '';
|
||||
$settings['domain_name'] = defined('FLUENTMAIL_MAILGUN_DOMAIN') ? FLUENTMAIL_MAILGUN_DOMAIN : '';
|
||||
}
|
||||
$this->settings = $settings;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
protected function getFrom()
|
||||
{
|
||||
return $this->getParam('from');
|
||||
}
|
||||
|
||||
protected function getReplyTo()
|
||||
{
|
||||
return $this->getRecipients(
|
||||
$this->getParam('headers.reply-to')
|
||||
);
|
||||
}
|
||||
|
||||
protected function getTo()
|
||||
{
|
||||
return $this->getRecipients($this->getParam('to'));
|
||||
}
|
||||
|
||||
protected function getCarbonCopy()
|
||||
{
|
||||
return $this->getRecipients($this->getParam('headers.cc'));
|
||||
}
|
||||
|
||||
protected function getBlindCarbonCopy()
|
||||
{
|
||||
return $this->getRecipients($this->getParam('headers.bcc'));
|
||||
}
|
||||
|
||||
protected function getRecipients($recipients)
|
||||
{
|
||||
$array = array_map(function ($recipient) {
|
||||
return isset($recipient['name'])
|
||||
? $recipient['name'] . ' <' . $recipient['email'] . '>'
|
||||
: $recipient['email'];
|
||||
}, $recipients);
|
||||
|
||||
return implode(', ', $array);
|
||||
}
|
||||
|
||||
protected function getBody()
|
||||
{
|
||||
return $this->getParam('message');
|
||||
}
|
||||
|
||||
protected function getAttachments($params)
|
||||
{
|
||||
$data = [];
|
||||
$payload = '';
|
||||
$attachments = $this->attributes['attachments'];
|
||||
|
||||
foreach ($attachments as $attachment) {
|
||||
$file = false;
|
||||
|
||||
try {
|
||||
if (is_file($attachment[0]) && is_readable($attachment[0])) {
|
||||
$fileName = basename($attachment[0]);
|
||||
$file = file_get_contents($attachment[0]);
|
||||
}
|
||||
} catch (\Exception $e) {
|
||||
$file = false;
|
||||
}
|
||||
|
||||
if ($file === false) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$data[] = [
|
||||
'content' => $file,
|
||||
'name' => $fileName,
|
||||
];
|
||||
}
|
||||
|
||||
if (!empty($data)) {
|
||||
$boundary = hash('sha256', uniqid('', true));
|
||||
|
||||
foreach ($params['body'] as $key => $value) {
|
||||
if (is_array($value)) {
|
||||
foreach ($value as $child_key => $child_value) {
|
||||
$payload .= '--' . $boundary;
|
||||
$payload .= "\r\n";
|
||||
$payload .= 'Content-Disposition: form-data; name="' . $key . "\"\r\n\r\n";
|
||||
$payload .= $child_value;
|
||||
$payload .= "\r\n";
|
||||
}
|
||||
} else {
|
||||
$payload .= '--' . $boundary;
|
||||
$payload .= "\r\n";
|
||||
$payload .= 'Content-Disposition: form-data; name="' . $key . '"' . "\r\n\r\n";
|
||||
$payload .= $value;
|
||||
$payload .= "\r\n";
|
||||
}
|
||||
}
|
||||
|
||||
foreach ($data as $key => $attachment) {
|
||||
$payload .= '--' . $boundary;
|
||||
$payload .= "\r\n";
|
||||
$payload .= 'Content-Disposition: form-data; name="attachment[' . $key . ']"; filename="' . $attachment['name'] . '"' . "\r\n\r\n";
|
||||
$payload .= $attachment['content'];
|
||||
$payload .= "\r\n";
|
||||
}
|
||||
|
||||
$payload .= '--' . $boundary . '--';
|
||||
|
||||
$params['body'] = $payload;
|
||||
|
||||
$params['headers']['Content-Type'] = 'multipart/form-data; boundary=' . $boundary;
|
||||
|
||||
$this->attributes['headers']['content-type'] = 'multipart/form-data';
|
||||
}
|
||||
|
||||
return $params;
|
||||
}
|
||||
|
||||
protected function getRequestHeaders()
|
||||
{
|
||||
$apiKey = $this->getSetting('api_key');
|
||||
|
||||
return [
|
||||
'Authorization' => 'Basic ' . base64_encode('api:' . $apiKey)
|
||||
];
|
||||
}
|
||||
}
|
||||
+40
@@ -0,0 +1,40 @@
|
||||
<?php
|
||||
|
||||
namespace FluentMail\App\Services\Mailer\Providers\Mailgun;
|
||||
|
||||
use FluentMail\Includes\Support\Arr;
|
||||
use FluentMail\App\Services\Mailer\ValidatorTrait as BaseValidatorTrait;
|
||||
|
||||
trait ValidatorTrait
|
||||
{
|
||||
use BaseValidatorTrait;
|
||||
|
||||
public function validateProviderInformation($connection)
|
||||
{
|
||||
$errors = [];
|
||||
$keyStoreType = $connection['key_store'];
|
||||
|
||||
if($keyStoreType == 'db') {
|
||||
if (! Arr::get($connection, 'api_key')) {
|
||||
$errors['api_key']['required'] = __('Api key is required.', 'fluent-smtp');
|
||||
}
|
||||
|
||||
if (! Arr::get($connection, 'domain_name')) {
|
||||
$errors['domain_name']['required'] = __('Domain name is required.', 'fluent-smtp');
|
||||
}
|
||||
} else if($keyStoreType == 'wp_config') {
|
||||
if(!defined('FLUENTMAIL_MAILGUN_API_KEY') || !FLUENTMAIL_MAILGUN_API_KEY) {
|
||||
$errors['api_key']['required'] = __('Please define FLUENTMAIL_MAILGUN_API_KEY in wp-config.php file.', 'fluent-smtp');
|
||||
}
|
||||
|
||||
if(!defined('FLUENTMAIL_MAILGUN_DOMAIN') || !FLUENTMAIL_MAILGUN_DOMAIN) {
|
||||
$errors['domain_name']['required'] = __('Please define FLUENTMAIL_MAILGUN_DOMAIN in wp-config.php file.', 'fluent-smtp');
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if ($errors) {
|
||||
$this->throwValidationException($errors);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,106 @@
|
||||
<?php
|
||||
|
||||
namespace FluentMail\App\Services\Mailer\Providers\Outlook;
|
||||
|
||||
use FluentMail\Includes\Support\Arr;
|
||||
|
||||
class API
|
||||
{
|
||||
private $clientId;
|
||||
private $clientSecret;
|
||||
|
||||
public function __construct($clientId = '', $clientSecret = '')
|
||||
{
|
||||
$this->clientId = $clientId;
|
||||
$this->clientSecret = $clientSecret;
|
||||
}
|
||||
|
||||
public function getAuthUrl()
|
||||
{
|
||||
|
||||
$fluentClient = new \FluentMail\Includes\OAuth2Provider($this->getConfig());
|
||||
|
||||
return $fluentClient->getAuthorizationUrl();
|
||||
|
||||
}
|
||||
|
||||
public function generateToken($authCode)
|
||||
{
|
||||
return $this->sendTokenRequest('authorization_code', [
|
||||
'code' => $authCode
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return mixed|string
|
||||
*/
|
||||
public function sendTokenRequest($type, $params)
|
||||
{
|
||||
$fluentClient = new \FluentMail\Includes\OAuth2Provider($this->getConfig());
|
||||
try {
|
||||
$tokens = $fluentClient->getAccessToken($type, $params);
|
||||
return $tokens;
|
||||
} catch (\Exception$exception) {
|
||||
return new \WP_Error(422, $exception->getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array | \WP_Error
|
||||
*/
|
||||
public function sendMime($mime, $accessToken)
|
||||
{
|
||||
$response = wp_remote_request('https://graph.microsoft.com/v1.0/me/sendMail', [
|
||||
'method' => 'POST',
|
||||
'headers' => [
|
||||
'Authorization' => 'Bearer ' . $accessToken,
|
||||
'Content-Type' => 'text/plain'
|
||||
],
|
||||
'body' => $mime
|
||||
]);
|
||||
|
||||
if (is_wp_error($response)) {
|
||||
return $response;
|
||||
}
|
||||
|
||||
$responseCode = wp_remote_retrieve_response_code($response);
|
||||
|
||||
if ($responseCode >= 300) {
|
||||
$error = Arr::get($response, 'response.message');
|
||||
|
||||
if (!$error) {
|
||||
$responseBody = json_decode(wp_remote_retrieve_body($response), true);
|
||||
|
||||
$error = Arr::get($responseBody, 'error.message');
|
||||
if (!$error) {
|
||||
$error = __('Something with wrong with Outlook API. Please check your API Settings', 'fluent-smtp');
|
||||
}
|
||||
}
|
||||
|
||||
return new \WP_Error($responseCode, $error);
|
||||
}
|
||||
|
||||
$header = wp_remote_retrieve_headers($response);
|
||||
|
||||
return $header->getAll();
|
||||
}
|
||||
|
||||
public function getRedirectUrl()
|
||||
{
|
||||
return rest_url('fluent-smtp/outlook_callback');
|
||||
}
|
||||
|
||||
private function getConfig()
|
||||
{
|
||||
return [
|
||||
'clientId' => $this->clientId,
|
||||
'clientSecret' => $this->clientSecret,
|
||||
'redirectUri' => $this->getRedirectUrl(),
|
||||
'urlAuthorize' => 'https://login.microsoftonline.com/common/oauth2/v2.0/authorize',
|
||||
'urlAccessToken' => 'https://login.microsoftonline.com/common/oauth2/v2.0/token',
|
||||
'urlResourceOwnerDetails' => '',
|
||||
'scopes' => 'https://graph.microsoft.com/user.read https://graph.microsoft.com/mail.readwrite https://graph.microsoft.com/mail.send https://graph.microsoft.com/mail.send.shared offline_access'
|
||||
];
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,208 @@
|
||||
<?php
|
||||
|
||||
namespace FluentMail\App\Services\Mailer\Providers\Outlook;
|
||||
|
||||
use FluentMail\App\Models\Settings;
|
||||
use FluentMail\Includes\Support\Arr;
|
||||
use FluentMail\App\Services\Mailer\BaseHandler;
|
||||
|
||||
class Handler extends BaseHandler
|
||||
{
|
||||
|
||||
public function send()
|
||||
{
|
||||
$this->phpMailer->Encoding = 'base64';
|
||||
|
||||
if ($this->preSend() && $this->phpMailer->preSend()) {
|
||||
return $this->postSend();
|
||||
}
|
||||
|
||||
return $this->handleResponse(new \WP_Error(422, __('Something went wrong!', 'fluent-smtp'), []));
|
||||
}
|
||||
|
||||
protected function postSend()
|
||||
{
|
||||
try {
|
||||
$returnResponse = $this->sendViaApi();
|
||||
} catch (\Exception $e) {
|
||||
$returnResponse = new \WP_Error(422, $e->getMessage(), []);
|
||||
}
|
||||
|
||||
$this->response = $returnResponse;
|
||||
|
||||
return $this->handleResponse($this->response);
|
||||
}
|
||||
|
||||
public function setSettings($settings)
|
||||
{
|
||||
if (Arr::get($settings, 'key_store') == 'wp_config') {
|
||||
$settings['client_id'] = defined('FLUENTMAIL_OUTLOOK_CLIENT_ID') ? FLUENTMAIL_OUTLOOK_CLIENT_ID : '';
|
||||
$settings['client_secret'] = defined('FLUENTMAIL_OUTLOOK_CLIENT_SECRET') ? FLUENTMAIL_OUTLOOK_CLIENT_SECRET : '';
|
||||
}
|
||||
|
||||
$this->settings = $settings;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
private function sendViaApi()
|
||||
{
|
||||
$mime = chunk_split(base64_encode($this->phpMailer->getSentMIMEMessage()), 76, "\n");
|
||||
|
||||
$data = $this->getSetting();
|
||||
|
||||
$accessToken = $this->getAccessToken($data);
|
||||
|
||||
$api = (new API($data['client_id'], $data['client_secret']));
|
||||
|
||||
$result = $api->sendMime($mime, $accessToken);
|
||||
|
||||
if(is_wp_error($result)) {
|
||||
$errorMessage = $result->get_error_message();
|
||||
return new \WP_Error(422, $errorMessage, []);
|
||||
} else {
|
||||
return array(
|
||||
'RequestId' => $result['request-id'],
|
||||
);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public function validateProviderInformation($connection)
|
||||
{
|
||||
$errors = [];
|
||||
|
||||
$keyStoreType = $connection['key_store'];
|
||||
|
||||
$clientId = Arr::get($connection, 'client_id');
|
||||
$clientSecret = Arr::get($connection, 'client_secret');
|
||||
|
||||
if ($keyStoreType == 'db') {
|
||||
if (!$clientId) {
|
||||
$errors['client_id']['required'] = __('Application Client ID is required.', 'fluent-smtp');
|
||||
}
|
||||
|
||||
if (!$clientSecret) {
|
||||
$errors['client_secret']['required'] = __('Application Client Secret key is required.', 'fluent-smtp');
|
||||
}
|
||||
} else if ($keyStoreType == 'wp_config') {
|
||||
if (!defined('FLUENTMAIL_OUTLOOK_CLIENT_ID') || !FLUENTMAIL_OUTLOOK_CLIENT_ID) {
|
||||
$errors['client_id']['required'] = __('Please define FLUENTMAIL_OUTLOOK_CLIENT_ID in wp-config.php file.', 'fluent-smtp');
|
||||
} else {
|
||||
$clientId = FLUENTMAIL_OUTLOOK_CLIENT_ID;
|
||||
}
|
||||
|
||||
if (!defined('FLUENTMAIL_OUTLOOK_CLIENT_SECRET') || !FLUENTMAIL_OUTLOOK_CLIENT_SECRET) {
|
||||
$errors['client_secret']['required'] = __('Please define FLUENTMAIL_OUTLOOK_CLIENT_SECRET in wp-config.php file.', 'fluent-smtp');
|
||||
} else {
|
||||
$clientSecret = FLUENTMAIL_OUTLOOK_CLIENT_SECRET;
|
||||
}
|
||||
}
|
||||
|
||||
if ($errors) {
|
||||
$this->throwValidationException($errors);
|
||||
}
|
||||
|
||||
$accessToken = Arr::get($connection, 'access_token');
|
||||
$authToken = Arr::get($connection, 'auth_token');
|
||||
|
||||
if (!$accessToken && $authToken) {
|
||||
$tokens = (new API($clientId, $clientSecret))->generateToken($authToken);
|
||||
if (is_wp_error($tokens)) {
|
||||
$errors['auth_token']['required'] = $tokens->get_error_message();
|
||||
} else {
|
||||
add_filter('fluentmail_saving_connection_data', function ($con, $provider) use ($connection, $tokens) {
|
||||
|
||||
if ($provider != 'outlook') {
|
||||
return $con;
|
||||
}
|
||||
|
||||
if (Arr::get($con, 'connection.sender_email') != $connection['sender_email']) {
|
||||
return $con;
|
||||
}
|
||||
|
||||
$con['connection']['refresh_token'] = $tokens['refresh_token'];
|
||||
$con['connection']['access_token'] = $tokens['access_token'];
|
||||
$con['connection']['auth_token'] = '';
|
||||
$con['connection']['expire_stamp'] = time() + $tokens['expires_in'];
|
||||
|
||||
return $con;
|
||||
}, 10, 2);
|
||||
}
|
||||
} else if (!$authToken && !$accessToken) {
|
||||
$errors['auth_token']['required'] = __('Please Provide Auth Token.', 'fluent-smtp');
|
||||
}
|
||||
|
||||
if ($errors) {
|
||||
$this->throwValidationException($errors);
|
||||
}
|
||||
}
|
||||
|
||||
private function saveNewTokens($existingData, $tokens)
|
||||
{
|
||||
if (empty($tokens['access_token']) || empty($tokens['refresh_token'])) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$senderEmail = $existingData['sender_email'];
|
||||
|
||||
$existingData['access_token'] = $tokens['access_token'];
|
||||
$existingData['refresh_token'] = $tokens['refresh_token'];
|
||||
$existingData['expire_stamp'] = $tokens['expires_in'] + time();
|
||||
|
||||
(new Settings())->updateConnection($senderEmail, $existingData);
|
||||
return fluentMailGetProvider($senderEmail, true); // we are clearing the static cache here
|
||||
}
|
||||
|
||||
private function getAccessToken($config)
|
||||
{
|
||||
$accessToken = $config['access_token'];
|
||||
// check if expired or will be expired in 300 seconds
|
||||
if ( ($config['expire_stamp'] - 300) < time()) {
|
||||
$fluentAPi = (new API($config['client_id'], $config['client_secret']));
|
||||
|
||||
$tokens = $fluentAPi->sendTokenRequest('refresh_token', [
|
||||
'refresh_token' => $config['refresh_token']
|
||||
]);
|
||||
|
||||
if(is_wp_error($tokens)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$this->saveNewTokens($config, $tokens);
|
||||
|
||||
$accessToken = $tokens['access_token'];
|
||||
}
|
||||
|
||||
return $accessToken;
|
||||
}
|
||||
|
||||
public function getConnectionInfo($connection)
|
||||
{
|
||||
if (Arr::get($connection, 'key_store') == 'wp_config') {
|
||||
$connection['client_id'] = defined('FLUENTMAIL_OUTLOOK_CLIENT_ID') ? FLUENTMAIL_OUTLOOK_CLIENT_ID : '';
|
||||
$connection['client_secret'] = defined('FLUENTMAIL_OUTLOOK_CLIENT_SECRET') ? FLUENTMAIL_OUTLOOK_CLIENT_SECRET : '';
|
||||
}
|
||||
|
||||
$this->getAccessToken($connection);
|
||||
$info = fluentMailgetConnection($connection['sender_email']);
|
||||
$connection = $info->getSetting();
|
||||
|
||||
$extraRow = [
|
||||
'title' => __('Token Validity', 'fluent-smtp'),
|
||||
'content' => 'Valid (' . intval((($connection['expire_stamp'] - time()) / 60)) . 'm)'
|
||||
];
|
||||
|
||||
if (($connection['expire_stamp']) < time()) {
|
||||
$extraRow['content'] = 'Invalid. Please re-authenticate';
|
||||
}
|
||||
|
||||
$connection['extra_rows'] = [$extraRow];
|
||||
|
||||
return [
|
||||
'info' => (string)fluentMail('view')->make('admin.general_connection_info', [
|
||||
'connection' => $connection
|
||||
])
|
||||
];
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,211 @@
|
||||
<?php
|
||||
|
||||
namespace FluentMail\App\Services\Mailer\Providers\PepiPost;
|
||||
|
||||
use WP_Error as WPError;
|
||||
use FluentMail\Includes\Support\Arr;
|
||||
use FluentMail\Includes\Core\Application;
|
||||
use FluentMail\App\Services\Mailer\Manager;
|
||||
use FluentMail\App\Services\Mailer\BaseHandler;
|
||||
use FluentMail\App\Services\Mailer\Providers\PepiPost\ValidatorTrait;
|
||||
|
||||
class Handler extends BaseHandler
|
||||
{
|
||||
use ValidatorTrait;
|
||||
|
||||
protected $emailSentCode = 202;
|
||||
|
||||
protected $url = 'https://api.pepipost.com/v5/mail/send';
|
||||
|
||||
public function send()
|
||||
{
|
||||
if ($this->preSend()) {
|
||||
return $this->postSend();
|
||||
}
|
||||
|
||||
return $this->handleResponse(new \WP_Error(422, __('Something went wrong!', 'fluent-smtp'), []));
|
||||
}
|
||||
|
||||
public function postSend()
|
||||
{
|
||||
$body = [
|
||||
'from' => $this->getFrom(),
|
||||
'personalizations' => $this->getRecipients(),
|
||||
'subject' => $this->getSubject(),
|
||||
'content' => $this->getBody(),
|
||||
'headers' => $this->getCustomEmailHeaders()
|
||||
];
|
||||
|
||||
if ($replyTo = $this->getReplyTo()) {
|
||||
$body['reply_to'] = $replyTo;
|
||||
}
|
||||
|
||||
if (!empty($this->getParam('attachments'))) {
|
||||
$body['attachments'] = $this->getAttachments();
|
||||
}
|
||||
|
||||
$params = [
|
||||
'body' => json_encode($body),
|
||||
'headers' => $this->getRequestHeaders()
|
||||
];
|
||||
|
||||
$params = array_merge($params, $this->getDefaultParams());
|
||||
|
||||
$response = wp_safe_remote_post($this->url, $params);
|
||||
|
||||
if (is_wp_error($response)) {
|
||||
$returnResponse = new \WP_Error($response->get_error_code(), $response->get_error_message(), $response->get_error_messages());
|
||||
} else {
|
||||
$responseBody = wp_remote_retrieve_body($response);
|
||||
|
||||
$responseCode = wp_remote_retrieve_response_code($response);
|
||||
|
||||
$isOKCode = $responseCode == $this->emailSentCode;
|
||||
|
||||
$responseBody = \json_decode($responseBody, true);
|
||||
|
||||
if ($isOKCode) {
|
||||
$returnResponse = [
|
||||
'id' => Arr::get($responseBody, 'data.message_id'),
|
||||
'message' => Arr::get($responseBody, 'message_id')
|
||||
];
|
||||
} else {
|
||||
$returnResponse = new \WP_Error($responseCode, Arr::get($responseBody, 'error', 'Unknown Error'), $responseBody);
|
||||
}
|
||||
}
|
||||
|
||||
$this->response = $returnResponse;
|
||||
|
||||
return $this->handleResponse($this->response);
|
||||
}
|
||||
|
||||
public function setSettings($settings)
|
||||
{
|
||||
if ($settings['key_store'] == 'wp_config') {
|
||||
$settings['api_key'] = defined('FLUENTMAIL_PEPIPOST_API_KEY') ? FLUENTMAIL_PEPIPOST_API_KEY : '';
|
||||
}
|
||||
|
||||
$this->settings = $settings;
|
||||
return $this;
|
||||
}
|
||||
|
||||
protected function getFrom()
|
||||
{
|
||||
return [
|
||||
'name' => $this->getParam('sender_name'),
|
||||
'email' => $this->getParam('sender_email')
|
||||
];
|
||||
}
|
||||
|
||||
protected function getReplyTo()
|
||||
{
|
||||
if ($replyTo = $this->getParam('headers.reply-to')) {
|
||||
$replyTo = reset($replyTo);
|
||||
|
||||
return $replyTo['email'];
|
||||
}
|
||||
}
|
||||
|
||||
protected function getRecipients()
|
||||
{
|
||||
$recipients = [
|
||||
'to' => $this->getTo(),
|
||||
'cc' => $this->getCarbonCopy(),
|
||||
'bcc' => $this->getBlindCarbonCopy(),
|
||||
];
|
||||
|
||||
$recipients = array_filter($recipients);
|
||||
|
||||
foreach ($recipients as $key => $recipient) {
|
||||
$array = array_map(function ($recipient) {
|
||||
return isset($recipient['name'])
|
||||
? $recipient['name'] . ' <' . $recipient['email'] . '>'
|
||||
: $recipient['email'];
|
||||
}, $recipient);
|
||||
|
||||
$this->attributes['formatted'][$key] = implode(', ', $array);
|
||||
}
|
||||
|
||||
return [$recipients];
|
||||
}
|
||||
|
||||
protected function getTo()
|
||||
{
|
||||
return $this->getParam('to');
|
||||
}
|
||||
|
||||
protected function getCarbonCopy()
|
||||
{
|
||||
return array_map(function ($cc) {
|
||||
return ['email' => $cc['email']];
|
||||
}, $this->getParam('headers.cc'));
|
||||
}
|
||||
|
||||
protected function getBlindCarbonCopy()
|
||||
{
|
||||
return array_map(function ($bcc) {
|
||||
return ['email' => $bcc['email']];
|
||||
}, $this->getParam('headers.bcc'));
|
||||
}
|
||||
|
||||
protected function getBody()
|
||||
{
|
||||
$return = [
|
||||
[
|
||||
'type' => 'html',
|
||||
'value' => $this->getParam('message')
|
||||
]
|
||||
];
|
||||
|
||||
if ($this->phpMailer->contentType == 'multipart/alternative') {
|
||||
$return[] = [
|
||||
'type' => 'amp',
|
||||
'value' => $this->phpMailer->AltBody
|
||||
];
|
||||
}
|
||||
|
||||
return $return;
|
||||
}
|
||||
|
||||
protected function getAttachments()
|
||||
{
|
||||
$data = [];
|
||||
|
||||
foreach ($this->getParam('attachments') as $attachment) {
|
||||
$file = false;
|
||||
|
||||
try {
|
||||
if (is_file($attachment[0]) && is_readable($attachment[0])) {
|
||||
$fileName = basename($attachment[0]);
|
||||
$file = file_get_contents($attachment[0]);
|
||||
}
|
||||
} catch (\Exception $e) {
|
||||
$file = false;
|
||||
}
|
||||
|
||||
if ($file === false) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$data[] = [
|
||||
'name' => $fileName,
|
||||
'content' => base64_encode($file)
|
||||
];
|
||||
}
|
||||
|
||||
return $data;
|
||||
}
|
||||
|
||||
protected function getCustomEmailHeaders()
|
||||
{
|
||||
return [];
|
||||
}
|
||||
|
||||
protected function getRequestHeaders()
|
||||
{
|
||||
return [
|
||||
'content-type' => 'application/json',
|
||||
'api_key' => $this->getSetting('api_key')
|
||||
];
|
||||
}
|
||||
}
|
||||
+32
@@ -0,0 +1,32 @@
|
||||
<?php
|
||||
|
||||
namespace FluentMail\App\Services\Mailer\Providers\PepiPost;
|
||||
|
||||
use FluentMail\Includes\Support\Arr;
|
||||
use FluentMail\App\Services\Mailer\ValidatorTrait as BaseValidatorTrait;
|
||||
|
||||
trait ValidatorTrait
|
||||
{
|
||||
use BaseValidatorTrait;
|
||||
|
||||
public function validateProviderInformation($connection)
|
||||
{
|
||||
$errors = [];
|
||||
|
||||
$keyStoreType = $connection['key_store'];
|
||||
|
||||
if($keyStoreType == 'db') {
|
||||
if (! Arr::get($connection, 'api_key')) {
|
||||
$errors['api_key']['required'] = __('Api key is required.', 'fluent-smtp');
|
||||
}
|
||||
} else if($keyStoreType == 'wp_config') {
|
||||
if(!defined('FLUENTMAIL_PEPIPOST_API_KEY') || !FLUENTMAIL_PEPIPOST_API_KEY) {
|
||||
$errors['api_key']['required'] = __('Please define FLUENTMAIL_PEPIPOST_API_KEY in wp-config.php file.', 'fluent-smtp');
|
||||
}
|
||||
}
|
||||
|
||||
if ($errors) {
|
||||
$this->throwValidationException($errors);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,212 @@
|
||||
<?php
|
||||
|
||||
namespace FluentMail\App\Services\Mailer\Providers\Postmark;
|
||||
|
||||
use FluentMail\Includes\Support\Arr;
|
||||
use FluentMail\App\Services\Mailer\BaseHandler;
|
||||
|
||||
class Handler extends BaseHandler
|
||||
{
|
||||
use ValidatorTrait;
|
||||
|
||||
protected $emailSentCode = 200;
|
||||
|
||||
protected $url = 'https://api.postmarkapp.com/email';
|
||||
|
||||
public function send()
|
||||
{
|
||||
if ($this->preSend() && $this->phpMailer->preSend()) {
|
||||
return $this->postSend();
|
||||
}
|
||||
|
||||
return $this->handleResponse(new \WP_Error(422, __('Something went wrong!', 'fluent-smtp'), []));
|
||||
}
|
||||
|
||||
public function postSend()
|
||||
{
|
||||
$body = [
|
||||
'From' => $this->getParam('from'),
|
||||
'To' => $this->getTo(),
|
||||
'Subject' => $this->getSubject(),
|
||||
'MessageStream' => $this->getSetting('message_stream', 'outbound')
|
||||
];
|
||||
|
||||
if ($replyTo = $this->getReplyTo()) {
|
||||
$body['ReplyTo'] = $replyTo;
|
||||
}
|
||||
|
||||
if ($bcc = $this->getBlindCarbonCopy()) {
|
||||
$body['Bcc'] = $bcc;
|
||||
}
|
||||
|
||||
if ($cc = $this->getCarbonCopy()) {
|
||||
$body['Cc'] = $cc;
|
||||
}
|
||||
|
||||
$contentType = $this->getHeader('content-type');
|
||||
|
||||
if ($contentType == 'text/html') {
|
||||
$body['HtmlBody'] = $this->getParam('message');
|
||||
|
||||
if ($this->getSetting('track_opens') == 'yes') {
|
||||
$body['TrackOpens'] = true;
|
||||
}
|
||||
|
||||
if ($this->getSetting('track_links') == 'yes') {
|
||||
$body['TrackLinks'] = 'HtmlOnly';
|
||||
}
|
||||
} else if ($contentType == 'multipart/alternative') {
|
||||
$body['HtmlBody'] = $this->getParam('message');
|
||||
$body['TextBody'] = $this->phpMailer->AltBody;
|
||||
} else {
|
||||
$body['TextBody'] = $this->getParam('message');
|
||||
}
|
||||
|
||||
if (!empty($this->getParam('attachments'))) {
|
||||
$body['Attachments'] = $this->getAttachments();
|
||||
}
|
||||
|
||||
// Add any custom headers
|
||||
$customHeaders = $this->phpMailer->getCustomHeaders();
|
||||
if (!empty($customHeaders)) {
|
||||
foreach ($customHeaders as $header) {
|
||||
$body['Headers'][] = [
|
||||
'Name' => $header[0],
|
||||
'Value' => $header[1]
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Handle apostrophes in email address From names by escaping them for the Postmark API.
|
||||
$from_regex = "/(\"From\": \"[a-zA-Z\\d]+)*[\\\\]{2,}'/";
|
||||
|
||||
$args = array(
|
||||
'headers' => $this->getRequestHeaders(),
|
||||
'body' => preg_replace($from_regex, "'", wp_json_encode($body), 1),
|
||||
);
|
||||
|
||||
$response = wp_remote_post($this->url, $args);
|
||||
|
||||
if (is_wp_error($response)) {
|
||||
$returnResponse = new \WP_Error($response->get_error_code(), $response->get_error_message(), $response->get_error_messages());
|
||||
} else {
|
||||
$responseBody = wp_remote_retrieve_body($response);
|
||||
$responseCode = wp_remote_retrieve_response_code($response);
|
||||
|
||||
$isOKCode = $responseCode == $this->emailSentCode;
|
||||
|
||||
$responseBody = \json_decode($responseBody, true);
|
||||
|
||||
if ($isOKCode) {
|
||||
$returnResponse = [
|
||||
'id' => Arr::get($responseBody, 'MessageID'),
|
||||
'message' => Arr::get($responseBody, 'Message')
|
||||
];
|
||||
} else {
|
||||
$returnResponse = new \WP_Error($responseCode, Arr::get($responseBody, 'Message', 'Unknown Error'), $responseBody);
|
||||
}
|
||||
}
|
||||
|
||||
$this->response = $returnResponse;
|
||||
|
||||
return $this->handleResponse($this->response);
|
||||
}
|
||||
|
||||
public function setSettings($settings)
|
||||
{
|
||||
if ($settings['key_store'] == 'wp_config') {
|
||||
$settings['api_key'] = defined('FLUENTMAIL_POSTMARK_API_KEY') ? FLUENTMAIL_POSTMARK_API_KEY : '';
|
||||
}
|
||||
|
||||
$this->settings = $settings;
|
||||
return $this;
|
||||
}
|
||||
|
||||
protected function getReplyTo()
|
||||
{
|
||||
if ($replyTo = $this->getParam('headers.reply-to')) {
|
||||
$replyTo = reset($replyTo);
|
||||
return $replyTo['email'];
|
||||
}
|
||||
}
|
||||
|
||||
protected function getTo()
|
||||
{
|
||||
return $this->getRecipients($this->getParam('to'));
|
||||
}
|
||||
|
||||
protected function getCarbonCopy()
|
||||
{
|
||||
return $this->getRecipients($this->getParam('headers.cc'));
|
||||
}
|
||||
|
||||
protected function getBlindCarbonCopy()
|
||||
{
|
||||
return $this->getRecipients($this->getParam('headers.bcc'));
|
||||
}
|
||||
|
||||
protected function getRecipients($recipients)
|
||||
{
|
||||
$array = array_map(function ($recipient) {
|
||||
return isset($recipient['name'])
|
||||
? $recipient['name'] . ' <' . $recipient['email'] . '>'
|
||||
: $recipient['email'];
|
||||
}, $recipients);
|
||||
|
||||
return implode(', ', $array);
|
||||
}
|
||||
|
||||
protected function getAttachments()
|
||||
{
|
||||
$data = [];
|
||||
|
||||
foreach ($this->getParam('attachments') as $attachment) {
|
||||
$file = false;
|
||||
|
||||
try {
|
||||
if (is_file($attachment[0]) && is_readable($attachment[0])) {
|
||||
$fileName = basename($attachment[0]);
|
||||
$file = file_get_contents($attachment[0]);
|
||||
}
|
||||
} catch (\Exception $e) {
|
||||
$file = false;
|
||||
}
|
||||
|
||||
if ($file === false) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$data[] = [
|
||||
'Name' => $fileName,
|
||||
'Content' => base64_encode($file),
|
||||
'ContentType' => $this->determineMimeContentRype($attachment[0])
|
||||
];
|
||||
}
|
||||
|
||||
return $data;
|
||||
}
|
||||
|
||||
protected function getRequestHeaders()
|
||||
{
|
||||
return [
|
||||
'Accept' => 'application/json',
|
||||
'Content-Type' => 'application/json',
|
||||
'X-Postmark-Server-Token' => $this->getSetting('api_key'),
|
||||
];
|
||||
}
|
||||
|
||||
protected function determineMimeContentRype($filename)
|
||||
{
|
||||
if (function_exists('mime_content_type')) {
|
||||
return mime_content_type($filename);
|
||||
} elseif (function_exists('finfo_open')) {
|
||||
$finfo = finfo_open(FILEINFO_MIME_TYPE);
|
||||
$mime_type = finfo_file($finfo, $filename);
|
||||
finfo_close($finfo);
|
||||
return $mime_type;
|
||||
} else {
|
||||
return 'application/octet-stream';
|
||||
}
|
||||
}
|
||||
}
|
||||
+32
@@ -0,0 +1,32 @@
|
||||
<?php
|
||||
|
||||
namespace FluentMail\App\Services\Mailer\Providers\Postmark;
|
||||
|
||||
use FluentMail\Includes\Support\Arr;
|
||||
use FluentMail\App\Services\Mailer\ValidatorTrait as BaseValidatorTrait;
|
||||
|
||||
trait ValidatorTrait
|
||||
{
|
||||
use BaseValidatorTrait;
|
||||
|
||||
public function validateProviderInformation($connection)
|
||||
{
|
||||
$errors = [];
|
||||
|
||||
$keyStoreType = $connection['key_store'];
|
||||
|
||||
if($keyStoreType == 'db') {
|
||||
if (! Arr::get($connection, 'api_key')) {
|
||||
$errors['api_key']['required'] = __('Api key is required.', 'fluent-smtp');
|
||||
}
|
||||
} else if($keyStoreType == 'wp_config') {
|
||||
if(!defined('FLUENTMAIL_POSTMARK_API_KEY') || !FLUENTMAIL_POSTMARK_API_KEY) {
|
||||
$errors['api_key']['required'] = __('Please define FLUENTMAIL_POSTMARK_API_KEY in wp-config.php file.', 'fluent-smtp');
|
||||
}
|
||||
}
|
||||
|
||||
if ($errors) {
|
||||
$this->throwValidationException($errors);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,219 @@
|
||||
<?php
|
||||
|
||||
namespace FluentMail\App\Services\Mailer\Providers\SendGrid;
|
||||
|
||||
use WP_Error as WPError;
|
||||
use FluentMail\Includes\Support\Arr;
|
||||
use FluentMail\Includes\Core\Application;
|
||||
use FluentMail\App\Services\Mailer\Manager;
|
||||
use FluentMail\App\Services\Mailer\BaseHandler;
|
||||
use FluentMail\App\Services\Mailer\Providers\SendGrid\ValidatorTrait;
|
||||
|
||||
class Handler extends BaseHandler
|
||||
{
|
||||
use ValidatorTrait;
|
||||
|
||||
protected $emailSentCode = 202;
|
||||
|
||||
protected $url = 'https://api.sendgrid.com/v3/mail/send';
|
||||
|
||||
public function send()
|
||||
{
|
||||
if ($this->preSend()) {
|
||||
return $this->postSend();
|
||||
}
|
||||
|
||||
return $this->handleResponse(new \WP_Error(422, __('Something went wrong!', 'fluent-smtp'), []));
|
||||
}
|
||||
|
||||
public function postSend()
|
||||
{
|
||||
$body = [
|
||||
'from' => $this->getFrom(),
|
||||
'personalizations' => $this->getRecipients(),
|
||||
'subject' => $this->getSubject(),
|
||||
'content' => $this->getBody()
|
||||
];
|
||||
|
||||
if ($replyTo = $this->getReplyTo()) {
|
||||
$body['reply_to'] = $replyTo;
|
||||
}
|
||||
|
||||
|
||||
if (!empty($this->getParam('attachments'))) {
|
||||
$body['attachments'] = $this->getAttachments();
|
||||
}
|
||||
|
||||
$params = [
|
||||
'body' => json_encode($body),
|
||||
'headers' => $this->getRequestHeaders()
|
||||
];
|
||||
|
||||
$params = array_merge($params, $this->getDefaultParams());
|
||||
|
||||
$response = wp_safe_remote_post($this->url, $params);
|
||||
|
||||
if (is_wp_error($response)) {
|
||||
$returnResponse = new \WP_Error($response->get_error_code(), $response->get_error_message(), $response->get_error_messages());
|
||||
} else {
|
||||
$responseBody = wp_remote_retrieve_body($response);
|
||||
$responseCode = wp_remote_retrieve_response_code($response);
|
||||
$isOKCode = $responseCode == $this->emailSentCode;
|
||||
$responseBody = \json_decode($responseBody, true);
|
||||
|
||||
if ($isOKCode) {
|
||||
$returnResponse = [
|
||||
'code' => 202,
|
||||
'message' => Arr::get($responseBody, 'message')
|
||||
];
|
||||
} else {
|
||||
$returnResponse = new \WP_Error($responseCode, Arr::get($responseBody, 'errors.0.message', 'Unknown Error'), $responseBody);
|
||||
}
|
||||
}
|
||||
|
||||
$this->response = $returnResponse;
|
||||
|
||||
return $this->handleResponse($this->response);
|
||||
}
|
||||
|
||||
protected function getFrom()
|
||||
{
|
||||
$from = [
|
||||
'email' => $this->getParam('sender_email')
|
||||
];
|
||||
|
||||
if ($name = $this->getParam('sender_name')) {
|
||||
$from['name'] = $name;
|
||||
}
|
||||
|
||||
return $from;
|
||||
}
|
||||
|
||||
protected function getReplyTo()
|
||||
{
|
||||
if ($replyTo = $this->getParam('headers.reply-to')) {
|
||||
return reset($replyTo);
|
||||
}
|
||||
}
|
||||
|
||||
protected function getRecipients()
|
||||
{
|
||||
$recipients = [
|
||||
'to' => $this->getTo(),
|
||||
'cc' => $this->getCarbonCopy(),
|
||||
'bcc' => $this->getBlindCarbonCopy(),
|
||||
];
|
||||
|
||||
$recipients = array_filter($recipients);
|
||||
|
||||
foreach ($recipients as $key => $recipient) {
|
||||
$array = array_map(function ($recipient) {
|
||||
return isset($recipient['name'])
|
||||
? $recipient['name'] . ' <' . $recipient['email'] . '>'
|
||||
: $recipient['email'];
|
||||
}, $recipient);
|
||||
|
||||
$this->attributes['formatted'][$key] = implode(', ', $array);
|
||||
}
|
||||
|
||||
return [$recipients];
|
||||
}
|
||||
|
||||
protected function getTo()
|
||||
{
|
||||
return $this->getParam('to');
|
||||
}
|
||||
|
||||
protected function getCarbonCopy()
|
||||
{
|
||||
return $this->getParam('headers.cc');
|
||||
}
|
||||
|
||||
protected function getBlindCarbonCopy()
|
||||
{
|
||||
return $this->getParam('headers.bcc');
|
||||
}
|
||||
|
||||
protected function getBody()
|
||||
{
|
||||
$contentType = $this->getParam('headers.content-type');
|
||||
|
||||
if ($contentType == 'multipart/alternative') {
|
||||
return [
|
||||
[
|
||||
'value' => $this->phpMailer->AltBody,
|
||||
'type' => 'text/plain'
|
||||
],
|
||||
[
|
||||
'value' => $this->getParam('message'),
|
||||
'type' => 'text/html'
|
||||
]
|
||||
];
|
||||
}
|
||||
|
||||
return [
|
||||
[
|
||||
'value' => $this->getParam('message'),
|
||||
'type' => $contentType
|
||||
]
|
||||
];
|
||||
|
||||
}
|
||||
|
||||
protected function getAttachments()
|
||||
{
|
||||
$data = [];
|
||||
|
||||
foreach ($this->getParam('attachments') as $attachment) {
|
||||
$file = false;
|
||||
|
||||
try {
|
||||
if (is_file($attachment[0]) && is_readable($attachment[0])) {
|
||||
$fileName = basename($attachment[0]);
|
||||
$contentId = wp_hash($attachment[0]);
|
||||
$file = file_get_contents($attachment[0]);
|
||||
$mimeType = mime_content_type($attachment[0]);
|
||||
$filetype = str_replace(';', '', trim($mimeType));
|
||||
}
|
||||
} catch (\Exception $e) {
|
||||
$file = false;
|
||||
}
|
||||
|
||||
if ($file === false) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$data[] = [
|
||||
'type' => $filetype,
|
||||
'filename' => $fileName,
|
||||
'disposition' => 'attachment',
|
||||
'content_id' => $contentId,
|
||||
'content' => base64_encode($file)
|
||||
];
|
||||
}
|
||||
|
||||
return $data;
|
||||
}
|
||||
|
||||
protected function getCustomEmailHeaders()
|
||||
{
|
||||
return [];
|
||||
}
|
||||
|
||||
protected function getRequestHeaders()
|
||||
{
|
||||
return [
|
||||
'Content-Type' => 'application/json',
|
||||
'Authorization' => 'Bearer ' . $this->getSetting('api_key')
|
||||
];
|
||||
}
|
||||
|
||||
public function setSettings($settings)
|
||||
{
|
||||
if ($settings['key_store'] == 'wp_config') {
|
||||
$settings['api_key'] = defined('FLUENTMAIL_SENDGRID_API_KEY') ? FLUENTMAIL_SENDGRID_API_KEY : '';
|
||||
}
|
||||
$this->settings = $settings;
|
||||
return $this;
|
||||
}
|
||||
}
|
||||
+37
@@ -0,0 +1,37 @@
|
||||
<?php
|
||||
|
||||
namespace FluentMail\App\Services\Mailer\Providers\SendGrid;
|
||||
|
||||
use FluentMail\Includes\Support\Arr;
|
||||
use FluentMail\App\Services\Mailer\ValidatorTrait as BaseValidatorTrait;
|
||||
|
||||
trait ValidatorTrait
|
||||
{
|
||||
use BaseValidatorTrait;
|
||||
|
||||
public function validateProviderInformation($connection)
|
||||
{
|
||||
$errors = [];
|
||||
|
||||
$keyStoreType = $connection['key_store'];
|
||||
|
||||
if($keyStoreType == 'db') {
|
||||
if (! Arr::get($connection, 'api_key')) {
|
||||
$errors['api_key']['required'] = __('Api key is required.', 'fluent-smtp');
|
||||
}
|
||||
} else if($keyStoreType == 'wp_config') {
|
||||
if(!defined('FLUENTMAIL_SENDGRID_API_KEY') || !FLUENTMAIL_SENDGRID_API_KEY) {
|
||||
$errors['api_key']['required'] = __('Please define FLUENTMAIL_SENDGRID_API_KEY in wp-config.php file.', 'fluent-smtp');
|
||||
}
|
||||
}
|
||||
|
||||
if ($errors) {
|
||||
$this->throwValidationException($errors);
|
||||
}
|
||||
}
|
||||
|
||||
public function checkConnection($connection)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,199 @@
|
||||
<?php
|
||||
|
||||
namespace FluentMail\App\Services\Mailer\Providers\SendInBlue;
|
||||
|
||||
use WP_Error as WPError;
|
||||
use FluentMail\Includes\Support\Arr;
|
||||
use FluentMail\Includes\Core\Application;
|
||||
use FluentMail\App\Services\Mailer\Manager;
|
||||
use FluentMail\App\Services\Mailer\BaseHandler;
|
||||
use FluentMail\App\Services\Mailer\Providers\SendInBlue\ValidatorTrait;
|
||||
|
||||
class Handler extends BaseHandler
|
||||
{
|
||||
use ValidatorTrait;
|
||||
|
||||
protected $emailSentCode = 201;
|
||||
|
||||
protected $url = 'https://api.brevo.com/v3/smtp/email';
|
||||
|
||||
protected $allowedAttachmentExts = [
|
||||
'xlsx', 'xls', 'ods', 'docx', 'docm', 'doc', 'csv', 'pdf', 'txt', 'gif',
|
||||
'jpg', 'jpeg', 'png', 'tif', 'tiff', 'rtf', 'bmp', 'cgm', 'css', 'shtml',
|
||||
'html', 'htm', 'zip', 'xml', 'ppt', 'pptx', 'tar', 'ez', 'ics', 'mobi',
|
||||
'msg', 'pub', 'eps', 'odt', 'mp3', 'm4a', 'm4v', 'wma', 'ogg', 'flac',
|
||||
'wav', 'aif', 'aifc', 'aiff', 'mp4', 'mov', 'avi', 'mkv', 'mpeg', 'mpg', 'wmv'
|
||||
];
|
||||
|
||||
public function send()
|
||||
{
|
||||
if ($this->preSend()) {
|
||||
return $this->postSend();
|
||||
}
|
||||
|
||||
return $this->handleResponse(new \WP_Error(422, __('Something went wrong!', 'fluent-smtp'), []));
|
||||
}
|
||||
|
||||
public function postSend()
|
||||
{
|
||||
$body = [
|
||||
'sender' => $this->getFrom(),
|
||||
'subject' => $this->getSubject(),
|
||||
'htmlContent' => $this->getBody()
|
||||
];
|
||||
|
||||
$contentType = $this->getParam('headers.content-type');
|
||||
|
||||
if ($contentType == 'multipart/alternative') {
|
||||
$body['textContent'] = $this->phpMailer->AltBody;
|
||||
} else if ($contentType == 'text/plain') {
|
||||
$body['textContent'] = $this->getBody();
|
||||
unset($body['htmlContent']);
|
||||
}
|
||||
|
||||
if ($replyTo = $this->getReplyTo()) {
|
||||
$body['replyTo'] = $replyTo;
|
||||
}
|
||||
|
||||
$recipients = $this->setRecipients();
|
||||
|
||||
$body = array_merge($body, $recipients);
|
||||
|
||||
if (!empty($this->getParam('attachments'))) {
|
||||
$body['attachment'] = $this->getAttachments();
|
||||
}
|
||||
|
||||
$params = [
|
||||
'body' => json_encode($body),
|
||||
'headers' => $this->getRequestHeaders()
|
||||
];
|
||||
|
||||
$params = array_merge($params, $this->getDefaultParams());
|
||||
|
||||
$response = wp_safe_remote_post($this->url, $params);
|
||||
|
||||
if (is_wp_error($response)) {
|
||||
$returnResponse = new \WP_Error($response->get_error_code(), $response->get_error_message(), $response->get_error_messages());
|
||||
} else {
|
||||
$responseBody = wp_remote_retrieve_body($response);
|
||||
$responseCode = wp_remote_retrieve_response_code($response);
|
||||
|
||||
$isOKCode = $responseCode == $this->emailSentCode;
|
||||
|
||||
$responseBody = \json_decode($responseBody, true);
|
||||
|
||||
if ($isOKCode) {
|
||||
$returnResponse = [
|
||||
'messageId' => Arr::get($responseBody, 'messageId')
|
||||
];
|
||||
} else {
|
||||
$returnResponse = new \WP_Error($responseCode, Arr::get($responseBody, 'message', __('SendInBlueError API Error', 'fluent-smtp')), $responseBody);
|
||||
}
|
||||
}
|
||||
|
||||
$this->response = $returnResponse;
|
||||
|
||||
return $this->handleResponse($this->response);
|
||||
}
|
||||
|
||||
public function setSettings($settings)
|
||||
{
|
||||
if ($settings['key_store'] == 'wp_config') {
|
||||
$settings['api_key'] = defined('FLUENTMAIL_SENDINBLUE_API_KEY') ? FLUENTMAIL_SENDINBLUE_API_KEY : '';
|
||||
}
|
||||
$this->settings = $settings;
|
||||
return $this;
|
||||
}
|
||||
|
||||
protected function getFrom()
|
||||
{
|
||||
return [
|
||||
'name' => $this->getParam('sender_name'),
|
||||
'email' => $this->getParam('sender_email')
|
||||
];
|
||||
}
|
||||
|
||||
protected function getReplyTo()
|
||||
{
|
||||
if ($replyTo = $this->getParam('headers.reply-to')) {
|
||||
return reset($replyTo);
|
||||
}
|
||||
}
|
||||
|
||||
protected function setRecipients()
|
||||
{
|
||||
$recipients = [
|
||||
'to' => $this->getTo(),
|
||||
'cc' => $this->getCarbonCopy(),
|
||||
'bcc' => $this->getBlindCarbonCopy()
|
||||
];
|
||||
|
||||
$recipients = array_filter($recipients);
|
||||
|
||||
foreach ($recipients as $key => $recipient) {
|
||||
$array = array_map(function ($recipient) {
|
||||
return isset($recipient['name'])
|
||||
? $recipient['name'] . ' <' . $recipient['email'] . '>'
|
||||
: $recipient['email'];
|
||||
}, $recipient);
|
||||
|
||||
$this->attributes['formatted'][$key] = implode(', ', $array);
|
||||
}
|
||||
|
||||
return $recipients;
|
||||
}
|
||||
|
||||
protected function getTo()
|
||||
{
|
||||
return $this->getParam('to');
|
||||
}
|
||||
|
||||
protected function getCarbonCopy()
|
||||
{
|
||||
return $this->getParam('headers.cc');
|
||||
}
|
||||
|
||||
protected function getBlindCarbonCopy()
|
||||
{
|
||||
return $this->getParam('headers.bcc');
|
||||
}
|
||||
|
||||
protected function getBody()
|
||||
{
|
||||
return $this->getParam('message');
|
||||
}
|
||||
|
||||
protected function getAttachments()
|
||||
{
|
||||
$files = [];
|
||||
|
||||
foreach ($this->getParam('attachments') as $attachment) {
|
||||
if (is_file($attachment[0]) && is_readable($attachment[0])) {
|
||||
$ext = pathinfo($attachment[0], PATHINFO_EXTENSION);
|
||||
|
||||
if (in_array($ext, $this->allowedAttachmentExts, true)) {
|
||||
$files[] = [
|
||||
'name' => basename($attachment[0]),
|
||||
'content' => base64_encode(file_get_contents($attachment[0]))
|
||||
];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $files;
|
||||
}
|
||||
|
||||
protected function getCustomEmailHeaders()
|
||||
{
|
||||
return [];
|
||||
}
|
||||
|
||||
protected function getRequestHeaders()
|
||||
{
|
||||
return [
|
||||
'Api-Key' => $this->getSetting('api_key'),
|
||||
'Content-Type' => 'application/json',
|
||||
'Accept' => 'application/json'
|
||||
];
|
||||
}
|
||||
}
|
||||
+31
@@ -0,0 +1,31 @@
|
||||
<?php
|
||||
|
||||
namespace FluentMail\App\Services\Mailer\Providers\SendInBlue;
|
||||
|
||||
use FluentMail\Includes\Support\Arr;
|
||||
use FluentMail\App\Services\Mailer\ValidatorTrait as BaseValidatorTrait;
|
||||
|
||||
trait ValidatorTrait
|
||||
{
|
||||
use BaseValidatorTrait;
|
||||
|
||||
public function validateProviderInformation($connection)
|
||||
{
|
||||
$errors = [];
|
||||
$keyStoreType = $connection['key_store'];
|
||||
|
||||
if($keyStoreType == 'db') {
|
||||
if (! Arr::get($connection, 'api_key')) {
|
||||
$errors['api_key']['required'] = __('Api key is required.', 'fluent-smtp');
|
||||
}
|
||||
} else if($keyStoreType == 'wp_config') {
|
||||
if(!defined('FLUENTMAIL_SENDINBLUE_API_KEY') || !FLUENTMAIL_SENDINBLUE_API_KEY) {
|
||||
$errors['api_key']['required'] = __('Please define FLUENTMAIL_SENDINBLUE_API_KEY in wp-config.php file.', 'fluent-smtp');
|
||||
}
|
||||
}
|
||||
|
||||
if ($errors) {
|
||||
$this->throwValidationException($errors);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,57 @@
|
||||
<?php
|
||||
|
||||
namespace FluentMail\App\Services\Mailer\Providers\Simulator;
|
||||
|
||||
use FluentMail\App\Models\Logger;
|
||||
use FluentMail\App\Services\Mailer\BaseHandler;
|
||||
|
||||
class Handler extends BaseHandler
|
||||
{
|
||||
public function send()
|
||||
{
|
||||
if($this->shouldBeLogged(true)) {
|
||||
$atts = $this->setAttributes();
|
||||
|
||||
$customHeaders = $atts['custom_headers'];
|
||||
$headers = $atts['headers'];
|
||||
foreach ($customHeaders as $customHeader) {
|
||||
$headers[$customHeader['key']] = $customHeader['value'];
|
||||
}
|
||||
|
||||
$headers = $this->phpMailer->getCustomHeaders();
|
||||
$headers['content-type'] = $this->phpMailer->ContentType;
|
||||
|
||||
$logData = [
|
||||
'to' => maybe_serialize($this->setRecipientsArray($this->phpMailer->getToAddresses())),
|
||||
'from' => maybe_serialize($this->phpMailer->From),
|
||||
'subject' => $this->phpMailer->Subject,
|
||||
'body' => $this->phpMailer->Body,
|
||||
'attachments' => maybe_serialize($this->phpMailer->getAttachments()),
|
||||
'status' => 'sent',
|
||||
'response' => maybe_serialize(['status' => __('Email sending was simulated, No Email was sent originally', 'fluent-smtp')]),
|
||||
'headers' => maybe_serialize($headers),
|
||||
'extra' => maybe_serialize(['provider' => 'Simulator'])
|
||||
];
|
||||
|
||||
(new Logger)->add($logData);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
protected function postSend()
|
||||
{
|
||||
$returnResponse = [
|
||||
'response' => 'OK'
|
||||
];
|
||||
|
||||
$this->response = $returnResponse;
|
||||
return $this->handleResponse($this->response);
|
||||
}
|
||||
|
||||
public function setSettings($settings)
|
||||
{
|
||||
$this->settings = $settings;
|
||||
return $this;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,141 @@
|
||||
<?php
|
||||
|
||||
namespace FluentMail\App\Services\Mailer\Providers\Smtp;
|
||||
|
||||
use FluentMail\Includes\Support\Arr;
|
||||
use FluentMail\Includes\Core\Application;
|
||||
use FluentMail\App\Services\Mailer\BaseHandler;
|
||||
use FluentMail\App\Services\Mailer\Providers\Smtp\ValidatorTrait;
|
||||
|
||||
class Handler extends BaseHandler
|
||||
{
|
||||
use ValidatorTrait;
|
||||
|
||||
public function send()
|
||||
{
|
||||
if ($this->preSend()) {
|
||||
if ($this->getSetting('auto_tls') == 'no') {
|
||||
$this->phpMailer->SMTPAutoTLS = false;
|
||||
}
|
||||
return $this->postSend();
|
||||
}
|
||||
|
||||
return $this->handleResponse(new \WP_Error(422, __('Something went wrong!', 'fluent-smtp'), []));
|
||||
}
|
||||
|
||||
protected function postSend()
|
||||
{
|
||||
try {
|
||||
$this->phpMailer->isSMTP();
|
||||
$this->phpMailer->Host = $this->getSetting('host');
|
||||
$this->phpMailer->Port = $this->getSetting('port');
|
||||
|
||||
if ($this->getSetting('auth') == 'yes') {
|
||||
$this->phpMailer->SMTPAuth = true;
|
||||
$this->phpMailer->Username = $this->getSetting('username');
|
||||
$this->phpMailer->Password = $this->getSetting('password');
|
||||
}
|
||||
|
||||
if (($encryption = $this->getSetting('encryption')) != 'none') {
|
||||
$this->phpMailer->SMTPSecure = $encryption;
|
||||
}
|
||||
|
||||
$fromEmail = $this->phpMailer->From;
|
||||
|
||||
if ($this->isForcedEmail() && !fluentMailIsListedSenderEmail($fromEmail)) {
|
||||
$fromEmail = $this->getSetting('sender_email');
|
||||
}
|
||||
|
||||
if (isset($this->phpMailer->FromName)) {
|
||||
$fromName = $this->phpMailer->FromName;
|
||||
|
||||
if (
|
||||
$this->getSetting('force_from_name') == 'yes' &&
|
||||
$customFrom = $this->getSetting('sender_name')
|
||||
) {
|
||||
$fromName = $customFrom;
|
||||
}
|
||||
|
||||
$this->phpMailer->setFrom($fromEmail, $fromName);
|
||||
} else {
|
||||
$this->phpMailer->setFrom($fromEmail);
|
||||
}
|
||||
|
||||
foreach ($this->getParam('to') as $to) {
|
||||
if (isset($to['name'])) {
|
||||
$this->phpMailer->addAddress($to['email'], $to['name']);
|
||||
} else {
|
||||
$this->phpMailer->addAddress($to['email']);
|
||||
}
|
||||
}
|
||||
|
||||
foreach ($this->getParam('headers.reply-to') as $replyTo) {
|
||||
if (isset($replyTo['name'])) {
|
||||
$this->phpMailer->addReplyTo($replyTo['email'], $replyTo['name']);
|
||||
} else {
|
||||
$this->phpMailer->addReplyTo($replyTo['email']);
|
||||
}
|
||||
}
|
||||
|
||||
foreach ($this->getParam('headers.cc') as $cc) {
|
||||
if (isset($cc['name'])) {
|
||||
$this->phpMailer->addCC($cc['email'], $cc['name']);
|
||||
} else {
|
||||
$this->phpMailer->addCC($cc['email']);
|
||||
}
|
||||
}
|
||||
|
||||
foreach ($this->getParam('headers.bcc') as $bcc) {
|
||||
if (isset($bcc['name'])) {
|
||||
$this->phpMailer->addBCC($bcc['email'], $bcc['name']);
|
||||
} else {
|
||||
$this->phpMailer->addBCC($bcc['email']);
|
||||
}
|
||||
}
|
||||
|
||||
if ($attachments = $this->getParam('attachments')) {
|
||||
foreach ($attachments as $attachment) {
|
||||
$this->phpMailer->addAttachment($attachment[0], $attachment[7]);
|
||||
}
|
||||
}
|
||||
|
||||
if ($this->getParam('headers.content-type') == 'text/html' || $this->getParam('headers.content-type') == 'multipart/alternative') {
|
||||
$this->phpMailer->isHTML(true);
|
||||
}
|
||||
|
||||
$this->phpMailer->Subject = $this->getSubject();
|
||||
|
||||
$this->phpMailer->Body = $this->getParam('message');
|
||||
|
||||
if ($this->getParam('headers.content-type') == 'multipart/alternative') {
|
||||
$this->phpMailer->AltBody = $this->getParam('alt_body');
|
||||
$this->phpMailer->ContentType = 'multipart/alternative';
|
||||
}
|
||||
|
||||
$this->phpMailer->send();
|
||||
|
||||
$returnResponse = [
|
||||
'response' => 'OK'
|
||||
];
|
||||
|
||||
} catch (\Exception $e) {
|
||||
$returnResponse = new \WP_Error(422, $e->getMessage(), []);
|
||||
}
|
||||
|
||||
$this->response = $returnResponse;
|
||||
|
||||
return $this->handleResponse($this->response);
|
||||
}
|
||||
|
||||
public function setSettings($settings)
|
||||
{
|
||||
if (Arr::get($settings, 'key_store') == 'wp_config') {
|
||||
$settings['username'] = defined('FLUENTMAIL_SMTP_USERNAME') ? FLUENTMAIL_SMTP_USERNAME : '';
|
||||
$settings['password'] = defined('FLUENTMAIL_SMTP_PASSWORD') ? FLUENTMAIL_SMTP_PASSWORD : '';
|
||||
}
|
||||
|
||||
$this->settings = $settings;
|
||||
|
||||
return $this;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,50 @@
|
||||
<?php
|
||||
|
||||
namespace FluentMail\App\Services\Mailer\Providers\Smtp;
|
||||
|
||||
use FluentMail\Includes\Support\Arr;
|
||||
use FluentMail\App\Services\Mailer\ValidatorTrait as BaseValidatorTrait;
|
||||
|
||||
trait ValidatorTrait
|
||||
{
|
||||
use BaseValidatorTrait;
|
||||
|
||||
public function validateProviderInformation($connection)
|
||||
{
|
||||
$errors = [];
|
||||
|
||||
$keyStoreType = Arr::get($connection, 'key_store', 'db');
|
||||
|
||||
if (!Arr::get($connection, 'host')) {
|
||||
$errors['host']['required'] = __('SMTP host is required.', 'fluent-smtp');
|
||||
}
|
||||
|
||||
if (!Arr::get($connection, 'port')) {
|
||||
$errors['port']['required'] = __('SMTP port is required.', 'fluent-smtp');
|
||||
}
|
||||
|
||||
if (Arr::get($connection, 'auth') == 'yes') {
|
||||
if ($keyStoreType == 'wp_config') {
|
||||
if (!defined('FLUENTMAIL_SMTP_USERNAME') || !FLUENTMAIL_SMTP_USERNAME) {
|
||||
$errors['username']['required'] = __('Please define FLUENTMAIL_SMTP_USERNAME in wp-config.php file.', 'fluent-smtp');
|
||||
}
|
||||
|
||||
if (!defined('FLUENTMAIL_SMTP_PASSWORD') || !FLUENTMAIL_SMTP_PASSWORD) {
|
||||
$errors['password']['required'] = __('Please define FLUENTMAIL_SMTP_PASSWORD in wp-config.php file.', 'fluent-smtp');
|
||||
}
|
||||
} else {
|
||||
if (!Arr::get($connection, 'username')) {
|
||||
$errors['username']['required'] = __('SMTP username is required.', 'fluent-smtp');
|
||||
}
|
||||
|
||||
if (!Arr::get($connection, 'password')) {
|
||||
$errors['password']['required'] = __('SMTP password is required.', 'fluent-smtp');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ($errors) {
|
||||
$this->throwValidationException($errors);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,174 @@
|
||||
<?php
|
||||
|
||||
namespace FluentMail\App\Services\Mailer\Providers\Smtp2Go;
|
||||
|
||||
use WP_Error as WPError;
|
||||
use FluentMail\Includes\Support\Arr;
|
||||
use FluentMail\Includes\Core\Application;
|
||||
use FluentMail\App\Services\Mailer\Manager;
|
||||
use FluentMail\App\Services\Mailer\BaseHandler;
|
||||
use FluentMail\App\Services\Mailer\Providers\Smtp2Go\ValidatorTrait;
|
||||
|
||||
class Handler extends BaseHandler {
|
||||
use ValidatorTrait;
|
||||
|
||||
protected $emailSentCode = 200;
|
||||
|
||||
protected $url = 'https://api.smtp2go.com/v3/email/send';
|
||||
|
||||
public function send() {
|
||||
if ($this->preSend()) {
|
||||
return $this->postSend();
|
||||
}
|
||||
|
||||
return $this->handleResponse(new \WP_Error(422, __('Something went wrong!', 'fluent-smtp'), []));
|
||||
}
|
||||
|
||||
public function postSend() {
|
||||
$body = [
|
||||
'sender' => $this->getFrom(),
|
||||
'to' => $this->getTo(),
|
||||
'cc' => $this->getCarbonCopy(),
|
||||
'bcc' => $this->getBlindCarbonCopy(),
|
||||
'subject' => $this->getSubject(),
|
||||
'html_body' => $this->getBody(),
|
||||
'text_body' => $this->phpMailer->AltBody
|
||||
];
|
||||
|
||||
if ($replyTo = $this->getReplyTo()) {
|
||||
$body['custom_headers'][] = [
|
||||
'header' => 'Reply-To',
|
||||
'value' => $replyTo
|
||||
];
|
||||
}
|
||||
|
||||
|
||||
if (!empty($this->getParam('attachments'))) {
|
||||
$body['attachments'] = $this->getAttachments();
|
||||
}
|
||||
|
||||
$params = [
|
||||
'body' => json_encode($body),
|
||||
'headers' => $this->getRequestHeaders()
|
||||
];
|
||||
|
||||
$params = array_merge($params, $this->getDefaultParams());
|
||||
|
||||
$response = wp_safe_remote_post($this->url, $params);
|
||||
|
||||
if (is_wp_error($response)) {
|
||||
$returnResponse = new \WP_Error($response->get_error_code(), $response->get_error_message(), $response->get_error_messages());
|
||||
} else {
|
||||
$responseBody = wp_remote_retrieve_body($response);
|
||||
$responseCode = wp_remote_retrieve_response_code($response);
|
||||
$isOKCode = $responseCode == $this->emailSentCode;
|
||||
$responseBody = \json_decode($responseBody, true);
|
||||
|
||||
if ($isOKCode) {
|
||||
$returnResponse = [
|
||||
'email_id' => Arr::get($responseBody, 'data.email_id'),
|
||||
'succeeded' => Arr::get($responseBody, 'data.succeeded'),
|
||||
];
|
||||
} else {
|
||||
$returnResponse = new \WP_Error($responseCode, Arr::get($responseBody, 'data.error', 'Unknown Error'), $responseBody);
|
||||
}
|
||||
}
|
||||
|
||||
$this->response = $returnResponse;
|
||||
|
||||
return $this->handleResponse($this->response);
|
||||
}
|
||||
|
||||
protected function getFrom() {
|
||||
$from = $this->getParam('sender_email');
|
||||
|
||||
if ($name = $this->getParam('sender_name')) {
|
||||
$from = $name . ' <' . $from . '>';
|
||||
}
|
||||
|
||||
return $from;
|
||||
}
|
||||
|
||||
protected function getReplyTo() {
|
||||
if ($replyTo = $this->getParam('headers.reply-to')) {
|
||||
$replyTo = reset($replyTo);
|
||||
|
||||
return $replyTo['email'];
|
||||
}
|
||||
}
|
||||
|
||||
protected function getRecipients($recipients) {
|
||||
return array_map(function ($recipient) {
|
||||
return isset($recipient['name'])
|
||||
? $recipient['name'] . ' <' . $recipient['email'] . '>'
|
||||
: $recipient['email'];
|
||||
}, $recipients);
|
||||
}
|
||||
|
||||
protected function getTo() {
|
||||
return $this->getRecipients($this->getParam('to'));
|
||||
}
|
||||
|
||||
protected function getCarbonCopy() {
|
||||
return $this->getRecipients($this->getParam('headers.cc'));
|
||||
}
|
||||
|
||||
protected function getBlindCarbonCopy() {
|
||||
return $this->getRecipients($this->getParam('headers.bcc'));
|
||||
}
|
||||
|
||||
protected function getBody() {
|
||||
return $this->getParam('message');
|
||||
}
|
||||
|
||||
protected function getAttachments() {
|
||||
$data = [];
|
||||
|
||||
foreach ($this->getParam('attachments') as $attachment) {
|
||||
$file = false;
|
||||
|
||||
try {
|
||||
if (is_file($attachment[0]) && is_readable($attachment[0])) {
|
||||
$fileName = basename($attachment[0]);
|
||||
$file = file_get_contents($attachment[0]);
|
||||
$mimeType = mime_content_type($attachment[0]);
|
||||
$filetype = str_replace(';', '', trim($mimeType));
|
||||
}
|
||||
} catch (\Exception $e) {
|
||||
$file = false;
|
||||
}
|
||||
|
||||
if ($file === false) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$data[] = [
|
||||
'mimetype' => $filetype,
|
||||
'filename' => $fileName,
|
||||
'fileblob' => base64_encode($file)
|
||||
];
|
||||
}
|
||||
|
||||
return $data;
|
||||
}
|
||||
|
||||
protected function getCustomEmailHeaders() {
|
||||
return [];
|
||||
}
|
||||
|
||||
protected function getRequestHeaders() {
|
||||
return [
|
||||
'Content-Type' => 'application/json',
|
||||
'X-Smtp2go-Api-Key' => $this->getSetting('api_key')
|
||||
];
|
||||
}
|
||||
|
||||
public function setSettings($settings) {
|
||||
if ($settings['key_store'] == 'wp_config') {
|
||||
$settings['api_key'] = defined('FLUENTMAIL_SMTP2GO_API_KEY') ? FLUENTMAIL_SMTP2GO_API_KEY : '';
|
||||
}
|
||||
$this->settings = $settings;
|
||||
|
||||
return $this;
|
||||
}
|
||||
}
|
||||
+37
@@ -0,0 +1,37 @@
|
||||
<?php
|
||||
|
||||
namespace FluentMail\App\Services\Mailer\Providers\Smtp2Go;
|
||||
|
||||
use FluentMail\Includes\Support\Arr;
|
||||
use FluentMail\App\Services\Mailer\ValidatorTrait as BaseValidatorTrait;
|
||||
|
||||
trait ValidatorTrait
|
||||
{
|
||||
use BaseValidatorTrait;
|
||||
|
||||
public function validateProviderInformation($connection)
|
||||
{
|
||||
$errors = [];
|
||||
|
||||
$keyStoreType = $connection['key_store'];
|
||||
|
||||
if($keyStoreType == 'db') {
|
||||
if (! Arr::get($connection, 'api_key')) {
|
||||
$errors['api_key']['required'] = __('Api key is required.', 'fluent-smtp');
|
||||
}
|
||||
} else if($keyStoreType == 'wp_config') {
|
||||
if(!defined('FLUENTMAIL_SMTP2GO_API_KEY') || !FLUENTMAIL_SMTP2GO_API_KEY) {
|
||||
$errors['api_key']['required'] = __('Please define FLUENTMAIL_SMTP2GO_API_KEY in wp-config.php file.', 'fluent-smtp');
|
||||
}
|
||||
}
|
||||
|
||||
if ($errors) {
|
||||
$this->throwValidationException($errors);
|
||||
}
|
||||
}
|
||||
|
||||
public function checkConnection($connection)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,210 @@
|
||||
<?php
|
||||
|
||||
namespace FluentMail\App\Services\Mailer\Providers\SparkPost;
|
||||
|
||||
use WP_Error as WPError;
|
||||
use FluentMail\Includes\Support\Arr;
|
||||
use FluentMail\Includes\Core\Application;
|
||||
use FluentMail\App\Services\Mailer\Manager;
|
||||
use FluentMail\App\Services\Mailer\BaseHandler;
|
||||
use FluentMail\App\Services\Mailer\Providers\SparkPost\ValidatorTrait;
|
||||
|
||||
class Handler extends BaseHandler
|
||||
{
|
||||
use ValidatorTrait;
|
||||
|
||||
protected $emailSentCode = 202;
|
||||
|
||||
protected $url = 'https://api.sparkpost.com/api/v1/transmissions';
|
||||
|
||||
public function send()
|
||||
{
|
||||
if ($this->preSend()) {
|
||||
return $this->postSend();
|
||||
}
|
||||
|
||||
return $this->handleResponse(new \WP_Error(422, __('Something went wrong!', 'fluent-smtp'), []) );
|
||||
}
|
||||
|
||||
public function postSend()
|
||||
{
|
||||
$body = [
|
||||
'options' => [
|
||||
'sandbox' => false
|
||||
],
|
||||
'content' => [
|
||||
'from' => $this->getFrom(),
|
||||
'subject' => $this->getSubject(),
|
||||
'html' => $this->phpMailer->Body,
|
||||
'text' => $this->phpMailer->AltBody,
|
||||
'headers' => (object) []
|
||||
],
|
||||
'recipients' => $this->getTo(),
|
||||
'cc' => $this->getCarbonCopy(),
|
||||
'bcc' => $this->getBlindCarbonCopy()
|
||||
];
|
||||
|
||||
if ($replyTo = $this->getReplyTo()) {
|
||||
$body['content']['reply_to'] = $replyTo;
|
||||
}
|
||||
|
||||
if (!empty($this->getParam('attachments'))) {
|
||||
$body['content']['attachments'] = $this->getAttachments();
|
||||
}
|
||||
|
||||
$params = [
|
||||
'body' => json_encode($body),
|
||||
'headers' => $this->getRequestHeaders()
|
||||
];
|
||||
|
||||
$params = array_merge($params, $this->getDefaultParams());
|
||||
|
||||
$response = wp_safe_remote_post($this->url, $params);
|
||||
|
||||
if (is_wp_error($response)) {
|
||||
$returnResponse = new \WP_Error($response->get_error_code(), $response->get_error_message(), $response->get_error_messages());
|
||||
} else {
|
||||
$responseBody = wp_remote_retrieve_body($response);
|
||||
$responseCode = wp_remote_retrieve_response_code($response);
|
||||
|
||||
$isOKCode = $responseCode < 300;
|
||||
|
||||
$responseBody = \json_decode($responseBody, true);
|
||||
|
||||
if($isOKCode) {
|
||||
$returnResponse = [
|
||||
'response' => $responseBody
|
||||
];
|
||||
} else {
|
||||
$returnResponse = new \WP_Error($responseCode, __('SparkPost API Error', 'fluent-smtp'), $responseBody);
|
||||
}
|
||||
}
|
||||
|
||||
$this->response = $returnResponse;
|
||||
|
||||
return $this->handleResponse($this->response);
|
||||
}
|
||||
|
||||
public function setSettings($settings)
|
||||
{
|
||||
if($settings['key_store'] == 'wp_config') {
|
||||
$settings['api_key'] = defined('FLUENTMAIL_SPARKPOST_API_KEY') ? FLUENTMAIL_SPARKPOST_API_KEY : '';
|
||||
}
|
||||
$this->settings = $settings;
|
||||
return $this;
|
||||
}
|
||||
|
||||
protected function getFrom()
|
||||
{
|
||||
$email = $this->getParam('sender_email');
|
||||
|
||||
if ($name = $this->getParam('sender_name')) {
|
||||
$from = $name . ' <' . $email . '>';
|
||||
} else {
|
||||
$from = $email;
|
||||
}
|
||||
|
||||
return $from;
|
||||
}
|
||||
|
||||
protected function getTo()
|
||||
{
|
||||
$address = [];
|
||||
|
||||
foreach ($this->getParam('to') as $to) {
|
||||
$address[] = [
|
||||
'address' => [
|
||||
'email' => $to['email']
|
||||
]
|
||||
];
|
||||
}
|
||||
|
||||
return $address;
|
||||
}
|
||||
|
||||
protected function getReplyTo()
|
||||
{
|
||||
if ($replyTo = $this->getParam('headers.reply-to')) {
|
||||
$replyTo = reset($replyTo);
|
||||
|
||||
return $replyTo['email'];
|
||||
}
|
||||
}
|
||||
|
||||
protected function getCarbonCopy()
|
||||
{
|
||||
$address = [];
|
||||
|
||||
foreach ($this->getParam('headers.cc') as $cc) {
|
||||
$address[] = [
|
||||
'address' => [
|
||||
'email' => $cc['email']
|
||||
]
|
||||
];
|
||||
}
|
||||
|
||||
return $address;
|
||||
}
|
||||
|
||||
protected function getBlindCarbonCopy()
|
||||
{
|
||||
$address = [];
|
||||
|
||||
foreach ($this->getParam('headers.bcc') as $bcc) {
|
||||
$address[] = [
|
||||
'address' => [
|
||||
'email' => $bcc['email']
|
||||
]
|
||||
];
|
||||
}
|
||||
|
||||
return $address;
|
||||
}
|
||||
|
||||
protected function getAttachments()
|
||||
{
|
||||
$data = [];
|
||||
|
||||
foreach ($this->getParam('attachments') as $attachment) {
|
||||
$file = false;
|
||||
|
||||
try {
|
||||
if (is_file($attachment[0]) && is_readable($attachment[0])) {
|
||||
$fileName = basename($attachment[0]);
|
||||
$file = file_get_contents($attachment[0]);
|
||||
$mimeType = mime_content_type($attachment[0]);
|
||||
$filetype = str_replace(';', '', trim($mimeType));
|
||||
}
|
||||
} catch (\Exception $e) {
|
||||
$file = false;
|
||||
}
|
||||
|
||||
if ($file === false) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$data[] = [
|
||||
'name' => $fileName,
|
||||
'type' => $filetype,
|
||||
'content' => base64_encode($file)
|
||||
];
|
||||
}
|
||||
|
||||
return $data;
|
||||
}
|
||||
|
||||
protected function getCustomEmailHeaders()
|
||||
{
|
||||
return [
|
||||
'X-Mailer' => 'FluentMail - SparkPost'
|
||||
];
|
||||
}
|
||||
|
||||
protected function getRequestHeaders()
|
||||
{
|
||||
return [
|
||||
'Content-Type' => 'application/json',
|
||||
'Authorization' => $this->getSetting('api_key')
|
||||
];
|
||||
}
|
||||
}
|
||||
+32
@@ -0,0 +1,32 @@
|
||||
<?php
|
||||
|
||||
namespace FluentMail\App\Services\Mailer\Providers\SparkPost;
|
||||
|
||||
use FluentMail\Includes\Support\Arr;
|
||||
use FluentMail\App\Services\Mailer\ValidatorTrait as BaseValidatorTrait;
|
||||
|
||||
trait ValidatorTrait
|
||||
{
|
||||
use BaseValidatorTrait;
|
||||
|
||||
public function validateProviderInformation($connection)
|
||||
{
|
||||
$errors = [];
|
||||
|
||||
$keyStoreType = $connection['key_store'];
|
||||
|
||||
if($keyStoreType == 'db') {
|
||||
if (! Arr::get($connection, 'api_key')) {
|
||||
$errors['api_key']['required'] = __('Api key is required.', 'fluent-smtp');
|
||||
}
|
||||
} else if($keyStoreType == 'wp_config') {
|
||||
if(!defined('FLUENTMAIL_SPARKPOST_API_KEY') || !FLUENTMAIL_SPARKPOST_API_KEY) {
|
||||
$errors['api_key']['required'] = __('Please define FLUENTMAIL_SPARKPOST_API_KEY in wp-config.php file.', 'fluent-smtp');
|
||||
}
|
||||
}
|
||||
|
||||
if ($errors) {
|
||||
$this->throwValidationException($errors);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,394 @@
|
||||
<?php
|
||||
|
||||
namespace FluentMail\App\Services\Mailer\Providers\ToSend;
|
||||
|
||||
use FluentMail\Includes\Support\Arr;
|
||||
use FluentMail\App\Services\Mailer\BaseHandler;
|
||||
|
||||
class Handler extends BaseHandler
|
||||
{
|
||||
use ValidatorTrait;
|
||||
|
||||
protected $emailSentCode = 200;
|
||||
|
||||
protected $baseUrl = 'https://api.tosend.com/v2/';
|
||||
|
||||
public function send()
|
||||
{
|
||||
if ($this->preSend() && $this->phpMailer->preSend()) {
|
||||
return $this->postSend();
|
||||
}
|
||||
|
||||
return $this->handleResponse(new \WP_Error(422, __('Something went wrong!', 'fluent-smtp'), []));
|
||||
}
|
||||
|
||||
public function postSend()
|
||||
{
|
||||
$body = [
|
||||
'from' => $this->getFrom(),
|
||||
'to' => $this->getTo(),
|
||||
'subject' => $this->getSubject(),
|
||||
'api_key' => $this->getSetting('api_key')
|
||||
];
|
||||
|
||||
|
||||
if ($replyTo = $this->getReplyTo()) {
|
||||
$body['reply_to'] = $replyTo;
|
||||
}
|
||||
|
||||
if ($bcc = $this->getBlindCarbonCopy()) {
|
||||
$body['bcc'] = $bcc;
|
||||
}
|
||||
|
||||
if ($cc = $this->getCarbonCopy()) {
|
||||
$body['cc'] = $cc;
|
||||
}
|
||||
|
||||
$contentType = $this->getHeader('content-type');
|
||||
|
||||
if ($contentType == 'text/html') {
|
||||
$body['html'] = $this->getParam('message');
|
||||
} else if ($contentType == 'multipart/alternative') {
|
||||
$body['html'] = $this->getParam('message');
|
||||
$body['text'] = $this->phpMailer->AltBody;
|
||||
} else {
|
||||
$body['text'] = $this->getParam('message');
|
||||
}
|
||||
|
||||
if (!empty($this->getParam('attachments'))) {
|
||||
$body['attachments'] = $this->getAttachments();
|
||||
}
|
||||
|
||||
// Add any custom headers
|
||||
$customHeaders = $this->phpMailer->getCustomHeaders();
|
||||
if (!empty($customHeaders)) {
|
||||
foreach ($customHeaders as $header) {
|
||||
$body['headers'][] = [
|
||||
$header[0] => $header[1]
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
$args = array(
|
||||
'headers' => $this->getRequestHeaders(),
|
||||
'body' => json_encode($body),
|
||||
'sslverify' => false
|
||||
);
|
||||
|
||||
$response = wp_remote_post($this->baseUrl . 'emails', $args);
|
||||
|
||||
if (is_wp_error($response)) {
|
||||
$returnResponse = new \WP_Error($response->get_error_code(), $response->get_error_message(), $response->get_error_messages());
|
||||
} else {
|
||||
$responseBody = wp_remote_retrieve_body($response);
|
||||
|
||||
$responseCode = wp_remote_retrieve_response_code($response);
|
||||
$isOKCode = $responseCode == $this->emailSentCode;
|
||||
$responseBody = \json_decode($responseBody, true);
|
||||
$messageId = Arr::get($responseBody, 'message_id');
|
||||
|
||||
if ($isOKCode && $messageId) {
|
||||
$returnResponse = [
|
||||
'id' => $messageId
|
||||
];
|
||||
} else {
|
||||
$returnResponse = new \WP_Error($responseCode, Arr::get($responseBody, 'message', 'Unknown Error'), $responseBody);
|
||||
}
|
||||
}
|
||||
|
||||
$this->response = $returnResponse;
|
||||
|
||||
return $this->handleResponse($this->response);
|
||||
}
|
||||
|
||||
public function getFrom()
|
||||
{
|
||||
$fromEmail = $this->phpMailer->From;
|
||||
if ($this->isForcedEmail() && !fluentMailIsListedSenderEmail($fromEmail)) {
|
||||
$fromEmail = $this->getSetting('sender_email');
|
||||
}
|
||||
|
||||
$fromName = '';
|
||||
if (isset($this->phpMailer->FromName)) {
|
||||
$fromName = $this->phpMailer->FromName;
|
||||
if ($this->getSetting('force_from_name') == 'yes' &&
|
||||
$customFrom = $this->getSetting('sender_name')
|
||||
) {
|
||||
$fromName = $customFrom;
|
||||
}
|
||||
}
|
||||
|
||||
return [
|
||||
'name' => $fromName,
|
||||
'email' => $fromEmail
|
||||
];
|
||||
}
|
||||
|
||||
public function setSettings($settings)
|
||||
{
|
||||
if ($settings['key_store'] == 'wp_config') {
|
||||
$settings['api_key'] = defined('FLUENTMAIL_TOSEND_API_KEY') ? FLUENTMAIL_TOSEND_API_KEY : '';
|
||||
}
|
||||
|
||||
$this->settings = $settings;
|
||||
return $this;
|
||||
}
|
||||
|
||||
protected function getReplyTo()
|
||||
{
|
||||
if ($replyTo = $this->getParam('headers.reply-to')) {
|
||||
$replyTo = reset($replyTo);
|
||||
if (!filter_var($replyTo['email'], FILTER_VALIDATE_EMAIL)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
$name = Arr::get($replyTo, 'name', '');
|
||||
|
||||
if ($name) {
|
||||
return $name . ' <' . $replyTo['email'] . '>';
|
||||
}
|
||||
|
||||
return $replyTo['email'];
|
||||
}
|
||||
return '';
|
||||
}
|
||||
|
||||
protected function getTo()
|
||||
{
|
||||
return $this->getRecipients($this->getParam('to'));
|
||||
}
|
||||
|
||||
protected function getCarbonCopy()
|
||||
{
|
||||
return $this->getRecipients($this->getParam('headers.cc'));
|
||||
}
|
||||
|
||||
protected function getBlindCarbonCopy()
|
||||
{
|
||||
return $this->getRecipients($this->getParam('headers.bcc'));
|
||||
}
|
||||
|
||||
protected function getRecipients($recipients)
|
||||
{
|
||||
if (!$recipients) {
|
||||
return [];
|
||||
}
|
||||
|
||||
$emails = array_map(function ($recipient) {
|
||||
$email = Arr::get($recipient, 'email');
|
||||
// validate the email
|
||||
if (!filter_var($email, FILTER_VALIDATE_EMAIL)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return [
|
||||
'name' => Arr::get($recipient, 'name', ''),
|
||||
'email' => Arr::get($recipient, 'email', '')
|
||||
];
|
||||
}, $recipients);
|
||||
|
||||
return array_values(array_filter($emails));
|
||||
}
|
||||
|
||||
protected function getAttachments()
|
||||
{
|
||||
$attachments = [];
|
||||
|
||||
foreach ($this->getParam('attachments') as $attachment) {
|
||||
$file = false;
|
||||
|
||||
try {
|
||||
if (is_file($attachment[0]) && is_readable($attachment[0])) {
|
||||
$fileName = basename($attachment[0]);
|
||||
$file = file_get_contents($attachment[0]);
|
||||
$mimeType = mime_content_type($attachment[0]);
|
||||
$filetype = str_replace(';', '', trim($mimeType));
|
||||
}
|
||||
} catch (\Exception $e) {
|
||||
$file = false;
|
||||
}
|
||||
|
||||
if ($file === false) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$chunkSize = 76;
|
||||
$file = base64_encode($file);
|
||||
$file = trim(chunk_split($file, $chunkSize, "\n"));
|
||||
|
||||
$attachments[] = [
|
||||
'type' => $filetype,
|
||||
'name' => $fileName,
|
||||
'content' => $file
|
||||
];
|
||||
}
|
||||
|
||||
return $attachments;
|
||||
}
|
||||
|
||||
protected function getRequestHeaders()
|
||||
{
|
||||
return [
|
||||
'Accept' => 'application/json',
|
||||
'Content-Type' => 'application/json'
|
||||
];
|
||||
}
|
||||
|
||||
private function filterConnectionVars($connection)
|
||||
{
|
||||
if ($connection['key_store'] == 'wp_config') {
|
||||
$connection['api_key'] = defined('FLUENTMAIL_TOSEND_API_KEY') ? FLUENTMAIL_TOSEND_API_KEY : '';
|
||||
}
|
||||
|
||||
return $connection;
|
||||
}
|
||||
|
||||
|
||||
public function getConnectionInfo($connection)
|
||||
{
|
||||
$connection = $this->filterConnectionVars($connection);
|
||||
$stats = $this->getAccountInfo($connection['api_key']);
|
||||
$error = '';
|
||||
|
||||
if (is_wp_error($stats)) {
|
||||
$error = $stats->get_error_message();
|
||||
$stats = [];
|
||||
}
|
||||
|
||||
|
||||
if (empty($stats['account'])) {
|
||||
$info = (string)fluentMail('view')->make('admin.tosend_mailer_connection_info', [
|
||||
'connection' => $connection,
|
||||
'valid_senders' => [$connection['sender_email']],
|
||||
'stats' => $stats['account'] ?? [],
|
||||
'error' => $error
|
||||
]);
|
||||
|
||||
return [
|
||||
'info' => $info
|
||||
];
|
||||
}
|
||||
|
||||
$validSenders = $this->getSendersFromMappings($connection);
|
||||
|
||||
$connection['valid_senders'] = $validSenders['all_senders'];
|
||||
|
||||
$info = (string)fluentMail('view')->make('admin.tosend_mailer_connection_info', [
|
||||
'connection' => $connection,
|
||||
'stats' => $stats['account'] ?? [],
|
||||
'error' => $error
|
||||
]);
|
||||
|
||||
$hasMultiDomain = $stats['verified_domains'] ? count($validSenders['verified_senders']) > 1 : false;
|
||||
|
||||
return [
|
||||
'info' => $info,
|
||||
'verificationSettings' => [
|
||||
'connection_name' => 'ToSend',
|
||||
'all_senders' => $validSenders['all_senders'],
|
||||
'verified_senders' => $validSenders['verified_senders'],
|
||||
'verified_domain' => $validSenders['verified_domain'],
|
||||
'supports_multi_domain' => $hasMultiDomain,
|
||||
'api_info' => $stats,
|
||||
'email_help_message' => $hasMultiDomain ? __('Make sure to verify your sender emails or domain in toSend dashboard and available in the provided API Key.', 'fluent-smtp') : ''
|
||||
]
|
||||
];
|
||||
}
|
||||
|
||||
public function addNewSenderEmail($connection, $email)
|
||||
{
|
||||
|
||||
$connection = $this->filterConnectionVars($connection);
|
||||
$stats = $this->getAccountInfo($connection['api_key']);
|
||||
if (is_wp_error($stats)) {
|
||||
return new \WP_Error(422, __('Unable to verify the connection details. Please check the API Key.', 'fluent-smtp'));
|
||||
}
|
||||
$verifiedDomains = Arr::get($stats, 'verified_domains', []);
|
||||
$emailDomain = explode('@', $email);
|
||||
$emailDomain = $emailDomain[1];
|
||||
|
||||
if (!in_array($emailDomain, $verifiedDomains)) {
|
||||
return new \WP_Error(422, __('Invalid email address! Please use an email with verified domain.', 'fluent-smtp'));
|
||||
}
|
||||
|
||||
$settings = fluentMailGetSettings();
|
||||
$mappings = Arr::get($settings, 'mappings', []);
|
||||
|
||||
if (isset($mappings[$email])) {
|
||||
return new \WP_Error(422, __('Email address already exists with another connection. Please choose a different email.', 'fluent-smtp'));
|
||||
}
|
||||
|
||||
$settings = get_option('fluentmail-settings');
|
||||
|
||||
$settings['mappings'][$email] = md5($connection['sender_email']);
|
||||
|
||||
update_option('fluentmail-settings', $settings);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public function removeSenderEmail($connection, $email)
|
||||
{
|
||||
$connection = $this->filterConnectionVars($connection);
|
||||
|
||||
$settings = fluentMailGetSettings();
|
||||
$mappings = Arr::get($settings, 'mappings', []);
|
||||
|
||||
if (!isset($mappings[$email])) {
|
||||
return new \WP_Error(422, __('Email does not exists. Please try again.', 'fluent-smtp'));
|
||||
}
|
||||
|
||||
if ($email == $connection['sender_email']) {
|
||||
return new \WP_Error(422, __('You can not remove the primary sender email of this connection.', 'fluent-smtp'));
|
||||
}
|
||||
|
||||
// check if the it's the same email or not
|
||||
if ($mappings[$email] != md5($connection['sender_email'])) {
|
||||
return new \WP_Error(422, __('Email does not exists. Please try again.', 'fluent-smtp'));
|
||||
}
|
||||
|
||||
$settings = get_option('fluentmail-settings');
|
||||
|
||||
unset($settings['mappings'][$email]);
|
||||
|
||||
update_option('fluentmail-settings', $settings);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private function getSendersFromMappings($connection)
|
||||
{
|
||||
$validSenders = [
|
||||
'emails' => [$connection['sender_email']]
|
||||
];
|
||||
$verifiedDomain = explode('@', $connection['sender_email'])[1] ?? '';
|
||||
|
||||
if ($verifiedDomain) {
|
||||
$settings = fluentMailGetSettings();
|
||||
$mappings = Arr::get($settings, 'mappings', []);
|
||||
|
||||
$mapKey = md5($connection['sender_email']);
|
||||
$mapSenders = array_filter($mappings, function ($key) use ($mapKey) {
|
||||
return $key == $mapKey;
|
||||
});
|
||||
|
||||
$mapSenders[$connection['sender_email']] = true;
|
||||
|
||||
foreach ($validSenders['emails'] as $email) {
|
||||
$mapSenders[$email] = $email;
|
||||
}
|
||||
|
||||
$mapSenders = array_keys($mapSenders);
|
||||
|
||||
} else {
|
||||
$mapSenders = $validSenders['emails'];
|
||||
}
|
||||
|
||||
return [
|
||||
'all_senders' => $mapSenders,
|
||||
'verified_senders' => $validSenders['emails'],
|
||||
'verified_domain' => $verifiedDomain
|
||||
];
|
||||
}
|
||||
|
||||
}
|
||||
+104
@@ -0,0 +1,104 @@
|
||||
<?php
|
||||
|
||||
namespace FluentMail\App\Services\Mailer\Providers\ToSend;
|
||||
|
||||
use FluentMail\Includes\Support\Arr;
|
||||
use FluentMail\App\Services\Mailer\ValidatorTrait as BaseValidatorTrait;
|
||||
|
||||
trait ValidatorTrait
|
||||
{
|
||||
use BaseValidatorTrait;
|
||||
|
||||
public function validateProviderInformation($connection)
|
||||
{
|
||||
$errors = [];
|
||||
|
||||
$keyStoreType = $connection['key_store'];
|
||||
|
||||
$apiKey = '';
|
||||
|
||||
if ($keyStoreType == 'db') {
|
||||
$apiKey = Arr::get($connection, 'api_key');
|
||||
if (!$apiKey) {
|
||||
$errors['api_key']['required'] = __('Api key is required.', 'fluent-smtp');
|
||||
}
|
||||
} else if ($keyStoreType == 'wp_config') {
|
||||
if (!defined('FLUENTMAIL_TOSEND_API_KEY') || !FLUENTMAIL_TOSEND_API_KEY) {
|
||||
$errors['api_key']['required'] = __('Please define FLUENTMAIL_TOSEND_API_KEY in wp-config.php file.', 'fluent-smtp');
|
||||
} else {
|
||||
$apiKey = FLUENTMAIL_TOSEND_API_KEY;
|
||||
}
|
||||
}
|
||||
|
||||
// validate the api key
|
||||
|
||||
if ($apiKey) {
|
||||
$senderEmail = Arr::get($connection, 'sender_email');
|
||||
if ($senderEmail) {
|
||||
$accountInfo = $this->getAccountInfo($apiKey);
|
||||
if (is_wp_error($accountInfo)) {
|
||||
$errors['api_key']['required'] = $accountInfo->get_error_message();
|
||||
} else {
|
||||
if (empty($accountInfo['verified_domains'])) {
|
||||
$errors['api_key']['required'] = 'No verified domains found in FluentMailer API';
|
||||
} else {
|
||||
$emailDomain = explode('@', $senderEmail)[1];
|
||||
$verifiedDomains = $accountInfo['verified_domains'];
|
||||
if (!in_array($emailDomain, $accountInfo['verified_domains'])) {
|
||||
$errors['sender_email']['required'] = 'Please provide a sender email that match with your verfied emails. Verfied domains: ' . implode(', ', $verifiedDomains) . '.';
|
||||
$errors['api_key']['required'] = 'Please provide a sender email that match with your verfied emails. Verfied domains: ' . implode(', ', $verifiedDomains) . '.';
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ($errors) {
|
||||
$this->throwValidationException($errors);
|
||||
}
|
||||
}
|
||||
|
||||
public function getAccountInfo($apiKey)
|
||||
{
|
||||
$request = wp_remote_get($this->baseUrl . 'info?api_key=' . $apiKey, [
|
||||
'sslverify' => false
|
||||
]);
|
||||
|
||||
if (is_wp_error($request)) {
|
||||
return $request;
|
||||
}
|
||||
|
||||
// remote status code
|
||||
$statusCode = wp_remote_retrieve_response_code($request);
|
||||
$body = wp_remote_retrieve_body($request);
|
||||
$body = json_decode($body, true);
|
||||
|
||||
if (!$body || !is_array($body)) {
|
||||
return new \WP_Error('invalid_response', 'Invalid Reponse from remote server');
|
||||
}
|
||||
|
||||
if ($statusCode === 200) {
|
||||
|
||||
$verifiedDomains = [];
|
||||
|
||||
foreach (Arr::get($body, 'domains') as $domain) {
|
||||
if ($domain['verification_status'] === 'verified') {
|
||||
$verifiedDomains[] = $domain['domain_name'];
|
||||
}
|
||||
}
|
||||
|
||||
$body['verified_domains'] = $verifiedDomains;
|
||||
|
||||
return $body;
|
||||
}
|
||||
|
||||
$message = Arr::get($body, 'message');
|
||||
|
||||
if (!$message) {
|
||||
$message = 'Unknown error from remote server';
|
||||
}
|
||||
|
||||
return new \WP_Error('invalid_response', $message, $body);
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,253 @@
|
||||
<?php
|
||||
|
||||
namespace FluentMail\App\Services\Mailer\Providers\TransMail;
|
||||
|
||||
use FluentMail\Includes\Support\Arr;
|
||||
use FluentMail\App\Services\Mailer\BaseHandler;
|
||||
|
||||
class Handler extends BaseHandler
|
||||
{
|
||||
use ValidatorTrait;
|
||||
|
||||
protected $emailSentCode = 200;
|
||||
|
||||
protected $url = null;
|
||||
|
||||
public function send()
|
||||
{
|
||||
if ($this->preSend()) {
|
||||
$this->setUrl();
|
||||
return $this->postSend();
|
||||
}
|
||||
|
||||
return $this->handleResponse(new \WP_Error(422, __('Something went wrong!', 'fluent-smtp'), []));
|
||||
}
|
||||
|
||||
protected function setUrl()
|
||||
{
|
||||
return $this->url = 'https://transmail.zoho.' . $this->getSetting('domain_name') . '/v1.1/email';
|
||||
}
|
||||
|
||||
public function postSend()
|
||||
{
|
||||
$body = [
|
||||
'bounce_address' => $this->getSetting('bounce_address'),
|
||||
'from' => json_encode([
|
||||
'name' => $this->phpMailer->FromName,
|
||||
'address' => $this->phpMailer->From,
|
||||
]),
|
||||
'to' => json_encode([
|
||||
[
|
||||
'email_address' => [
|
||||
'address' => '',
|
||||
'name' => ''
|
||||
]
|
||||
]
|
||||
]),
|
||||
'cc' => json_encode([
|
||||
[
|
||||
'email_address' => [
|
||||
'address' => '',
|
||||
'name' => ''
|
||||
]
|
||||
]
|
||||
]),
|
||||
'bcc' => json_encode([
|
||||
[
|
||||
'email_address' => [
|
||||
'address' => '',
|
||||
'name' => ''
|
||||
]
|
||||
]
|
||||
]),
|
||||
'reply_to' => json_encode([
|
||||
'address' => '',
|
||||
'name' => ''
|
||||
]),
|
||||
'subject' => $this->getSubject()
|
||||
];
|
||||
|
||||
if ($this->phpMailer->ContentType == 'text/html') {
|
||||
$body['htmlbody'] = $this->getBody();
|
||||
} else if ($this->phpMailer->ContentType == 'multipart/alternative') {
|
||||
$body['htmlbody'] = $this->getBody();
|
||||
$body['textbody'] = $this->getParam('alt_body');
|
||||
} else {
|
||||
$body['textbody'] = $this->getBody();
|
||||
}
|
||||
|
||||
$headers1 = array(
|
||||
'Authorization' => 'Zoho-enczapikey ' . $this->getSetting('token'),
|
||||
'Content-Type' => 'application/json',
|
||||
'Accept' => 'application/json'
|
||||
);
|
||||
|
||||
$data_string = json_encode($body);
|
||||
|
||||
$args = array(
|
||||
'body' => $data_string,
|
||||
'headers' => $headers1,
|
||||
'method' => 'POST'
|
||||
);
|
||||
|
||||
$response = wp_safe_remote_post($this->url, $args);
|
||||
|
||||
if (is_wp_error($response)) {
|
||||
$returnResponse = new \WP_Error($response->get_error_code(), $response->get_error_message(), $response->get_error_messages());
|
||||
} else {
|
||||
$responseBody = wp_remote_retrieve_body($response);
|
||||
$responseCode = wp_remote_retrieve_response_code($response);
|
||||
|
||||
$isOKCode = $responseCode == $this->emailSentCode;
|
||||
|
||||
if ($isOKCode) {
|
||||
$responseBody = \json_decode($responseBody, true);
|
||||
}
|
||||
|
||||
if ($isOKCode && isset($responseBody['id'])) {
|
||||
$returnResponse = [
|
||||
'id' => Arr::get($responseBody, 'id'),
|
||||
'message' => Arr::get($responseBody, 'message')
|
||||
];
|
||||
} else {
|
||||
$returnResponse = new \WP_Error($responseCode, __('Mailgun API Error', 'fluent-smtp'), $responseBody);
|
||||
}
|
||||
}
|
||||
|
||||
$this->response = $returnResponse;
|
||||
|
||||
return $this->handleResponse($this->response);
|
||||
}
|
||||
|
||||
public function setSettings($settings)
|
||||
{
|
||||
if ($settings['key_store'] == 'wp_config') {
|
||||
$settings['api_key'] = defined('FLUENTMAIL_MAILGUN_API_KEY') ? FLUENTMAIL_MAILGUN_API_KEY : '';
|
||||
$settings['domain_name'] = defined('FLUENTMAIL_MAILGUN_DOMAIN') ? FLUENTMAIL_MAILGUN_DOMAIN : '';
|
||||
}
|
||||
$this->settings = $settings;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
protected function getFrom()
|
||||
{
|
||||
return $this->getParam('from');
|
||||
}
|
||||
|
||||
protected function getReplyTo()
|
||||
{
|
||||
return $this->getRecipients(
|
||||
$this->getParam('headers.reply-to')
|
||||
);
|
||||
}
|
||||
|
||||
protected function getTo()
|
||||
{
|
||||
return $this->getRecipients($this->getParam('to'));
|
||||
}
|
||||
|
||||
protected function getCarbonCopy()
|
||||
{
|
||||
return $this->getRecipients($this->getParam('headers.cc'));
|
||||
}
|
||||
|
||||
protected function getBlindCarbonCopy()
|
||||
{
|
||||
return $this->getRecipients($this->getParam('headers.bcc'));
|
||||
}
|
||||
|
||||
protected function getRecipients($recipients)
|
||||
{
|
||||
$array = array_map(function ($recipient) {
|
||||
return isset($recipient['name'])
|
||||
? $recipient['name'] . ' <' . $recipient['email'] . '>'
|
||||
: $recipient['email'];
|
||||
}, $recipients);
|
||||
|
||||
return implode(', ', $array);
|
||||
}
|
||||
|
||||
protected function getBody()
|
||||
{
|
||||
return $this->getParam('message');
|
||||
}
|
||||
|
||||
protected function getAttachments($params)
|
||||
{
|
||||
$data = [];
|
||||
$payload = '';
|
||||
$attachments = $this->attributes['attachments'];
|
||||
|
||||
foreach ($attachments as $attachment) {
|
||||
$file = false;
|
||||
|
||||
try {
|
||||
if (is_file($attachment[0]) && is_readable($attachment[0])) {
|
||||
$fileName = basename($attachment[0]);
|
||||
$file = file_get_contents($attachment[0]);
|
||||
}
|
||||
} catch (\Exception $e) {
|
||||
$file = false;
|
||||
}
|
||||
|
||||
if ($file === false) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$data[] = [
|
||||
'content' => $file,
|
||||
'name' => $fileName,
|
||||
];
|
||||
}
|
||||
|
||||
if (!empty($data)) {
|
||||
$boundary = hash('sha256', uniqid('', true));
|
||||
|
||||
foreach ($params['body'] as $key => $value) {
|
||||
if (is_array($value)) {
|
||||
foreach ($value as $child_key => $child_value) {
|
||||
$payload .= '--' . $boundary;
|
||||
$payload .= "\r\n";
|
||||
$payload .= 'Content-Disposition: form-data; name="' . $key . "\"\r\n\r\n";
|
||||
$payload .= $child_value;
|
||||
$payload .= "\r\n";
|
||||
}
|
||||
} else {
|
||||
$payload .= '--' . $boundary;
|
||||
$payload .= "\r\n";
|
||||
$payload .= 'Content-Disposition: form-data; name="' . $key . '"' . "\r\n\r\n";
|
||||
$payload .= $value;
|
||||
$payload .= "\r\n";
|
||||
}
|
||||
}
|
||||
|
||||
foreach ($data as $key => $attachment) {
|
||||
$payload .= '--' . $boundary;
|
||||
$payload .= "\r\n";
|
||||
$payload .= 'Content-Disposition: form-data; name="attachment[' . $key . ']"; filename="' . $attachment['name'] . '"' . "\r\n\r\n";
|
||||
$payload .= $attachment['content'];
|
||||
$payload .= "\r\n";
|
||||
}
|
||||
|
||||
$payload .= '--' . $boundary . '--';
|
||||
|
||||
$params['body'] = $payload;
|
||||
|
||||
$params['headers']['Content-Type'] = 'multipart/form-data; boundary=' . $boundary;
|
||||
|
||||
$this->attributes['headers']['content-type'] = 'multipart/form-data';
|
||||
}
|
||||
|
||||
return $params;
|
||||
}
|
||||
|
||||
protected function getRequestHeaders()
|
||||
{
|
||||
$apiKey = $this->getSetting('api_key');
|
||||
|
||||
return [
|
||||
'Authorization' => 'Basic ' . base64_encode('api:' . $apiKey)
|
||||
];
|
||||
}
|
||||
}
|
||||
+39
@@ -0,0 +1,39 @@
|
||||
<?php
|
||||
|
||||
namespace FluentMail\App\Services\Mailer\Providers\TransMail;
|
||||
|
||||
use FluentMail\Includes\Support\Arr;
|
||||
use FluentMail\App\Services\Mailer\ValidatorTrait as BaseValidatorTrait;
|
||||
|
||||
trait ValidatorTrait
|
||||
{
|
||||
use BaseValidatorTrait;
|
||||
|
||||
public function validateProviderInformation($connection)
|
||||
{
|
||||
$errors = [];
|
||||
$keyStoreType = $connection['key_store'];
|
||||
|
||||
if($keyStoreType == 'db') {
|
||||
if (! Arr::get($connection, 'api_key')) {
|
||||
$errors['api_key']['required'] = __('Api key is required.', 'fluent-smtp');
|
||||
}
|
||||
|
||||
if (! Arr::get($connection, 'domain_name')) {
|
||||
$errors['domain_name']['required'] = __('Domain name is required.', 'fluent-smtp');
|
||||
}
|
||||
} else if($keyStoreType == 'wp_config') {
|
||||
if(!defined('FLUENTMAIL_MAILGUN_API_KEY') || !FLUENTMAIL_MAILGUN_API_KEY) {
|
||||
$errors['api_key']['required'] = __('Please define FLUENTMAIL_MAILGUN_API_KEY in wp-config.php file.', 'fluent-smtp');
|
||||
}
|
||||
|
||||
if(!defined('FLUENTMAIL_MAILGUN_DOMAIN') || !FLUENTMAIL_MAILGUN_DOMAIN) {
|
||||
$errors['domain_name']['required'] = __('Please define FLUENTMAIL_MAILGUN_DOMAIN in wp-config.php file.', 'fluent-smtp');
|
||||
}
|
||||
}
|
||||
|
||||
if ($errors) {
|
||||
$this->throwValidationException($errors);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,267 @@
|
||||
<?php
|
||||
|
||||
return [
|
||||
'connections' => [],
|
||||
'mappings' => [],
|
||||
'providers' => [
|
||||
'smtp' => [
|
||||
'key' => 'smtp',
|
||||
'title' => __('SMTP server', 'fluent-smtp'),
|
||||
'image' => fluentMailAssetUrl('images/provider-smtp.svg'),
|
||||
'provider' => 'Smtp',
|
||||
'need_pro' => 'no',
|
||||
'is_smtp' => true,
|
||||
'options' => [
|
||||
'sender_name' => '',
|
||||
'sender_email' => '',
|
||||
'force_from_name' => 'no',
|
||||
'force_from_email' => 'yes',
|
||||
'return_path' => 'yes',
|
||||
'host' => '',
|
||||
'port' => '',
|
||||
'auth' => 'yes',
|
||||
'username' => '',
|
||||
'password' => '',
|
||||
'auto_tls' => 'yes',
|
||||
'encryption' => 'none',
|
||||
'key_store' => 'db'
|
||||
],
|
||||
'note' => '<a href="https://fluentsmtp.com/docs/set-up-fluent-smtp-with-any-host-or-mailer/" target="_blank" rel="noopener">' . __('Read the documentation', 'fluent-smtp') . '</a>' . __(' for how to configure any SMTP with FluentSMTP.', 'fluent-smtp')
|
||||
],
|
||||
'ses' => [
|
||||
'key' => 'ses',
|
||||
'title' => __('Amazon SES', 'fluent-smtp'),
|
||||
'image' => fluentMailAssetUrl('images/provider-aws-ses.svg'),
|
||||
'provider' => 'AmazonSes',
|
||||
'options' => [
|
||||
'sender_name' => '',
|
||||
'sender_email' => '',
|
||||
'force_from_name' => 'no',
|
||||
'force_from_email' => 'yes',
|
||||
'return_path' => 'yes',
|
||||
'access_key' => '',
|
||||
'secret_key' => '',
|
||||
'region' => 'us-east-1',
|
||||
'key_store' => 'db'
|
||||
],
|
||||
'regions' => [
|
||||
'us-east-1' => __('US East (N. Virginia)', 'fluent-smtp'),
|
||||
'us-east-2' => __('US East (Ohio)', 'fluent-smtp'),
|
||||
'us-west-1' => __('US West (N. California)', 'fluent-smtp'),
|
||||
'us-west-2' => __('US West (Oregon)', 'fluent-smtp'),
|
||||
'ca-central-1' => __('Canada (Central)', 'fluent-smtp'),
|
||||
'eu-west-1' => __('EU (Ireland)', 'fluent-smtp'),
|
||||
'eu-west-2' => __('EU (London)', 'fluent-smtp'),
|
||||
'eu-west-3' => __('Europe (Paris)', 'fluent-smtp'),
|
||||
'eu-central-1' => __('EU (Frankfurt)', 'fluent-smtp'),
|
||||
'eu-south-1' => __('Europe (Milan)', 'fluent-smtp'),
|
||||
'eu-north-1' => __('Europe (Stockholm)', 'fluent-smtp'),
|
||||
'ap-south-1' => __('Asia Pacific (Mumbai)', 'fluent-smtp'),
|
||||
'ap-northeast-2' => __('Asia Pacific (Seoul)', 'fluent-smtp'),
|
||||
'ap-southeast-1' => __('Asia Pacific (Singapore)', 'fluent-smtp'),
|
||||
'ap-southeast-2' => __('Asia Pacific (Sydney)', 'fluent-smtp'),
|
||||
'ap-northeast-1' => __('Asia Pacific (Tokyo)', 'fluent-smtp'),
|
||||
'ap-northeast-3' => __('Asia Pacific (Osaka)', 'fluent-smtp'),
|
||||
'sa-east-1' => __('South America (São Paulo)', 'fluent-smtp'),
|
||||
'me-south-1' => __('Middle East (Bahrain)', 'fluent-smtp'),
|
||||
'us-gov-west-1' => __('AWS GovCloud (US)', 'fluent-smtp'),
|
||||
'af-south-1' => __('Africa (Cape Town)', 'fluent-smtp'),
|
||||
'cn-northwest-1' => __('China (Ningxia)', 'fluent-smtp')
|
||||
],
|
||||
'note' => '<a href="https://fluentsmtp.com/docs/set-up-amazon-ses-in-fluent-smtp/" target="_blank" rel="noopener">' . __('Read the documentation', 'fluent-smtp') . '</a>' . __(' for how to configure Amazon SES with FluentSMTP.', 'fluent-smtp')
|
||||
],
|
||||
'mailgun' => [
|
||||
'key' => 'mailgun',
|
||||
'title' => __('Mailgun', 'fluent-smtp'),
|
||||
'image' => fluentMailAssetUrl('images/provider-mailgun.svg'),
|
||||
'provider' => 'Mailgun',
|
||||
'options' => [
|
||||
'sender_name' => '',
|
||||
'sender_email' => '',
|
||||
'force_from_name' => 'no',
|
||||
'return_path' => 'yes',
|
||||
'api_key' => '',
|
||||
'domain_name' => '',
|
||||
'key_store' => 'db',
|
||||
'region' => 'us'
|
||||
],
|
||||
'note' => '<a href="https://fluentsmtp.com/docs/configure-mailgun-in-fluent-smtp-to-send-emails/" target="_blank" rel="noopener">' . __('Read the documentation', 'fluent-smtp') . '</a>' . __(' for how to configure Mailgun with FluentSMTP.', 'fluent-smtp')
|
||||
],
|
||||
'sendgrid' => [
|
||||
'key' => 'sendgrid',
|
||||
'title' => __('SendGrid', 'fluent-smtp'),
|
||||
'image' => fluentMailAssetUrl('images/provider-sendgrid.svg'),
|
||||
'provider' => 'SendGrid',
|
||||
'options' => [
|
||||
'sender_name' => '',
|
||||
'sender_email' => '',
|
||||
'force_from_name' => 'no',
|
||||
'api_key' => '',
|
||||
'key_store' => 'db'
|
||||
],
|
||||
'note' => '<a href="https://fluentsmtp.com/docs/set-up-the-sendgrid-driver-in-fluent-smtp/" target="_blank" rel="noopener">' . __('Read the documentation', 'fluent-smtp') . '</a>' . __(' for how to configure SendGrid with FluentSMTP.', 'fluent-smtp')
|
||||
],
|
||||
'sendinblue' => [
|
||||
'key' => 'sendinblue',
|
||||
'title' => __('Sendinblue', 'fluent-smtp'),
|
||||
'image' => fluentMailAssetUrl('images/provider-sendinblue.svg'),
|
||||
'provider' => 'SendInBlue',
|
||||
'options' => [
|
||||
'sender_name' => '',
|
||||
'sender_email' => '',
|
||||
'force_from_name' => 'no',
|
||||
'api_key' => '',
|
||||
'key_store' => 'db'
|
||||
],
|
||||
'note' => '<a href="https://fluentsmtp.com/docs/setting-up-sendinblue-mailer-in-fluent-smtp/" target="_blank" rel="noopener">' . __('Read the documentation', 'fluent-smtp') . '</a>' . __(' for how to configure Sendinblue with FluentSMTP.', 'fluent-smtp')
|
||||
],
|
||||
'sparkpost' => [
|
||||
'key' => 'sparkpost',
|
||||
'title' => __('SparkPost', 'fluent-smtp'),
|
||||
'image' => fluentMailAssetUrl('images/provider-sparkpost.svg'),
|
||||
'provider' => 'SparkPost',
|
||||
'options' => [
|
||||
'sender_name' => '',
|
||||
'sender_email' => '',
|
||||
'force_from_name' => 'no',
|
||||
'api_key' => '',
|
||||
'key_store' => 'db'
|
||||
],
|
||||
'note' => '<a href="https://fluentsmtp.com/docs/configure-sparkpost-in-fluent-smtp-to-send-emails/" target="_blank" rel="noopener">' . __('Read the documentation', 'fluent-smtp') . '</a>' . __(' for how to configure SparkPost with FluentSMTP.', 'fluent-smtp')
|
||||
],
|
||||
'pepipost' => [
|
||||
'key' => 'pepipost',
|
||||
'title' => __('Netcore Email API, formerly Pepipost', 'fluent-smtp'),
|
||||
'image' => fluentMailAssetUrl('images/provider-netcore.svg'),
|
||||
'provider' => 'PepiPost',
|
||||
'options' => [
|
||||
'sender_name' => '',
|
||||
'sender_email' => '',
|
||||
'force_from_name' => 'no',
|
||||
'api_key' => '',
|
||||
'key_store' => 'db'
|
||||
],
|
||||
'note' => '<a href="https://fluentsmtp.com/docs/set-up-the-pepipost-mailer-in-fluent-smtp/" target="_blank" rel="noopener">' . __('Read the documentation', 'fluent-smtp') . '</a>' . __(' for how to configure Netcore (formerly Pepipost) with FluentSMTP.', 'fluent-smtp')
|
||||
],
|
||||
'postmark' => [
|
||||
'key' => 'postmark',
|
||||
'title' => __('Postmark', 'fluent-smtp'),
|
||||
'image' => fluentMailAssetUrl('images/provider-postmark.svg'),
|
||||
'provider' => 'Postmark',
|
||||
'options' => [
|
||||
'sender_name' => '',
|
||||
'sender_email' => '',
|
||||
'force_from_name' => 'no',
|
||||
'track_opens' => 'no',
|
||||
'track_links' => 'no',
|
||||
'api_key' => '',
|
||||
'message_stream' => 'outbound',
|
||||
'key_store' => 'db'
|
||||
],
|
||||
'note' => '<a href="https://fluentsmtp.com/docs/configure-postmark-in-fluent-smtp-to-send-emails/" target="_blank" rel="noopener">' . __('Read the documentation', 'fluent-smtp') . '</a>' . __(' for how to configure Postmark with FluentSMTP.', 'fluent-smtp')
|
||||
],
|
||||
'elasticmail' => [
|
||||
'key' => 'elasticmail',
|
||||
'title' => __('Elastic Email', 'fluent-smtp'),
|
||||
'image' => fluentMailAssetUrl('images/provider-elastic-email.svg'),
|
||||
'provider' => 'ElasticMail',
|
||||
'options' => [
|
||||
'sender_name' => '',
|
||||
'sender_email' => '',
|
||||
'force_from_name' => 'no',
|
||||
'api_key' => '',
|
||||
'mail_type' => 'transactional',
|
||||
'key_store' => 'db'
|
||||
],
|
||||
'note' => '<a href="https://fluentsmtp.com/docs/configure-elastic-email-in-fluent-smtp/" target="_blank" rel="noopener">' . __('Read the documentation', 'fluent-smtp') . '</a>' . __(' for how to configure Elastic Email with FluentSMTP.', 'fluent-smtp')
|
||||
],
|
||||
'smtp2go' => [
|
||||
'key' => 'smtp2go',
|
||||
'title' => __('SMTP2GO', 'fluent-smtp'),
|
||||
'image' => fluentMailAssetUrl('images/provider-smtp2go.svg'),
|
||||
'provider' => 'Smtp2Go',
|
||||
'options' => [
|
||||
'sender_name' => '',
|
||||
'sender_email' => '',
|
||||
'force_from_name' => 'no',
|
||||
'api_key' => '',
|
||||
'key_store' => 'db'
|
||||
]
|
||||
],
|
||||
'gmail' => [
|
||||
'key' => 'gmail',
|
||||
'title' => __('Gmail or Google Workspace', 'fluent-smtp'),
|
||||
'image' => fluentMailAssetUrl('images/provider-gmail-google-workspace.svg'),
|
||||
'provider' => 'Gmail',
|
||||
'options' => [
|
||||
'sender_name' => '',
|
||||
'sender_email' => '',
|
||||
'force_from_name' => 'no',
|
||||
'return_path' => 'yes',
|
||||
'key_store' => 'db',
|
||||
'client_id' => '',
|
||||
'client_secret' => '',
|
||||
'auth_token' => '',
|
||||
'access_token' => '',
|
||||
'refresh_token' => ''
|
||||
],
|
||||
'note' => __('Gmail/Google Workspace is not recommended for sending mass marketing emails.', 'fluent-smtp')
|
||||
],
|
||||
'outlook' => [
|
||||
'key' => 'outlook',
|
||||
'title' => __('Outlook or Office 365', 'fluent-smtp'),
|
||||
'image' => fluentMailAssetUrl('images/provider-microsoft.svg'),
|
||||
'provider' => 'Outlook',
|
||||
'options' => [
|
||||
'sender_name' => '',
|
||||
'sender_email' => '',
|
||||
'force_from_name' => 'no',
|
||||
'return_path' => 'yes',
|
||||
'key_store' => 'db',
|
||||
'client_id' => '',
|
||||
'client_secret' => '',
|
||||
'auth_token' => '',
|
||||
'access_token' => '',
|
||||
'refresh_token' => ''
|
||||
],
|
||||
'note' => __('Outlook/Office365 is not recommended for sending mass marketing emails.', 'fluent-smtp')
|
||||
],
|
||||
'tosend' => [
|
||||
'key' => 'tosend',
|
||||
'title' => 'ToSend',
|
||||
'image' => fluentMailAssetUrl('images/provider-tosend.svg'),
|
||||
'provider' => 'tosend',
|
||||
'options' => [
|
||||
'sender_name' => '',
|
||||
'sender_email' => '',
|
||||
'force_from_name' => 'no',
|
||||
'force_from_email' => 'yes',
|
||||
'api_key' => '',
|
||||
'key_store' => 'db'
|
||||
],
|
||||
'note' => '<a href="https://fluentsmtp.com/docs/set-up-tosend-in-fluent-smtp/" target="_blank" rel="noopener">' . __('Read the documentation', 'fluent-smtp') . '</a>' . __(' for how to configure ToSend with FluentSMTP.', 'fluent-smtp')
|
||||
],
|
||||
'default' => [
|
||||
'key' => 'default',
|
||||
'title' => __('PHP mail()', 'fluent-smtp'),
|
||||
'image' => fluentMailAssetUrl('images/provider-php.svg'),
|
||||
'provider' => 'DefaultMail',
|
||||
'options' => [
|
||||
'sender_name' => '',
|
||||
'sender_email' => '',
|
||||
'force_from_name' => 'no',
|
||||
'force_from_email' => 'yes',
|
||||
'return_path' => 'yes',
|
||||
'key_store' => 'db'
|
||||
],
|
||||
'note' => __('The Default option does not use SMTP or any Email Service Providers so it will not improve email delivery on your site.', 'fluent-smtp')
|
||||
],
|
||||
],
|
||||
'misc' => [
|
||||
'log_emails' => 'yes',
|
||||
'log_saved_interval_days' => '14',
|
||||
'disable_fluentcrm_logs' => 'no',
|
||||
'default_connection' => '',
|
||||
'fallback_connection' => ''
|
||||
]
|
||||
];
|
||||
@@ -0,0 +1,39 @@
|
||||
<?php
|
||||
|
||||
namespace FluentMail\App\Services\Mailer;
|
||||
|
||||
use FluentMail\App\Models\Settings;
|
||||
use FluentMail\Includes\Support\Arr;
|
||||
use FluentMail\Includes\Support\ValidationException;
|
||||
|
||||
trait ValidatorTrait
|
||||
{
|
||||
public function validateBasicInformation($connection)
|
||||
{
|
||||
$errors = [];
|
||||
|
||||
if (!($email = Arr::get($connection, 'sender_email'))) {
|
||||
$errors['sender_email']['required'] = __('Sender email is required.', 'fluent-smtp');
|
||||
}
|
||||
|
||||
if (!filter_var($email, FILTER_VALIDATE_EMAIL)) {
|
||||
$errors['sender_email']['email'] = __('Invalid email address.', 'fluent-smtp');
|
||||
}
|
||||
|
||||
if ($errors) {
|
||||
$this->throwValidationException($errors);
|
||||
}
|
||||
}
|
||||
|
||||
public function validateProviderInformation($inputs)
|
||||
{
|
||||
// Required Method
|
||||
}
|
||||
|
||||
public function throwValidationException($errors)
|
||||
{
|
||||
throw new ValidationException(
|
||||
esc_html__('Unprocessable Entity', 'fluent-smtp'), 422, null, $errors // phpcs:ignore WordPress.Security.EscapeOutput.ExceptionNotEscaped
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
<?php // silence is golden
|
||||
Reference in New Issue
Block a user