- Adds Amazon SES tests

- Refactors all API mailers
- Updates unit tests for all API mailers
- Adds Mailer router + tests
This commit is contained in:
MrCasual
2015-10-06 20:47:34 -04:00
parent 1ab55f8991
commit 1d9ef9bd91
21 changed files with 897 additions and 804 deletions

View File

@ -0,0 +1,108 @@
<?php
namespace MailPoet\Mailer\API;
if(!defined('ABSPATH')) exit;
class AmazonSES {
function __construct($region, $access_key, $secret_key, $from) {
$this->awsAccessKey = $access_key;
$this->awsSecret_key = $secret_key;
$this->awsRegion = $region;
$this->awsEndpoint = sprintf('email.%s.amazonaws.com', $region);
$this->awsSigningAlgorithm = 'AWS4-HMAC-SHA256';
$this->awsService = 'ses';
$this->awsTerminationString = 'aws4_request';
$this->hashAlgorithm = 'sha256';
$this->url = 'https://' . $this->awsEndpoint;
$this->from = $from;
$this->date = gmdate('Ymd\THis\Z');
$this->dateWithoutTime = gmdate('Ymd');
}
function send($newsletter, $subscriber) {
$this->newsletter = $newsletter;
$this->subscriber = $subscriber;
$result = wp_remote_post(
$this->url,
$this->request()
);
return ($result['response']['code'] === 200);
}
function getBody() {
$parameters = array(
'Action' => 'SendEmail',
'Version' => '2010-12-01',
'Source' => $this->from,
'Destination.ToAddresses.member.1' => $this->subscriber,
'Message.Subject.Data' => $this->newsletter['subject'],
'Message.Body.Html.Data' => $this->newsletter['body']['html'],
'Message.Body.Text.Data' => $this->newsletter['body']['text'],
'ReplyToAddresses.member.1' => $this->from,
'ReturnPath' => $this->from
);
return urldecode(http_build_query($parameters));
}
function request() {
return array(
'timeout' => 10,
'httpversion' => '1.1',
'method' => 'POST',
'headers' => array(
'Host' => $this->awsEndpoint,
'Authorization' => $this->signRequest($this->getBody()),
'X-Amz-Date' => $this->date
),
'body' => $this->getBody()
);
}
function signRequest() {
$stringToSign = $this->createStringToSign(
$this->getCredentialScope(),
$this->getCanonicalRequest()
);
$signature = hash_hmac($this->hashAlgorithm, $stringToSign, $this->getSigningKey());
return sprintf(
'%s Credential=%s/%s, SignedHeaders=host;x-amz-date, Signature=%s',
$this->awsSigningAlgorithm,
$this->awsAccessKey,
$this->getCredentialScope(),
$signature);
}
function getCredentialScope() {
return sprintf('%s/%s/%s/%s', $this->dateWithoutTime, $this->awsRegion, $this->awsService, $this->awsTerminationString);
}
function getCanonicalRequest() {
return implode("\n", array(
'POST',
'/',
'',
'host:' . $this->awsEndpoint,
'x-amz-date:' . $this->date,
'',
'host;x-amz-date',
hash($this->hashAlgorithm, $this->getBody())
));
}
function createStringToSign($credentialScope, $canonicalRequest) {
return implode("\n", array(
$this->awsSigningAlgorithm,
$this->date,
$credentialScope,
hash($this->hashAlgorithm, $canonicalRequest)
));
}
function getSigningKey() {
$dateKey = hash_hmac($this->hashAlgorithm, $this->dateWithoutTime, 'AWS4' . $this->awsSecret_key, true);
$regionKey = hash_hmac($this->hashAlgorithm, $this->awsRegion, $dateKey, true);
$serviceKey = hash_hmac($this->hashAlgorithm, $this->awsService, $regionKey, true);
return hash_hmac($this->hashAlgorithm, $this->awsTerminationString, $serviceKey, true);
}
}

View File

@ -0,0 +1,45 @@
<?php
namespace MailPoet\Mailer\API;
if(!defined('ABSPATH')) exit;
class ElasticEmail {
function __construct($api_key, $from_email, $from_name) {
$this->url = 'https://api.elasticemail.com/mailer/send';
$this->api_key = $api_key;
$this->from_name = $from_name;
$this->from_email = $from_email;
}
function send($newsletter, $subscriber) {
$this->newsletter = $newsletter;
$this->subscriber = $subscriber;
$result = wp_remote_post(
$this->url,
$this->request());
if(is_object($result) && get_class($result) === 'WP_Error') return false;
return (!preg_match('/\w{8}-\w{4}-\w{4}-\w{4}-\w{12}/', $result['body']) === false);
}
function getBody() {
$parameters = array(
'api_key' => $this->api_key,
'from' => $this->from_email,
'from_name' => $this->from_name,
'to' => $this->subscriber,
'subject' => $this->newsletter['subject'],
'body_html' => $this->newsletter['body']['html'],
'body_text' => $this->newsletter['body']['text']
);
return urldecode(http_build_query($parameters));
}
function request() {
return array(
'timeout' => 10,
'httpversion' => '1.0',
'method' => 'POST',
'body' => $this->getBody()
);
}
}

View File

@ -0,0 +1,52 @@
<?php
namespace MailPoet\Mailer\API;
if(!defined('ABSPATH')) exit;
class MailGun {
function __construct($domain, $api_key, $from) {
$this->url = 'https://api.mailgun.net/v3';
$this->domain = $domain;
$this->api_key = $api_key;
$this->from = $from;
}
function send($newsletter, $subscriber) {
$this->newsletter = $newsletter;
$this->subscriber = $subscriber;
$result = wp_remote_post(
$this->url . '/' . $this->domain . '/messages',
$this->request()
);
if(is_object($result) && get_class($result) === 'WP_Error') return false;
return ($result['response']['code'] === 200);
}
function getBody() {
$parameters = array(
'from' => $this->from,
'to' => $this->subscriber,
'subject' => $this->newsletter['subject'],
'html' => $this->newsletter['body']['html'],
'text' => $this->newsletter['body']['text']
);
return urldecode(http_build_query($parameters));
}
function auth() {
return 'Basic ' . base64_encode('api:' . $this->api_key);
}
function request() {
return array(
'timeout' => 10,
'httpversion' => '1.0',
'method' => 'POST',
'headers' => array(
'Content-Type' => 'application/x-www-form-urlencoded',
'Authorization' => $this->auth()
),
'body' => $this->getBody()
);
}
}

View File

@ -1,20 +1,19 @@
<?php
namespace MailPoet\Mailer;
namespace MailPoet\Mailer\API;
if(!defined('ABSPATH')) exit;
class Mandrill {
function __construct($api_key, $from_email, $from_name, $newsletter,
$subscribers) {
function __construct($api_key, $from_email, $from_name) {
$this->url = 'https://mandrillapp.com/api/1.0/messages/send.json';
$this->api_key = $api_key;
$this->newsletter = $newsletter;
$this->subscribers = $subscribers;
$this->from_name = $from_name;
$this->from_email = $from_email;
}
function send() {
function send($newsletter, $subscriber) {
$this->newsletter = $newsletter;
$this->subscriber = $this->processSubscriber($subscriber);
$result = wp_remote_post(
$this->url,
$this->request()
@ -23,38 +22,34 @@ class Mandrill {
return (!preg_match('!invalid!', $result['body']) === true && $result['response']['code'] === 200);
}
function getSubscribers() {
$subscribers = array_map(function ($subscriber) {
if(!isset($subscriber['email'])) return;
$first_name = (isset($subscriber['first_name']))
? $subscriber['first_name'] : '';
$last_name = (isset($subscriber['last_name']))
? $subscriber['last_name'] : '';
$full_name = sprintf(
'%s %s', $first_name, $last_name
function processSubscriber($subscriber) {
preg_match('!(?P<name>.*?)\s<(?P<email>.*?)>!', $subscriber, $subscriberData);
if(!isset($subscriberData['email'])) {
$subscriberData = array(
'email' => $subscriber,
);
$full_name = trim(preg_replace('!\s\s+!', ' ', $full_name));
}
return array(
'email' => $subscriber['email'],
'name' => $full_name
array(
'name' => (isset($subscriberData['name'])) ? $subscriberData['name'] : '',
'email' => $subscriberData['email']
)
);
}, $this->subscribers);
return array_filter($subscribers);
}
function getBody() {
return array(
'key' => $this->api_key,
'message' => array(
'html' => $this->newsletter['body'],
'subject' => $this->newsletter['subject'],
'from_email' => $this->from_email,
'from_name' => $this->from_name,
'to' => $this->getSubscribers(),
'to' => $this->subscriber,
'subject' => $this->newsletter['subject'],
'html' => $this->newsletter['body']['html'],
'text' => $this->newsletter['body']['text'],
'headers' => array(
'Reply-To' => $this->from_email
),
'preserve_recipients' => false
)
),
'async' => false,
);

View File

@ -0,0 +1,51 @@
<?php
namespace MailPoet\Mailer\API;
if(!defined('ABSPATH')) exit;
class SendGrid {
function __construct($api_key, $from) {
$this->url = 'https://api.sendgrid.com/api/mail.send.json';
$this->api_key = $api_key;
$this->from = $from;
}
function send($newsletter, $subscriber) {
$this->newsletter = $newsletter;
$this->subscriber = $subscriber;
$result = wp_remote_post(
$this->url,
$this->request()
);
if(is_object($result) && get_class($result) === 'WP_Error') return false;
$result = json_decode($result['body'], true);
return (!isset($result['errors']) === true);
}
function getBody() {
$parameters = array(
'to' => $this->subscriber,
'from' => $this->from,
'subject' => $this->newsletter['subject'],
'html' => $this->newsletter['body']['html'],
'text' => $this->newsletter['body']['text']
);
return urldecode(http_build_query($parameters));
}
function auth() {
return 'Bearer ' . $this->api_key;
}
function request() {
return array(
'timeout' => 10,
'httpversion' => '1.1',
'method' => 'POST',
'headers' => array(
'Authorization' => $this->auth()
),
'body' => $this->getBody()
);
}
}

View File

@ -1,97 +0,0 @@
<?php
namespace MailPoet\Mailer;
if(!defined('ABSPATH')) exit;
class AmazonSES {
function __construct($region, $access_key, $secret_key, $from, $to, $newsletter) {
$this->region = $region;
$this->host = sprintf('email.%s.amazonaws.com', $region);
$this->url = 'https://' . $this->host;
$this->access_key = $access_key;
$this->secret_key = $secret_key;
$this->newsletter = $newsletter;
$this->from = $from;
$this->to = $to;
$this->date = gmdate('Ymd\THis\Z');
}
function send() {
$result = wp_remote_post(
$this->url,
$this->request()
);
return ($result['response']['code'] === 200);
}
function getBody() {
$parameters = array(
'Action' => 'SendEmail',
'Version' => '2010-12-01',
'Source' => $this->from,
'Destination.ToAddresses.member.1' => $this->to,
'Message.Subject.Data' => $this->newsletter['subject'],
'Message.Body.Html.Data' => $this->newsletter['body'],
'ReplyToAddresses.member.1' => $this->from,
'ReturnPath' => $this->from
);
return urldecode(http_build_query($parameters));
}
function request() {
return array(
'timeout' => 10,
'httpversion' => '1.1',
'method' => 'POST',
'headers' => array(
'Host' => $this->host,
'Authorization' => $this->signRequest($this->getBody()),
'X-Amz-Date' => $this->date
),
'body' => $this->getBody()
);
}
function signRequest($bodyToSign) {
$requestDate = $this->date;
$requestDateShorted = substr($requestDate, 0, 8);
$awsSigningAlgorithm = 'AWS4-HMAC-SHA256';
$hashAlgorithm = 'sha256';
$service = 'ses';
$type = 'aws4_request';
$scope = sprintf('%s/%s/%s/%s', $requestDateShorted, $this->region, $service, $type);
$requestToSign = array(
'POST',
'/',
'',
'host:' . $this->host,
'x-amz-date:' . $requestDate,
'',
'host;x-amz-date',
hash($hashAlgorithm, $bodyToSign)
);
$requestToSign = implode("\n", $requestToSign);
$stringToSign = array(
$awsSigningAlgorithm,
$requestDate,
$scope,
hash($hashAlgorithm, $requestToSign)
);
$stringToSign = implode("\n", $stringToSign);
$dateKey = hash_hmac($hashAlgorithm, $requestDateShorted, 'AWS4' . $this->secret_key, true);
$regionKey = hash_hmac($hashAlgorithm, $this->region, $dateKey, true);
$serviceKey = hash_hmac($hashAlgorithm, $service, $regionKey, true);
$signingKey = hash_hmac($hashAlgorithm, $type, $serviceKey, true);
$signature = hash_hmac($hashAlgorithm, $stringToSign, $signingKey);
return sprintf(
'%s Credential=%s/%s, SignedHeaders=host;x-amz-date, Signature=%s',
$awsSigningAlgorithm,
$this->access_key,
$scope,
$signature);
}
}

View File

@ -1,5 +1,5 @@
<?php
namespace MailPoet\Mailer;
namespace MailPoet\Mailer\API;
use MailPoet\Models\Setting;

View File

@ -1,61 +0,0 @@
<?php
namespace MailPoet\Mailer;
if(!defined('ABSPATH')) exit;
class ElasticEmail {
function __construct($api_key, $from_email, $from_name, $newsletter,
$subscribers) {
$this->url = 'https://api.elasticemail.com/mailer/send';
$this->api_key = $api_key;
$this->newsletter = $newsletter;
$this->subscribers = $subscribers;
$this->from_name = $from_name;
$this->from_email = $from_email;
}
function send() {
$result = wp_remote_post(
$this->url,
$this->request());
if(is_object($result) && get_class($result) === 'WP_Error') return false;
return (preg_match('/\w{8}-\w{4}-\w{4}-\w{4}-\w{12}/', $result['body']) == true);
}
function getSubscribers() {
$subscribers = array_map(function ($subscriber) {
if(!isset($subscriber['email'])) return;
$first_name = (isset($subscriber['first_name']))
? $subscriber['first_name'] : '';
$last_name = (isset($subscriber['last_name']))
? $subscriber['last_name'] : '';
$subscriber = sprintf(
'%s %s <%s>', $first_name, $last_name, $subscriber['email']
);
$subscriber = trim(preg_replace('!\s\s+!', ' ', $subscriber));
return $subscriber;
}, $this->subscribers);
return array_filter($subscribers);
}
function getBody() {
$parameters = array(
'api_key' => $this->api_key,
'from' => $this->from_email,
'from_name' => $this->from_name,
'to' => implode(';', $this->getSubscribers()),
'subject' => $this->newsletter['subject'],
'body_html' => $this->newsletter['body']
);
return urldecode(http_build_query($parameters));
}
function request() {
return array(
'timeout' => 10,
'httpversion' => '1.0',
'method' => 'POST',
'body' => $this->getBody()
);
}
}

View File

@ -1,82 +0,0 @@
<?php
namespace MailPoet\Mailer;
if(!defined('ABSPATH')) exit;
class MailGun {
function __construct($domain, $api_key, $from_email, $from_name,
$newsletter, $subscribers) {
$this->url = 'https://api.mailgun.net/v3';
$this->domain = $domain;
$this->api_key = $api_key;
$this->newsletter = $newsletter;
$this->subscribers = $subscribers;
$this->from = sprintf('%s <%s>', $from_name, $from_email);
}
function send() {
$result = wp_remote_post(
$this->url . '/' . $this->domain . '/messages',
$this->request()
);
if(is_object($result) && get_class($result) === 'WP_Error') return false;
return ($result['response']['code'] === 200);
}
function getSubscribers() {
$subscribers = array_map(function ($subscriber) {
if(!isset($subscriber['email'])) return;
$first_name = (isset($subscriber['first_name']))
? $subscriber['first_name'] : '';
$last_name = (isset($subscriber['last_name']))
? $subscriber['last_name'] : '';
$subscriber = sprintf(
'%s %s <%s>', $first_name, $last_name, $subscriber['email']
);
$subscriber = trim(preg_replace('!\s\s+!', ' ', $subscriber));
return $subscriber;
}, $this->subscribers);
$subscribers = array_filter($subscribers);
$subscribersData = array_map(function ($subscriber) {
return array($subscriber => array());
}, $subscribers);
$subscribersData = array_map('array_merge', $subscribersData);
return array(
'emails' => $subscribers,
'data' => $subscribersData
);
}
function getBody() {
$subscribers = $this->getSubscribers();
$parameters = array(
'from' => $this->from,
'to' => $subscribers['emails'],
'recipient-variables' => json_encode($subscribers['data']),
'subject' => $this->newsletter['subject'],
'text' => $this->newsletter['body']
);
$parameters = http_build_query($parameters);
$parameters = preg_replace('!\[\d+\]!', '', urldecode($parameters));
return $parameters;
}
function auth() {
return 'Basic ' . base64_encode('api:' . $this->api_key);
}
function request() {
return array(
'timeout' => 10,
'httpversion' => '1.0',
'method' => 'POST',
'headers' => array(
'Content-Type' => 'application/x-www-form-urlencoded',
'Authorization' => $this->auth()
),
'body' => $this->getBody()
);
}
}

View File

@ -1,68 +0,0 @@
<?php
namespace MailPoet\Mailer;
if(!defined('ABSPATH')) exit;
class SendGrid {
function __construct($api_key, $from_email, $from_name, $newsletter,
$subscribers) {
$this->url = 'https://api.sendgrid.com/api/mail.send.json';
$this->api_key = $api_key;
$this->newsletter = $newsletter;
$this->subscribers = $subscribers;
$this->from = sprintf('%s <%s>', $from_name, $from_email);
}
function send() {
$result = wp_remote_post(
$this->url,
$this->request()
);
if(is_object($result) && get_class($result) === 'WP_Error') return false;
$result = json_decode($result['body'], true);
return (isset($result['errors']) === false);
}
function getSubscribers() {
$subscribers = array_map(function ($subscriber) {
if(!isset($subscriber['email'])) return;
$first_name = (isset($subscriber['first_name']))
? $subscriber['first_name'] : '';
$last_name = (isset($subscriber['last_name']))
? $subscriber['last_name'] : '';
$subscriber = sprintf(
'%s %s <%s>', $first_name, $last_name, $subscriber['email']
);
$subscriber = trim(preg_replace('!\s\s+!', ' ', $subscriber));
return $subscriber;
}, $this->subscribers);
return array_filter($subscribers);
}
function getBody() {
$parameters = array(
'to' => $this->from,
'from' => $this->from,
'x-smtpapi' => json_encode(array('to' => $this->getSubscribers())),
'subject' => $this->newsletter['subject'],
'html' => $this->newsletter['body']
);
return urldecode(http_build_query($parameters));
}
function auth() {
return 'Bearer ' . $this->api_key;
}
function request() {
return array(
'timeout' => 10,
'httpversion' => '1.1',
'method' => 'POST',
'headers' => array(
'Authorization' => $this->auth()
),
'body' => $this->getBody()
);
}
}

90
lib/Router/Mailer.php Normal file
View File

@ -0,0 +1,90 @@
<?php
namespace MailPoet\Router;
if(!defined('ABSPATH')) exit;
class Mailer {
function __construct() {
$this->fromName = $this->getSetting('from_name');
$this->fromEmail = $this->getSetting('from_address');
$this->mailer = $this->getSetting('mailer');
$this->from = sprintf('%s <%s>', $this->fromName, $this->fromEmail);
}
function send($newsletter, $subscriber) {
$subscriber = $this->transformSubscriber($subscriber);
$mailer = $this->configureMailer();
return wp_send_json($mailer->send($newsletter, $subscriber));
}
function configureMailer() {
switch ($this->mailer['name']) {
case 'AmazonSES':
$mailer = new $this->mailer['class']($this->mailer['region'], $this->mailer['access_key'], $this->mailer['secret_key'], $this->from);
break;
case 'ElasticEmail':
$mailer = new $this->mailer['class']($this->mailer['api_key'], $this->fromEmail, $this->fromName);
break;
case 'MailGun':
$mailer = new $this->mailer['class']($this->mailer['domain'], $this->mailer['api_key'], $this->from);
break;
case 'Mandrill':
$mailer = new $this->mailer['class']($this->mailer['api_key'], $this->fromEmail, $this->fromName);
break;
case 'SendGrid':
$mailer = new $this->mailer['class']($this->mailer['api_key'], $this->from);
break;
}
return $mailer;
}
function transformSubscriber($subscriber) {
if(!is_array($subscriber)) return $subscriber;
$first_name = (isset($subscriber['first_name'])) ? $subscriber['first_name'] : '';
$last_name = (isset($subscriber['last_name'])) ? $subscriber['last_name'] : '';
$subscriber = sprintf('%s %s <%s>', $first_name, $last_name, $subscriber['email']);
$subscriber = trim(preg_replace('!\s\s+!', ' ', $subscriber));
return $subscriber;
}
function getSetting($setting) {
if($setting === 'mailer') {
$mailers = array(
array(
'name' => 'AmazonSES',
'type' => 'API',
'access_key' => 'AKIAJM6Y5HMGXBLDNSRA',
'secret_key' => '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',
'region' => 'us-east-1',
),
array(
'name' => 'ElasticEmail',
'type' => 'API',
'api_key' => '997f1f7f-41de-4d7f-a8cb-86c8481370fa'
),
array(
'name' => 'MailGun',
'type' => 'API',
'api_key' => 'key-6cf5g5qjzenk-7nodj44gdt8phe6vam2',
'domain' => 'mrcasual.com'
),
array(
'name' => 'Mandrill',
'type' => 'API',
'api_key' => '692ys1B7REEoZN7R-dYwNA'
),
array(
'name' => 'SendGrid',
'type' => 'API',
'api_key' => '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'
)
);
$mailer = $mailers[array_rand($mailers)];
return array_merge($mailer, array('class' => sprintf('MailPoet\\Mailer\\%s\\%s', $mailer['type'], $mailer['name'])));
}
if($setting === 'from_name') return 'Sender';
if($setting === 'from_address') return 'mailpoet-test1@mailinator.com';
return Setting::where('name', $setting)
->findOne()->value;
}
}

View File

@ -0,0 +1,149 @@
<?php
use MailPoet\Mailer\API\AmazonSES;
class AmazonSESCest {
function __construct() {
$this->settings = array(
'name' => 'AmazonSES',
'type' => 'API',
'access_key' => 'AKIAJM6Y5HMGXBLDNSRA',
'secret_key' => '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',
'region' => 'us-east-1',
);
$this->from = 'Sender <vlad@mailpoet.com>';
$this->mailer = new AmazonSES($this->settings['region'], $this->settings['access_key'], $this->settings['secret_key'], $this->from);
$this->mailer->subscriber = 'Recipient <mailpoet-test1@mailinator.com>';
$this->mailer->newsletter = array(
'subject' => 'testing AmazonSES',
'body' => array(
'html' => 'HTML body',
'text' => 'TEXT body'
)
);
}
function itsConstructorWorks() {
expect($this->mailer->awsEndpoint)->equals('email.us-east-1.amazonaws.com');
expect($this->mailer->url)->equals('https://email.us-east-1.amazonaws.com');
expect(preg_match('!^\d{8}T\d{6}Z$!', $this->mailer->date))->equals(1);
expect(preg_match('!^\d{8}$!', $this->mailer->dateWithoutTime))->equals(1);
}
function itCanGenerateBody() {
$body = explode('&', $this->mailer->getBody());
expect($body[0])
->equals('Action=SendEmail');
expect($body[1])
->equals('Version=2010-12-01');
expect($body[2])
->equals('Source=' . $this->from);
expect($body[3])
->contains('Destination.ToAddresses.member.1=' . $this->mailer->subscriber);
expect($body[4])
->equals('Message.Subject.Data=' . $this->mailer->newsletter['subject']);
expect($body[5])
->equals('Message.Body.Html.Data=' . $this->mailer->newsletter['body']['html']);
expect($body[6])
->equals('Message.Body.Text.Data=' . $this->mailer->newsletter['body']['text']);
expect($body[7])
->equals('ReplyToAddresses.member.1=' . $this->from);
expect($body[8])
->equals('ReturnPath=' . $this->from);
}
function itCanCreateRequest() {
$request = $this->mailer->request();
expect($request['timeout'])
->equals(10);
expect($request['httpversion'])
->equals('1.1');
expect($request['method'])
->equals('POST');
expect($request['headers']['Host'])
->equals($this->mailer->awsEndpoint);
expect($request['headers']['Authorization'])
->equals($this->mailer->signRequest($this->mailer->getBody()));
expect($request['headers']['X-Amz-Date'])
->equals($this->mailer->date);
expect($request['body'])
->equals($this->mailer->getBody());
}
function itCanCreateCanonicalRequest() {
$canonicalRequest = explode("\n", $this->mailer->getCanonicalRequest());
expect($canonicalRequest)
->equals(
array(
'POST',
'/',
'',
'host:' . $this->mailer->awsEndpoint,
'x-amz-date:' . $this->mailer->date,
'',
'host;x-amz-date',
hash($this->mailer->hashAlgorithm, $this->mailer->getBody())
)
);
}
function itCanCreateCredentialScope() {
$credentialScope = $this->mailer->getCredentialScope();
expect($credentialScope)
->equals(
$this->mailer->dateWithoutTime . '/' .
$this->mailer->awsRegion . '/' .
$this->mailer->awsService . '/' .
$this->mailer->awsTerminationString
);
}
function itCanCreateStringToSign() {
$credentialScope = $this->mailer->getCredentialScope();
$canonicalRequest = $this->mailer->getCanonicalRequest();
$stringToSing = $this->mailer->createStringToSign(
$credentialScope,
$canonicalRequest
);
$stringToSing = explode("\n", $stringToSing);
expect($stringToSing)
->equals(
array(
$this->mailer->awsSigningAlgorithm,
$this->mailer->date,
$credentialScope,
hash($this->mailer->hashAlgorithm, $canonicalRequest)
)
);
}
function itCanSignRequest() {
$signedRequest = $this->mailer->signRequest();
expect($signedRequest)
->contains(
$this->mailer->awsSigningAlgorithm . ' Credential=' .
$this->mailer->awsAccessKey . '/' .
$this->mailer->getCredentialScope() . ', ' .
'SignedHeaders=host;x-amz-date, Signature='
);
expect(preg_match('!Signature=[A-Fa-f0-9]{64}$!', $signedRequest))->equals(1);
}
function itCannotSendWithoutProperAccessKey() {
$mailer = clone $this->mailer;
$mailer->awsAccessKey = 'somekey';
$result = $mailer->send(
$mailer->newsletter,
$mailer->subscriber
);
expect($result)->false();
}
function itCanSend() {
$result = $this->mailer->send(
$this->mailer->newsletter,
$this->mailer->subscriber
);
expect($result)->true();
}
}

View File

@ -0,0 +1,72 @@
<?php
use MailPoet\Mailer\API\ElasticEmail;
class ElasticEmailCest {
function __construct() {
$this->settings = array(
'name' => 'ElasticEmail',
'type' => 'API',
'api_key' => '997f1f7f-41de-4d7f-a8cb-86c8481370fa'
);
$this->fromEmail = 'do-not-reply@mailpoet.com';
$this->fromName = 'Sender';
$this->mailer = new ElasticEmail($this->settings['api_key'], $this->fromEmail, $this->fromName);
$this->mailer->subscriber = 'Recipient <mailpoet-test1@mailinator.com>';
$this->mailer->newsletter = array(
'subject' => 'testing ElasticEmail',
'body' => array(
'html' => 'HTML body',
'text' => 'TEXT body'
)
);
}
function itCanGenerateBody() {
$body = explode('&', $this->mailer->getBody());
expect($body[0])
->equals('api_key=' . $this->settings['api_key']);
expect($body[1])
->equals('from=' . $this->fromEmail);
expect($body[2])
->equals('from_name=' . $this->fromName);
expect($body[3])
->contains('to=' . $this->mailer->subscriber);
expect($body[4])
->equals('subject=' . $this->mailer->newsletter['subject']);
expect($body[5])
->equals('body_html=' . $this->mailer->newsletter['body']['html']);
expect($body[6])
->equals('body_text=' . $this->mailer->newsletter['body']['text']);
}
function itCanCreateRequest() {
$request = $this->mailer->request();
expect($request['timeout'])
->equals(10);
expect($request['httpversion'])
->equals('1.0');
expect($request['method'])
->equals('POST');
expect($request['body'])
->equals($this->mailer->getBody());
}
function itCannotSendWithoutProperAPIKey() {
$mailer = clone $this->mailer;
$mailer->api_key = 'someapi';
$result = $mailer->send(
$mailer->newsletter,
$mailer->subscriber
);
expect($result)->false();
}
function itCanSend() {
$result = $this->mailer->send(
$this->mailer->newsletter,
$this->mailer->subscriber
);
expect($result)->true();
}
}

View File

@ -0,0 +1,88 @@
<?php
use MailPoet\Mailer\API\MailGun;
class MailGunCest {
function __construct() {
$this->settings = array(
'name' => 'MailGun',
'type' => 'API',
'api_key' => 'key-6cf5g5qjzenk-7nodj44gdt8phe6vam2',
'domain' => 'mrcasual.com'
);
$this->from = 'Sender <do-not-reply@mailpoet.com>';
$this->mailer = new MailGun($this->settings['domain'], $this->settings['api_key'], $this->from);
$this->mailer->subscriber = 'Recipient <mailpoet-test1@mailinator.com>';
$this->mailer->newsletter = array(
'subject' => 'testing MailGun',
'body' => array(
'html' => 'HTML body',
'text' => 'TEXT body'
)
);
}
function itCanGenerateBody() {
$body = $this->mailer->getBody();
$body = explode('&', $body);
expect($body[0])
->equals('from=' . $this->from);
expect($body[1])
->equals('to=' . $this->mailer->subscriber);
expect($body[2])
->equals('subject=' . $this->mailer->newsletter['subject']);
expect($body[3])
->equals('html=' . $this->mailer->newsletter['body']['html']);
expect($body[4])
->equals('text=' . $this->mailer->newsletter['body']['text']);
}
function itCanDoBasicAuth() {
expect($this->mailer->auth())
->equals('Basic ' . base64_encode('api:' . $this->settings['api_key']));
}
function itCanCreateRequest() {
$request = $this->mailer->request();
expect($request['timeout'])
->equals(10);
expect($request['httpversion'])
->equals('1.0');
expect($request['method'])
->equals('POST');
expect($request['headers']['Content-Type'])
->equals('application/x-www-form-urlencoded');
expect($request['headers']['Authorization'])
->equals('Basic ' . base64_encode('api:' . $this->settings['api_key']));
expect($request['body'])
->equals($this->mailer->getBody());
}
function itCannotSendWithoutProperAPIKey() {
$mailer = clone $this->mailer;
$mailer->api_key = 'someapi';
$result = $mailer->send(
$mailer->newsletter,
$mailer->subscriber
);
expect($result)->false();
}
function itCannotSendWithoutProperDomain() {
$mailer = clone $this->mailer;
$mailer->domain = 'somedomain';
$result = $mailer->send(
$mailer->newsletter,
$mailer->subscriber
);
expect($result)->false();
}
function itCanSend() {
$result = $this->mailer->send(
$this->mailer->newsletter,
$this->mailer->subscriber
);
expect($result)->true();
}
}

View File

@ -0,0 +1,83 @@
<?php
use MailPoet\Mailer\API\Mandrill;
class MandrillCest {
function __construct() {
$this->settings = array(
'name' => 'Mandrill',
'type' => 'API',
'api_key' => '692ys1B7REEoZN7R-dYwNA'
);
$this->fromEmail = 'do-not-reply@mailpoet.com';
$this->fromName = 'Sender';
$this->mailer = new Mandrill($this->settings['api_key'], $this->fromEmail, $this->fromName);
$this->mailer->subscriber = 'Recipient <mailpoet-test1@mailinator.com>';
$this->mailer->newsletter = array(
'subject' => 'testing Mandrill',
'body' => array(
'html' => 'HTML body',
'text' => 'TEXT body'
)
);
}
function itCanGenerateBody() {
$body = $this->mailer->getBody();
expect($body['key'])->equals($this->settings['api_key']);
expect($body['message']['from_email'])->equals(
$this->fromEmail
);
expect($body['message']['from_name'])->equals(
$this->fromName
);
expect($body['message']['to'])->equals(
$this->mailer->subscriber
);
expect($body['message']['subject'])->equals(
$this->mailer->newsletter['subject']
);
expect($body['message']['html'])->equals(
$this->mailer->newsletter['body']['html']
);
expect($body['message']['text'])->equals(
$this->mailer->newsletter['body']['text']
);
expect($body['message']['headers']['Reply-To'])->equals(
$this->fromEmail
);
expect($body['async'])->false();
}
function itCanCreateRequest() {
$request = $this->mailer->request();
expect($request['timeout'])
->equals(10);
expect($request['httpversion'])
->equals('1.0');
expect($request['method'])
->equals('POST');
expect($request['headers']['Content-Type'])
->equals('application/json');
expect($request['body'])
->equals(json_encode($this->mailer->getBody()));
}
function itCannotSendWithoutProperAPIKey() {
$mailer = clone $this->mailer;
$mailer->api_key = 'someapi';
$result = $mailer->send(
$mailer->newsletter,
$mailer->subscriber
);
expect($result)->false();
}
function itCanSend() {
$result = $this->mailer->send(
$this->mailer->newsletter,
$this->mailer->subscriber
);
expect($result)->true();
}
}

View File

@ -0,0 +1,74 @@
<?php
use MailPoet\Mailer\API\SendGrid;
class SendGridCest {
function __construct() {
$this->settings = array(
'name' => 'SendGrid',
'type' => 'API',
'api_key' => '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'
);
$this->from = 'Sender <do-not-reply@mailpoet.com>';
$this->mailer = new SendGrid($this->settings['api_key'], $this->from);
$this->mailer->subscriber = 'Recipient <mailpoet-test1@mailinator.com>';
$this->mailer->newsletter = array(
'subject' => 'testing SendGrid',
'body' => array(
'html' => 'HTML body',
'text' => 'TEXT body'
)
);
}
function itCanGenerateBody() {
$body = explode('&', $this->mailer->getBody());
expect($body[0])
->contains('to=' . $this->mailer->subscriber);
expect($body[1])
->equals('from=' . $this->from);
expect($body[2])
->equals('subject=' . $this->mailer->newsletter['subject']);
expect($body[3])
->equals('html=' . $this->mailer->newsletter['body']['html']);
expect($body[4])
->equals('text=' . $this->mailer->newsletter['body']['text']);
}
function itCanCreateRequest() {
$request = $this->mailer->request();
expect($request['timeout'])
->equals(10);
expect($request['httpversion'])
->equals('1.1');
expect($request['method'])
->equals('POST');
expect($request['headers']['Authorization'])
->equals('Bearer ' . $this->settings['api_key']);
expect($request['body'])
->equals($this->mailer->getBody());
}
function itCanDoBasicAuth() {
expect($this->mailer->auth())
->equals('Bearer ' . $this->settings['api_key']);
}
function itCannotSendWithoutProperAPIKey() {
$mailer = clone $this->mailer;
$mailer->api_key = 'someapi';
$result = $mailer->send(
$mailer->newsletter,
$mailer->subscriber
);
expect($result)->false();
}
function itCanSend() {
$result = $this->mailer->send(
$this->mailer->newsletter,
$this->mailer->subscriber
);
expect($result)->true();
}
}

View File

@ -1,102 +0,0 @@
<?php
use MailPoet\Mailer\ElasticEmail;
class ElasticEmailCest {
function __construct() {
$this->data = array(
'api_key' => '997f1f7f-41de-4d7f-a8cb-86c8481370fa',
'from_email' => 'do-not-reply@mailpoet.com',
'from_name' => 'Phoenix',
'newsletter' => array(
'subject' => 'Testing ElasticEmail',
'body' => 'this is a test message....'
),
'subscribers' => array(
array(
'email' => 'mailpoet-test1@mailinator.com',
'last_name' => 'Smith'
),
array(
'email' => 'mailpoet-test2@mailinator.com',
'first_name' => 'Jane',
'last_name' => 'Smith'
),
array(
'email' => 'mailpoet-test3@mailinator.com',
),
array()
)
);
$this->mailer = new ElasticEmail(
$this->data['api_key'],
$this->data['from_email'],
$this->data['from_name'],
$this->data['newsletter'],
$this->data['subscribers']);
}
function itCanGenerateSubscribers() {
$subscribers = $this->mailer->getSubscribers();
expect(count($subscribers))->equals(3);
// test proper handling of spaces between first/last name
expect($subscribers[0])->equals(
sprintf(
'%s <%s>',
$this->data['subscribers'][0]['last_name'],
$this->data['subscribers'][0]['email'])
);
expect($subscribers[1])->equals(
sprintf(
'%s %s <%s>', $this->data['subscribers'][1]['first_name'],
$this->data['subscribers'][1]['last_name'],
$this->data['subscribers'][1]['email']
)
);
}
function itCanGenerateBody() {
$body = explode('&', $this->mailer->getBody());
expect($body[0])
->equals("api_key=" . $this->data['api_key']);
expect($body[1])
->equals("from=" . $this->data['from_email']);
expect($body[2])
->equals("from_name=" . $this->data['from_name']);
expect($body[3])
->contains($this->data['subscribers'][0]['email']);
expect($body[4])
->equals("subject=" . $this->data['newsletter']['subject']);
expect($body[5])
->equals("body_html=" . $this->data['newsletter']['body']);
}
function itCanCreateRequest() {
$request = $this->mailer->request();
expect($request['timeout'])
->equals(10);
expect($request['httpversion'])
->equals('1.0');
expect($request['method'])
->equals('POST');
expect($request['body'])
->equals($this->mailer->getBody());
}
function itCannotSendWithoutProperAPIKey() {
$mailer = new ElasticEmail(
'someapikey',
$this->data['from_email'],
$this->data['from_name'],
$this->data['newsletter'],
$this->data['subscribers']
);
expect($mailer->send())->equals(false);
}
function itCanSend() {
$result = $this->mailer->send();
expect($result)->equals(true);
}
}

View File

@ -1,144 +0,0 @@
<?php
use MailPoet\Mailer\MailGun;
class MailGunCest {
function __construct() {
$this->data = array(
'domain' => 'mrcasual.com',
'api_key' => 'key-6cf5g5qjzenk-7nodj44gdt8phe6vam2',
'from_email' => 'do-not-reply@mailpoet.com',
'from_name' => 'Phoenix',
'newsletter' => array(
'subject' => 'Testing MailGun',
'body' => 'this is a test message....'
),
'subscribers' => array(
array(
'email' => 'mailpoet-test1@mailinator.com',
'last_name' => 'Smith'
),
array(
'email' => 'mailpoet-test2@mailinator.com',
'first_name' => 'Jane',
'last_name' => 'Smith'
),
array(
'email' => 'mailpoet-test3@mailinator.com',
),
array()
)
);
$this->mailer = new MailGun(
$this->data['domain'],
$this->data['api_key'],
$this->data['from_email'],
$this->data['from_name'],
$this->data['newsletter'],
$this->data['subscribers']);
}
function itCanGenerateSubscribers() {
$subscribers = $this->mailer->getSubscribers();
expect(count($subscribers))->equals(2);
expect(count($subscribers['emails']))->equals(3);
expect(count($subscribers['data']))->equals(3);
// test proper handling of spaces between first/last name
expect($subscribers['emails'][0])->equals(
sprintf(
'%s <%s>',
$this->data['subscribers'][0]['last_name'],
$this->data['subscribers'][0]['email'])
);
expect($subscribers['emails'][1])->equals(
sprintf(
'%s %s <%s>', $this->data['subscribers'][1]['first_name'],
$this->data['subscribers'][1]['last_name'],
$this->data['subscribers'][1]['email']
)
);
expect($subscribers['data'][0])->equals(
array(
sprintf(
'%s <%s>',
$this->data['subscribers'][0]['last_name'],
$this->data['subscribers'][0]['email']
) => array()
)
);
}
function itCanGenerateBody() {
$body = $this->mailer->getBody();
expect(substr_count($body, 'to='))->equals(3);
$body = explode('&', $body);
expect($body[0])
->equals('from=' .
sprintf(
'%s <%s>', $this->data['from_name'], $this->data['from_email']
)
);
expect($body[1])
->equals('to=' . $this->mailer->getSubscribers()['emails'][0]
);
expect($body[2])
->equals('to=' . $this->mailer->getSubscribers()['emails'][1]
);
expect($body[3])
->equals('to=' . $this->mailer->getSubscribers()['emails'][2]
);
expect($body[4])
->equals('recipient-variables=' .
json_encode($this->mailer->getSubscribers()['data'])
);
expect($body[5])->equals('subject=' . $this->data['newsletter']['subject']);
expect($body[6])->equals('text=' . $this->data['newsletter']['body']);
}
function itCanCreateRequest() {
$request = $this->mailer->request();
expect($request['timeout'])
->equals(10);
expect($request['httpversion'])
->equals('1.0');
expect($request['method'])
->equals('POST');
expect($request['headers']['Content-Type'])
->equals('application/x-www-form-urlencoded');
expect($request['headers']['Authorization'])
->equals('Basic ' . base64_encode('api:' . $this->data['api_key']));
expect($request['body'])
->equals($this->mailer->getBody());
}
function itCannotSendWithoutProperAPIKey() {
$mailer = new MailGun(
$this->data['domain'],
'someapikey',
$this->data['from_email'],
$this->data['from_name'],
$this->data['newsletter'],
$this->data['subscribers']
);
expect($mailer->send())->equals(false);
}
function itCannotSendWithoutProperDomain() {
$mailer = new MailGun(
'mailpoet.com',
$this->data['api_key'],
$this->data['from_email'],
$this->data['from_name'],
$this->data['newsletter'],
$this->data['subscribers']
);
expect($mailer->send())->equals(false);
}
function itCanSend() {
$result = $this->mailer->send();
expect($result)->equals(true);
}
}

View File

@ -1,112 +0,0 @@
<?php
use MailPoet\Mailer\Mandrill;
class MandrillCest {
function __construct() {
$this->data = array(
'api_key' => '692ys1B7REEoZN7R-dYwNA',
'from_email' => 'do-not-reply@mailpoet.com',
'from_name' => 'Phoenix',
'newsletter' => array(
'subject' => 'Testing Mandrill',
'body' => 'this is a test message....'
),
'subscribers' => array(
array(
'email' => 'mailpoet-test1@mailinator.com',
'last_name' => 'Smith'
),
array(
'email' => 'mailpoet-test2@mailinator.com',
'first_name' => 'Jane',
'last_name' => 'Smith'
),
array(
'email' => 'mailpoet-test3@mailinator.com',
),
array()
)
);
$this->mailer = new Mandrill(
$this->data['api_key'],
$this->data['from_email'],
$this->data['from_name'],
$this->data['newsletter'],
$this->data['subscribers']);
}
function itCanGenerateSubscribers() {
$subscribers = $this->mailer->getSubscribers();
expect(count($subscribers))->equals(3);
// test proper handling of spaces between first/last name
expect($subscribers[0]['email'])->equals(
$this->data['subscribers'][0]['email']
);
expect($subscribers[0]['name'])->equals(
$this->data['subscribers'][0]['last_name']
);
expect($subscribers[1]['name'])->equals(
sprintf(
'%s %s', $this->data['subscribers'][1]['first_name'],
$this->data['subscribers'][1]['last_name']
)
);
}
function itCanGenerateBody() {
$body = $this->mailer->getBody();
expect($body['key'])->equals($this->data['api_key']);
expect($body['message']['html'])->equals(
$this->data['newsletter']['body']
);
expect($body['message']['subject'])->equals(
$this->data['newsletter']['subject']
);
expect($body['message']['from_email'])->equals(
$this->data['from_email']
);
expect($body['message']['from_name'])->equals(
$this->data['from_name']
);
expect($body['message']['to'])->equals(
$this->mailer->getSubscribers()
);
expect($body['message']['headers']['Reply-To'])->equals(
$this->data['from_email']
);
expect($body['message']['preserve_recipients'])->false();
expect($body['async'])->false();
}
function itCanCreateRequest() {
$request = $this->mailer->request();
expect($request['timeout'])
->equals(10);
expect($request['httpversion'])
->equals('1.0');
expect($request['method'])
->equals('POST');
expect($request['headers']['Content-Type'])
->equals('application/json');
expect($request['body'])
->equals(json_encode($this->mailer->getBody()));
}
function itCannotSendWithoutProperAPIKey() {
$mailer = new Mandrill(
'someapikey',
$this->data['from_email'],
$this->data['from_name'],
$this->data['newsletter'],
$this->data['subscribers']
);
expect($mailer->send())->equals(false);
}
function itCanSend() {
$result = $this->mailer->send();
expect($result)->equals(true);
}
}

View File

@ -1,110 +0,0 @@
<?php
use MailPoet\Mailer\SendGrid;
class SendGridCest {
function __construct() {
$this->data = array(
'api_key' => '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',
'from_email' => 'do-not-reply@mailpoet.com',
'from_name' => 'Phoenix',
'newsletter' => array(
'subject' => 'Testing SendGrid',
'body' => 'this is a test message....'
),
'subscribers' => array(
array(
'email' => 'mailpoet-test1@mailinator.com',
'last_name' => 'Smith'
),
array(
'email' => 'mailpoet-test2@mailinator.com',
'first_name' => 'Jane',
'last_name' => 'Smith'
),
array(
'email' => 'mailpoet-test3@mailinator.com',
),
array()
)
);
$this->mailer = new SendGrid(
$this->data['api_key'],
$this->data['from_email'],
$this->data['from_name'],
$this->data['newsletter'],
$this->data['subscribers']);
}
function itCanGenerateSubscribers() {
$subscribers = $this->mailer->getSubscribers();
expect(count($subscribers))->equals(3);
// test proper handling of spaces between first/last name
expect($subscribers[0])->equals(
sprintf(
'%s <%s>',
$this->data['subscribers'][0]['last_name'],
$this->data['subscribers'][0]['email'])
);
expect($subscribers[1])->equals(
sprintf(
'%s %s <%s>', $this->data['subscribers'][1]['first_name'],
$this->data['subscribers'][1]['last_name'],
$this->data['subscribers'][1]['email']
)
);
}
function itCanGenerateBody() {
$body = explode('&', $this->mailer->getBody());
expect($body[0])
->equals("to=" .
sprintf(
'%s <%s>', $this->data['from_name'], $this->data['from_email']
)
);
expect($body[1])
->equals("from=" .
sprintf(
'%s <%s>', $this->data['from_name'], $this->data['from_email']
)
);
expect($body[2])
->contains($this->data['subscribers'][0]['email']);
expect($body[3])
->equals("subject=" . $this->data['newsletter']['subject']);
expect($body[4])
->equals("html=" . $this->data['newsletter']['body']);
}
function itCanCreateRequest() {
$request = $this->mailer->request();
expect($request['timeout'])
->equals(10);
expect($request['httpversion'])
->equals('1.1');
expect($request['method'])
->equals('POST');
expect($request['headers']['Authorization'])
->equals('Bearer ' . $this->data['api_key']);
expect($request['body'])
->equals($this->mailer->getBody());
}
function itCannotSendWithoutProperAPIKey() {
$mailer = new SendGrid(
'someapikey',
$this->data['from_email'],
$this->data['from_name'],
$this->data['newsletter'],
$this->data['subscribers']
);
expect($mailer->send())->equals(false);
}
function itCanSend() {
$result = $this->mailer->send();
expect($result)->equals(true);
}
}

View File

@ -0,0 +1,62 @@
<?php
use MailPoet\Router\Mailer;
class MailerCest {
function __construct() {
$this->router = new Mailer();
}
function itCanConstruct() {
expect($this->router->from)->equals('Sender <mailpoet-test1@mailinator.com>');
}
function itCanTransformSubscriber() {
expect($this->router->transformSubscriber('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() {
$mailer = $this->router->configureMailer();
$class = 'Mailpoet\\Mailer\\' .
$this->router->mailer['type'] . '\\' .
$this->router->mailer['name'];
expect($mailer instanceof $class)->true();
expect(method_exists($mailer, 'send'))->true();
}
function itCanSend() {
$newsletter = array(
'subject' => 'testing Mailer router with '.$this->router->mailer['name'],
'body' => array(
'html' => 'HTML body',
'text' => 'TEXT body'
)
);
$subscriber = array(
'first_name' => 'First',
'last_name' => 'Last',
'email' => 'mailpoet-test1@mailinator.com'
);
expect($this->router->send($newsletter, $subscriber))->true();
}
}