Skip to content

Commit

Permalink
Merge pull request #108 from SparkPost/issue97
Browse files Browse the repository at this point in the history
Attachments in templates
  • Loading branch information
rajumsys committed Mar 30, 2017
2 parents 77ca17a + 15d558b commit a0e5a95
Show file tree
Hide file tree
Showing 8 changed files with 471 additions and 56 deletions.
43 changes: 28 additions & 15 deletions admin.widget.class.php
Original file line number Diff line number Diff line change
Expand Up @@ -48,11 +48,10 @@ public function set_html_content_type()
return 'text/html';
}

private function send_email($recipient)
private function send_email($recipient, $attachments = array())
{
add_filter('wp_mail_content_type', array($this, 'set_html_content_type'));
$headers = array();
$attachments= array(__DIR__ . '/sample.txt');
$result = wp_mail($recipient,
'SparkPost email test',
'<h3>Hurray!!</h3><p>You\'ve got mail! <br/><br> Regards,<br/><a href="https://www.sparkpost.com">SparkPost</a> WordPress plugin</p>',
Expand All @@ -63,7 +62,7 @@ private function send_email($recipient)
return $result;
}

public function test_email_sending($recipient, $debug = false)
public function test_email_sending($recipient, $debug = false, $include_attachment = false)
{
if (empty($recipient)) {
return $this->render_message('Please enter a valid email address in the recipient field below.');
Expand All @@ -73,14 +72,21 @@ public function test_email_sending($recipient, $debug = false)
return $this->render_message('Recipient is not a valid email address.');
}


if($include_attachment) {
$attachments = array(__DIR__ . '/sample.txt');
} else {
$attachments = array();
}

if ($debug) {
add_action('phpmailer_init', array($this, 'phpmailer_enable_debugging'));
echo '<div class="notice is-dismissible">';
echo '<h4>Debug Messages</h4>';
$result = $this->send_email($recipient);
$result = $this->send_email($recipient, $attachments);
echo '</div>';
} else {
$result = $this->send_email($recipient);
$result = $this->send_email($recipient, $attachments);
}

if ($result) {
Expand Down Expand Up @@ -111,7 +117,7 @@ public function wpsp_admin_page()
<h3>Test Email</h3>
<?php
if (isset($_POST['sp_test_email'])) {
$this->test_email_sending($_POST['to_email'], !empty($_POST['enable_debugging']));
$this->test_email_sending($_POST['to_email'], !empty($_POST['enable_debugging']), !empty($_POST['include_attachment']));
}
?>

Expand Down Expand Up @@ -144,6 +150,7 @@ public function admin_page_init()

add_settings_section('test_email', '', null, 'sp-test-email');
add_settings_field('to_email', 'Recipient*', array($this, 'render_to_email_field'), 'sp-test-email', 'test_email');
add_settings_field('include_attachment', '', array($this, 'render_include_attachment_field'), 'sp-test-email', 'test_email');
add_settings_field('debug_messages', 'Debug', array($this, 'render_enable_debugging_field'), 'sp-test-email', 'test_email');
}

Expand Down Expand Up @@ -233,7 +240,8 @@ public function render_password_field()

printf(
'<input type="text" id="password" name="sp_settings[password]" class="regular-text" value="%s" /><br/>
<small><ul><li>For SMTP, set up an API key with the <strong>Send via SMTP</strong> permission</li> <li>For HTTP API, set up an API Key with the <strong>Transmissions: Read/Write</strong> permission</li><a href="https://support.sparkpost.com/customer/portal/articles/1933377-create-api-keys" target="_blank">Need help creating a SparkPost API key?</a></small>',
<small><ul><li>For SMTP, set up an API key with the <strong>Send via SMTP</strong> permission</li>
<li>For HTTP API, set up an API Key with the <strong>Transmissions: Read/Write, Templates: Read/Write</strong> permissions</li><a href="https://support.sparkpost.com/customer/portal/articles/1933377-create-api-keys" target="_blank">Need help creating a SparkPost API key?</a></small>',
isset($api_key) ? $api_key : ''
);
}
Expand All @@ -247,7 +255,6 @@ public function render_template_field()
<ul>
<li>- Please see <a href="https://support.sparkpost.com/customer/portal/articles/2409547-using-templates-with-the-sparkpost-wordpress-plugin" target="_blank">this article</a> for detailed information about using templates with this plugin.</li>
<li>- Templates can only be used with the HTTP API.</li>
<li>- <a href="https://github.com/SparkPost/wordpress-sparkpost/blob/master/docs/templates-attachments.md" target="_blank">Does not work with attachment.</a>
<li>- Leave this field blank to disable use of a template. You can still specify it by <a href="https://github.com/SparkPost/wordpress-sparkpost/blob/master/docs/hooks.md" target="_blank">using hooks</a>.</li>
</ul>
</small>
Expand All @@ -256,7 +263,7 @@ public function render_template_field()

public function render_from_email_field()
{
$hint = 'Important: Domain must match with one of your verified sending domains.';
$hint = '<strong>Important:</strong> Domain must match with one of your verified sending domains.';
if(empty($this->settings['from_email'])){
$hostname = parse_url(get_bloginfo('url'), PHP_URL_HOST);
$hint .= sprintf(' When left blank, <strong>%s</strong> will be used as email domain', $hostname);
Expand Down Expand Up @@ -309,11 +316,17 @@ public function render_enable_debugging_field()
echo '<label><input type="checkbox" id="enable_debugging" name="enable_debugging" value="1" checked />Show email debugging messages</label>';
}

public function render_transactional_field()
{
printf('<label><input type="checkbox" id="transactional" name="sp_settings[transactional]" value="1" %s />Mark emails as transactional</label>
<br/><small>Upon checked, by default, it\'ll set mark all emails as transactional. It should be set false (using hooks) for non-transactional emails.</small>',
$this->settings['transactional'] ? 'checked' : '');
public function render_transactional_field()
{
printf('<label><input type="checkbox" id="transactional" name="sp_settings[transactional]" value="1" %s />Mark emails as transactional</label>
<br/><small>Upon checked, by default, it\'ll set mark all emails as transactional. It should be set false (using hooks) for non-transactional emails.</small>',
$this->settings['transactional'] ? 'checked' : '');

}


}
public function render_include_attachment_field()
{
echo '<label><input type="checkbox" id="include_attachment" name="include_attachment" value="1" />Include Attachment</label>';
}
}
1 change: 1 addition & 0 deletions docs/hooks.md
Original file line number Diff line number Diff line change
Expand Up @@ -27,3 +27,4 @@ Hook names are prefixed with `wpsp_`.
| wpsp_body_headers | Filter |
| wpsp_smtp_msys_api | Filter |
| wpsp_transactional | Filter | Set whether an email is transactional or not.
| wpsp_substitution_data | Filter | Modify substitution_data object
149 changes: 109 additions & 40 deletions mailer.http.class.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
if (!defined('ABSPATH')) exit();

require_once ABSPATH . WPINC . '/class-phpmailer.php';
require_once WPSP_PLUGIN_DIR . '/templates.class.php';

class SparkPostHTTPMailer extends \PHPMailer
{
Expand All @@ -18,6 +19,7 @@ class SparkPostHTTPMailer extends \PHPMailer
function __construct($exceptions = false)
{
$this->settings = SparkPost::get_settings();
$this->template = new SparkPostTemplates($this);

parent::__construct($exceptions);
do_action('wpsp_init_mailer', $this);
Expand All @@ -38,34 +40,55 @@ protected function mailSend($header, $body)

function sparkpost_send()
{
$this->edebug('Preparing request data');
$this->debug('Preparing request data');

$request_body = $this->get_request_body();

if(!$request_body) {
$this->error('Failed to prepare transmission request body');
return false;
}

$data = array(
'method' => 'POST',
'timeout' => 15,
'headers' => $this->get_request_headers(),
'body' => json_encode($this->get_request_body())
'body' => json_encode($request_body)
);

$http = apply_filters('wpsp_get_http_lib', _wp_http_get_object());

$this->edebug(sprintf('Request headers: %s', print_r($this->get_request_headers(true), true)));
$this->edebug(sprintf('Request body: %s', $data['body']));
$this->edebug(sprintf('Making HTTP POST request to %s', $this->endpoint));
do_action('wpsp_before_send', $this->endpoint, $data);
$result = $http->request($this->endpoint, $data);
do_action('wpsp_after_send', $result);
$this->edebug('Response received');
$result = $this->request($this->endpoint, $data);

$result = apply_filters('wpsp_handle_response', $result);
$this->check_permission_error($result, 'Transmissions: Read/Write');
if(is_bool($result)) { // it means, response been already processed by the hooked filter. so just return the value.
$this->edebug('Skipping response processing');
$this->debug('Skipping response processing');
return $result;
} else {
return $this->handle_response($result);
}
}

/**
* Prepare substitution data to be used in template
*/
protected function get_template_substitutes($sender, $replyTo){
$substitution_data = array();
$substitution_data['content'] = $this->Body;
$substitution_data['subject'] = $this->Subject;
$substitution_data['from_name'] = $sender['name'];
$substitution_data['from'] = $sender['email'];
if ($replyTo) {
$substitution_data['reply_to'] = $replyTo;
}
$localpart = explode('@', $sender['email']);

if (!empty($localpart)) {
$substitution_data['from_localpart'] = $localpart[0];
}

return apply_filters('wpsp_substitution_data', $substitution_data);
}

/**
* Build the request body to be sent to the SparkPost API.
*/
Expand All @@ -88,23 +111,39 @@ protected function get_request_body()

$template_id = apply_filters('wpsp_template_id', $this->settings['template']);

$attachments = $this->get_attachments();

// pass through either stored template or inline content
if (!empty($template_id)) {
// stored template
$body['content']['template_id'] = $template_id;
// stored template
$substitution_data = $this->get_template_substitutes($sender, $replyTo);
if(sizeof($attachments) > 0){ //get template preview data and then send it as inline
$preview_contents = $this->template->preview($template_id, $substitution_data);
if($preview_contents === false) {
return false;
}
$body['content'] = array(
'from' => (array) $preview_contents->from,
'subject' => (string) $preview_contents->subject,
'headers' => (array) $this->get_headers()
);

// supply substitution data so users can add variables to templates
$body['substitution_data']['content'] = $this->Body;
$body['substitution_data']['subject'] = $this->Subject;
$body['substitution_data']['from_name'] = $sender['name'];
$body['substitution_data']['from'] = $sender['email'];
if ($replyTo) {
$body['substitution_data']['reply_to'] = $replyTo;
if(property_exists($preview_contents, 'text')) {
$body['content']['text'] = $preview_contents->text;
}
$localpart = explode('@', $sender['email']);
if (!empty($localpart)) {
$body['substitution_data']['from_localpart'] = $localpart[0];

if(property_exists($preview_contents, 'html')){
$body['content']['html'] = $preview_contents->html;
}

if(property_exists($preview_contents, 'reply_to')) {
$body['content']['reply_to'] = $preview_contents->reply_to;
}

} else { // simply subsititute template tags
$body['content']['template_id'] = $template_id;
$body['substitution_data'] = $substitution_data;
}
} else {
// inline content
$body['content'] = array(
Expand All @@ -131,8 +170,7 @@ protected function get_request_body()
}
}

$attachments = $this->get_attachments();
if (count($attachments)) {
if (sizeof($attachments)) {
$body['content']['attachments'] = $attachments;
}

Expand Down Expand Up @@ -191,41 +229,41 @@ public function isMail()
protected function handle_response($response)
{
if (is_wp_error($response)) {
$this->edebug('Request completed with error');
$this->setError($response->get_error_messages()); //WP_Error implements this method
$this->edebug($response->get_error_messages());
$this->debug('Request completed with error');
$this->error($response->get_error_messages()); //WP_Error implements this method
$this->debug($response->get_error_messages());
return false;
}

$this->edebug('Response headers: ' . print_r($response['headers'], true));
$this->edebug('Response body: ' . print_r($response['body'], true));
$this->debug('Response headers: ' . print_r($response['headers'], true));
$this->debug('Response body: ' . print_r($response['body'], true));

$body = json_decode($response['body']);
do_action('wpsp_response_body', $body);

if (property_exists($body, 'errors')) {
$this->edebug('Error in transmission');
$this->setError($body->errors);
$this->debug('Error in transmission');
$this->error($body->errors);
return false;
}

if (property_exists($body, 'results')) {
$data = $body->results;
} else {
$this->edebug('API response is unknown');
$this->setError('Unknown response');
$this->debug('API response is unknown');
$this->error('Unknown response');
return false;
}

if ($data->total_rejected_recipients > 0) {
$this->edebug(sprintf('Sending to %d recipient(s) failed', $data->total_rejected_recipients));
$this->setError($data);
$this->debug(sprintf('Sending to %d recipient(s) failed', $data->total_rejected_recipients));
$this->error($data);
return false;
}

if ($data->total_accepted_recipients > 0) {
$this->edebug(sprintf('Successfully sent to %d recipient(s)', $data->total_accepted_recipients));
$this->edebug(sprintf('Transmission ID is %s', $data->id));
$this->debug(sprintf('Successfully sent to %d recipient(s)', $data->total_accepted_recipients));
$this->debug(sprintf('Transmission ID is %s', $data->id));
return true;
}
return false;
Expand Down Expand Up @@ -259,7 +297,7 @@ protected function get_recipients()
return apply_filters('wpsp_recipients', $recipients);
}

protected function get_request_headers($hide_api_key = false)
public function get_request_headers($hide_api_key = false)
{
$api_key = apply_filters('wpsp_api_key', $this->settings['password']);
if ($hide_api_key) {
Expand Down Expand Up @@ -417,4 +455,35 @@ protected function get_headers()

return apply_filters('wpsp_body_headers', $formatted_headers);
}

function check_permission_error($response, $permission) {
$response = (array) $response;
if(!empty($response['response']) && $response['response']['code'] === 403) {
$this->debug("API Key might not have {$permission} permission. Actual Error: " . print_r($response['response'], true));
$this->error("API Key might not have {$permission} permission");
return true;
}
return false;
}

public function debug($msg) {
$this->edebug($msg);
}

public function error($msg) {
$this->setError($msg);
}

public function request($endpoint, $data) {
$http = apply_filters('wpsp_get_http_lib', _wp_http_get_object());

$this->debug(sprintf('Request headers: %s', print_r($this->get_request_headers(true), true)));
$this->debug(sprintf('Request body: %s', $data['body']));
$this->debug(sprintf('Making HTTP POST request to %s', $endpoint));
do_action('wpsp_before_send', $this->endpoint, $data);
$result = $http->request($endpoint, $data);
do_action('wpsp_after_send', $result);
$this->debug('Response received');
return $result;
}
}
Loading

0 comments on commit a0e5a95

Please sign in to comment.