- Addresses issues identified during code review

This commit is contained in:
Vlad
2016-01-06 19:19:06 -05:00
parent f1bf2bb097
commit 0dbe04c3f8
29 changed files with 493 additions and 438 deletions

View File

@ -37,7 +37,7 @@ define(
} }
}, },
controlCron: function(action) { controlCron: function(action) {
if (jQuery('.button-primary').hasClass('disabled')) { if(jQuery('.button-primary').hasClass('disabled')) {
return; return;
} }
jQuery('.button-primary') jQuery('.button-primary')

View File

@ -142,7 +142,7 @@ class Initializer {
} }
function runQueueSupervisor() { function runQueueSupervisor() {
if (php_sapi_name() === 'cli') return; if(php_sapi_name() === 'cli') return;
try { try {
$supervisor = new Supervisor(); $supervisor = new Supervisor();
$supervisor->checkDaemon(); $supervisor->checkDaemon();

View File

@ -7,6 +7,11 @@ use MailPoet\Util\Helpers;
if(!defined('ABSPATH')) exit; if(!defined('ABSPATH')) exit;
class PublicAPI { class PublicAPI {
public $api;
public $section;
public $action;
public $request_payload;
function __construct() { function __construct() {
# http://example.com/?mailpoet-api&section=&action=&request_payload= # http://example.com/?mailpoet-api&section=&action=&request_payload=
$this->api = isset($_GET['mailpoet-api']) ? true : false; $this->api = isset($_GET['mailpoet-api']) ? true : false;
@ -14,7 +19,7 @@ class PublicAPI {
$this->action = isset($_GET['action']) ? $this->action = isset($_GET['action']) ?
Helpers::underscoreToCamelCase($_GET['action']) : Helpers::underscoreToCamelCase($_GET['action']) :
false; false;
$this->requestPayload = isset($_GET['request_payload']) ? $this->request_payload = isset($_GET['request_payload']) ?
json_decode(urldecode($_GET['request_payload']), true) : json_decode(urldecode($_GET['request_payload']), true) :
false; false;
} }
@ -26,7 +31,7 @@ class PublicAPI {
function queue() { function queue() {
try { try {
$queue = new Daemon($this->requestPayload); $queue = new Daemon($this->request_payload);
$this->_checkAndCallMethod($queue, $this->action); $this->_checkAndCallMethod($queue, $this->action);
} catch(\Exception $e) { } catch(\Exception $e) {
} }

View File

@ -10,91 +10,93 @@ require_once(ABSPATH . 'wp-includes/pluggable.php');
if(!defined('ABSPATH')) exit; if(!defined('ABSPATH')) exit;
class Daemon { class Daemon {
function __construct($requestPayload = array()) { public $daemon;
public $request_payload;
public $refreshed_token;
public $timer;
function __construct($request_payload = array()) {
set_time_limit(0); set_time_limit(0);
ignore_user_abort(); ignore_user_abort();
list ($this->daemon, $this->daemonData) = $this->getDaemon(); $this->daemon = $this->getDaemon();
$this->refreshedToken = $this->refreshToken(); $this->refreshed_token = $this->refreshToken();
$this->requestPayload = $requestPayload; $this->request_payload = $request_payload;
$this->timer = microtime(true); $this->timer = microtime(true);
} }
function start() { function start() {
if(!isset($this->requestPayload['session'])) { if(!isset($this->request_payload['session'])) {
$this->abortWithError(__('Missing session ID.')); $this->abortWithError(__('Missing session ID.'));
} }
$this->manageSession('start'); $this->manageSession('start');
$daemon = $this->daemon; $daemon = $this->daemon;
$daemonData = $this->daemonData;
if(!$daemon) { if(!$daemon) {
$daemon = Setting::create(); $this->saveDaemon(
$daemon->name = 'cron_daemon'; array(
$daemonData = array( 'status' => 'starting',
'status' => 'starting', 'counter' => 0
'counter' => 0 )
); );
$daemon->value = json_encode($daemonData);
$daemon->save();
} }
if($daemonData['status'] === 'started') { if($daemon['status'] === 'started') {
$_SESSION['cron_daemon'] = array( $_SESSION['cron_daemon'] = array(
'result' => false, 'result' => false,
'errors' => array(__('Daemon already running.')) 'errors' => array(__('Daemon already running.'))
); );
} }
if($daemonData['status'] === 'starting') { if($daemon['status'] === 'starting') {
$_SESSION['cron_daemon'] = 'started'; $_SESSION['cron_daemon'] = 'started';
$_SESSION['cron_daemon'] = array('result' => true); $_SESSION['cron_daemon'] = array('result' => true);
$daemonData['status'] = 'started';
$daemonData['token'] = $this->refreshedToken;
$this->manageSession('end'); $this->manageSession('end');
$daemon->value = json_encode($daemonData); $daemon['status'] = 'started';
$daemon->save(); $daemon['token'] = $this->refreshed_token;
$this->saveDaemon($daemon);
$this->callSelf(); $this->callSelf();
} }
$this->manageSession('end'); $this->manageSession('end');
} }
function run() { function run() {
$allowedStatuses = array( $allowed_statuses = array(
'stopping', 'stopping',
'starting', 'starting',
'started' 'started'
); );
if(!$this->daemon || !in_array($this->daemonData['status'], $allowedStatuses)) { if(!$this->daemon || !in_array($this->daemon['status'], $allowed_statuses)) {
$this->abortWithError(__('Invalid daemon status.')); $this->abortWithError(__('Invalid daemon status.'));
} }
if(!isset($this->requestPayload['token']) || if(!isset($this->request_payload['token']) ||
$this->requestPayload['token'] !== $this->daemonData['token'] $this->request_payload['token'] !== $this->daemon['token']
) { ) {
$this->abortWithError('Invalid token.'); $this->abortWithError('Invalid token.');
} }
try { try {
$sendingQueue = new SendingQueue($this->timer); $sending_queue = new SendingQueue($this->timer);
$sendingQueue->process(); $sending_queue->process();
} catch(Exception $e) { } catch(Exception $e) {
} }
$elapsedTime = microtime(true) - $this->timer; $elapsed_time = microtime(true) - $this->timer;
if($elapsedTime < 30) { if($elapsed_time < 30) {
sleep(30 - $elapsedTime); sleep(30 - $elapsed_time);
} }
// after each execution, read daemon in case it's status was modified // after each execution, read daemon in case it's status was modified
list($daemon, $daemonData) = $this->getDaemon(); $daemon = $this->getDaemon();
if($daemonData['status'] === 'stopping') $daemonData['status'] = 'stopped'; if($daemon['status'] === 'stopping') $daemon['status'] = 'stopped';
if($daemonData['status'] === 'starting') $daemonData['status'] = 'started'; if($daemon['status'] === 'starting') $daemon['status'] = 'started';
$daemonData['token'] = $this->refreshedToken; $daemon['token'] = $this->refreshed_token;
$daemonData['counter']++; $daemon['counter']++;
$daemon->value = json_encode($daemonData); $this->saveDaemon($daemon);
$daemon->save(); if($daemon['status'] === 'started') $this->callSelf();
if($daemonData['status'] === 'started') $this->callSelf();
} }
function getDaemon() { function getDaemon() {
$daemon = Setting::where('name', 'cron_daemon') return Setting::getValue('cron_daemon', null);
->findOne(); }
return array(
($daemon) ? $daemon : null, function saveDaemon($daemon_data) {
($daemon) ? json_decode($daemon->value, true) : null return Setting::setValue(
'cron_daemon',
$daemon_data
); );
} }
@ -108,7 +110,7 @@ class Daemon {
if(session_id()) { if(session_id()) {
session_write_close(); session_write_close();
} }
session_id($this->requestPayload['session']); session_id($this->request_payload['session']);
session_start(); session_start();
break; break;
case 'end': case 'end':
@ -118,7 +120,7 @@ class Daemon {
} }
function callSelf() { function callSelf() {
$payload = json_encode(array('token' => $this->refreshedToken)); $payload = json_encode(array('token' => $this->refreshed_token));
Supervisor::accessRemoteUrl( Supervisor::accessRemoteUrl(
'/?mailpoet-api&section=queue&action=run&request_payload=' . urlencode($payload) '/?mailpoet-api&section=queue&action=run&request_payload=' . urlencode($payload)
); );

View File

@ -8,38 +8,39 @@ use MailPoet\Models\Setting;
if(!defined('ABSPATH')) exit; if(!defined('ABSPATH')) exit;
class Supervisor { class Supervisor {
function __construct($forceStart = false) { public $daemon;
$this->forceStart = $forceStart;
function __construct($force_start = false) {
$this->force_start = $force_start;
if(!Env::isPluginActivated()) { if(!Env::isPluginActivated()) {
throw new \Exception(__('MailPoet is not activated.')); throw new \Exception(__('MailPoet is not activated.'));
} }
list ($this->daemon, $this->daemonData) = $this->getDaemon(); $this->daemon = $this->getDaemon();
} }
function checkDaemon() { function checkDaemon() {
if(!$this->daemon) { if(!$this->daemon) {
return $this->startDaemon(); return $this->startDaemon();
} }
if(!$this->forceStart && ( if(!$this->force_start && (
$this->daemonData['status'] === 'stopped' || $this->daemon['value']['status'] === 'stopped' ||
$this->daemonData['status'] === 'stopping') $this->daemon['value']['status'] === 'stopping')
) { ) {
return $this->daemonData['status']; return $this->daemon['value']['status'];
} }
$timeSinceLastRun = $this->getDaemonLastRunTime(); $time_since_last_run = $this->getDaemonLastRunTime();
if($timeSinceLastRun < 40) { if($time_since_last_run < 40) {
if(!$this->forceStart) { if(!$this->force_start) {
return; return;
} }
if($this->daemonData['status'] === 'stopping' || if($this->daemon['value']['status'] === 'stopping' ||
$this->daemonData['status'] === 'starting' $this->daemon['value']['status'] === 'starting'
) { ) {
return $this->daemonData['status']; return $this->daemon['value']['status'];
} }
} }
$this->daemonData['status'] = 'starting'; $this->daemon['value']['status'] = 'starting';
$this->daemon->value = json_encode($this->daemonData); $this->saveDaemon($this->daemon['value']);
$this->daemon->save();
return $this->startDaemon(); return $this->startDaemon();
} }
@ -50,7 +51,8 @@ class Supervisor {
$_SESSION['cron_daemon'] = null; $_SESSION['cron_daemon'] = null;
$requestPayload = json_encode(array('session' => $sessionId)); $requestPayload = json_encode(array('session' => $sessionId));
self::accessRemoteUrl( self::accessRemoteUrl(
'/?mailpoet-api&section=queue&action=start&request_payload=' . urlencode($requestPayload) '/?mailpoet-api&section=queue&action=start&request_payload=' .
urlencode($requestPayload)
); );
session_start(); session_start();
$daemonStatus = $_SESSION['cron_daemon']; $daemonStatus = $_SESSION['cron_daemon'];
@ -62,10 +64,16 @@ class Supervisor {
function getDaemon() { function getDaemon() {
$daemon = Setting::where('name', 'cron_daemon') $daemon = Setting::where('name', 'cron_daemon')
->findOne(); ->findOne();
$daemonData = ($daemon) ? json_decode($daemon->value, true) : false; if(!$daemon) return false;
return array( $daemon = $daemon->asArray();
$daemon, $daemon['value'] = unserialize($daemon['value']);
$daemonData return $daemon;
}
function saveDaemon($daemon_data) {
return Setting::setValue(
'cron_daemon',
$daemon_data
); );
} }
@ -98,11 +106,11 @@ class Supervisor {
} }
function getDaemonLastRunTime() { function getDaemonLastRunTime() {
$currentTime = Carbon::now('UTC'); $current_time = Carbon::now('UTC');
$lastUpdateTime = Carbon::createFromFormat( $last_update_time = Carbon::createFromFormat(
'Y-m-d H:i:s', 'Y-m-d H:i:s',
$this->daemon->updated_at, 'UTC' $this->daemon['updated_at'], 'UTC'
); );
return $currentTime->diffInSeconds($lastUpdateTime); return $current_time->diffInSeconds($last_update_time);
} }
} }

View File

@ -10,36 +10,41 @@ use MailPoet\Newsletter\Renderer\Renderer;
if(!defined('ABSPATH')) exit; if(!defined('ABSPATH')) exit;
class SendingQueue { class SendingQueue {
public $timer;
function __construct($timer = false) { function __construct($timer = false) {
$this->timer = ($timer) ? $timer : microtime(true); $this->timer = ($timer) ? $timer : microtime(true);
} }
function process() { function process() {
// TODO: implement mailer sending frequency limits
foreach($this->getQueues() as $queue) { foreach($this->getQueues() as $queue) {
$newsletter = Newsletter::findOne($queue->newsletter_id) $newsletter = Newsletter::findOne($queue->newsletter_id)
->asArray(); ->asArray();
if(!$newsletter) { if(!$newsletter) {
continue; continue;
}; };
$newsletter = $this->renderNewsletter($newsletter);
$mailer = $this->configureMailerForNewsletter($newsletter); $mailer = $this->configureMailerForNewsletter($newsletter);
$newsletter = $this->renderNewsletter($newsletter);
$subscribers = json_decode($queue->subscribers, true); $subscribers = json_decode($queue->subscribers, true);
$subscribersToProcess = $subscribers['to_process']; $subscribers_to_process = $subscribers['to_process'];
if(!isset($subscribers['processed'])) $subscribers['processed'] = array(); if(!isset($subscribers['processed'])) $subscribers['processed'] = array();
if(!isset($subscribers['failed'])) $subscribers['failed'] = array(); if(!isset($subscribers['failed'])) $subscribers['failed'] = array();
foreach(array_chunk($subscribersToProcess, 200) as $subscriberIds) { foreach(array_chunk($subscribers_to_process, 200) as $subscriber_ids) {
$dbSubscribers = Subscriber::whereIn('id', $subscriberIds) $db_subscribers = Subscriber::whereIn('id', $subscriber_ids)
->findArray(); ->findArray();
foreach($dbSubscribers as $dbSubscriber) { foreach($db_subscribers as $db_subscriber) {
$this->checkExecutionTimer(); $this->checkExecutionTimer();
$result = $this->sendNewsletter( $result = $this->sendNewsletter(
$mailer, $mailer,
$this->processNewsletter($newsletter), $this->processNewsletter($newsletter),
$dbSubscriber); $db_subscriber);
if($result) { if($result) {
$this->updateStatistics($newsletter['id'], $dbSubscriber['id'], $queue->id); $this->updateStatistics($newsletter['id'], $db_subscriber['id'], $queue->id);
$subscribers['processed'][] = $dbSubscriber['id']; $subscribers['processed'][] = $db_subscriber['id'];
} else $subscribers['failed'][] = $dbSubscriber['id']; } else {
$subscribers['failed'][] = $db_subscriber['id'];
}
$this->updateQueue($queue, $subscribers); $this->updateQueue($queue, $subscribers);
} }
} }
@ -52,18 +57,18 @@ class SendingQueue {
} }
function sendNewsletter($mailer, $newsletter, $subscriber) { function sendNewsletter($mailer, $newsletter, $subscriber) {
return $mailer->mailerInstance->send( return $mailer->mailer_instance->send(
$newsletter, $newsletter,
$mailer->transformSubscriber($subscriber) $mailer->transformSubscriber($subscriber)
); );
} }
function updateStatistics($newsletterId, $subscriberId, $queueId) { function updateStatistics($newsletter_id, $subscriber_id, $queue_id) {
$newsletterStatistics = NewsletterStatistics::create(); $newsletter_statistic = NewsletterStatistics::create();
$newsletterStatistics->subscriber_id = $newsletterId; $newsletter_statistic->subscriber_id = $newsletter_id;
$newsletterStatistics->newsletter_id = $subscriberId; $newsletter_statistic->newsletter_id = $subscriber_id;
$newsletterStatistics->queue_id = $queueId; $newsletter_statistic->queue_id = $queue_id;
$newsletterStatistics->save(); $newsletter_statistic->save();
} }
function updateQueue($queue, $subscribers) { function updateQueue($queue, $subscribers) {
@ -93,20 +98,24 @@ class SendingQueue {
'name' => $newsletter['sender_name'], 'name' => $newsletter['sender_name'],
'address' => $newsletter['sender_address'] 'address' => $newsletter['sender_address']
); );
} else $sender = false; } else {
$sender = false;
}
if(!empty($newsletter['reply_to_address']) && !empty($newsletter['reply_to_name'])) { if(!empty($newsletter['reply_to_address']) && !empty($newsletter['reply_to_name'])) {
$replyTo = array( $reply_to = array(
'name' => $newsletter['reply_to_name'], 'name' => $newsletter['reply_to_name'],
'address' => $newsletter['reply_to_address'] 'address' => $newsletter['reply_to_address']
); );
} else $replyTo = false; } else {
$mailer = new Mailer($method = false, $sender, $replyTo); $reply_to = false;
}
$mailer = new Mailer($method = false, $sender, $reply_to);
return $mailer; return $mailer;
} }
function checkExecutionTimer() { function checkExecutionTimer() {
$elapsedTime = microtime(true) - $this->timer; $elapsed_time = microtime(true) - $this->timer;
if($elapsedTime >= 30) throw new \Exception('Maximum execution time reached.'); if($elapsed_time >= 30) throw new \Exception('Maximum execution time reached.');
} }
function getQueues() { function getQueues() {
@ -118,7 +127,8 @@ class SendingQueue {
function renderNewsletter($newsletter) { function renderNewsletter($newsletter) {
$renderer = new Renderer(json_decode($newsletter['body'], true)); $renderer = new Renderer(json_decode($newsletter['body'], true));
$newsletter['body'] = $renderer->renderAll(); // TODO: update once text rendering is implemented/enderer returns an array
$newsletter['body'] = array('html' => $renderer->render(), 'text' => '');
return $newsletter; return $newsletter;
} }
} }

View File

@ -8,86 +8,91 @@ require_once(ABSPATH . 'wp-includes/pluggable.php');
if(!defined('ABSPATH')) exit; if(!defined('ABSPATH')) exit;
class Mailer { class Mailer {
public $mailer;
public $sender;
public $reply_to;
public $mailer_instance;
function __construct($mailer = false, $sender = false, $reply_to = false) { function __construct($mailer = false, $sender = false, $reply_to = false) {
$this->mailer = $this->getMailer($mailer); $this->mailer = $this->getMailer($mailer);
$this->sender = $this->getSender($sender); $this->sender = $this->getSender($sender);
$this->replyTo = $this->getReplyTo($reply_to); $this->reply_to = $this->getReplyTo($reply_to);
$this->mailerInstance = $this->buildMailer(); $this->mailer_instance = $this->buildMailer();
} }
function send($newsletter, $subscriber) { function send($newsletter, $subscriber) {
$subscriber = $this->transformSubscriber($subscriber); $subscriber = $this->transformSubscriber($subscriber);
return $this->mailerInstance->send($newsletter, $subscriber); return $this->mailer_instance->send($newsletter, $subscriber);
} }
function buildMailer() { function buildMailer() {
switch($this->mailer['method']) { switch($this->mailer['method']) {
case 'AmazonSES': case 'AmazonSES':
$mailerInstance = new $this->mailer['class']( $mailer_instance = new $this->mailer['class'](
$this->mailer['region'], $this->mailer['region'],
$this->mailer['access_key'], $this->mailer['access_key'],
$this->mailer['secret_key'], $this->mailer['secret_key'],
$this->sender['fromNameEmail'] $this->sender['from_name_email']
); );
break; break;
case 'ElasticEmail': case 'ElasticEmail':
$mailerInstance = new $this->mailer['class']( $mailer_instance = new $this->mailer['class'](
$this->mailer['api_key'], $this->mailer['api_key'],
$this->sender['fromEmail'], $this->sender['from_email'],
$this->sender['fromName'] $this->sender['from_name']
); );
break; break;
case 'MailGun': case 'MailGun':
$mailerInstance = new $this->mailer['class']( $mailer_instance = new $this->mailer['class'](
$this->mailer['domain'], $this->mailer['domain'],
$this->mailer['api_key'], $this->mailer['api_key'],
$this->sender['fromNameEmail'] $this->sender['from_name_email']
); );
break; break;
case 'MailPoet': case 'MailPoet':
$mailerInstance = new $this->mailer['class']( $mailer_instance = new $this->mailer['class'](
$this->mailer['mailpoet_api_key'], $this->mailer['mailpoet_api_key'],
$this->sender['fromEmail'], $this->sender['from_email'],
$this->sender['fromName'] $this->sender['from_name']
); );
break; break;
case 'Mandrill': case 'Mandrill':
$mailerInstance = new $this->mailer['class']( $mailer_instance = new $this->mailer['class'](
$this->mailer['api_key'], $this->mailer['api_key'],
$this->sender['fromEmail'], $this->sender['from_email'],
$this->sender['fromName'] $this->sender['from_name']
); );
break; break;
case 'SendGrid': case 'SendGrid':
$mailerInstance = new $this->mailer['class']( $mailer_instance = new $this->mailer['class'](
$this->mailer['api_key'], $this->mailer['api_key'],
$this->sender['fromEmail'], $this->sender['from_email'],
$this->sender['fromName'] $this->sender['from_name']
); );
break; break;
case 'WPMail': case 'WPMail':
$mailerInstance = new $this->mailer['class']( $mailer_instance = new $this->mailer['class'](
$this->sender['fromEmail'], $this->sender['from_email'],
$this->sender['fromName'] $this->sender['from_name']
); );
break; break;
case 'SMTP': case 'SMTP':
$mailerInstance = new $this->mailer['class']( $mailer_instance = new $this->mailer['class'](
$this->mailer['host'], $this->mailer['host'],
$this->mailer['port'], $this->mailer['port'],
$this->mailer['authentication'], $this->mailer['authentication'],
$this->mailer['login'], $this->mailer['login'],
$this->mailer['password'], $this->mailer['password'],
$this->mailer['encryption'], $this->mailer['encryption'],
$this->sender['fromEmail'], $this->sender['from_email'],
$this->sender['fromName'] $this->sender['from_name']
); );
break; break;
default: default:
throw new \Exception(__('Mailing method does not exist.')); throw new \Exception(__('Mailing method does not exist.'));
break; break;
} }
return $mailerInstance; return $mailer_instance;
} }
function getMailer($mailer = false) { function getMailer($mailer = false) {
@ -105,26 +110,26 @@ class Mailer {
if(!$sender) throw new \Exception(__('Sender name and email are not configured.')); if(!$sender) throw new \Exception(__('Sender name and email are not configured.'));
} }
return array( return array(
'fromName' => $sender['name'], 'from_name' => $sender['name'],
'fromEmail' => $sender['address'], 'from_email' => $sender['address'],
'fromNameEmail' => sprintf('%s <%s>', $sender['name'], $sender['address']) 'from_name_email' => sprintf('%s <%s>', $sender['name'], $sender['address'])
); );
} }
function getReplyTo($replyTo = false) { function getReplyTo($reply_to = false) {
if(!$replyTo) { if(!$reply_to) {
$replyTo = Setting::getValue('replyTo', null); $reply_to = Setting::getValue('reply_to', null);
if(!$replyTo) { if(!$reply_to) {
$replyTo = array( $reply_to = array(
'name' => $this->sender['fromName'], 'name' => $this->sender['from_name'],
'address' => $this->sender['fromEmail'] 'address' => $this->sender['from_email']
); );
} }
} }
return array( return array(
'replyToName' => $replyTo['name'], 'reply_to_name' => $reply_to['name'],
'replyToEmail' => $replyTo['address'], 'reply_to_email' => $reply_to['address'],
'replyToNameEmail' => sprintf('%s <%s>', $replyTo['name'], $replyTo['address']) 'reply_to_name_email' => sprintf('%s <%s>', $reply_to['name'], $reply_to['address'])
); );
} }

View File

@ -4,21 +4,34 @@ namespace MailPoet\Mailer\Methods;
if(!defined('ABSPATH')) exit; if(!defined('ABSPATH')) exit;
class AmazonSES { class AmazonSES {
function __construct($region, $accessKey, $secretKey, $from) { public $aws_access_key;
$this->awsAccessKey = $accessKey; public $aws_secret_key;
$this->awsSecret_key = $secretKey; public $aws_region;
$this->awsRegion = $region; public $aws_endpoint;
$this->awsEndpoint = sprintf('email.%s.amazonaws.com', $region); public $aws_signing_algorithm;
$this->awsSigningAlgorithm = 'AWS4-HMAC-SHA256'; public $aws_service;
$this->awsService = 'ses'; public $aws_termination_string;
$this->awsTerminationString = 'aws4_request'; public $hash_algorithm;
$this->hashAlgorithm = 'sha256'; public $url;
$this->url = 'https://' . $this->awsEndpoint; public $from;
public $date;
public $date_without_time;
function __construct($region, $access_key, $secret_key, $from) {
$this->aws_access_key = $access_key;
$this->aws_secret_key = $secret_key;
$this->aws_region = $region;
$this->aws_endpoint = sprintf('email.%s.amazonaws.com', $region);
$this->aws_signing_algorithm = 'AWS4-HMAC-SHA256';
$this->aws_service = 'ses';
$this->aws_termination_string = 'aws4_request';
$this->hash_algorithm = 'sha256';
$this->url = 'https://' . $this->aws_endpoint;
$this->from = $from; $this->from = $from;
$this->date = gmdate('Ymd\THis\Z'); $this->date = gmdate('Ymd\THis\Z');
$this->dateWithoutTime = gmdate('Ymd'); $this->date_without_time = gmdate('Ymd');
} }
function send($newsletter, $subscriber) { function send($newsletter, $subscriber) {
$result = wp_remote_post( $result = wp_remote_post(
$this->url, $this->url,
@ -29,7 +42,7 @@ class AmazonSES {
wp_remote_retrieve_response_code($result) === 200 wp_remote_retrieve_response_code($result) === 200
); );
} }
function getBody($newsletter, $subscriber) { function getBody($newsletter, $subscriber) {
$body = array( $body = array(
'Action' => 'SendEmail', 'Action' => 'SendEmail',
@ -47,7 +60,7 @@ class AmazonSES {
} }
return $body; return $body;
} }
function request($newsletter, $subscriber) { function request($newsletter, $subscriber) {
$body = $this->getBody($newsletter, $subscriber); $body = $this->getBody($newsletter, $subscriber);
return array( return array(
@ -55,59 +68,88 @@ class AmazonSES {
'httpversion' => '1.1', 'httpversion' => '1.1',
'method' => 'POST', 'method' => 'POST',
'headers' => array( 'headers' => array(
'Host' => $this->awsEndpoint, 'Host' => $this->aws_endpoint,
'Authorization' => $this->signRequest($body), 'Authorization' => $this->signRequest($body),
'X-Amz-Date' => $this->date 'X-Amz-Date' => $this->date
), ),
'body' => urldecode(http_build_query($body)) 'body' => urldecode(http_build_query($body))
); );
} }
function signRequest($body) { function signRequest($body) {
$stringToSign = $this->createStringToSign( $string_to_sign = $this->createStringToSign(
$this->getCredentialScope(), $this->getCredentialScope(),
$this->getCanonicalRequest($body) $this->getCanonicalRequest($body)
); );
$signature = hash_hmac($this->hashAlgorithm, $stringToSign, $this->getSigningKey()); $signature = hash_hmac(
$this->hash_algorithm,
$string_to_sign,
$this->getSigningKey()
);
return sprintf( return sprintf(
'%s Credential=%s/%s, SignedHeaders=host;x-amz-date, Signature=%s', '%s Credential=%s/%s, SignedHeaders=host;x-amz-date, Signature=%s',
$this->awsSigningAlgorithm, $this->aws_signing_algorithm,
$this->awsAccessKey, $this->aws_access_key,
$this->getCredentialScope(), $this->getCredentialScope(),
$signature); $signature);
} }
function getCredentialScope() { function getCredentialScope() {
return sprintf('%s/%s/%s/%s', $this->dateWithoutTime, $this->awsRegion, $this->awsService, $this->awsTerminationString); return sprintf(
'%s/%s/%s/%s',
$this->date_without_time,
$this->aws_region,
$this->aws_service,
$this->aws_termination_string);
} }
function getCanonicalRequest($body) { function getCanonicalRequest($body) {
return implode("\n", array( return implode("\n", array(
'POST', 'POST',
'/', '/',
'', '',
'host:' . $this->awsEndpoint, 'host:' . $this->aws_endpoint,
'x-amz-date:' . $this->date, 'x-amz-date:' . $this->date,
'', '',
'host;x-amz-date', 'host;x-amz-date',
hash($this->hashAlgorithm, urldecode(http_build_query($body))) hash($this->hash_algorithm, urldecode(http_build_query($body)))
)); ));
} }
function createStringToSign($credentialScope, $canonicalRequest) { function createStringToSign($credential_scope, $canonical_request) {
return implode("\n", array( return implode("\n", array(
$this->awsSigningAlgorithm, $this->aws_signing_algorithm,
$this->date, $this->date,
$credentialScope, $credential_scope,
hash($this->hashAlgorithm, $canonicalRequest) hash($this->hash_algorithm, $canonical_request)
)); ));
} }
function getSigningKey() { function getSigningKey() {
$dateKey = hash_hmac($this->hashAlgorithm, $this->dateWithoutTime, 'AWS4' . $this->awsSecret_key, true); $date_key = hash_hmac(
$regionKey = hash_hmac($this->hashAlgorithm, $this->awsRegion, $dateKey, true); $this->hash_algorithm,
$serviceKey = hash_hmac($this->hashAlgorithm, $this->awsService, $regionKey, true); $this->date_without_time,
return hash_hmac($this->hashAlgorithm, $this->awsTerminationString, $serviceKey, true); 'AWS4' . $this->aws_secret_key,
true
);
$region_key = hash_hmac(
$this->hash_algorithm,
$this->aws_region,
$date_key,
true
);
$service_key = hash_hmac(
$this->hash_algorithm,
$this->aws_service,
$region_key,
true
);
return hash_hmac(
$this->hash_algorithm,
$this->aws_termination_string,
$service_key,
true
);
} }
} }

View File

@ -4,11 +4,15 @@ namespace MailPoet\Mailer\Methods;
if(!defined('ABSPATH')) exit; if(!defined('ABSPATH')) exit;
class ElasticEmail { class ElasticEmail {
function __construct($apiKey, $fromEmail, $fromName) { public $url = 'https://api.elasticemail.com/mailer/send';
$this->url = 'https://api.elasticemail.com/mailer/send'; public $api_key;
$this->apiKey = $apiKey; public $from_email;
$this->fromEmail = $fromEmail; public $from_name;
$this->fromName = $fromName;
function __construct($api_key, $from_email, $from_name) {
$this->api_key = $api_key;
$this->from_email = $from_email;
$this->from_name = $from_name;
} }
function send($newsletter, $subscriber) { function send($newsletter, $subscriber) {
@ -23,9 +27,9 @@ class ElasticEmail {
function getBody($newsletter, $subscriber) { function getBody($newsletter, $subscriber) {
$body = array( $body = array(
'api_key' => $this->apiKey, 'api_key' => $this->api_key,
'from' => $this->fromEmail, 'from' => $this->from_email,
'from_name' => $this->fromName, 'from_name' => $this->from_name,
'to' => $subscriber, 'to' => $subscriber,
'subject' => $newsletter['subject'] 'subject' => $newsletter['subject']
); );

View File

@ -4,9 +4,13 @@ namespace MailPoet\Mailer\Methods;
if(!defined('ABSPATH')) exit; if(!defined('ABSPATH')) exit;
class MailGun { class MailGun {
function __construct($domain, $apiKey, $from) { public $url;
public $api_key;
public $from;
function __construct($domain, $api_key, $from) {
$this->url = sprintf('https://api.mailgun.net/v3/%s/messages', $domain); $this->url = sprintf('https://api.mailgun.net/v3/%s/messages', $domain);
$this->apiKey = $apiKey; $this->api_key = $api_key;
$this->from = $from; $this->from = $from;
} }
@ -37,7 +41,7 @@ class MailGun {
} }
function auth() { function auth() {
return 'Basic ' . base64_encode('api:' . $this->apiKey); return 'Basic ' . base64_encode('api:' . $this->api_key);
} }
function request($newsletter, $subscriber) { function request($newsletter, $subscriber) {

View File

@ -4,13 +4,17 @@ namespace MailPoet\Mailer\Methods;
if(!defined('ABSPATH')) exit; if(!defined('ABSPATH')) exit;
class MailPoet { class MailPoet {
function __construct($apiKey, $fromEmail, $fromName) { public $url = 'https://bridge.mailpoet.com/api/messages';
$this->url = 'https://bridge.mailpoet.com/api/messages'; public $api_key;
$this->apiKey = $apiKey; public $from_email;
$this->fromEmail = $fromEmail; public $from_name;
$this->fromName = $fromName;
function __construct($api_key, $from_email, $from_name) {
$this->api_key = $api_key;
$this->from_email = $from_email;
$this->from_name = $from_name;
} }
function send($newsletter, $subscriber) { function send($newsletter, $subscriber) {
$result = wp_remote_post( $result = wp_remote_post(
$this->url, $this->url,
@ -21,20 +25,20 @@ class MailPoet {
wp_remote_retrieve_response_code($result) === 201 wp_remote_retrieve_response_code($result) === 201
); );
} }
function processSubscriber($subscriber) { function processSubscriber($subscriber) {
preg_match('!(?P<name>.*?)\s<(?P<email>.*?)>!', $subscriber, $subscriberData); preg_match('!(?P<name>.*?)\s<(?P<email>.*?)>!', $subscriber, $subscriber_data);
if(!isset($subscriberData['email'])) { if(!isset($subscriber_data['email'])) {
$subscriberData = array( $subscriber_data = array(
'email' => $subscriber, 'email' => $subscriber,
); );
} }
return array( return array(
'email' => $subscriberData['email'], 'email' => $subscriber_data['email'],
'name' => (isset($subscriberData['name'])) ? $subscriberData['name'] : '' 'name' => (isset($subscriber_data['name'])) ? $subscriber_data['name'] : ''
); );
} }
function getBody($newsletter, $subscriber) { function getBody($newsletter, $subscriber) {
$body = array( $body = array(
'to' => (array( 'to' => (array(
@ -42,8 +46,8 @@ class MailPoet {
'name' => $subscriber['name'] 'name' => $subscriber['name']
)), )),
'from' => (array( 'from' => (array(
'address' => $this->fromEmail, 'address' => $this->from_email,
'name' => $this->fromName 'name' => $this->from_name
)), )),
'subject' => $newsletter['subject'] 'subject' => $newsletter['subject']
); );
@ -55,11 +59,11 @@ class MailPoet {
} }
return $body; return $body;
} }
function auth() { function auth() {
return 'Basic ' . base64_encode('api:' . $this->apiKey); return 'Basic ' . base64_encode('api:' . $this->api_key);
} }
function request($newsletter, $subscriber) { function request($newsletter, $subscriber) {
$body = array($this->getBody($newsletter, $subscriber)); $body = array($this->getBody($newsletter, $subscriber));
return array( return array(

View File

@ -4,11 +4,15 @@ namespace MailPoet\Mailer\Methods;
if(!defined('ABSPATH')) exit; if(!defined('ABSPATH')) exit;
class Mandrill { class Mandrill {
function __construct($apiKey, $fromEmail, $fromName) { public $url = 'https://mandrillapp.com/api/1.0/messages/send.json';
$this->url = 'https://mandrillapp.com/api/1.0/messages/send.json'; public $api_key;
$this->apiKey = $apiKey; public $from_email;
$this->fromName = $fromName; public $from_name;
$this->fromEmail = $fromEmail;
function __construct($api_key, $from_email, $from_name) {
$this->api_key = $api_key;
$this->from_name = $from_name;
$this->from_email = $from_email;
} }
function send($newsletter, $subscriber) { function send($newsletter, $subscriber) {
@ -24,24 +28,24 @@ class Mandrill {
} }
function processSubscriber($subscriber) { function processSubscriber($subscriber) {
preg_match('!(?P<name>.*?)\s<(?P<email>.*?)>!', $subscriber, $subscriberData); preg_match('!(?P<name>.*?)\s<(?P<email>.*?)>!', $subscriber, $subscriber_data);
if(!isset($subscriberData['email'])) { if(!isset($subscriber_data['email'])) {
$subscriberData = array( $subscriber_data = array(
'email' => $subscriber, 'email' => $subscriber,
); );
} }
return array( return array(
'email' => $subscriberData['email'], 'email' => $subscriber_data['email'],
'name' => (isset($subscriberData['name'])) ? $subscriberData['name'] : '' 'name' => (isset($subscriber_data['name'])) ? $subscriber_data['name'] : ''
); );
} }
function getBody($newsletter, $subscriber) { function getBody($newsletter, $subscriber) {
$body = array( $body = array(
'key' => $this->apiKey, 'key' => $this->api_key,
'message' => array( 'message' => array(
'from_email' => $this->fromEmail, 'from_email' => $this->from_email,
'from_name' => $this->fromName, 'from_name' => $this->from_name,
'to' => array($subscriber), 'to' => array($subscriber),
'subject' => $newsletter['subject'] 'subject' => $newsletter['subject']
), ),

View File

@ -4,16 +4,27 @@ namespace MailPoet\Mailer\Methods;
if(!defined('ABSPATH')) exit; if(!defined('ABSPATH')) exit;
class SMTP { class SMTP {
function __construct($host, $port, $authentication, $login = null, $password = null, $encryption, public $host;
$fromEmail, $fromName) { public $port;
public $authentication;
public $login;
public $password;
public $encryption;
public $from_name;
public $from_email;
public $mailer;
function __construct(
$host, $port, $authentication, $login = null, $password = null, $encryption,
$from_email, $from_name) {
$this->host = $host; $this->host = $host;
$this->port = $port; $this->port = $port;
$this->authentication = $authentication; $this->authentication = $authentication;
$this->login = $login; $this->login = $login;
$this->password = $password; $this->password = $password;
$this->encryption = $encryption; $this->encryption = $encryption;
$this->fromName = $fromName; $this->from_name = $from_name;
$this->fromEmail = $fromEmail; $this->from_email = $from_email;
$this->mailer = $this->buildMailer(); $this->mailer = $this->buildMailer();
} }
@ -42,7 +53,7 @@ class SMTP {
function createMessage($newsletter, $subscriber) { function createMessage($newsletter, $subscriber) {
$message = \Swift_Message::newInstance() $message = \Swift_Message::newInstance()
->setFrom(array($this->fromEmail => $this->fromName)) ->setFrom(array($this->from_email => $this->from_name))
->setTo($this->processSubscriber($subscriber)) ->setTo($this->processSubscriber($subscriber))
->setSubject($newsletter['subject']); ->setSubject($newsletter['subject']);
if(!empty($newsletter['body']['html'])) { if(!empty($newsletter['body']['html'])) {
@ -55,15 +66,15 @@ class SMTP {
} }
function processSubscriber($subscriber) { function processSubscriber($subscriber) {
preg_match('!(?P<name>.*?)\s<(?P<email>.*?)>!', $subscriber, $subscriberData); preg_match('!(?P<name>.*?)\s<(?P<email>.*?)>!', $subscriber, $subscriber_data);
if(!isset($subscriberData['email'])) { if(!isset($subscriber_data['email'])) {
$subscriberData = array( $subscriber_data = array(
'email' => $subscriber, 'email' => $subscriber,
); );
} }
return array( return array(
$subscriberData['email'] => $subscriber_data['email'] =>
(isset($subscriberData['name'])) ? $subscriberData['name'] : '' (isset($subscriber_data['name'])) ? $subscriber_data['name'] : ''
); );
} }
} }

View File

@ -4,11 +4,15 @@ namespace MailPoet\Mailer\Methods;
if(!defined('ABSPATH')) exit; if(!defined('ABSPATH')) exit;
class SendGrid { class SendGrid {
function __construct($apiKey, $fromEmail, $fromName) { public $url = 'https://api.sendgrid.com/api/mail.send.json';
$this->url = 'https://api.sendgrid.com/api/mail.send.json'; public $api_key;
$this->apiKey = $apiKey; public $from_email;
$this->fromEmail = $fromEmail; public $from_name;
$this->fromName = $fromName;
function __construct($api_key, $from_email, $from_name) {
$this->api_key = $api_key;
$this->from_email = $from_email;
$this->from_name = $from_name;
} }
function send($newsletter, $subscriber) { function send($newsletter, $subscriber) {
@ -27,8 +31,8 @@ class SendGrid {
function getBody($newsletter, $subscriber) { function getBody($newsletter, $subscriber) {
$body = array( $body = array(
'to' => $subscriber, 'to' => $subscriber,
'from' => $this->fromEmail, 'from' => $this->from_email,
'fromname' => $this->fromName, 'from_name' => $this->from_name,
'subject' => $newsletter['subject'] 'subject' => $newsletter['subject']
); );
if(!empty($newsletter['body']['html'])) { if(!empty($newsletter['body']['html'])) {
@ -41,7 +45,7 @@ class SendGrid {
} }
function auth() { function auth() {
return 'Bearer ' . $this->apiKey; return 'Bearer ' . $this->api_key;
} }
function request($newsletter, $subscriber) { function request($newsletter, $subscriber) {

View File

@ -6,18 +6,17 @@ require_once(ABSPATH . 'wp-includes/pluggable.php');
if(!defined('ABSPATH')) exit; if(!defined('ABSPATH')) exit;
class WPMail { class WPMail {
function __construct($fromEmail, $fromName) { public $from_email;
$this->fromEmail = $fromEmail; public $from_name;
$this->fromName = $fromName; public $filters = array(
add_filter('wp_mail_from', array( 'wp_mail_from' => 'setFromEmail',
$this, 'wp_mail_from_name' => 'setFromName',
'setFromEmail' 'wp_mail_content_type' => 'setContentType'
)); );
$this->filters = array(
'wp_mail_from' => 'setFromEmail', function __construct($from_email, $from_name) {
'wp_mail_from_name' => 'setFromName', $this->from_email = $from_email;
'wp_mail_content_type' => 'setContentType' $this->from_name = $from_name;
);
} }
function addFilters() { function addFilters() {
@ -39,11 +38,11 @@ class WPMail {
} }
function setFromEmail() { function setFromEmail() {
return $this->fromEmail; return $this->from_email;
} }
function setFromName() { function setFromName() {
return $this->fromName; return $this->from_name;
} }
function setContentType() { function setContentType() {
@ -54,7 +53,9 @@ class WPMail {
$this->addFilters(); $this->addFilters();
$result = wp_mail( $result = wp_mail(
$subscriber, $newsletter['subject'], $subscriber, $newsletter['subject'],
(!empty($newsletter['body']['html'])) ? $newsletter['body']['html'] : $newsletter['body']['text'] (!empty($newsletter['body']['html'])) ?
$newsletter['body']['html'] :
$newsletter['body']['text']
); );
$this->removeFilters(); $this->removeFilters();
return ($result === true); return ($result === true);

View File

@ -15,7 +15,7 @@ class Renderer {
$this->template = file_get_contents(dirname(__FILE__) . '/' . $this->template); $this->template = file_get_contents(dirname(__FILE__) . '/' . $this->template);
} }
function renderAll() { function render() {
$newsletterContent = $this->renderContent($this->data['content']); $newsletterContent = $this->renderContent($this->data['content']);
$newsletterStyles = $this->renderStyles($this->data['globalStyles']); $newsletterStyles = $this->renderStyles($this->data['globalStyles']);

View File

@ -1,8 +1,10 @@
<?php <?php
namespace MailPoet\Router; namespace MailPoet\Router;
use Carbon\Carbon;
use MailPoet\Cron\Daemon; use MailPoet\Cron\Daemon;
use MailPoet\Cron\Supervisor; use MailPoet\Cron\Supervisor;
use MailPoet\Models\Setting;
if(!defined('ABSPATH')) exit; if(!defined('ABSPATH')) exit;
@ -19,13 +21,12 @@ class Cron {
function stop() { function stop() {
$daemon = new Daemon(); $daemon = new Daemon();
if(!$daemon->daemon || if(!$daemon->daemon ||
$daemon->daemonData['status'] !== 'started' $daemon->daemon['status'] !== 'started'
) { ) {
$result = false; $result = false;
} else { } else {
$daemon->daemonData['status'] = 'stopping'; $daemon->daemon['status'] = 'stopping';
$daemon->daemon->value = json_encode($daemon->daemonData); $result = $daemon->saveDaemon($daemon->daemon);
$result = $daemon->daemon->save();
} }
wp_send_json( wp_send_json(
array( array(
@ -35,7 +36,28 @@ class Cron {
} }
function getStatus() { function getStatus() {
$daemon = new \MailPoet\Cron\BootStrapMenu(); $daemon = Setting::where('name', 'cron_daemon')
wp_send_json($daemon->bootStrap()); ->findOne();
wp_send_json(
($daemon) ?
array_merge(
array(
'timeSinceStart' =>
Carbon::createFromFormat(
'Y-m-d H:i:s',
$daemon->created_at,
'UTC'
)->diffForHumans(),
'timeSinceUpdate' =>
Carbon::createFromFormat(
'Y-m-d H:i:s',
$daemon->updated_at,
'UTC'
)->diffForHumans()
),
unserialize($daemon->value)
) :
"false"
);
} }
} }

View File

@ -188,12 +188,12 @@ class Newsletters {
)); ));
} }
// TO REMOVE once we add the columns from/reply_to // TODO: TO REMOVE once we add the columns from/reply_to
$newsletter = array_merge($newsletter, $data['newsletter']); $newsletter = array_merge($newsletter, $data['newsletter']);
// END - TO REMOVE // END - TO REMOVE
$renderer = new Renderer(json_decode($newsletter['body'], true)); $renderer = new Renderer(json_decode($newsletter['body'], true));
$newsletter['body']['html'] = $renderer->renderAll(); $newsletter['body']['html'] = $renderer->render();
$newsletter['body']['text'] = ''; $newsletter['body']['text'] = '';
$subscribers = Subscriber::find_array(); $subscribers = Subscriber::find_array();
@ -218,7 +218,7 @@ class Newsletters {
wp_send_json(false); wp_send_json(false);
} }
$renderer = new Renderer(json_decode($data['body'], true)); $renderer = new Renderer(json_decode($data['body'], true));
wp_send_json(array('rendered_body' => $renderer->renderAll())); wp_send_json(array('rendered_body' => $renderer->render()));
} }
function listing($data = array()) { function listing($data = array()) {

View File

@ -7,7 +7,7 @@ class MailerCest {
'name' => 'Sender', 'name' => 'Sender',
'address' => 'staff@mailinator.com' 'address' => 'staff@mailinator.com'
); );
$this->replyTo = array( $this->reply_to = array(
'name' => 'Reply To', 'name' => 'Reply To',
'address' => 'staff@mailinator.com' 'address' => 'staff@mailinator.com'
); );
@ -42,16 +42,16 @@ class MailerCest {
} }
function itCanConstruct() { function itCanConstruct() {
$mailer = new Mailer($this->mailer, $this->sender, $this->replyTo); $mailer = new Mailer($this->mailer, $this->sender, $this->reply_to);
expect($mailer->sender['fromName'])->equals($this->sender['name']); expect($mailer->sender['from_name'])->equals($this->sender['name']);
expect($mailer->sender['fromEmail'])->equals($this->sender['address']); expect($mailer->sender['from_email'])->equals($this->sender['address']);
expect($mailer->replyTo['replyToName'])->equals($this->replyTo['name']); expect($mailer->reply_to['reply_to_name'])->equals($this->reply_to['name']);
expect($mailer->replyTo['replyToEmail'])->equals($this->replyTo['address']); expect($mailer->reply_to['reply_to_email'])->equals($this->reply_to['address']);
} }
function itCanBuildMailerInstance() { function itCanBuildMailerInstance() {
$mailer = new Mailer($this->mailer, $this->sender); $mailer = new Mailer($this->mailer, $this->sender);
expect(get_class($mailer->mailerInstance)) expect(get_class($mailer->mailer_instance))
->equals('MailPoet\Mailer\Methods\MailPoet'); ->equals('MailPoet\Mailer\Methods\MailPoet');
} }
@ -64,7 +64,7 @@ class MailerCest {
} }
function itCanTransformSubscriber() { function itCanTransformSubscriber() {
$mailer = new Mailer($this->mailer, $this->sender, $this->replyTo); $mailer = new Mailer($this->mailer, $this->sender, $this->reply_to);
expect($mailer->transformSubscriber('test@email.com')) expect($mailer->transformSubscriber('test@email.com'))
->equals('test@email.com'); ->equals('test@email.com');
expect($mailer->transformSubscriber( expect($mailer->transformSubscriber(
@ -94,7 +94,7 @@ class MailerCest {
} }
function itCanSend() { function itCanSend() {
$mailer = new Mailer($this->mailer, $this->sender, $this->replyTo); $mailer = new Mailer($this->mailer, $this->sender, $this->reply_to);
expect($mailer->send($this->newsletter, $this->subscriber))->true(); expect($mailer->send($this->newsletter, $this->subscriber))->true();
} }
} }

View File

@ -27,15 +27,16 @@ class AmazonSESCest {
} }
function itsConstructorWorks() { function itsConstructorWorks() {
expect($this->mailer->awsEndpoint) expect($this->mailer->aws_endpoint)
->equals( ->equals(
sprintf('email.%s.amazonaws.com', $this->settings['region']) sprintf('email.%s.amazonaws.com', $this->settings['region'])
); );
expect($this->mailer->url) ->equals( expect($this->mailer->url)
->equals(
sprintf('https://email.%s.amazonaws.com', $this->settings['region']) sprintf('https://email.%s.amazonaws.com', $this->settings['region'])
); );
expect(preg_match('!^\d{8}T\d{6}Z$!', $this->mailer->date))->equals(1); expect(preg_match('!^\d{8}T\d{6}Z$!', $this->mailer->date))->equals(1);
expect(preg_match('!^\d{8}$!', $this->mailer->dateWithoutTime))->equals(1); expect(preg_match('!^\d{8}$!', $this->mailer->date_without_time))->equals(1);
} }
function itCanGenerateBody() { function itCanGenerateBody() {
@ -60,7 +61,7 @@ class AmazonSESCest {
expect($request['timeout'])->equals(10); expect($request['timeout'])->equals(10);
expect($request['httpversion'])->equals('1.1'); expect($request['httpversion'])->equals('1.1');
expect($request['method'])->equals('POST'); expect($request['method'])->equals('POST');
expect($request['headers']['Host'])->equals($this->mailer->awsEndpoint); expect($request['headers']['Host'])->equals($this->mailer->aws_endpoint);
expect($request['headers']['Authorization']) expect($request['headers']['Authorization'])
->equals($this->mailer->signRequest($body)); ->equals($this->mailer->signRequest($body));
expect($request['headers']['X-Amz-Date'])->equals($this->mailer->date); expect($request['headers']['X-Amz-Date'])->equals($this->mailer->date);
@ -79,11 +80,11 @@ class AmazonSESCest {
'POST', 'POST',
'/', '/',
'', '',
'host:' . $this->mailer->awsEndpoint, 'host:' . $this->mailer->aws_endpoint,
'x-amz-date:' . $this->mailer->date, 'x-amz-date:' . $this->mailer->date,
'', '',
'host;x-amz-date', 'host;x-amz-date',
hash($this->mailer->hashAlgorithm, hash($this->mailer->hash_algorithm,
urldecode(http_build_query($body)) urldecode(http_build_query($body))
) )
) )
@ -94,10 +95,10 @@ class AmazonSESCest {
$credentialScope = $this->mailer->getCredentialScope(); $credentialScope = $this->mailer->getCredentialScope();
expect($credentialScope) expect($credentialScope)
->equals( ->equals(
$this->mailer->dateWithoutTime . '/' . $this->mailer->date_without_time . '/' .
$this->mailer->awsRegion . '/' . $this->mailer->aws_region . '/' .
$this->mailer->awsService . '/' . $this->mailer->aws_service . '/' .
$this->mailer->awsTerminationString $this->mailer->aws_termination_string
); );
} }
@ -113,10 +114,10 @@ class AmazonSESCest {
expect($stringToSing) expect($stringToSing)
->equals( ->equals(
array( array(
$this->mailer->awsSigningAlgorithm, $this->mailer->aws_signing_algorithm,
$this->mailer->date, $this->mailer->date,
$credentialScope, $credentialScope,
hash($this->mailer->hashAlgorithm, $canonicalRequest) hash($this->mailer->hash_algorithm, $canonicalRequest)
) )
); );
} }
@ -126,8 +127,8 @@ class AmazonSESCest {
$signedRequest = $this->mailer->signRequest($body); $signedRequest = $this->mailer->signRequest($body);
expect($signedRequest) expect($signedRequest)
->contains( ->contains(
$this->mailer->awsSigningAlgorithm . ' Credential=' . $this->mailer->aws_signing_algorithm . ' Credential=' .
$this->mailer->awsAccessKey . '/' . $this->mailer->aws_access_key . '/' .
$this->mailer->getCredentialScope() . ', ' . $this->mailer->getCredentialScope() . ', ' .
'SignedHeaders=host;x-amz-date, Signature=' 'SignedHeaders=host;x-amz-date, Signature='
); );
@ -136,7 +137,7 @@ class AmazonSESCest {
} }
function itCannotSendWithoutProperAccessKey() { function itCannotSendWithoutProperAccessKey() {
$this->mailer->awsAccessKey = 'somekey'; $this->mailer->aws_access_key = 'somekey';
$result = $this->mailer->send( $result = $this->mailer->send(
$this->newsletter, $this->newsletter,
$this->subscriber $this->subscriber

View File

@ -8,12 +8,12 @@ class ElasticEmailCest {
'method' => 'ElasticEmail', 'method' => 'ElasticEmail',
'api_key' => '997f1f7f-41de-4d7f-a8cb-86c8481370fa' 'api_key' => '997f1f7f-41de-4d7f-a8cb-86c8481370fa'
); );
$this->fromEmail = 'staff@mailpoet.com'; $this->from_email = 'staff@mailpoet.com';
$this->fromName = 'Sender'; $this->from_name = 'Sender';
$this->mailer = new ElasticEmail( $this->mailer = new ElasticEmail(
$this->settings['api_key'], $this->settings['api_key'],
$this->fromEmail, $this->from_email,
$this->fromName $this->from_name
); );
$this->subscriber = 'Recipient <mailpoet-phoenix-test@mailinator.com>'; $this->subscriber = 'Recipient <mailpoet-phoenix-test@mailinator.com>';
$this->newsletter = array( $this->newsletter = array(
@ -28,8 +28,8 @@ class ElasticEmailCest {
function itCanGenerateBody() { function itCanGenerateBody() {
$body = $this->mailer->getBody($this->newsletter, $this->subscriber); $body = $this->mailer->getBody($this->newsletter, $this->subscriber);
expect($body['api_key'])->equals($this->settings['api_key']); expect($body['api_key'])->equals($this->settings['api_key']);
expect($body['from'])->equals($this->fromEmail); expect($body['from'])->equals($this->from_email);
expect($body['from_name'])->equals($this->fromName); expect($body['from_name'])->equals($this->from_name);
expect($body['to'])->contains($this->subscriber); expect($body['to'])->contains($this->subscriber);
expect($body['subject'])->equals($this->newsletter['subject']); expect($body['subject'])->equals($this->newsletter['subject']);
expect($body['body_html'])->equals($this->newsletter['body']['html']); expect($body['body_html'])->equals($this->newsletter['body']['html']);
@ -45,8 +45,8 @@ class ElasticEmailCest {
expect($request['body'])->equals(urldecode(http_build_query($body))); expect($request['body'])->equals(urldecode(http_build_query($body)));
} }
function itCannotSendWithoutProperAPIKey() { function itCannotSendWithoutProperApiKey() {
$this->mailer->apiKey = 'someapi'; $this->mailer->api_key = 'someapi';
$result = $this->mailer->send( $result = $this->mailer->send(
$this->newsletter, $this->newsletter,
$this->subscriber $this->subscriber

View File

@ -52,8 +52,8 @@ class MailGunCest {
expect($request['body'])->equals(urldecode(http_build_query($body))); expect($request['body'])->equals(urldecode(http_build_query($body)));
} }
function itCannotSendWithoutProperAPIKey() { function itCannotSendWithoutProperApiKey() {
$this->mailer->apiKey = 'someapi'; $this->mailer->api_key = 'someapi';
$result = $this->mailer->send( $result = $this->mailer->send(
$this->newsletter, $this->newsletter,
$this->subscriber $this->subscriber

View File

@ -8,12 +8,12 @@ class MailPoetCest {
'method' => 'MailPoet', 'method' => 'MailPoet',
'api_key' => 'dhNSqj1XHkVltIliyQDvMiKzQShOA5rs0m_DdRUVZHU' 'api_key' => 'dhNSqj1XHkVltIliyQDvMiKzQShOA5rs0m_DdRUVZHU'
); );
$this->fromEmail = 'staff@mailpoet.com'; $this->from_email = 'staff@mailpoet.com';
$this->fromName = 'Sender'; $this->from_name = 'Sender';
$this->mailer = new MailPoet( $this->mailer = new MailPoet(
$this->settings['api_key'], $this->settings['api_key'],
$this->fromEmail, $this->from_email,
$this->fromName $this->from_name
); );
$this->subscriber = 'Recipient <mailpoet-phoenix-test@mailinator.com>'; $this->subscriber = 'Recipient <mailpoet-phoenix-test@mailinator.com>';
$this->newsletter = array( $this->newsletter = array(
@ -30,7 +30,7 @@ class MailPoetCest {
$body = $this->mailer->getBody($this->newsletter, $subscriber); $body = $this->mailer->getBody($this->newsletter, $subscriber);
expect($body['to']['address'])->equals($subscriber['email']); expect($body['to']['address'])->equals($subscriber['email']);
expect($body['to']['name'])->equals($subscriber['name']); expect($body['to']['name'])->equals($subscriber['name']);
expect($body['from']['address'])->equals($this->fromEmail); expect($body['from']['address'])->equals($this->from_email);
expect($body['subject'])->equals($this->newsletter['subject']); expect($body['subject'])->equals($this->newsletter['subject']);
expect($body['html'])->equals($this->newsletter['body']['html']); expect($body['html'])->equals($this->newsletter['body']['html']);
expect($body['text'])->equals($this->newsletter['body']['text']); expect($body['text'])->equals($this->newsletter['body']['text']);
@ -76,8 +76,8 @@ class MailPoetCest {
->equals('Basic ' . base64_encode('api:' . $this->settings['api_key'])); ->equals('Basic ' . base64_encode('api:' . $this->settings['api_key']));
} }
function itCannotSendWithoutProperAPIKey() { function itCannotSendWithoutProperApiKey() {
$this->mailer->apiKey = 'someapi'; $this->mailer->api_key = 'someapi';
$result = $this->mailer->send( $result = $this->mailer->send(
$this->newsletter, $this->newsletter,
$this->subscriber $this->subscriber

View File

@ -8,12 +8,12 @@ class MandrillCest {
'method' => 'Mandrill', 'method' => 'Mandrill',
'api_key' => '692ys1B7REEoZN7R-dYwNA' 'api_key' => '692ys1B7REEoZN7R-dYwNA'
); );
$this->fromEmail = 'staff@mailpoet.com'; $this->from_email = 'staff@mailpoet.com';
$this->fromName = 'Sender'; $this->from_name = 'Sender';
$this->mailer = new Mandrill( $this->mailer = new Mandrill(
$this->settings['api_key'], $this->settings['api_key'],
$this->fromEmail, $this->from_email,
$this->fromName $this->from_name
); );
$this->subscriber = 'Recipient <mailpoet-phoenix-test@mailinator.com>'; $this->subscriber = 'Recipient <mailpoet-phoenix-test@mailinator.com>';
$this->newsletter = array( $this->newsletter = array(
@ -29,8 +29,8 @@ class MandrillCest {
$subscriber = $this->mailer->processSubscriber($this->subscriber); $subscriber = $this->mailer->processSubscriber($this->subscriber);
$body = $this->mailer->getBody($this->newsletter, $subscriber); $body = $this->mailer->getBody($this->newsletter, $subscriber);
expect($body['key'])->equals($this->settings['api_key']); expect($body['key'])->equals($this->settings['api_key']);
expect($body['message']['from_email'])->equals($this->fromEmail); expect($body['message']['from_email'])->equals($this->from_email);
expect($body['message']['from_name'])->equals($this->fromName); expect($body['message']['from_name'])->equals($this->from_name);
expect($body['message']['to'])->equals(array($subscriber)); expect($body['message']['to'])->equals(array($subscriber));
expect($body['message']['subject'])->equals($this->newsletter['subject']); expect($body['message']['subject'])->equals($this->newsletter['subject']);
expect($body['message']['html'])->equals($this->newsletter['body']['html']); expect($body['message']['html'])->equals($this->newsletter['body']['html']);
@ -70,8 +70,8 @@ class MandrillCest {
)); ));
} }
function itCannotSendWithoutProperAPIKey() { function itCannotSendWithoutProperApiKey() {
$this->mailer->apiKey = 'someapi'; $this->mailer->api_key = 'someapi';
$result = $this->mailer->send( $result = $this->mailer->send(
$this->newsletter, $this->newsletter,
$this->subscriber $this->subscriber

View File

@ -13,8 +13,8 @@ class SMTPCest {
'authentication' => '1', 'authentication' => '1',
'encryption' => 'tls' 'encryption' => 'tls'
); );
$this->fromEmail = 'staff@mailpoet.com'; $this->from_email = 'staff@mailpoet.com';
$this->fromName = 'Sender'; $this->from_name = 'Sender';
$this->mailer = new SMTP( $this->mailer = new SMTP(
$this->settings['host'], $this->settings['host'],
$this->settings['port'], $this->settings['port'],
@ -22,8 +22,8 @@ class SMTPCest {
$this->settings['login'], $this->settings['login'],
$this->settings['password'], $this->settings['password'],
$this->settings['encryption'], $this->settings['encryption'],
$this->fromEmail, $this->from_email,
$this->fromName $this->from_name
); );
$this->subscriber = 'Recipient <mailpoet-phoenix-test@mailinator.com>'; $this->subscriber = 'Recipient <mailpoet-phoenix-test@mailinator.com>';
$this->newsletter = array( $this->newsletter = array(
@ -54,7 +54,7 @@ class SMTPCest {
expect($message->getTo()) expect($message->getTo())
->equals(array('mailpoet-phoenix-test@mailinator.com' => 'Recipient')); ->equals(array('mailpoet-phoenix-test@mailinator.com' => 'Recipient'));
expect($message->getFrom()) expect($message->getFrom())
->equals(array($this->fromEmail => $this->fromName)); ->equals(array($this->from_email => $this->from_name));
expect($message->getSubject()) expect($message->getSubject())
->equals($this->newsletter['subject']); ->equals($this->newsletter['subject']);
expect($message->getBody()) expect($message->getBody())

View File

@ -8,12 +8,12 @@ class SendGridCest {
'method' => 'SendGrid', 'method' => 'SendGrid',
'api_key' => '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' 'api_key' => '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'
); );
$this->fromEmail = 'staff@mailpoet.com'; $this->from_email = 'staff@mailpoet.com';
$this->fromName = 'Sender'; $this->from_name = 'Sender';
$this->mailer = new SendGrid( $this->mailer = new SendGrid(
$this->settings['api_key'], $this->settings['api_key'],
$this->fromEmail, $this->from_email,
$this->fromName $this->from_name
); );
$this->subscriber = 'Recipient <mailpoet-phoenix-test@mailinator.com>'; $this->subscriber = 'Recipient <mailpoet-phoenix-test@mailinator.com>';
$this->newsletter = array( $this->newsletter = array(
@ -28,8 +28,8 @@ class SendGridCest {
function itCanGenerateBody() { function itCanGenerateBody() {
$body = $this->mailer->getBody($this->newsletter, $this->subscriber); $body = $this->mailer->getBody($this->newsletter, $this->subscriber);
expect($body['to'])->contains($this->subscriber); expect($body['to'])->contains($this->subscriber);
expect($body['from'])->equals($this->fromEmail); expect($body['from'])->equals($this->from_email);
expect($body['fromname'])->equals($this->fromName); expect($body['from_name'])->equals($this->from_name);
expect($body['subject'])->equals($this->newsletter['subject']); expect($body['subject'])->equals($this->newsletter['subject']);
expect($body['html'])->equals($this->newsletter['body']['html']); expect($body['html'])->equals($this->newsletter['body']['html']);
expect($body['text'])->equals($this->newsletter['body']['text']); expect($body['text'])->equals($this->newsletter['body']['text']);
@ -51,8 +51,8 @@ class SendGridCest {
->equals('Bearer ' . $this->settings['api_key']); ->equals('Bearer ' . $this->settings['api_key']);
} }
function itCannotSendWithoutProperAPIKey() { function itCannotSendWithoutProperApiKey() {
$this->mailer->apiKey = 'someapi'; $this->mailer->api_key = 'someapi';
$result = $this->mailer->send( $result = $this->mailer->send(
$this->newsletter, $this->newsletter,
$this->subscriber $this->subscriber

View File

@ -7,11 +7,11 @@ class WPMailCest {
$this->settings = array( $this->settings = array(
'method' => 'WPMail' 'method' => 'WPMail'
); );
$this->fromEmail = 'staff@mailpoet.com'; $this->from_email = 'staff@mailpoet.com';
$this->fromName = 'Sender'; $this->from_name = 'Sender';
$this->mailer = new WPMail( $this->mailer = new WPMail(
$this->fromEmail, $this->from_email,
$this->fromName $this->from_name
); );
$this->subscriber = 'Recipient <mailpoet-phoenix-test@mailinator.com>'; $this->subscriber = 'Recipient <mailpoet-phoenix-test@mailinator.com>';
$this->newsletter = array( $this->newsletter = array(
@ -48,11 +48,11 @@ class WPMailCest {
} }
function itCanSetFromName() { function itCanSetFromName() {
expect($this->mailer->setFromName())->equals($this->fromName); expect($this->mailer->setFromName())->equals($this->from_name);
} }
function itCanSetFromEmail() { function itCanSetFromEmail() {
expect($this->mailer->setFromName())->equals($this->fromName); expect($this->mailer->setFromEmail())->equals($this->from_email);
} }
function itCanSetContentType() { function itCanSetContentType() {

View File

@ -20,7 +20,7 @@ class NewsletterRendererCest {
} }
function itRendersCompleteNewsletter() { function itRendersCompleteNewsletter() {
$template = $this->renderer->renderAll(); $template = $this->renderer->render();
$DOM = $this->queryDOM->parseStr($template); $DOM = $this->queryDOM->parseStr($template);
// we expect to have 4 column containers and 7 columns (1x1, 1x2, 1x3, 1x1) // we expect to have 4 column containers and 7 columns (1x1, 1x2, 1x3, 1x1)

View File

@ -1,72 +0,0 @@
<?php
use MailPoet\Router\Mailer;
class MailerCest {
function __construct() {
$this->router = new Mailer();
}
function itCanConstruct() {
// TOFIX: "from" property doesn't exist on $this->router
// the sender should be explicitely defined in this unit test.
//expect($this->router->from)->equals('Sender <staff@mailpoet.com>');
}
function itCanTransformSubscriber() {
expect($this->router->transformSubscriber('test@email.com'))
->equals('test@email.com');
expect($this->router->transformSubscriber(
array(
'email' => 'test@email.com'
))
)->equals('test@email.com');
expect($this->router->transformSubscriber(
array(
'first_name' => 'First',
'email' => 'test@email.com'
))
)->equals('First <test@email.com>');
expect($this->router->transformSubscriber(
array(
'last_name' => 'Last',
'email' => 'test@email.com'
))
)->equals('Last <test@email.com>');
expect($this->router->transformSubscriber(
array(
'first_name' => 'First',
'last_name' => 'Last',
'email' => 'test@email.com'
))
)->equals('First Last <test@email.com>');
}
function itCanConfigureMailer() {
// TOFIX: This fails because $this->router->mailer is not set
/*$mailer = $this->router->buildMailer();
$class = 'Mailpoet\\Mailer\\' .
((isset($this->router->mailer['type'])) ?
$this->router->mailer['type'] . '\\' . $this->router->mailer['method'] :
$this->router->mailer['method']
);
expect($mailer instanceof $class)->true();
expect(method_exists($mailer, 'send'))->true();*/
}
function itCanSend() {
// TOFIX: This fails because $this->router->mailer is not set
/*$newsletter = array(
'subject' => 'testing Mailer router with ' . $this->router->mailer['method'],
'body' => array(
'html' => 'HTML body',
'text' => 'TEXT body'
)
);
$subscriber = array(
'first_name' => 'First',
'last_name' => 'Last',
'email' => 'mailpoet-phoenix-test@mailinator.com'
);
expect($this->router->send($newsletter, $subscriber))->true();*/
}
}