Post SMTP Mailer/Email Log - Version 2.0.13

Version Description

  • 2020-08-11
  • Fixed: WordPress 5.5 compatibility
  • Fixed: Email log filtering
  • Fixed: Pushover notifications
  • New: Suggest solution for email delivery errors
Download this release

Release Info

Developer yehudah
Plugin Icon 128x128 Post SMTP Mailer/Email Log
Version 2.0.13
Comparing to
See all releases

Code changes from version 2.0.12 to 2.0.13

Postman/Extensions/Admin/PostmanAdminView.php CHANGED
@@ -75,6 +75,10 @@
75
  <button type="submit" name="post_smtp_extension[<?php echo $short_name; ?>_activate]" class="button button-primary">Activate</button>
76
  <?php endif; ?>
77
 
 
 
 
 
78
  <button type="submit" name="post_smtp_extension[<?php echo $short_name; ?>_deactivate]" class="button button-secondary">Deactivate</button>
79
  </div>
80
  </div>
75
  <button type="submit" name="post_smtp_extension[<?php echo $short_name; ?>_activate]" class="button button-primary">Activate</button>
76
  <?php endif; ?>
77
 
78
+ <?php if ( $license_data->license === 'expired' ) : ?>
79
+ <a href="<?php echo $license_data->renew_url; ?>" target="_blank" class="button button-primary">Renew License</a>
80
+ <?php endif; ?>
81
+
82
  <button type="submit" name="post_smtp_extension[<?php echo $short_name; ?>_deactivate]" class="button button-secondary">Deactivate</button>
83
  </div>
84
  </div>
Postman/Extensions/Core/Notifications/PostmanPushoverNotify.php CHANGED
@@ -6,7 +6,7 @@ class PostmanPushoverNotify implements Postman_Notify {
6
 
7
  public function send_message($message)
8
  {
9
- $options = PostmanOptions::getInstance();
10
 
11
  $api_url = "https://api.pushover.net/1/messages.json";
12
  $app_token = $options->getPushoverToken();
6
 
7
  public function send_message($message)
8
  {
9
+ $options = PostmanNotifyOptions::getInstance();
10
 
11
  $api_url = "https://api.pushover.net/1/messages.json";
12
  $app_token = $options->getPushoverToken();
Postman/Extensions/Core/Notifications/PostmanSlackNotify.php CHANGED
@@ -37,4 +37,4 @@ class PostmanSlackNotify implements Postman_Notify {
37
  error_log( __CLASS__ . ': ' . $message );
38
  }
39
  }
40
- }
37
  error_log( __CLASS__ . ': ' . $message );
38
  }
39
  }
40
+ }
Postman/Extensions/Core/StatusSolution.php ADDED
@@ -0,0 +1,56 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ class StatusSolution {
4
+
5
+ private $status;
6
+
7
+ public function __construct() {
8
+ add_filter( 'post_smtp_log_solution', array( $this, 'find_solution' ), 10, 4 );
9
+ }
10
+
11
+ public function find_solution( $solution, $status, $log, $message ) {
12
+
13
+ if ( empty( $status ) ) {
14
+ return 'All good, mail sent.';
15
+ }
16
+
17
+ $this->status = addslashes( $status );
18
+ $possible_solution = [];
19
+
20
+ if ( $this->strExists('timed out') ) {
21
+ $possible_solution[] = $this->make_clickable('https://postmansmtp.com/office365-smtp-connection-timed-out/');
22
+ } elseif ( $this->strExists('timeout') || $this->strExists('open socket' ) ) {
23
+ $possible_solution[] = 'Your hosting is blocking the connection, contact their support';
24
+ } elseif ( $this->strExists( 'DATA NOT ACCEPTED' ) || $this->strExists('Exception:SendAsDeniedException' ) ) {
25
+ $possible_solution[] = $this->make_clickable('https://postmansmtp.com/storedrv-submission-exceptionsendasdeniedexception-mapiexceptionsendasdenied/');
26
+ } elseif ( $this->strExists( 'Incorrect authentication data') ) {
27
+ $possible_solution[] = $this->make_clickable( 'https://postmansmtp.com/incorrect-authentication-data/' );
28
+ } elseif ( $this->strExists( 'Unrecognized authentication type' ) ) {
29
+ $possible_solution[] = 'Change "Authentication" type on plugin settings to "Login"';
30
+ } elseif ( $this->strExists( 'Error executing "SendRawEmail"' ) ) {
31
+ $possible_solution[] = 'Amazon SES - account permission error (review account configuration)';
32
+ } elseif ( $this->strExists( 'Please log in via your web browser and then try again' ) ) {
33
+ $possible_solution[] = $this->make_clickable( 'https://postmansmtp.com/gmail-gsuite-please-log-in-via-your-web-browser-and-then-try-again/' );
34
+ } elseif ( $this->strExists( 'Application-specific password required' ) ) {
35
+ $possible_solution[] = 'Two factor authentication is enabled, replace your password with app password.';
36
+ $possible_solution[] = $this->make_clickable( 'https://support.google.com/mail/?p=InvalidSecondFactor' );
37
+ } elseif ( $this->strExists( 'Username and Password not accepted' ) || $this->strExists( 'Authentication unsuccessful' ) ) {
38
+ $possible_solution[] = 'Check you credentials, wrong email or password.';
39
+ } else {
40
+ $possible_solution[] = 'Not found, check status column for more info.';
41
+ }
42
+
43
+ return ! empty( $possible_solution ) ? implode( '<br>', $possible_solution ) : '';
44
+ }
45
+
46
+ private function make_clickable($url) {
47
+ return '<a target="_blank" href="' . esc_url($url ) . '">' . esc_html( 'Read here' ) . '</a>';
48
+ }
49
+
50
+ private function strExists( $value ) {
51
+ return strpos( strtolower( $this->status ), strtolower( addslashes( $value ) ) ) !== false;
52
+ }
53
+
54
+ }
55
+
56
+ new StatusSolution();
Postman/Extensions/License/PostmanLicenseHandler.php CHANGED
@@ -7,6 +7,9 @@ if ( ! class_exists( 'PostmanLicenseHandler' ) ) :
7
 
8
 
9
  class PostmanLicenseHandler {
 
 
 
10
  private $file;
11
  private $license;
12
  private $license_data;
@@ -81,7 +84,6 @@ class PostmanLicenseHandler {
81
 
82
  add_action( 'init', array( $this, 'cron' ), 20 );
83
 
84
- // Check that license is valid once per week
85
  add_action( 'admin_init', array( $this, 'validate_license' ) );
86
 
87
  // Updater
@@ -241,9 +243,9 @@ class PostmanLicenseHandler {
241
  set_site_transient( 'update_plugins', null );
242
 
243
  // Decode license data
244
- $license_data = json_decode( wp_remote_retrieve_body( $response ) );
245
 
246
- update_option( $this->item_shortname . '_license_active', $license_data );
247
  update_option( $this->item_shortname . '_license_key', $license );
248
 
249
  $slug = plugin_basename($this->file);
@@ -307,7 +309,7 @@ class PostmanLicenseHandler {
307
  }
308
 
309
  // Decode the license data
310
- $license_data = json_decode( wp_remote_retrieve_body( $response ) );
311
 
312
  delete_option( $this->item_shortname . '_license_active' );
313
  delete_option( $this->item_shortname . '_license_key' );
@@ -323,6 +325,39 @@ class PostmanLicenseHandler {
323
 
324
  set_transient( $this->item_shortname . '_cron', true, rand( 12, 48 ) * HOUR_IN_SECONDS );
325
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
326
  }
327
 
328
 
@@ -357,10 +392,18 @@ class PostmanLicenseHandler {
357
  return false;
358
  }
359
 
360
- $license_data = json_decode( wp_remote_retrieve_body( $response ) );
 
 
 
 
361
 
362
- update_option( $this->item_shortname . '_license_active', $license_data );
 
 
363
 
 
 
364
  }
365
 
366
 
7
 
8
 
9
  class PostmanLicenseHandler {
10
+
11
+ const DAYS_TO_ALERT = array( 30, 14, 7, 1);
12
+
13
  private $file;
14
  private $license;
15
  private $license_data;
84
 
85
  add_action( 'init', array( $this, 'cron' ), 20 );
86
 
 
87
  add_action( 'admin_init', array( $this, 'validate_license' ) );
88
 
89
  // Updater
243
  set_site_transient( 'update_plugins', null );
244
 
245
  // Decode license data
246
+ $this->license_data = json_decode( wp_remote_retrieve_body( $response ) );
247
 
248
+ update_option( $this->item_shortname . '_license_active', $this->license_data );
249
  update_option( $this->item_shortname . '_license_key', $license );
250
 
251
  $slug = plugin_basename($this->file);
309
  }
310
 
311
  // Decode the license data
312
+ $this->license_data = json_decode( wp_remote_retrieve_body( $response ) );
313
 
314
  delete_option( $this->item_shortname . '_license_active' );
315
  delete_option( $this->item_shortname . '_license_key' );
325
 
326
  set_transient( $this->item_shortname . '_cron', true, rand( 12, 48 ) * HOUR_IN_SECONDS );
327
  }
328
+
329
+ $license_data = $this->license_data;
330
+
331
+ $datetime1 = new DateTime();
332
+ $datetime2 = new DateTime( $license_data->expires );
333
+
334
+ foreach ( self::DAYS_TO_ALERT as $day_to_alert ) {
335
+
336
+ $interval = $datetime1->diff($datetime2);
337
+ if( $interval->days == $day_to_alert ){
338
+ add_action( 'admin_notices', function () use ( $day_to_alert, $license_data ) {
339
+ echo $this->item_name . ' is about to expire in ' . $day_to_alert . ' days: ' . $license_data->expires;
340
+ });
341
+
342
+ return;
343
+ }
344
+
345
+ if ( $interval->days == 0 ) {
346
+ add_action( 'admin_notices', function () use ( $license_data ) {
347
+ echo $this->item_name . ' license expire today at: ' . $license_data->expires;
348
+ });
349
+
350
+ return;
351
+ }
352
+ }
353
+
354
+ if ( $license_data->activations_left == 0 ) {
355
+ add_action( 'admin_notices', function () use ( $license_data ) {
356
+ echo $this->item_name . ' has no activations';
357
+ });
358
+
359
+ return;
360
+ }
361
  }
362
 
363
 
392
  return false;
393
  }
394
 
395
+ if ( wp_remote_retrieve_response_code( $response ) !== 200 ) {
396
+ return false;
397
+ }
398
+
399
+ $this->license_data = json_decode( wp_remote_retrieve_body( $response ) );
400
 
401
+ update_option( $this->item_shortname . '_license_active', $this->license_data );
402
+
403
+ }
404
 
405
+ private function get_license_data() {
406
+ return get_option( $this->item_shortname . '_license_active' );
407
  }
408
 
409
 
Postman/Extensions/License/PostmanLicenseManager.php CHANGED
@@ -3,7 +3,7 @@ if ( ! defined( 'ABSPATH' ) ) exit;
3
 
4
  class PostmanLicenseManager {
5
 
6
- const ENDPOINT = 'https://postmansmtp.com';
7
 
8
  const CORE_EXTENSIONS = [ 'gmail_api', 'sendgrid_api', 'mandrill_api', 'mailgun_api' ];
9
 
@@ -68,11 +68,9 @@ class PostmanLicenseManager {
68
  $this->extensions[$slug]['plugin_dir_and_filename'] = $plugin_dir_and_filename;
69
  $this->extensions[$slug]['license_manager'] = new PostmanLicenseHandler(
70
  $plugin_path, $plugin_data['Name'],
71
- $plugin_data['Version'], $plugin_data['Author']
72
  );
73
  if ( $this->extensions[$slug]['license_manager']->is_licensed() ) {
74
- include_once $plugin_path;
75
-
76
  $this->extensions[$slug]['instance'] = new $class;
77
  }
78
  }
3
 
4
  class PostmanLicenseManager {
5
 
6
+ const ENDPOINT = 'https://postmansmtpcom-staging.dxpsites.net';
7
 
8
  const CORE_EXTENSIONS = [ 'gmail_api', 'sendgrid_api', 'mandrill_api', 'mailgun_api' ];
9
 
68
  $this->extensions[$slug]['plugin_dir_and_filename'] = $plugin_dir_and_filename;
69
  $this->extensions[$slug]['license_manager'] = new PostmanLicenseHandler(
70
  $plugin_path, $plugin_data['Name'],
71
+ $plugin_data['Version'], $plugin_data['Author'], null, self::ENDPOINT
72
  );
73
  if ( $this->extensions[$slug]['license_manager']->is_licensed() ) {
 
 
74
  $this->extensions[$slug]['instance'] = new $class;
75
  }
76
  }
Postman/Phpmailer/PostsmtpMailer-old.php ADDED
@@ -0,0 +1,159 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ if ( ! defined( 'ABSPATH' ) ) {
3
+ exit; // Exit if accessed directly
4
+ }
5
+
6
+ if ( ! class_exists( 'PHPMailer', false ) ) {
7
+ require_once ABSPATH . WPINC . '/PHPMailer/PHPMailer.php';
8
+ require_once ABSPATH . WPINC . '/PHPMailer/SMTP.php';
9
+ require_once ABSPATH . WPINC . '/PHPMailer/Exception.php';
10
+ }
11
+
12
+ use PHPMailer\PHPMailer\PHPMailer;
13
+ use PHPMailer\PHPMailer\Exception;
14
+
15
+ add_action('plugins_loaded', function() {
16
+ global $phpmailer;
17
+
18
+ $phpmailer = new PostsmtpMailer(true);
19
+ });
20
+
21
+ class PostsmtpMailer extends PHPMailer {
22
+
23
+ private $mail_args = array();
24
+
25
+ private $options;
26
+
27
+ private $error;
28
+
29
+ private $transcript = '';
30
+
31
+ public function __construct($exceptions = null)
32
+ {
33
+ parent::__construct($exceptions);
34
+
35
+ $this->set_vars();
36
+ $this->hooks();
37
+
38
+ }
39
+
40
+ public function set_vars() {
41
+ $this->options = PostmanOptions::getInstance();
42
+ $this->Debugoutput = function($str, $level) {
43
+ $this->transcript .= $str;
44
+ };
45
+ }
46
+
47
+ public function hooks() {
48
+ add_filter( 'wp_mail', array( $this, 'get_mail_args' ) );
49
+ if ( $this->options->getTransportType() == 'smtp' ) {
50
+ add_action( 'phpmailer_init', array( $this, 'phpmailer_smtp_init' ), 999 );
51
+ }
52
+ }
53
+
54
+ public function get_mail_args( $atts ) {
55
+ $this->mail_args = array();
56
+ $this->mail_args[] = $atts['to'];
57
+ $this->mail_args[] = $atts['subject'];
58
+ $this->mail_args[] = $atts['message'];
59
+ $this->mail_args[] = $atts['headers'];
60
+ $this->mail_args[] = $atts['attachments'];
61
+
62
+ return $atts;
63
+ }
64
+
65
+ /**
66
+ * @param PHPMailer $mail
67
+ */
68
+ public function phpmailer_smtp_init($mail) {
69
+ $mail->SMTPDebug = 3;
70
+ $mail->isSMTP();
71
+ $mail->Host = $this->options->getHostname();
72
+
73
+ if ( $this->options->getAuthenticationType() !== 'none' ) {
74
+ $mail->SMTPAuth = true;
75
+ $mail->Username = $this->options->getUsername();
76
+ $mail->Password = $this->options->getPassword();
77
+ }
78
+
79
+ if ( $this->options->getEncryptionType() !== 'none' ) {
80
+ $mail->SMTPSecure = $this->options->getEncryptionType();
81
+ }
82
+
83
+ $mail->Port = $this->options->getPort();
84
+
85
+ if ( $this->options->isPluginSenderEmailEnforced() ) {
86
+ $mail->setFrom( $this->options->getMessageSenderEmail() , $this->options->getMessageSenderName () );
87
+ }
88
+ }
89
+
90
+ public function send()
91
+ {
92
+ require_once dirname(__DIR__) . '/PostmanWpMail.php';
93
+
94
+ // create a PostmanWpMail instance
95
+ $postmanWpMail = new PostmanWpMail();
96
+ $postmanWpMail->init();
97
+
98
+ list($to, $subject, $body, $headers, $attachments) = array_pad( $this->mail_args, 5, null );
99
+
100
+ // build the message
101
+ $postmanMessage = $postmanWpMail->processWpMailCall( $to, $subject, $body, $headers, $attachments );
102
+
103
+ // build the email log entry
104
+ $log = new PostmanEmailLog();
105
+ $log->originalTo = $to;
106
+ $log->originalSubject = $subject;
107
+ $log->originalMessage = $body;
108
+ $log->originalHeaders = $headers;
109
+
110
+ // get the transport and create the transportConfig and engine
111
+ $transport = PostmanTransportRegistry::getInstance()->getActiveTransport();
112
+
113
+ add_filter( 'postman_wp_mail_result', [ $this, 'postman_wp_mail_result' ] );
114
+
115
+ try {
116
+
117
+ if ( $send_email = apply_filters( 'post_smtp_do_send_email', true ) ) {
118
+ $result = $this->options->getTransportType() !== 'smtp' ?
119
+ $postmanWpMail->send( $to, $subject, $body, $headers, $attachments ) :
120
+ $this->sendSmtp();
121
+ }
122
+
123
+
124
+ do_action( 'post_smtp_on_success', $log, $postmanMessage, $this->transcript, $transport );
125
+
126
+ return $result;
127
+
128
+ } catch (Exception $exc) {
129
+
130
+ $this->error = $exc;
131
+
132
+ $this->mailHeader = '';
133
+
134
+ $this->setError($exc->getMessage());
135
+ if ($this->exceptions) {
136
+ throw $exc;
137
+ }
138
+ return false;
139
+ }
140
+
141
+ }
142
+
143
+ public function sendSmtp() {
144
+ if (!$this->preSend()) {
145
+ return false;
146
+ }
147
+ return $this->postSend();
148
+ }
149
+
150
+
151
+ public function postman_wp_mail_result() {
152
+ $result = [
153
+ 'time' => '',
154
+ 'exception' => $this->error,
155
+ 'transcript' => $this->transcript,
156
+ ];
157
+ return $result;
158
+ }
159
+ }
Postman/Phpmailer/PostsmtpMailer.php CHANGED
@@ -1,154 +1,154 @@
1
  <?php
2
  if ( ! defined( 'ABSPATH' ) ) {
3
- exit; // Exit if accessed directly
4
  }
5
 
6
  if ( ! class_exists( 'PHPMailer', false ) ) {
7
- require_once ABSPATH . WPINC . '/class-phpmailer.php';
8
  }
9
 
10
  add_action('plugins_loaded', function() {
11
- global $phpmailer;
12
 
13
- $phpmailer = new PostsmtpMailer(true);
14
  });
15
 
16
  class PostsmtpMailer extends PHPMailer {
17
 
18
- private $mail_args = array();
19
 
20
- private $options;
21
 
22
- private $error;
23
 
24
- private $transcript = '';
25
 
26
- public function __construct($exceptions = null)
27
- {
28
- parent::__construct($exceptions);
29
 
30
- $this->set_vars();
31
- $this->hooks();
32
 
33
- }
34
 
35
- public function set_vars() {
36
- $this->options = PostmanOptions::getInstance();
37
- $this->Debugoutput = function($str, $level) {
38
- $this->transcript .= $str;
39
- };
40
- }
41
 
42
- public function hooks() {
43
- add_filter( 'wp_mail', array( $this, 'get_mail_args' ) );
44
- if ( $this->options->getTransportType() == 'smtp' ) {
45
- add_action( 'phpmailer_init', array( $this, 'phpmailer_smtp_init' ), 999 );
46
- }
47
- }
48
 
49
- public function get_mail_args( $atts ) {
50
- $this->mail_args = array();
51
- $this->mail_args[] = $atts['to'];
52
- $this->mail_args[] = $atts['subject'];
53
- $this->mail_args[] = $atts['message'];
54
- $this->mail_args[] = $atts['headers'];
55
- $this->mail_args[] = $atts['attachments'];
56
 
57
- return $atts;
58
- }
59
 
60
- /**
61
- * @param PHPMailer $mail
62
- */
63
- public function phpmailer_smtp_init($mail) {
64
- $mail->SMTPDebug = 3;
65
- $mail->isSMTP();
66
- $mail->Host = $this->options->getHostname();
67
 
68
- if ( $this->options->getAuthenticationType() !== 'none' ) {
69
- $mail->SMTPAuth = true;
70
- $mail->Username = $this->options->getUsername();
71
- $mail->Password = $this->options->getPassword();
72
- }
73
 
74
- if ( $this->options->getEncryptionType() !== 'none' ) {
75
- $mail->SMTPSecure = $this->options->getEncryptionType();
76
- }
77
 
78
- $mail->Port = $this->options->getPort();
79
 
80
- if ( $this->options->isPluginSenderEmailEnforced() ) {
81
- $mail->setFrom( $this->options->getMessageSenderEmail() , $this->options->getMessageSenderName () );
82
- }
83
- }
84
 
85
- public function send()
86
- {
87
- require_once dirname(__DIR__) . '/PostmanWpMail.php';
88
 
89
- // create a PostmanWpMail instance
90
- $postmanWpMail = new PostmanWpMail();
91
- $postmanWpMail->init();
92
 
93
- list($to, $subject, $body, $headers, $attachments) = array_pad( $this->mail_args, 5, null );
94
 
95
- // build the message
96
- $postmanMessage = $postmanWpMail->processWpMailCall( $to, $subject, $body, $headers, $attachments );
97
 
98
- // build the email log entry
99
- $log = new PostmanEmailLog();
100
- $log->originalTo = $to;
101
- $log->originalSubject = $subject;
102
- $log->originalMessage = $body;
103
- $log->originalHeaders = $headers;
104
 
105
- // get the transport and create the transportConfig and engine
106
- $transport = PostmanTransportRegistry::getInstance()->getActiveTransport();
107
 
108
- add_filter( 'postman_wp_mail_result', [ $this, 'postman_wp_mail_result' ] );
109
 
110
- try {
111
 
112
- if ( $send_email = apply_filters( 'post_smtp_do_send_email', true ) ) {
113
- $result = $this->options->getTransportType() !== 'smtp' ?
114
- $postmanWpMail->send( $to, $subject, $body, $headers, $attachments ) :
115
- $this->sendSmtp();
116
- }
117
 
118
 
119
- do_action( 'post_smtp_on_success', $log, $postmanMessage, $this->transcript, $transport );
120
 
121
- return $result;
122
 
123
- } catch (phpmailerException $exc) {
124
 
125
- $this->error = $exc;
126
-
127
- $this->mailHeader = '';
128
 
129
- $this->setError($exc->getMessage());
130
- if ($this->exceptions) {
131
- throw $exc;
132
- }
133
- return false;
134
- }
135
-
136
- }
137
-
138
- public function sendSmtp() {
139
- if (!$this->preSend()) {
140
- return false;
141
- }
142
- return $this->postSend();
143
- }
144
 
145
 
146
- public function postman_wp_mail_result() {
147
- $result = [
148
- 'time' => '',
149
- 'exception' => $this->error,
150
- 'transcript' => $this->transcript,
151
- ];
152
- return $result;
153
- }
154
  }
1
  <?php
2
  if ( ! defined( 'ABSPATH' ) ) {
3
+ exit; // Exit if accessed directly
4
  }
5
 
6
  if ( ! class_exists( 'PHPMailer', false ) ) {
7
+ require_once ABSPATH . WPINC . '/class-phpmailer.php';
8
  }
9
 
10
  add_action('plugins_loaded', function() {
11
+ global $phpmailer;
12
 
13
+ $phpmailer = new PostsmtpMailer(true);
14
  });
15
 
16
  class PostsmtpMailer extends PHPMailer {
17
 
18
+ private $mail_args = array();
19
 
20
+ private $options;
21
 
22
+ private $error;
23
 
24
+ private $transcript = '';
25
 
26
+ public function __construct($exceptions = null)
27
+ {
28
+ parent::__construct($exceptions);
29
 
30
+ $this->set_vars();
31
+ $this->hooks();
32
 
33
+ }
34
 
35
+ public function set_vars() {
36
+ $this->options = PostmanOptions::getInstance();
37
+ $this->Debugoutput = function($str, $level) {
38
+ $this->transcript .= $str;
39
+ };
40
+ }
41
 
42
+ public function hooks() {
43
+ add_filter( 'wp_mail', array( $this, 'get_mail_args' ) );
44
+ if ( $this->options->getTransportType() == 'smtp' ) {
45
+ add_action( 'phpmailer_init', array( $this, 'phpmailer_smtp_init' ), 999 );
46
+ }
47
+ }
48
 
49
+ public function get_mail_args( $atts ) {
50
+ $this->mail_args = array();
51
+ $this->mail_args[] = $atts['to'];
52
+ $this->mail_args[] = $atts['subject'];
53
+ $this->mail_args[] = $atts['message'];
54
+ $this->mail_args[] = $atts['headers'];
55
+ $this->mail_args[] = $atts['attachments'];
56
 
57
+ return $atts;
58
+ }
59
 
60
+ /**
61
+ * @param PHPMailer $mail
62
+ */
63
+ public function phpmailer_smtp_init($mail) {
64
+ $mail->SMTPDebug = 3;
65
+ $mail->isSMTP();
66
+ $mail->Host = $this->options->getHostname();
67
 
68
+ if ( $this->options->getAuthenticationType() !== 'none' ) {
69
+ $mail->SMTPAuth = true;
70
+ $mail->Username = $this->options->getUsername();
71
+ $mail->Password = $this->options->getPassword();
72
+ }
73
 
74
+ if ( $this->options->getEncryptionType() !== 'none' ) {
75
+ $mail->SMTPSecure = $this->options->getEncryptionType();
76
+ }
77
 
78
+ $mail->Port = $this->options->getPort();
79
 
80
+ if ( $this->options->isPluginSenderEmailEnforced() ) {
81
+ $mail->setFrom( $this->options->getMessageSenderEmail() , $this->options->getMessageSenderName () );
82
+ }
83
+ }
84
 
85
+ public function send()
86
+ {
87
+ require_once dirname(__DIR__) . '/PostmanWpMail.php';
88
 
89
+ // create a PostmanWpMail instance
90
+ $postmanWpMail = new PostmanWpMail();
91
+ $postmanWpMail->init();
92
 
93
+ list($to, $subject, $body, $headers, $attachments) = array_pad( $this->mail_args, 5, null );
94
 
95
+ // build the message
96
+ $postmanMessage = $postmanWpMail->processWpMailCall( $to, $subject, $body, $headers, $attachments );
97
 
98
+ // build the email log entry
99
+ $log = new PostmanEmailLog();
100
+ $log->originalTo = $to;
101
+ $log->originalSubject = $subject;
102
+ $log->originalMessage = $body;
103
+ $log->originalHeaders = $headers;
104
 
105
+ // get the transport and create the transportConfig and engine
106
+ $transport = PostmanTransportRegistry::getInstance()->getActiveTransport();
107
 
108
+ add_filter( 'postman_wp_mail_result', [ $this, 'postman_wp_mail_result' ] );
109
 
110
+ try {
111
 
112
+ if ( $send_email = apply_filters( 'post_smtp_do_send_email', true ) ) {
113
+ $result = $this->options->getTransportType() !== 'smtp' ?
114
+ $postmanWpMail->send( $to, $subject, $body, $headers, $attachments ) :
115
+ $this->sendSmtp();
116
+ }
117
 
118
 
119
+ do_action( 'post_smtp_on_success', $log, $postmanMessage, $this->transcript, $transport );
120
 
121
+ return $result;
122
 
123
+ } catch (phpmailerException $exc) {
124
 
125
+ $this->error = $exc;
126
+
127
+ $this->mailHeader = '';
128
 
129
+ $this->setError($exc->getMessage());
130
+ if ($this->exceptions) {
131
+ throw $exc;
132
+ }
133
+ return false;
134
+ }
135
+
136
+ }
137
+
138
+ public function sendSmtp() {
139
+ if (!$this->preSend()) {
140
+ return false;
141
+ }
142
+ return $this->postSend();
143
+ }
144
 
145
 
146
+ public function postman_wp_mail_result() {
147
+ $result = [
148
+ 'time' => '',
149
+ 'exception' => $this->error,
150
+ 'transcript' => $this->transcript,
151
+ ];
152
+ return $result;
153
+ }
154
  }
Postman/Postman-Configuration/PostmanRegisterConfigurationSettings.php CHANGED
@@ -271,7 +271,7 @@ class PostmanSettingsRegistry {
271
  }
272
  print '</select>';
273
  ?>
274
- <p class="description" id="mailer-type-description"><?php _e( 'Beta Feature: Change this to <strong>PHPMailer</strong> only if you see <code>wp_mail</code> conflict message, conflicts when another plugin is activated, and <strong><u>sometimes</u></strong> spam issues.', 'post-smtp' ); ?></p>
275
  <?php
276
  }
277
 
271
  }
272
  print '</select>';
273
  ?>
274
+ <p class="description" id="mailer-type-description"><?php _e( 'Beta Feature: ONLY change this to <strong>PHPMailer</strong> only if you see <code>wp_mail</code> conflict message, conflicts when another plugin is activated, and <strong><u>sometimes</u></strong> your mail marked as spam.', 'post-smtp' ); ?></p>
275
  <?php
276
  }
277
 
Postman/Postman-Connectivity-Test/PostmanConnectivityTestController.php CHANGED
@@ -170,7 +170,7 @@ class PostmanConnectivityTestController {
170
  }
171
  print '</table>';
172
  /* Translators: Where %s is the name of the service providing Internet connectivity test */
173
- printf( '<p class="portquiz" style="display:none; font-size:0.8em">* %s</p>', sprintf( __( 'According to %s', 'post-smtp' ), '<a target="_blank" href="https://downor.me/portquiz.net">portquiz.net</a>' ) );
174
  printf( '<p class="ajax-loader" style="display:none"><img src="%s"/></p>', plugins_url( 'post-smtp/style/ajax-loader.gif' ) );
175
  print '<section id="conclusion" style="display:none">';
176
  print sprintf( '<h3>%s:</h3>', __( 'Summary', 'post-smtp' ) );
170
  }
171
  print '</table>';
172
  /* Translators: Where %s is the name of the service providing Internet connectivity test */
173
+ printf( '<p class="portquiz" style="display:none; font-size:0.8em">* %s</p>', sprintf( __( 'According to %s', 'post-smtp' ), '<a target="_blank" href="http://portquiz.net">portquiz.net</a>' ) );
174
  printf( '<p class="ajax-loader" style="display:none"><img src="%s"/></p>', plugins_url( 'post-smtp/style/ajax-loader.gif' ) );
175
  print '<section id="conclusion" style="display:none">';
176
  print sprintf( '<h3>%s:</h3>', __( 'Summary', 'post-smtp' ) );
Postman/Postman-Controller/PostmanWelcomeController.php CHANGED
@@ -189,11 +189,6 @@ class PostmanWelcomeController {
189
 
190
  <h4 class="wp-people-group"><?php esc_html_e( 'Project Leaders', 'post-smtp' ); ?></h4>
191
  <ul class="wp-people-group " id="wp-people-group-project-leaders">
192
- <li class="wp-person" id="wp-person-jasonhendriks">
193
- <a href="https://profiles.wordpress.org/jasonhendriks"><img src="https://secure.gravatar.com/avatar/8692c7b6084517a592f6cad107f7bcb0?s=60&d=mm&r=g" class="gravatar" alt="Jason Hendriks " /></a>
194
- <a class="web" href="http://profiles.wordpress.org/matt">Jason Hendriks</a>
195
- <span class="title"><?php esc_html_e( 'Founding Developer (abandoned)', 'post-smtp' ); ?></span>
196
- </li>
197
  <li class="wp-person" id="wp-person-yehudah">
198
  <a href="http://profiles.wordpress.org/yehudah"><img src="https://secure.gravatar.com/avatar/c561638d04ea8fef351f974dbb9ece39?s=60&d=mm&r=g" class="gravatar" alt="Yehuda Hassine" /></a>
199
  <a class="web" href="http://profiles.wordpress.org/yehudah">Yehuda Hassine</a>
189
 
190
  <h4 class="wp-people-group"><?php esc_html_e( 'Project Leaders', 'post-smtp' ); ?></h4>
191
  <ul class="wp-people-group " id="wp-people-group-project-leaders">
 
 
 
 
 
192
  <li class="wp-person" id="wp-person-yehudah">
193
  <a href="http://profiles.wordpress.org/yehudah"><img src="https://secure.gravatar.com/avatar/c561638d04ea8fef351f974dbb9ece39?s=60&d=mm&r=g" class="gravatar" alt="Yehuda Hassine" /></a>
194
  <a class="web" href="http://profiles.wordpress.org/yehudah">Yehuda Hassine</a>
Postman/Postman-Email-Log/PostmanEmailLogController.php CHANGED
@@ -76,10 +76,10 @@ class PostmanEmailLogController {
76
  }
77
 
78
  function handleCsvExport() {
79
- if ( ! empty( $_POST ) && ! wp_verify_nonce( $_REQUEST['post-smtp-log'], 'post-smtp' ) )
80
  die( 'Security check' );
81
 
82
- if ( isset( $_POST['postman_export_csv'] ) && current_user_can( Postman::MANAGE_POSTMAN_CAPABILITY_LOGS ) ) {
83
  $args = array(
84
  'post_type' => PostmanEmailLogPostType::POSTMAN_CUSTOM_POST_TYPE_SLUG,
85
  'post_status' => PostmanEmailLogService::POSTMAN_CUSTOM_POST_STATUS_PRIVATE,
@@ -97,14 +97,20 @@ class PostmanEmailLogController {
97
  $fp = fopen('php://output', 'wb');
98
 
99
  $headers = array_keys( PostmanLogFields::get_instance()->get_fields() );
 
 
100
  fputcsv($fp, $headers);
101
 
 
 
 
102
  foreach ( $logs->posts as $log ) {
103
  $meta = PostmanLogFields::get_instance()->get($log->ID);
104
  $data = [];
105
  foreach ( $meta as $header => $line ) {
106
  $data[] = $line[0];
107
  }
 
108
  fputcsv($fp, $data);
109
  }
110
 
@@ -411,16 +417,17 @@ class PostmanEmailLogController {
411
  </div>
412
 
413
  <?php
414
- $from_date = isset( $_POST['from_date'] ) ? sanitize_text_field( $_POST['from_date'] ) : '';
415
- $to_date = isset( $_POST['to_date'] ) ? sanitize_text_field( $_POST['to_date'] ) : '';
416
- $search = isset( $_POST['search'] ) ? sanitize_text_field( $_POST['search'] ) : '';
417
  $page_records = apply_filters( 'postman_log_per_page', array( 10, 15, 25, 50, 75, 100 ) );
418
- $postman_page_records = isset( $_POST['postman_page_records'] ) ? absint( $_POST['postman_page_records'] ) : '';
419
  ?>
420
 
421
- <form id="postman-email-log-filter" method="post">
422
- <input type="hidden" action="post-smtp-filter" value="1">
423
- <?php wp_nonce_field('post-smtp', 'post-smtp-log'); ?>
 
424
 
425
  <div id="email-log-filter" class="postman-log-row">
426
  <div class="form-control">
@@ -447,13 +454,13 @@ class PostmanEmailLogController {
447
  </select>
448
  </div>
449
 
450
- <div class="form-control">
451
- <button type="submit" id="postman_export_csv" name="postman_export_csv" class="button button-primary"><?php _e( 'Export To CSV', 'post-smtp' ); ?></button>
452
  </div>
453
 
454
- <div class="form-control" style="padding: 0 5px 0 5px; margin-right: 50px;">
455
- <button type="submit" name="filter" class="button button-primary"><?php _e( 'Filter/Search', 'post-smtp' ); ?></button>
456
- </div>
457
 
458
  <div class="form-control">
459
  <button type="submit" id="postman_trash_all" name="postman_trash_all" class="button button-primary"><?php _e( 'Trash All', 'post-smtp' ); ?></button>
76
  }
77
 
78
  function handleCsvExport() {
79
+ if ( isset( $_REQUEST['post-smtp-log-nonce'] ) && ! wp_verify_nonce( $_REQUEST['post-smtp-log-nonce'], 'post-smtp' ) )
80
  die( 'Security check' );
81
 
82
+ if ( isset( $_GET['postman_export_csv'] ) && current_user_can( Postman::MANAGE_POSTMAN_CAPABILITY_LOGS ) ) {
83
  $args = array(
84
  'post_type' => PostmanEmailLogPostType::POSTMAN_CUSTOM_POST_TYPE_SLUG,
85
  'post_status' => PostmanEmailLogService::POSTMAN_CUSTOM_POST_STATUS_PRIVATE,
97
  $fp = fopen('php://output', 'wb');
98
 
99
  $headers = array_keys( PostmanLogFields::get_instance()->get_fields() );
100
+ $headers[] = 'delivery_time';
101
+
102
  fputcsv($fp, $headers);
103
 
104
+ $date_format = get_option( 'date_format' );
105
+ $time_format = get_option( 'time_format' );
106
+
107
  foreach ( $logs->posts as $log ) {
108
  $meta = PostmanLogFields::get_instance()->get($log->ID);
109
  $data = [];
110
  foreach ( $meta as $header => $line ) {
111
  $data[] = $line[0];
112
  }
113
+ $data[] = date( "$date_format $time_format", strtotime( $log->post_date ) );
114
  fputcsv($fp, $data);
115
  }
116
 
417
  </div>
418
 
419
  <?php
420
+ $from_date = isset( $_GET['from_date'] ) ? sanitize_text_field( $_GET['from_date'] ) : '';
421
+ $to_date = isset( $_GET['to_date'] ) ? sanitize_text_field( $_GET['to_date'] ) : '';
422
+ $search = isset( $_GET['search'] ) ? sanitize_text_field( $_GET['search'] ) : '';
423
  $page_records = apply_filters( 'postman_log_per_page', array( 10, 15, 25, 50, 75, 100 ) );
424
+ $postman_page_records = isset( $_GET['postman_page_records'] ) ? absint( $_GET['postman_page_records'] ) : '';
425
  ?>
426
 
427
+ <form id="postman-email-log-filter" action="<?php echo admin_url( PostmanUtils::POSTMAN_EMAIL_LOG_PAGE_RELATIVE_URL ); ?>" method="get">
428
+ <input type="hidden" name="page" value="postman_email_log">
429
+ <input type="hidden" name="post-smtp-filter" value="1">
430
+ <?php wp_nonce_field('post-smtp', 'post-smtp-log-nonce'); ?>
431
 
432
  <div id="email-log-filter" class="postman-log-row">
433
  <div class="form-control">
454
  </select>
455
  </div>
456
 
457
+ <div class="form-control" style="padding: 0 5px 0 5px;">
458
+ <button type="submit" name="filter" class="button button-primary"><?php _e( 'Filter/Search', 'post-smtp' ); ?></button>
459
  </div>
460
 
461
+ <div class="form-control" style="padding: 0 5px 0 0px;">
462
+ <button type="submit" id="postman_export_csv" name="postman_export_csv" class="button button-primary"><?php _e( 'Export To CSV', 'post-smtp' ); ?></button>
463
+ </div>
464
 
465
  <div class="form-control">
466
  <button type="submit" id="postman_trash_all" name="postman_trash_all" class="button button-primary"><?php _e( 'Trash All', 'post-smtp' ); ?></button>
Postman/Postman-Email-Log/PostmanEmailLogService.php CHANGED
@@ -5,6 +5,7 @@ if ( ! defined( 'ABSPATH' ) ) {
5
 
6
  require_once dirname(__DIR__ ) . '/PostmanLogFields.php';
7
  require_once POST_SMTP_PATH . '/Postman/Extensions/Core/Notifications/PostmanNotify.php';
 
8
 
9
  if ( ! class_exists( 'PostmanEmailLog' ) ) {
10
  class PostmanEmailLog {
@@ -175,7 +176,10 @@ if ( ! class_exists( 'PostmanEmailLogService' ) ) {
175
  $this->logger->debug( sprintf( 'Saved message #%s to the database', $post_id ) );
176
  $this->logger->trace( $log );
177
 
 
 
178
  // Write the meta data related to the email
 
179
  PostmanLogFields::get_instance()->update( $post_id, 'success', $log->success );
180
  PostmanLogFields::get_instance()->update( $post_id, 'from_header', $log->sender );
181
  if ( ! empty( $log->toRecipients ) ) {
5
 
6
  require_once dirname(__DIR__ ) . '/PostmanLogFields.php';
7
  require_once POST_SMTP_PATH . '/Postman/Extensions/Core/Notifications/PostmanNotify.php';
8
+ require_once POST_SMTP_PATH . '/Postman/Extensions/Core/StatusSolution.php';
9
 
10
  if ( ! class_exists( 'PostmanEmailLog' ) ) {
11
  class PostmanEmailLog {
176
  $this->logger->debug( sprintf( 'Saved message #%s to the database', $post_id ) );
177
  $this->logger->trace( $log );
178
 
179
+ $solution = apply_filters( 'post_smtp_log_solution', null, $new_status, $log, $message );
180
+
181
  // Write the meta data related to the email
182
+ PostmanLogFields::get_instance()->update( $post_id, 'solution', $solution );
183
  PostmanLogFields::get_instance()->update( $post_id, 'success', $log->success );
184
  PostmanLogFields::get_instance()->update( $post_id, 'from_header', $log->sender );
185
  if ( ! empty( $log->toRecipients ) ) {
Postman/Postman-Email-Log/PostmanEmailLogView.php CHANGED
@@ -60,6 +60,7 @@ class PostmanEmailLogView extends WP_List_Table {
60
  function column_default( $item, $column_name ) {
61
  switch ( $column_name ) {
62
  case 'sent_to' :
 
63
  case 'date' :
64
  case 'status' :
65
  return $item [ $column_name ];
@@ -167,6 +168,7 @@ class PostmanEmailLogView extends WP_List_Table {
167
  'title' => _x( 'Subject', 'What is the subject of this message?', 'post-smtp' ),
168
  'sent_to' => __( 'Sent To', 'post-smtp' ),
169
  'status' => __( 'Status', 'post-smtp' ),
 
170
  'date' => _x( 'Delivery Time', 'When was this email sent?', 'post-smtp' ),
171
  );
172
  return $columns;
@@ -263,13 +265,13 @@ class PostmanEmailLogView extends WP_List_Table {
263
  * ************************************************************************
264
  */
265
  function prepare_items() {
266
- if ( ! empty( $_POST ) && ! wp_verify_nonce( $_REQUEST['post-smtp-log'], 'post-smtp' ) )
267
  die( 'Security check' );
268
 
269
  /**
270
  * First, lets decide how many records per page to show
271
  */
272
- $per_page = isset( $_POST['postman_page_records'] ) ? absint( $_POST['postman_page_records'] ) : 10;
273
 
274
  /**
275
  * REQUIRED.
@@ -324,36 +326,36 @@ class PostmanEmailLogView extends WP_List_Table {
324
  'suppress_filters' => true,
325
  );
326
 
327
- if ( isset( $_POST['from_date'] ) && ! empty( $_POST['from_date'] ) ) {
328
- $from_date = sanitize_text_field( $_POST['from_date'] );
329
 
330
  $args['date_query']['after'] = $from_date;
331
  $args['date_query']['column'] = 'post_date';
332
  $args['date_query']['inclusive'] = false;
333
  }
334
 
335
- if ( isset( $_POST['to_date'] ) && ! empty( $_POST['to_date'] ) ) {
336
- $to_date = sanitize_text_field( $_POST['to_date'] );
337
 
338
  $args['date_query']['before'] = $to_date;
339
  $args['date_query']['column'] = 'post_date';
340
  $args['date_query']['inclusive'] = true;
341
  }
342
 
343
- if ( ! empty( $_POST['search'] ) ) {
344
 
345
  if ( isset( $args['date_query'] ) ) {
346
  unset( $args['date_query'] ); }
347
 
348
- $args['s'] = sanitize_text_field( $_POST['search'] );
349
  }
350
 
351
- if ( isset( $_POST['postman_trash_all'] ) ) {
352
  $args['posts_per_page'] = -1;
353
  }
354
  $posts = new WP_query( $args );
355
 
356
- if ( isset( $_POST['postman_trash_all'] ) ) {
357
  foreach ( $posts->posts as $post ) {
358
  wp_delete_post( $post->ID, true );
359
  }
@@ -374,10 +376,19 @@ class PostmanEmailLogView extends WP_List_Table {
374
  }
375
  $meta_values = PostmanLogFields::get_instance()->get( $post->ID );
376
  $sent_to = array_map( 'esc_html', explode( ',' , $meta_values ['to_header'] [0] ) );
 
 
 
 
 
 
 
 
377
  $flattenedPost = array(
378
  // the post title must be escaped as they are displayed in the HTML output
379
  'sent_to' => implode( ', ', $sent_to ),
380
  'title' => esc_html( $post->post_title ),
 
381
  // the post status must be escaped as they are displayed in the HTML output
382
  'status' => ($post->post_excerpt != null ? esc_html( $post->post_excerpt ) : __( 'Sent', 'post-smtp' )),
383
  'date' => date( "$date_format $time_format", strtotime( $post->post_date ) ),
60
  function column_default( $item, $column_name ) {
61
  switch ( $column_name ) {
62
  case 'sent_to' :
63
+ case 'solution' :
64
  case 'date' :
65
  case 'status' :
66
  return $item [ $column_name ];
168
  'title' => _x( 'Subject', 'What is the subject of this message?', 'post-smtp' ),
169
  'sent_to' => __( 'Sent To', 'post-smtp' ),
170
  'status' => __( 'Status', 'post-smtp' ),
171
+ 'solution' => __( 'Solution', 'post-smtp' ),
172
  'date' => _x( 'Delivery Time', 'When was this email sent?', 'post-smtp' ),
173
  );
174
  return $columns;
265
  * ************************************************************************
266
  */
267
  function prepare_items() {
268
+ if ( isset( $_REQUEST['post-smtp-log-nonce'] ) && ! wp_verify_nonce( $_REQUEST['post-smtp-log-nonce'], 'post-smtp' ) )
269
  die( 'Security check' );
270
 
271
  /**
272
  * First, lets decide how many records per page to show
273
  */
274
+ $per_page = isset( $_GET['postman_page_records'] ) ? absint( $_GET['postman_page_records'] ) : 10;
275
 
276
  /**
277
  * REQUIRED.
326
  'suppress_filters' => true,
327
  );
328
 
329
+ if ( isset( $_GET['from_date'] ) && ! empty( $_GET['from_date'] ) ) {
330
+ $from_date = sanitize_text_field( $_GET['from_date'] );
331
 
332
  $args['date_query']['after'] = $from_date;
333
  $args['date_query']['column'] = 'post_date';
334
  $args['date_query']['inclusive'] = false;
335
  }
336
 
337
+ if ( isset( $_GET['to_date'] ) && ! empty( $_GET['to_date'] ) ) {
338
+ $to_date = sanitize_text_field( $_GET['to_date'] );
339
 
340
  $args['date_query']['before'] = $to_date;
341
  $args['date_query']['column'] = 'post_date';
342
  $args['date_query']['inclusive'] = true;
343
  }
344
 
345
+ if ( ! empty( $_GET['search'] ) ) {
346
 
347
  if ( isset( $args['date_query'] ) ) {
348
  unset( $args['date_query'] ); }
349
 
350
+ $args['s'] = sanitize_text_field( $_GET['search'] );
351
  }
352
 
353
+ if ( isset( $_GET['postman_trash_all'] ) ) {
354
  $args['posts_per_page'] = -1;
355
  }
356
  $posts = new WP_query( $args );
357
 
358
+ if ( isset( $_GET['postman_trash_all'] ) && current_user_can(Postman::MANAGE_POSTMAN_CAPABILITY_LOGS ) ) {
359
  foreach ( $posts->posts as $post ) {
360
  wp_delete_post( $post->ID, true );
361
  }
376
  }
377
  $meta_values = PostmanLogFields::get_instance()->get( $post->ID );
378
  $sent_to = array_map( 'esc_html', explode( ',' , $meta_values ['to_header'] [0] ) );
379
+ $solution_meta = $meta_values ['solution'] [0];
380
+
381
+ if ( empty( $solution_meta ) && empty( $post->post_excerpt ) ) {
382
+ $solution = 'No need - Mail sent';
383
+ } else {
384
+ $solution = $solution_meta;
385
+ }
386
+
387
  $flattenedPost = array(
388
  // the post title must be escaped as they are displayed in the HTML output
389
  'sent_to' => implode( ', ', $sent_to ),
390
  'title' => esc_html( $post->post_title ),
391
+ 'solution' => $solution,
392
  // the post status must be escaped as they are displayed in the HTML output
393
  'status' => ($post->post_excerpt != null ? esc_html( $post->post_excerpt ) : __( 'Sent', 'post-smtp' )),
394
  'date' => date( "$date_format $time_format", strtotime( $post->post_date ) ),
Postman/Postman-Mail/PostmanSmtpModuleTransport.php CHANGED
@@ -543,7 +543,7 @@ class PostmanSmtpModuleTransport extends PostmanAbstractZendModuleTransport impl
543
  printf( '<p>%s</p>', __( 'This is the Outgoing (SMTP) Mail Server, or Mail Submission Agent (MSA), which Postman delegates mail delivery to. This server is specific to your email account, and if you don\'t know what to use, ask your email service provider.', 'post-smtp' ) );
544
  printf( '<p>%s</p>', __( 'Note that many WordPress hosts, such as GoDaddy, Bluehost and Dreamhost, require that you use their mail accounts with their mail servers, and prevent you from using others.', 'post-smtp' ) );
545
 
546
- printf( '<div><strong><u>%s</u></strong></div><br>', __( 'If you plan to use An API and not SMTP just type any value.', 'post-smtp' ) );
547
  printf( '<label for="hostname">%s</label>', __( 'Outgoing Mail Server Hostname', 'post-smtp' ) );
548
  print $this->hostname_callback();
549
  printf( '<p class="ajax-loader" style="display:none"><img src="%s"/></p>', plugins_url( 'post-smtp/style/ajax-loader.gif' ) );
543
  printf( '<p>%s</p>', __( 'This is the Outgoing (SMTP) Mail Server, or Mail Submission Agent (MSA), which Postman delegates mail delivery to. This server is specific to your email account, and if you don\'t know what to use, ask your email service provider.', 'post-smtp' ) );
544
  printf( '<p>%s</p>', __( 'Note that many WordPress hosts, such as GoDaddy, Bluehost and Dreamhost, require that you use their mail accounts with their mail servers, and prevent you from using others.', 'post-smtp' ) );
545
 
546
+ //printf( '<div><strong><u>%s</u></strong></div><br>', __( 'If you plan to use An API and not SMTP just type any value.', 'post-smtp' ) );
547
  printf( '<label for="hostname">%s</label>', __( 'Outgoing Mail Server Hostname', 'post-smtp' ) );
548
  print $this->hostname_callback();
549
  printf( '<p class="ajax-loader" style="display:none"><img src="%s"/></p>', plugins_url( 'post-smtp/style/ajax-loader.gif' ) );
Postman/Postman-Mail/PostmanWooCommerce.php CHANGED
@@ -29,32 +29,12 @@ if ( ! class_exists( 'PostmanWoocommerce' ) ) {
29
 
30
  public function overide_email_settings( $settings ) {
31
 
32
- return array(
33
 
34
- array( 'title' => __( 'Email notifications', 'post-smtp' ), 'desc' => __( 'Email notifications sent from WooCommerce are listed below. Click on an email to configure it.', 'post-smtp' ), 'type' => 'title', 'id' => 'email_notification_settings' ),
35
-
36
- array( 'type' => 'email_notification' ),
37
-
38
- array( 'type' => 'sectionend', 'id' => 'email_notification_settings' ),
39
-
40
- array( 'type' => 'sectionend', 'id' => 'email_recipient_options' ),
41
-
42
- array( 'title' => __( 'Email sender options', 'post-smtp' ), 'type' => 'title', 'desc' => '', 'id' => 'email_options' ),
43
-
44
- array(
45
- 'title' => __( '"From" name', 'post-smtp' ),
46
- 'desc' => __( 'How the sender name appears in outgoing WooCommerce emails.', 'post-smtp' ),
47
- 'id' => 'woocommerce_email_from_name',
48
- 'type' => 'text',
49
- 'css' => 'min-width:300px;',
50
- 'default' => esc_attr( get_bloginfo( 'name', 'display' ) ),
51
- 'autoload' => false,
52
- 'desc_tip' => true,
53
- ),
54
-
55
- array(
56
  'title' => __( '"From" address', 'post-smtp' ),
57
- 'desc' => __( 'This is overided by the account configured on Post SMTP plugin configuration.', 'post-smtp' ),
58
  'id' => 'woocommerce_email_from_address',
59
  'type' => 'email',
60
  'custom_attributes' => array(
@@ -65,88 +45,20 @@ if ( ! class_exists( 'PostmanWoocommerce' ) ) {
65
  'default' => $this->options->getMessageSenderEmail(),
66
  'autoload' => false,
67
  'desc_tip' => true,
68
- ),
69
-
70
- array( 'type' => 'sectionend', 'id' => 'email_options' ),
71
 
72
- array( 'title' => __( 'Email template', 'post-smtp' ), 'type' => 'title', 'desc' => sprintf( __( 'This section lets you customize the WooCommerce emails. <a href="%s" target="_blank">Click here to preview your email template</a>.', 'post-smtp' ), wp_nonce_url( admin_url( '?preview_woocommerce_mail=true' ), 'preview-mail' ) ), 'id' => 'email_template_options' ),
73
-
74
- array(
75
- 'title' => __( 'Header image', 'post-smtp' ),
76
- 'desc' => __( 'URL to an image you want to show in the email header. Upload images using the media uploader (Admin > Media).', 'post-smtp' ),
77
- 'id' => 'woocommerce_email_header_image',
78
- 'type' => 'text',
79
- 'css' => 'min-width:300px;',
80
- 'placeholder' => __( 'N/A', 'post-smtp' ),
81
- 'default' => '',
82
- 'autoload' => false,
83
- 'desc_tip' => true,
84
- ),
85
-
86
- array(
87
- 'title' => __( 'Footer text', 'post-smtp' ),
88
- 'desc' => __( 'The text to appear in the footer of WooCommerce emails.', 'post-smtp' ),
89
- 'id' => 'woocommerce_email_footer_text',
90
- 'css' => 'width:300px; height: 75px;',
91
- 'placeholder' => __( 'N/A', 'post-smtp' ),
92
- 'type' => 'textarea',
93
- /* translators: %s: site name */
94
- 'default' => get_bloginfo( 'name', 'display' ),
95
- 'autoload' => false,
96
- 'desc_tip' => true,
97
- ),
98
-
99
- array(
100
- 'title' => __( 'Base color', 'post-smtp' ),
101
- /* translators: %s: default color */
102
- 'desc' => sprintf( __( 'The base color for WooCommerce email templates. Default %s.', 'post-smtp' ), '<code>#96588a</code>' ),
103
- 'id' => 'woocommerce_email_base_color',
104
- 'type' => 'color',
105
- 'css' => 'width:6em;',
106
- 'default' => '#96588a',
107
- 'autoload' => false,
108
- 'desc_tip' => true,
109
- ),
110
-
111
- array(
112
- 'title' => __( 'Background color', 'post-smtp' ),
113
- /* translators: %s: default color */
114
- 'desc' => sprintf( __( 'The background color for WooCommerce email templates. Default %s.', 'post-smtp' ), '<code>#f7f7f7</code>' ),
115
- 'id' => 'woocommerce_email_background_color',
116
- 'type' => 'color',
117
- 'css' => 'width:6em;',
118
- 'default' => '#f7f7f7',
119
- 'autoload' => false,
120
- 'desc_tip' => true,
121
- ),
122
-
123
- array(
124
- 'title' => __( 'Body background color', 'post-smtp' ),
125
- /* translators: %s: default color */
126
- 'desc' => sprintf( __( 'The main body background color. Default %s.', 'post-smtp' ), '<code>#ffffff</code>' ),
127
- 'id' => 'woocommerce_email_body_background_color',
128
- 'type' => 'color',
129
- 'css' => 'width:6em;',
130
- 'default' => '#ffffff',
131
- 'autoload' => false,
132
- 'desc_tip' => true,
133
- ),
134
-
135
- array(
136
- 'title' => __( 'Body text color', 'post-smtp' ),
137
- /* translators: %s: default color */
138
- 'desc' => sprintf( __( 'The main body text color. Default %s.', 'post-smtp' ), '<code>#3c3c3c</code>' ),
139
- 'id' => 'woocommerce_email_text_color',
140
- 'type' => 'color',
141
- 'css' => 'width:6em;',
142
- 'default' => '#3c3c3c',
143
- 'autoload' => false,
144
- 'desc_tip' => true,
145
- ),
146
 
147
- array( 'type' => 'sectionend', 'id' => 'email_template_options' ),
 
 
 
 
 
148
 
149
- );
150
  }
151
  }
152
  }
29
 
30
  public function overide_email_settings( $settings ) {
31
 
32
+ $key = $this->find_woocommerce_email_from_address( $settings );
33
 
34
+ if ( $key ) {
35
+ $settings[$key] = array(
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
36
  'title' => __( '"From" address', 'post-smtp' ),
37
+ 'desc' => __( 'This is override by the account configured on Post SMTP plugin configuration.', 'post-smtp' ),
38
  'id' => 'woocommerce_email_from_address',
39
  'type' => 'email',
40
  'custom_attributes' => array(
45
  'default' => $this->options->getMessageSenderEmail(),
46
  'autoload' => false,
47
  'desc_tip' => true,
48
+ );
49
+ }
 
50
 
51
+ return $settings;
52
+ }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
53
 
54
+ private function find_woocommerce_email_from_address($settings) {
55
+ foreach ( $settings as $key => $data ) {
56
+ if ( isset( $data['id'] ) && $data['id'] == 'woocommerce_email_from_address' ) {
57
+ return $key;
58
+ }
59
+ }
60
 
61
+ return false;
62
  }
63
  }
64
  }
Postman/Postman-Mail/mailgun/vendor/symfony/options-resolver/OptionsResolver.php CHANGED
@@ -103,7 +103,7 @@ class OptionsResolver implements Options
103
  *
104
  * The closure will be evaluated when {@link resolve()} is called. The
105
  * closure has access to the resolved values of other options through the
106
- * passed {@link Options} instance:
107
  *
108
  * function (Options $options) {
109
  * if (isset($options['port'])) {
@@ -120,7 +120,7 @@ class OptionsResolver implements Options
120
  * // 'Default Name' === $previousValue
121
  * });
122
  *
123
- * This is mostly useful if the configuration of the {@link Options} object
124
  * is spread across different locations of your code, such as base and
125
  * sub-classes.
126
  *
@@ -361,7 +361,7 @@ class OptionsResolver implements Options
361
  *
362
  * The closure is invoked when {@link resolve()} is called. The closure
363
  * has access to the resolved values of other options through the passed
364
- * {@link Options} instance.
365
  *
366
  * The second parameter passed to the closure is the value of
367
  * the option.
103
  *
104
  * The closure will be evaluated when {@link resolve()} is called. The
105
  * closure has access to the resolved values of other options through the
106
+ * passed {@link Admin} instance:
107
  *
108
  * function (Options $options) {
109
  * if (isset($options['port'])) {
120
  * // 'Default Name' === $previousValue
121
  * });
122
  *
123
+ * This is mostly useful if the configuration of the {@link Admin} object
124
  * is spread across different locations of your code, such as base and
125
  * sub-classes.
126
  *
361
  *
362
  * The closure is invoked when {@link resolve()} is called. The closure
363
  * has access to the resolved values of other options through the passed
364
+ * {@link Admin} instance.
365
  *
366
  * The second parameter passed to the closure is the value of
367
  * the option.
Postman/Postman-Send-Test-Email/PostmanSendTestEmailController.php CHANGED
@@ -117,7 +117,8 @@ class PostmanSendTestEmailController {
117
  'not_started' => _x( 'In Outbox', 'Email Test Status', 'post-smtp' ),
118
  'sending' => _x( 'Sending...', 'Email Test Status', 'post-smtp' ),
119
  'success' => _x( 'Success', 'Email Test Status', 'post-smtp' ),
120
- 'failed' => _x( 'Failed', 'Email Test Status', 'post-smtp' ),
 
121
  'ajax_error' => __( 'Ajax Error', 'post-smtp' ),
122
  ) );
123
  }
117
  'not_started' => _x( 'In Outbox', 'Email Test Status', 'post-smtp' ),
118
  'sending' => _x( 'Sending...', 'Email Test Status', 'post-smtp' ),
119
  'success' => _x( 'Success', 'Email Test Status', 'post-smtp' ),
120
+ //'failed' => _x( 'Failed', 'Email Test Status', 'post-smtp' ),
121
+ 'failed' => sprintf( 'Failed - Check the plugin email log for more info: %s', '<a href="' . esc_url( admin_url( 'admin.php?page=postman_email_log' ) ) . '">Here</a>' ),
122
  'ajax_error' => __( 'Ajax Error', 'post-smtp' ),
123
  ) );
124
  }
Postman/Postman.php CHANGED
@@ -97,8 +97,7 @@ class Postman {
97
  }
98
 
99
  // register the email transports
100
- $this->registerTransports( $rootPluginFilenameAndPath );
101
-
102
  // store an instance of the WpMailBinder
103
  $this->wpMailBinder = PostmanWpMailBinder::getInstance();
104
 
@@ -188,7 +187,10 @@ class Postman {
188
  */
189
  public function on_plugins_loaded() {
190
 
191
- PostmanLicenseManager::get_instance()->init();
 
 
 
192
 
193
  // load the text domain
194
  $this->loadTextDomain();
@@ -370,8 +372,8 @@ class Postman {
370
  <p style="font-size: 18px; font-weight: bold;">Please notice</p>
371
  <p style="font-size: 14px; line-height: 1.7;">
372
  <?php _e('Post SMTP v2 includes and new feature called: <b>Mailer Type</b>.', 'post-smtp' ); ?><br>
373
- <?php _e('I highly recommend to change and <strong>TEST</strong> Post SMTP with the value <code>PHPMailer</code>.', 'post-smtp' ); ?><br>
374
- <?php _e('if it will not work properly you can change back to the default value: <code>PostSMTP</code>.', 'post-smtp' ); ?><br>
375
  <a target="_blank" href="<?php echo POST_SMTP_URL; ?>/style/images/mailer-type.gif">
376
  <figure>
377
  <img width="180" src="<?php echo POST_SMTP_URL; ?>/style/images/mailer-type.gif" alt="how to set mailer type">
97
  }
98
 
99
  // register the email transports
100
+
 
101
  // store an instance of the WpMailBinder
102
  $this->wpMailBinder = PostmanWpMailBinder::getInstance();
103
 
187
  */
188
  public function on_plugins_loaded() {
189
 
190
+ PostmanLicenseManager::get_instance()->init();
191
+
192
+ // register the email transports
193
+ $this->registerTransports( $this->rootPluginFilenameAndPath );
194
 
195
  // load the text domain
196
  $this->loadTextDomain();
372
  <p style="font-size: 18px; font-weight: bold;">Please notice</p>
373
  <p style="font-size: 14px; line-height: 1.7;">
374
  <?php _e('Post SMTP v2 includes and new feature called: <b>Mailer Type</b>.', 'post-smtp' ); ?><br>
375
+ <?php _e('I recommend to change it and <strong>TEST</strong> Post SMTP with the value <code>PHPMailer</code>.', 'post-smtp' ); ?><br>
376
+ <?php _e('<strong>ONLY</strong> if the default mailer type is not working for you.', 'post-smtp' ); ?><br>
377
  <a target="_blank" href="<?php echo POST_SMTP_URL; ?>/style/images/mailer-type.gif">
378
  <figure>
379
  <img width="180" src="<?php echo POST_SMTP_URL; ?>/style/images/mailer-type.gif" alt="how to set mailer type">
Postman/PostmanInstaller.php CHANGED
@@ -77,7 +77,8 @@ class PostmanInstaller {
77
 
78
  // Bail if activating from network, or bulk
79
  if ( is_network_admin() || isset( $_GET['activate-multi'] ) ) {
80
- return; }
 
81
 
82
  // Add the transient to redirect
83
  //set_transient( '_post_activation_redirect', true, 30 );
77
 
78
  // Bail if activating from network, or bulk
79
  if ( is_network_admin() || isset( $_GET['activate-multi'] ) ) {
80
+ return;
81
+ }
82
 
83
  // Add the transient to redirect
84
  //set_transient( '_post_activation_redirect', true, 30 );
Postman/PostmanLogFields.php CHANGED
@@ -3,6 +3,7 @@ class PostmanLogFields {
3
 
4
  private $fields = array(
5
  'success' => 'sanitize_text_field',
 
6
  'from_header' => [ 'PostmanLogFields', 'email_header_sanitize' ],
7
  'to_header' => [ 'PostmanLogFields', 'email_header_sanitize' ],
8
  'cc_header' => [ 'PostmanLogFields', 'email_header_sanitize' ],
@@ -90,6 +91,17 @@ class PostmanLogFields {
90
  return wp_kses( $message, $allowed_tags );
91
  }
92
 
 
 
 
 
 
 
 
 
 
 
 
93
  private function encode( $value ) {
94
  if ( is_array( $value ) ) {
95
  return wp_json_encode( $value );
3
 
4
  private $fields = array(
5
  'success' => 'sanitize_text_field',
6
+ 'solution' => [ 'PostmanLogFields', 'sanitize_message' ],
7
  'from_header' => [ 'PostmanLogFields', 'email_header_sanitize' ],
8
  'to_header' => [ 'PostmanLogFields', 'email_header_sanitize' ],
9
  'cc_header' => [ 'PostmanLogFields', 'email_header_sanitize' ],
91
  return wp_kses( $message, $allowed_tags );
92
  }
93
 
94
+ private function sanitize_html( $value ) {
95
+ $allowed_html = array(
96
+ 'a' => array(
97
+ 'href' => array(),
98
+ ),
99
+ 'br' => array(),
100
+ );
101
+
102
+ return wp_kses( $value, $allowed_html );
103
+ }
104
+
105
  private function encode( $value ) {
106
  if ( is_array( $value ) ) {
107
  return wp_json_encode( $value );
postman-smtp.php CHANGED
@@ -6,7 +6,7 @@ if ( ! defined( 'ABSPATH' ) ) {
6
  * Plugin Name: Post SMTP
7
  * Plugin URI: https://wordpress.org/plugins/post-smtp/
8
  * Description: Email not reliable? Post SMTP is the first and only WordPress SMTP plugin to implement OAuth 2.0 for Gmail, Hotmail and Yahoo Mail. Setup is a breeze with the Configuration Wizard and integrated Port Tester. Enjoy worry-free delivery even if your password changes!
9
- * Version: 2.0.12
10
  * Author: Yehuda Hassine
11
  * Text Domain: post-smtp
12
  * Author URI: https://postmansmtp.com
@@ -35,7 +35,7 @@ if ( ! defined( 'ABSPATH' ) ) {
35
  define( 'POST_SMTP_BASE', __FILE__ );
36
  define( 'POST_SMTP_PATH', __DIR__ );
37
  define( 'POST_SMTP_URL', plugins_url('', POST_SMTP_BASE ) );
38
- define( 'POST_SMTP_VER', '2.0.12' );
39
  define( 'POST_SMTP_SHOW_RELEASE_MESSAGE', true );
40
  define( 'POST_SMTP_RELEASE_MESSAGE', "I have released a new Google Analytics AIO plugin, if you liked it please leave a review." );
41
  define( 'POST_SMTP_RELEASE_URL', 'https://wordpress.org/plugins/metrics-query/' );
6
  * Plugin Name: Post SMTP
7
  * Plugin URI: https://wordpress.org/plugins/post-smtp/
8
  * Description: Email not reliable? Post SMTP is the first and only WordPress SMTP plugin to implement OAuth 2.0 for Gmail, Hotmail and Yahoo Mail. Setup is a breeze with the Configuration Wizard and integrated Port Tester. Enjoy worry-free delivery even if your password changes!
9
+ * Version: 2.0.13
10
  * Author: Yehuda Hassine
11
  * Text Domain: post-smtp
12
  * Author URI: https://postmansmtp.com
35
  define( 'POST_SMTP_BASE', __FILE__ );
36
  define( 'POST_SMTP_PATH', __DIR__ );
37
  define( 'POST_SMTP_URL', plugins_url('', POST_SMTP_BASE ) );
38
+ define( 'POST_SMTP_VER', '2.0.13' );
39
  define( 'POST_SMTP_SHOW_RELEASE_MESSAGE', true );
40
  define( 'POST_SMTP_RELEASE_MESSAGE', "I have released a new Google Analytics AIO plugin, if you liked it please leave a review." );
41
  define( 'POST_SMTP_RELEASE_URL', 'https://wordpress.org/plugins/metrics-query/' );
readme.txt CHANGED
@@ -3,8 +3,8 @@ Contributors: yehudah
3
  Donate link: https://www.paypal.com/cgi-bin/webscr?cmd=_xclick&business=yehuda@myinbox.in&item_name=Donation+for+PostSMTP
4
  Tags: postman smtp, postman, smtp, email, mail, mailer, email log, oauth2, gmail, google apps, hotmail, yahoo, mandrill api, sendgrid api, elastic email, office365, mailgun
5
  Requires at least: 3.9
6
- Tested up to: 5.4.1
7
- Stable tag: 2.0.12
8
  License: GPLv2 or later
9
  License URI: http://www.gnu.org/licenses/gpl-2.0.html
10
 
@@ -281,6 +281,12 @@ To avoid being flagged as spam, you need to prove your email isn't forged. On a
281
 
282
  == Changelog ==
283
 
 
 
 
 
 
 
284
  = 2.0.12 - 2020-05-18
285
  * Updated: Readme file info
286
 
3
  Donate link: https://www.paypal.com/cgi-bin/webscr?cmd=_xclick&business=yehuda@myinbox.in&item_name=Donation+for+PostSMTP
4
  Tags: postman smtp, postman, smtp, email, mail, mailer, email log, oauth2, gmail, google apps, hotmail, yahoo, mandrill api, sendgrid api, elastic email, office365, mailgun
5
  Requires at least: 3.9
6
+ Tested up to: 5.5
7
+ Stable tag: 2.0.13
8
  License: GPLv2 or later
9
  License URI: http://www.gnu.org/licenses/gpl-2.0.html
10
 
281
 
282
  == Changelog ==
283
 
284
+ = 2.0.13 - 2020-08-11
285
+ * Fixed: WordPress 5.5 compatibility
286
+ * Fixed: Email log filtering
287
+ * Fixed: Pushover notifications
288
+ * New: Suggest solution for email delivery errors
289
+
290
  = 2.0.12 - 2020-05-18
291
  * Updated: Readme file info
292
 
style/postman-email-log.css CHANGED
@@ -176,6 +176,7 @@ th#date {
176
  .ui-datepicker td {
177
  padding: 0;
178
  border: 1px solid #f4f4f4;
 
179
  }
180
 
181
  .ui-datepicker td.ui-datepicker-other-month {
176
  .ui-datepicker td {
177
  padding: 0;
178
  border: 1px solid #f4f4f4;
179
+ background-color: #f4f4f4;
180
  }
181
 
182
  .ui-datepicker td.ui-datepicker-other-month {