Mailgun for WordPress - Version 1.5.11

Version Description

(2018-05-30): = - Fix an issue with authentication failing for newer API keys - Test plugin up to Wordpress 4.9.6

Download this release

Release Info

Developer Mailgun
Plugin Icon 128x128 Mailgun for WordPress
Version 1.5.11
Comparing to
See all releases

Code changes from version 1.5.8.5 to 1.5.11

CHANGELOG.md CHANGED
@@ -1,6 +1,17 @@
1
  Changelog
2
  =========
3
 
 
 
 
 
 
 
 
 
 
 
 
4
  1.5.8.5 (2017-09-05):
5
  - Change default click tracking setting to `htmlonly` (https://github.com/mailgun/wordpress-plugin/pull/58)
6
  - Change PHPMailer set-up stanza to use TLS
1
  Changelog
2
  =========
3
 
4
+ 1.5.11 (2018-05-30):
5
+ - Fix an issue with authentication failing for newer API keys
6
+ - Test plugin up to Wordpress 4.9.6
7
+
8
+ 1.5.10 (2017-11-22):
9
+ - Fix back to settings link on lists page (https://github.com/mailgun/wordpress-plugin/pull/65)
10
+ - Fix a bug causing `text/html` emails to send as both `text/plain` *and* `text/html` parts
11
+
12
+ 1.5.9 (2017-09-13):
13
+ - Add a configuration option to allow setting security type for SMTP connection (SSL / TLS)
14
+
15
  1.5.8.5 (2017-09-05):
16
  - Change default click tracking setting to `htmlonly` (https://github.com/mailgun/wordpress-plugin/pull/58)
17
  - Change PHPMailer set-up stanza to use TLS
includes/admin.php CHANGED
@@ -76,6 +76,7 @@ class MailgunAdmin extends Mailgun
76
  'username' => '',
77
  'password' => '',
78
  'secure' => '1',
 
79
  'track-clicks' => '',
80
  'track-opens' => '',
81
  'campaign-id' => '',
@@ -259,16 +260,21 @@ class MailgunAdmin extends Mailgun
259
  $apiKey = trim($options['apiKey']);
260
  $username = trim($options['username']);
261
  if (!empty($apiKey)) {
262
- $pos = strpos($apiKey, 'key-');
263
- if ($pos === false || $pos > 4) {
264
- $apiKey = "key-{$apiKey}";
265
- }
266
-
267
  $pos = strpos($apiKey, 'api:');
268
  if ($pos !== false && $pos == 0) {
269
  $apiKey = substr($apiKey, 4);
270
  }
271
- $options['apiKey'] = $apiKey;
 
 
 
 
 
 
 
 
 
 
272
  }
273
 
274
  if (!empty($username)) {
@@ -283,6 +289,10 @@ class MailgunAdmin extends Mailgun
283
  if (empty($options['override-from'])) {
284
  $options['override-from'] = $this->defaults['override-from'];
285
  }
 
 
 
 
286
  // alternatively:
287
  // foreach ($defaults as $key => $value) {
288
  // if (empty($options[$key])) {
@@ -374,10 +384,15 @@ class MailgunAdmin extends Mailgun
374
 
375
  $useAPI = (defined('MAILGUN_USEAPI') && MAILGUN_USEAPI) ? MAILGUN_USEAPI : $this->get_option('useAPI');
376
  $secure = (defined('MAILGUN_SECURE') && MAILGUN_SECURE) ? MAILGUN_SECURE : $this->get_option('secure');
 
 
377
  if ((bool) $useAPI) {
378
  $method = __('HTTP API', 'mailgun');
379
  } else {
380
  $method = ((bool) $secure) ? __('Secure SMTP', 'mailgun') : __('SMTP', 'mailgun');
 
 
 
381
  }
382
 
383
  $admin_email = get_option('admin_email');
76
  'username' => '',
77
  'password' => '',
78
  'secure' => '1',
79
+ 'sectype' => 'tls',
80
  'track-clicks' => '',
81
  'track-opens' => '',
82
  'campaign-id' => '',
260
  $apiKey = trim($options['apiKey']);
261
  $username = trim($options['username']);
262
  if (!empty($apiKey)) {
 
 
 
 
 
263
  $pos = strpos($apiKey, 'api:');
264
  if ($pos !== false && $pos == 0) {
265
  $apiKey = substr($apiKey, 4);
266
  }
267
+
268
+ if (1 === preg_match('(\w{32}-\w{8}-\w{8})', $apiKey)) {
269
+ $options['apiKey'] = $apiKey;
270
+ } else {
271
+ $pos = strpos($apiKey, 'key-');
272
+ if ($pos === false || $pos > 4) {
273
+ $apiKey = "key-{$apiKey}";
274
+ }
275
+
276
+ $options['apiKey'] = $apiKey;
277
+ }
278
  }
279
 
280
  if (!empty($username)) {
289
  if (empty($options['override-from'])) {
290
  $options['override-from'] = $this->defaults['override-from'];
291
  }
292
+
293
+ if (empty($options['sectype'])) {
294
+ $options['sectype'] = $this->defaults['sectype'];
295
+ }
296
  // alternatively:
297
  // foreach ($defaults as $key => $value) {
298
  // if (empty($options[$key])) {
384
 
385
  $useAPI = (defined('MAILGUN_USEAPI') && MAILGUN_USEAPI) ? MAILGUN_USEAPI : $this->get_option('useAPI');
386
  $secure = (defined('MAILGUN_SECURE') && MAILGUN_SECURE) ? MAILGUN_SECURE : $this->get_option('secure');
387
+ $sectype = (defined('MAILGUN_SECTYPE') && MAILGUN_SECTYPE) ? MAILGUN_SECTYPE : $this->get_option('sectype');
388
+
389
  if ((bool) $useAPI) {
390
  $method = __('HTTP API', 'mailgun');
391
  } else {
392
  $method = ((bool) $secure) ? __('Secure SMTP', 'mailgun') : __('SMTP', 'mailgun');
393
+ if ((bool) $secure) {
394
+ $method = $method . sprintf(__(' via %s', $sectype));
395
+ }
396
  }
397
 
398
  $admin_email = get_option('admin_email');
includes/lists-page.php CHANGED
@@ -52,7 +52,7 @@ $lists_arr = $mailgun->get_lists();
52
 
53
  <?php settings_fields('mailgun'); ?>
54
 
55
- <h3><?php _e('Available Mailing Lists', 'mailgun'); ?> | <a href="/wp-admin/options-general.php?page=mailgun">Back to settings</a></h3>
56
 
57
  <p><?php _e("{$missing_error}You must use a valid Mailgun domain name and API key to access lists", 'mailgun'); ?></p>
58
 
52
 
53
  <?php settings_fields('mailgun'); ?>
54
 
55
+ <h3><?php _e('Available Mailing Lists', 'mailgun'); ?> | <a href="<?php echo admin_url('options-general.php?page=mailgun'); ?>">Back to settings</a></h3>
56
 
57
  <p><?php _e("{$missing_error}You must use a valid Mailgun domain name and API key to access lists", 'mailgun'); ?></p>
58
 
includes/options-page.php CHANGED
@@ -57,7 +57,7 @@
57
  </th>
58
  <td>
59
  <input type="text" class="regular-text" name="mailgun[apiKey]" value="<?php esc_attr_e($this->get_option('apiKey')); ?>" placeholder="key-3ax6xnjp29jd6fds4gc373sgvjxteol0" />
60
- <p class="description"><?php _e('Your Mailgun API key, that starts with and includes "key-". Only valid for use with the API.', 'mailgun'); ?></p>
61
  </td>
62
  </tr>
63
  <tr valign="top" class="mailgun-smtp">
@@ -90,6 +90,18 @@
90
  <p class="description"><?php _e('Set this to "No" if your server cannot establish SSL SMTP connections or if emails are not being delivered. If you set this to "No" your password will be sent in plain text. Only valid for use with SMTP. Default "Yes".', 'mailgun'); ?></p>
91
  </td>
92
  </tr>
 
 
 
 
 
 
 
 
 
 
 
 
93
  <tr valign="top">
94
  <th scope="row">
95
  <?php _e('Click Tracking', 'mailgun'); ?>
57
  </th>
58
  <td>
59
  <input type="text" class="regular-text" name="mailgun[apiKey]" value="<?php esc_attr_e($this->get_option('apiKey')); ?>" placeholder="key-3ax6xnjp29jd6fds4gc373sgvjxteol0" />
60
+ <p class="description"><?php _e('Your Mailgun API key. Only valid for use with the API.', 'mailgun'); ?></p>
61
  </td>
62
  </tr>
63
  <tr valign="top" class="mailgun-smtp">
90
  <p class="description"><?php _e('Set this to "No" if your server cannot establish SSL SMTP connections or if emails are not being delivered. If you set this to "No" your password will be sent in plain text. Only valid for use with SMTP. Default "Yes".', 'mailgun'); ?></p>
91
  </td>
92
  </tr>
93
+ <tr valign="top" class="mailgun-smtp">
94
+ <th scope="row">
95
+ <?php _e('Security Type', 'mailgun'); ?>
96
+ </th>
97
+ <td>
98
+ <select name="mailgun[sectype]">
99
+ <option value="ssl"<?php selected('ssl', $this->get_option('sectype')); ?>>SSL</option>
100
+ <option value="tls"<?php selected('tls', $this->get_option('sectype')); ?>>TLS</option>
101
+ </select>
102
+ <p class="description"><php _e('Leave this at "TLS" unless mail sending fails. This option only matters for Secure SMTP. Default "TLS".', 'mailgun'); ?></p>
103
+ </td>
104
+ </tr>
105
  <tr valign="top">
106
  <th scope="row">
107
  <?php _e('Click Tracking', 'mailgun'); ?>
includes/widget.php CHANGED
File without changes
includes/wp-mail-api.php CHANGED
@@ -218,7 +218,6 @@ function wp_mail($to, $subject, $message, $headers = '', $attachments = array())
218
  'from' => "{$from_name} <{$from_email}>",
219
  'to' => $to,
220
  'subject' => $subject,
221
- 'text' => $message,
222
  );
223
 
224
  $rcpt_data = apply_filters('mg_mutate_to_rcpt_vars', $to);
@@ -256,21 +255,18 @@ function wp_mail($to, $subject, $message, $headers = '', $attachments = array())
256
  $body['bcc'] = implode(', ', $bcc);
257
  }
258
 
259
- // If we are not given a Content-Type from the supplied headers, use
260
- // text/html and *attempt* to strip tags and provide a text/plain
261
- // version.
262
  if (!isset($content_type)) {
263
- // Try to figure out the content type with mime_content_type.
264
  $tmppath = tempnam(sys_get_temp_dir(), 'mg');
265
  $tmp = fopen($tmppath, 'w+');
266
 
267
  fwrite($tmp, $message);
268
  fclose($tmp);
269
 
270
- // Get mime type with mime_content_type
271
  $content_type = get_mime_content_type($tmppath, 'text/plain');
272
 
273
- // Remove the tmpfile
274
  unlink($tmppath);
275
  }
276
 
@@ -284,8 +280,11 @@ function wp_mail($to, $subject, $message, $headers = '', $attachments = array())
284
 
285
  if ('text/plain' === $content_type) {
286
  $body['text'] = $message;
 
 
287
  } else {
288
  // Unknown Content-Type??
 
289
  $body['text'] = $message;
290
  $body['html'] = $message;
291
  }
@@ -320,50 +319,32 @@ function wp_mail($to, $subject, $message, $headers = '', $attachments = array())
320
  * not support files directly.
321
  */
322
 
 
 
323
  // First, generate a boundary for the multipart message.
324
  $boundary = base_convert(uniqid('boundary', true), 10, 36);
325
 
326
- $payload = null;
327
-
328
- // Allow other plugins to apply body changes before writing the payload.
329
  $body = apply_filters('mg_mutate_message_body', $body);
330
-
331
- // Iterate through pre-built params and build payload:
332
- foreach ($body as $key => $value) {
333
- if (is_array($value)) {
334
- $parent_key = $key;
335
- foreach ($value as $key => $value) {
336
- $payload .= '--'.$boundary;
337
- $payload .= "\r\n";
338
- $payload .= 'Content-Disposition: form-data; name="'.$parent_key."\"\r\n\r\n";
339
- $payload .= $value;
340
- $payload .= "\r\n";
341
- }
342
- } else {
343
- $payload .= '--'.$boundary;
344
- $payload .= "\r\n";
345
- $payload .= 'Content-Disposition: form-data; name="'.$key.'"'."\r\n\r\n";
346
- $payload .= $value;
347
- $payload .= "\r\n";
348
- }
349
  }
350
 
 
 
 
 
 
 
 
 
 
 
 
351
  // Allow other plugins to apply attachent changes before writing to the payload.
352
  $attachments = apply_filters('mg_mutate_attachments', $attachments);
353
-
354
- // If we have attachments, add them to the payload.
355
- if (!empty($attachments)) {
356
- $i = 0;
357
- foreach ($attachments as $attachment) {
358
- if (!empty($attachment)) {
359
- $payload .= '--'.$boundary;
360
- $payload .= "\r\n";
361
- $payload .= 'Content-Disposition: form-data; name="attachment['.$i.']"; filename="'.basename($attachment).'"'."\r\n\r\n";
362
- $payload .= file_get_contents($attachment);
363
- $payload .= "\r\n";
364
- $i++;
365
- }
366
- }
367
  }
368
 
369
  $payload .= '--'.$boundary.'--';
@@ -412,3 +393,55 @@ function wp_mail($to, $subject, $message, $headers = '', $attachments = array())
412
 
413
  return true;
414
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
218
  'from' => "{$from_name} <{$from_email}>",
219
  'to' => $to,
220
  'subject' => $subject,
 
221
  );
222
 
223
  $rcpt_data = apply_filters('mg_mutate_to_rcpt_vars', $to);
255
  $body['bcc'] = implode(', ', $bcc);
256
  }
257
 
258
+ // If we are not given a Content-Type in the supplied headers,
259
+ // write the message body to a file and try to determine the mimetype
260
+ // using get_mime_content_type.
261
  if (!isset($content_type)) {
 
262
  $tmppath = tempnam(sys_get_temp_dir(), 'mg');
263
  $tmp = fopen($tmppath, 'w+');
264
 
265
  fwrite($tmp, $message);
266
  fclose($tmp);
267
 
 
268
  $content_type = get_mime_content_type($tmppath, 'text/plain');
269
 
 
270
  unlink($tmppath);
271
  }
272
 
280
 
281
  if ('text/plain' === $content_type) {
282
  $body['text'] = $message;
283
+ } else if ('text/html' === $content_type) {
284
+ $body['html'] = $message;
285
  } else {
286
  // Unknown Content-Type??
287
+ error_log('[mailgun] Got unknown Content-Type: ' . $content_type);
288
  $body['text'] = $message;
289
  $body['html'] = $message;
290
  }
319
  * not support files directly.
320
  */
321
 
322
+ $payload = '';
323
+
324
  // First, generate a boundary for the multipart message.
325
  $boundary = base_convert(uniqid('boundary', true), 10, 36);
326
 
327
+ // Allow other plugins to apply body changes before creating the payload.
 
 
328
  $body = apply_filters('mg_mutate_message_body', $body);
329
+ if ( ($body_payload = mg_build_payload_from_body($body, $boundary)) != null ) {
330
+ $payload .= $body_payload;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
331
  }
332
 
333
+ // TODO: Special handling for multipart/alternative mail
334
+ // if ('multipart/alternative' === $content_type) {
335
+ // // Build payload from mime
336
+ // // error_log(sprintf('building message payload from multipart/alternative'));
337
+ // // error_log($body['message']);
338
+ // // error_log('Attachments:');
339
+ // // foreach ($attachments as $attachment) {
340
+ // // error_log($attachment);
341
+ // // }
342
+ // }
343
+
344
  // Allow other plugins to apply attachent changes before writing to the payload.
345
  $attachments = apply_filters('mg_mutate_attachments', $attachments);
346
+ if ( ($attachment_payload = mg_build_attachments_payload($attachments, $boundary)) != null ) {
347
+ $payload .= $attachment_payload;
 
 
 
 
 
 
 
 
 
 
 
 
348
  }
349
 
350
  $payload .= '--'.$boundary.'--';
393
 
394
  return true;
395
  }
396
+
397
+ function mg_build_payload_from_body($body, $boundary) {
398
+ $payload = '';
399
+
400
+ // Iterate through pre-built params and build payload:
401
+ foreach ($body as $key => $value) {
402
+ if (is_array($value)) {
403
+ $parent_key = $key;
404
+ foreach ($value as $key => $value) {
405
+ $payload .= '--'.$boundary;
406
+ $payload .= "\r\n";
407
+ $payload .= 'Content-Disposition: form-data; name="'.$parent_key."\"\r\n\r\n";
408
+ $payload .= $value;
409
+ $payload .= "\r\n";
410
+ }
411
+ } else {
412
+ $payload .= '--'.$boundary;
413
+ $payload .= "\r\n";
414
+ $payload .= 'Content-Disposition: form-data; name="'.$key.'"'."\r\n\r\n";
415
+ $payload .= $value;
416
+ $payload .= "\r\n";
417
+ }
418
+ }
419
+
420
+ return $payload;
421
+ }
422
+
423
+ function mg_build_payload_from_mime($body, $boundary) {
424
+ }
425
+
426
+ function mg_build_attachments_payload($attachments, $boundary) {
427
+ $payload = '';
428
+
429
+ // If we have attachments, add them to the payload.
430
+ if (!empty($attachments)) {
431
+ $i = 0;
432
+ foreach ($attachments as $attachment) {
433
+ if (!empty($attachment)) {
434
+ $payload .= '--'.$boundary;
435
+ $payload .= "\r\n";
436
+ $payload .= 'Content-Disposition: form-data; name="attachment['.$i.']"; filename="'.basename($attachment).'"'."\r\n\r\n";
437
+ $payload .= file_get_contents($attachment);
438
+ $payload .= "\r\n";
439
+ $i++;
440
+ }
441
+ }
442
+ } else {
443
+ return null;
444
+ }
445
+
446
+ return $payload;
447
+ }
mailgun.php CHANGED
@@ -4,7 +4,7 @@
4
  * Plugin Name: Mailgun
5
  * Plugin URI: http://wordpress.org/extend/plugins/mailgun/
6
  * Description: Mailgun integration for WordPress
7
- * Version: 1.5.8.5
8
  * Author: Mailgun
9
  * Author URI: http://www.mailgun.com/
10
  * License: GPLv2 or later
@@ -114,6 +114,7 @@ class Mailgun
114
  $domain = (defined('MAILGUN_DOMAIN') && MAILGUN_DOMAIN) ? MAILGUN_DOMAIN : $this->get_option('domain');
115
  $username = preg_replace('/@.+$/', '', $username)."@{$domain}";
116
  $secure = (defined('MAILGUN_SECURE') && MAILGUN_SECURE) ? MAILGUN_SECURE : $this->get_option('secure');
 
117
  $password = (defined('MAILGUN_PASSWORD') && MAILGUN_PASSWORD) ? MAILGUN_PASSWORD : $this->get_option('password');
118
 
119
  $phpmailer->Mailer = 'smtp';
@@ -123,7 +124,7 @@ class Mailgun
123
  $phpmailer->Username = $username;
124
  $phpmailer->Password = $password;
125
 
126
- $phpmailer->SMTPSecure = (bool) $secure ? 'tls' : 'none';
127
  // Without this line... wp_mail for SMTP-only will always return false. But why? :(
128
  $phpmailer->Debugoutput = 'mg_smtp_debug_output';
129
  $phpmailer->SMTPDebug = 2;
4
  * Plugin Name: Mailgun
5
  * Plugin URI: http://wordpress.org/extend/plugins/mailgun/
6
  * Description: Mailgun integration for WordPress
7
+ * Version: 1.5.11
8
  * Author: Mailgun
9
  * Author URI: http://www.mailgun.com/
10
  * License: GPLv2 or later
114
  $domain = (defined('MAILGUN_DOMAIN') && MAILGUN_DOMAIN) ? MAILGUN_DOMAIN : $this->get_option('domain');
115
  $username = preg_replace('/@.+$/', '', $username)."@{$domain}";
116
  $secure = (defined('MAILGUN_SECURE') && MAILGUN_SECURE) ? MAILGUN_SECURE : $this->get_option('secure');
117
+ $sectype = (defined('MAILGUN_SECTYPE') && MAILGUN_SECTYPE) ? MAILGUN_SECTYPE : $this->get_option('sectype');
118
  $password = (defined('MAILGUN_PASSWORD') && MAILGUN_PASSWORD) ? MAILGUN_PASSWORD : $this->get_option('password');
119
 
120
  $phpmailer->Mailer = 'smtp';
124
  $phpmailer->Username = $username;
125
  $phpmailer->Password = $password;
126
 
127
+ $phpmailer->SMTPSecure = (bool) $secure ? $sectype : 'none';
128
  // Without this line... wp_mail for SMTP-only will always return false. But why? :(
129
  $phpmailer->Debugoutput = 'mg_smtp_debug_output';
130
  $phpmailer->SMTPDebug = 2;
readme.txt CHANGED
@@ -4,8 +4,8 @@ Mailgun for WordPress
4
  Contributors: Mailgun, sivel, lookahead.io, m35dev
5
  Tags: mailgun, smtp, http, api, mail, email
6
  Requires at least: 3.3
7
- Tested up to: 4.8
8
- Stable tag: 1.5.8.5
9
  License: GPLv2 or later
10
 
11
 
@@ -59,6 +59,7 @@ MAILGUN_DOMAIN Type: string
59
  MAILGUN_USERNAME Type: string
60
  MAILGUN_PASSWORD Type: string
61
  MAILGUN_SECURE Type: boolean
 
62
  MAILGUN_FROM_NAME Type: string
63
  MAILGUN_FROM_ADDRESS Type: string
64
  `
@@ -126,6 +127,17 @@ MAILGUN_FROM_ADDRESS Type: string
126
 
127
  == Changelog ==
128
 
 
 
 
 
 
 
 
 
 
 
 
129
  = 1.5.8.5 (2017-09-05): =
130
  - Change default click tracking setting to `htmlonly` (https://github.com/mailgun/wordpress-plugin/pull/58)
131
  - Change PHPMailer set-up stanza to use TLS
4
  Contributors: Mailgun, sivel, lookahead.io, m35dev
5
  Tags: mailgun, smtp, http, api, mail, email
6
  Requires at least: 3.3
7
+ Tested up to: 4.9.6
8
+ Stable tag: 1.5.11
9
  License: GPLv2 or later
10
 
11
 
59
  MAILGUN_USERNAME Type: string
60
  MAILGUN_PASSWORD Type: string
61
  MAILGUN_SECURE Type: boolean
62
+ MAILGUN_SECTYPE Type: string Choices: 'ssl' or 'tls'
63
  MAILGUN_FROM_NAME Type: string
64
  MAILGUN_FROM_ADDRESS Type: string
65
  `
127
 
128
  == Changelog ==
129
 
130
+ = 1.5.11 (2018-05-30): =
131
+ - Fix an issue with authentication failing for newer API keys
132
+ - Test plugin up to Wordpress 4.9.6
133
+
134
+ = 1.5.10 (2017-11-22): =
135
+ - Fix back to settings link on lists page (https://github.com/mailgun/wordpress-plugin/pull/65)
136
+ - Fix a bug causing `text/html` emails to send as both `text/plain` *and* `text/html` parts
137
+
138
+ = 1.5.9 (2017-09-13): =
139
+ - Add a configuration option to allow setting security type for SMTP connection (SSL / TLS)
140
+
141
  = 1.5.8.5 (2017-09-05): =
142
  - Change default click tracking setting to `htmlonly` (https://github.com/mailgun/wordpress-plugin/pull/58)
143
  - Change PHPMailer set-up stanza to use TLS