Newsletter - Version 6.3.0

Version Description

  • New mailer infrastructure: better compatibility and performance
  • New [TEST] prefix for newsletter tests
  • Fix on composer subject saving
  • General performance improvements
  • Fixed title display in header composer block
Download this release

Release Info

Developer satollo
Plugin Icon 128x128 Newsletter
Version 6.3.0
Comparing to
See all releases

Code changes from version 6.2.2 to 6.3.0

emails/blocks/header/block.php CHANGED
@@ -52,20 +52,24 @@ $empty = empty($info['header_logo']['id']) && empty($info['header_sub']) && empt
52
  }
53
  </style>
54
 
55
- <table border="0" cellpadding="0" cellspacing="0" width="100%">
56
- <tr>
57
- <td align="left" width="50%" inline-class="header-logo">
58
- <?php if ($image) { ?>
59
- <a href="#" target="_blank">
60
- <img alt="<?php echo esc_attr($info['header_title']) ?>" src="<?php echo $image ?>" style="display: block; max-width: 100%" border="0">
61
- </a>
62
- <?php } else { ?>
63
- <?php } ?>
64
- </td>
65
- <td width="50%" align="right" class="mobile-hide" inline-class="header-text">
66
- <?php echo $info['header_sub'] ?>
67
- </td>
68
- </tr>
69
- </table>
 
 
 
 
70
 
71
  <?php } ?>
52
  }
53
  </style>
54
 
55
+ <table border="0" cellpadding="0" cellspacing="0" width="100%">
56
+ <tr>
57
+ <?php if ( $image ) { ?>
58
+ <td align="left" width="50%" inline-class="header-logo">
59
+ <a href="#" target="_blank">
60
+ <img alt="<?php echo esc_attr( $info['header_title'] ) ?>" src="<?php echo $image ?>"
61
+ style="display: block; max-width: 100%" border="0">
62
+ </a>
63
+ <?php } else { ?>
64
+ <td align="left" width="50%" inline-class="heading-text"
65
+ style="padding: 5px; font-size: 24px; font-family: Helvetica, Arial, sans-serif; font-weight: bold; color: #444444;">
66
+ <?php echo esc_attr( $info['header_title'] ) ?>
67
+ <?php } ?>
68
+ </td>
69
+ <td width="50%" align="right" class="mobile-hide" inline-class="header-text">
70
+ <?php echo $info['header_sub'] ?>
71
+ </td>
72
+ </tr>
73
+ </table>
74
 
75
  <?php } ?>
emails/composer.php CHANGED
@@ -12,8 +12,6 @@ include NEWSLETTER_INCLUDES_DIR . '/codemirror.php';
12
 
13
  if ($controls->is_action()) {
14
 
15
- /* * * Save or create ** */
16
-
17
  if (empty($_GET['id'])) {
18
 
19
  $email = array();
12
 
13
  if ($controls->is_action()) {
14
 
 
 
15
  if (empty($_GET['id'])) {
16
 
17
  $email = array();
emails/emails.php CHANGED
@@ -187,12 +187,12 @@ class NewsletterEmails extends NewsletterModule {
187
  function regenerate($theme, $context = array()) {
188
  $this->logger->debug('Starting email regeneration');
189
  $this->logger->debug($context);
190
-
191
  if (empty($theme)) {
192
  $this->logger->debug('The email was empty');
193
  return array('body' => '', 'subject' => '');
194
  }
195
-
196
  $context = array_merge(array('last_run' => 0, 'type' => ''), $context);
197
 
198
  preg_match_all('/data-json="(.*?)"/m', $theme, $matches, PREG_PATTERN_ORDER);
@@ -799,7 +799,7 @@ class NewsletterEmails extends NewsletterModule {
799
  $blocks = array_merge($extended, $blocks);
800
 
801
  $dirs = apply_filters('newsletter_blocks_dir', array());
802
-
803
  $this->logger->debug('Block dirs: ' . print_r($dirs, true));
804
 
805
  foreach ($dirs as $dir) {
@@ -942,8 +942,8 @@ class NewsletterEmails extends NewsletterModule {
942
  continue;
943
  }
944
  $css .= "\n\n";
945
- $css .= "/* " . $block['name'] . " */\n";
946
- $css .= file_get_contents($block['dir'] . '/style.css');
947
  }
948
  return $css;
949
  }
@@ -954,7 +954,9 @@ class NewsletterEmails extends NewsletterModule {
954
  return;
955
  }
956
  if ($email->subject == '') {
957
- $email->subject = 'Dummy subject, it was empty (remember to set it)';
 
 
958
  }
959
  $users = NewsletterUsers::instance()->get_test_users();
960
  if (count($users) == 0) {
@@ -962,15 +964,20 @@ class NewsletterEmails extends NewsletterModule {
962
  '. <a href="https://www.thenewsletterplugin.com/plugins/newsletter/subscribers-module#test" target="_blank"><strong>' .
963
  __('Read more', 'newsletter') . '</strong></a>.';
964
  } else {
965
- Newsletter::instance()->send($email, $users);
966
- $controls->messages = __('Test newsletter sent to:', 'newsletter');
967
- foreach ($users as $user) {
968
- $controls->messages .= ' ' . $user->email;
 
 
 
 
 
 
 
 
 
969
  }
970
- $controls->messages .= '.<br>';
971
- $controls->messages .= '<a href="https://www.thenewsletterplugin.com/documentation/subscribers#test" target="_blank"><strong>' .
972
- __('Read more about test subscribers', 'newsletter') . '</strong></a>.<br>';
973
- $controls->messages .= '<a href="https://www.thenewsletterplugin.com/documentation/email-sending-issues" target="_blank"><strong>' . __('Read more about delivery issues', 'newsletter') . '</strong></a>.';
974
  }
975
  }
976
 
187
  function regenerate($theme, $context = array()) {
188
  $this->logger->debug('Starting email regeneration');
189
  $this->logger->debug($context);
190
+
191
  if (empty($theme)) {
192
  $this->logger->debug('The email was empty');
193
  return array('body' => '', 'subject' => '');
194
  }
195
+
196
  $context = array_merge(array('last_run' => 0, 'type' => ''), $context);
197
 
198
  preg_match_all('/data-json="(.*?)"/m', $theme, $matches, PREG_PATTERN_ORDER);
799
  $blocks = array_merge($extended, $blocks);
800
 
801
  $dirs = apply_filters('newsletter_blocks_dir', array());
802
+
803
  $this->logger->debug('Block dirs: ' . print_r($dirs, true));
804
 
805
  foreach ($dirs as $dir) {
942
  continue;
943
  }
944
  $css .= "\n\n";
945
+ $css .= "/* " . $block['name'] . " */\n";
946
+ $css .= file_get_contents($block['dir'] . '/style.css');
947
  }
948
  return $css;
949
  }
954
  return;
955
  }
956
  if ($email->subject == '') {
957
+ $email->subject = '[TEST] Dummy subject, it was empty (remember to set it)';
958
+ } else {
959
+ $email->subject = '[TEST] ' . $email->subject;
960
  }
961
  $users = NewsletterUsers::instance()->get_test_users();
962
  if (count($users) == 0) {
964
  '. <a href="https://www.thenewsletterplugin.com/plugins/newsletter/subscribers-module#test" target="_blank"><strong>' .
965
  __('Read more', 'newsletter') . '</strong></a>.';
966
  } else {
967
+ $r = Newsletter::instance()->send($email, $users);
968
+ if (is_wp_error($r)) {
969
+ $controls->errors = $r->get_error_message();
970
+ $controls->errors .= '<br><a href="https://www.thenewsletterplugin.com/documentation/email-sending-issues" target="_blank"><strong>' . __('Read more about delivery issues', 'newsletter') . '</strong></a>.';
971
+ } else {
972
+ $controls->messages = __('Test newsletter sent to:', 'newsletter');
973
+ foreach ($users as $user) {
974
+ $controls->messages .= ' ' . $user->email;
975
+ }
976
+ $controls->messages .= '.<br>';
977
+ $controls->messages .= '<a href="https://www.thenewsletterplugin.com/documentation/subscribers#test" target="_blank"><strong>' .
978
+ __('Read more about test subscribers', 'newsletter') . '</strong></a>.<br>';
979
+ $controls->messages .= '<a href="https://www.thenewsletterplugin.com/documentation/email-sending-issues" target="_blank"><strong>' . __('Read more about delivery issues', 'newsletter') . '</strong></a>.';
980
  }
 
 
 
 
981
  }
982
  }
983
 
includes/controls.php CHANGED
@@ -442,7 +442,7 @@ class NewsletterControls {
442
  echo '</select>&nbsp;&nbsp;&nbsp;';
443
  }
444
 
445
- function enabled($name) {
446
  $value = isset($this->data[$name]) ? (int) $this->data[$name] : 0;
447
 
448
  echo '<select style="width: 100px" name="options[' . esc_attr($name) . ']">';
@@ -746,7 +746,7 @@ class NewsletterControls {
746
  $value = $this->get_value($name);
747
  echo '<input id="options-', esc_attr($name), '" placeholder="' . esc_attr($placeholder) . '" name="options[' . $name . ']" type="text" ';
748
  if (!empty($size)) {
749
- echo 'size="' . $size . '"';
750
  }
751
  echo 'value="', esc_attr($value), '">';
752
  }
@@ -1659,7 +1659,7 @@ class NewsletterControls {
1659
  $value = str_replace('"', '&quot;', $value);
1660
  $value = str_replace('<', '&lt;', $value);
1661
  $value = str_replace('>', '&gt;', $value);
1662
- echo '<input type="hidden" name="options[', esc_attr($name), ']" id="options-', esc_attr($name), '" value="', $value, '">';
1663
 
1664
  // Used by composer to rebuild the full HTML
1665
  $css = NewsletterEmails::instance()->get_composer_css();
@@ -1667,7 +1667,7 @@ class NewsletterControls {
1667
 
1668
  // subject
1669
  $value = $this->get_value('subject');
1670
- echo '<input type="hidden" name="options[subject]" id="options-subject" value="', $value, '">';
1671
  }
1672
 
1673
  function composer_load($name = 'body', $show_subject = false, $show_test = true) {
442
  echo '</select>&nbsp;&nbsp;&nbsp;';
443
  }
444
 
445
+ function enabled($name = 'enabled') {
446
  $value = isset($this->data[$name]) ? (int) $this->data[$name] : 0;
447
 
448
  echo '<select style="width: 100px" name="options[' . esc_attr($name) . ']">';
746
  $value = $this->get_value($name);
747
  echo '<input id="options-', esc_attr($name), '" placeholder="' . esc_attr($placeholder) . '" name="options[' . $name . ']" type="text" ';
748
  if (!empty($size)) {
749
+ echo 'size="' . $size . '" ';
750
  }
751
  echo 'value="', esc_attr($value), '">';
752
  }
1659
  $value = str_replace('"', '&quot;', $value);
1660
  $value = str_replace('<', '&lt;', $value);
1661
  $value = str_replace('>', '&gt;', $value);
1662
+ echo '<input type="hidden" name="options[', esc_attr($name), ']" id="options-', esc_attr($name), '" value="', esc_attr($value), '">';
1663
 
1664
  // Used by composer to rebuild the full HTML
1665
  $css = NewsletterEmails::instance()->get_composer_css();
1667
 
1668
  // subject
1669
  $value = $this->get_value('subject');
1670
+ echo '<input type="hidden" name="options[subject]" id="options-subject" value="', esc_attr($value), '">';
1671
  }
1672
 
1673
  function composer_load($name = 'body', $show_subject = false, $show_test = true) {
includes/helper.php CHANGED
@@ -109,7 +109,7 @@ function tnp_media_resize($media_id, $size) {
109
  // Thumbnail generation if needed.
110
  if (!file_exists($absolute_thumb) || filemtime($absolute_thumb) < filemtime($absolute_file)) {
111
  $r = wp_mkdir_p($uploads['basedir'] . '/newsletter/thumbnails/' . $pathinfo['dirname']);
112
-
113
  if (!$r) {
114
  $src = wp_get_attachment_image_src($media_id, $size);
115
  return $src[0];
@@ -140,7 +140,5 @@ function tnp_media_resize($media_id, $size) {
140
  }
141
  }
142
 
143
-
144
-
145
  return $uploads['baseurl'] . '/newsletter/thumbnails/' . $relative_thumb;
146
  }
109
  // Thumbnail generation if needed.
110
  if (!file_exists($absolute_thumb) || filemtime($absolute_thumb) < filemtime($absolute_file)) {
111
  $r = wp_mkdir_p($uploads['basedir'] . '/newsletter/thumbnails/' . $pathinfo['dirname']);
112
+
113
  if (!$r) {
114
  $src = wp_get_attachment_image_src($media_id, $size);
115
  return $src[0];
140
  }
141
  }
142
 
 
 
143
  return $uploads['baseurl'] . '/newsletter/thumbnails/' . $relative_thumb;
144
  }
includes/mailer.php DELETED
@@ -1,42 +0,0 @@
1
- <?php
2
-
3
- abstract class TNP_Mailer {
4
-
5
- var $queue = array();
6
- var $errors = array();
7
- var $name = '';
8
-
9
- public function __construct($name) {
10
- $this->name = $name;
11
- }
12
-
13
- abstract public function mail($to, $subject, $message, $headers = null, $enqueue = false, $from = false);
14
-
15
- /**
16
- * @return WP_Error[] A list of errors associated to flushed messages
17
- */
18
- public function flush() {
19
- $this->queue = array();
20
- }
21
-
22
- function get_errors() {
23
- return $this->errors;
24
- }
25
-
26
- function clear_errors() {
27
- $this->errors = array();
28
- }
29
-
30
- /**
31
- * @return NewsletterLogger
32
- */
33
- function get_logger() {
34
- static $logger = null;
35
- if (is_null($logger)) {
36
- $logger = new NewsletterLogger($this->name);
37
- }
38
-
39
- return $logger;
40
- }
41
-
42
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
includes/mailers.php ADDED
@@ -0,0 +1,304 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /**
4
+ * Wrapper mailer for old addons registering the "mail" method (ultra deprecated).
5
+ */
6
+ class NewsletterMailMethodWrapper extends NewsletterMailer {
7
+
8
+ var $mail_method;
9
+
10
+ /**
11
+ * The reference to the mail method.
12
+ *
13
+ * @param callback $callable Must be an array with object and method to call, no other callback formats allowed.
14
+ */
15
+ function __construct($callable) {
16
+ parent::__construct(strtolower(get_class($callable[0])), array());
17
+ $this->mail_method = $callable;
18
+ }
19
+
20
+ function get_description() {
21
+ if ($this->mail_method != null) {
22
+ return 'Mail method of ' . get_class($this->mail_method[0]);
23
+ } else {
24
+ return 'Undetectable mailer class';
25
+ }
26
+ }
27
+
28
+ function send($message) {
29
+ if ($this->mail_method != null) {
30
+ $r = call_user_func($this->mail_method, $message->to, $message->subject, array('html' => $message->body, 'text' => $message->body_text), $message->headers);
31
+ if (!$r) {
32
+ $message->error = 'Unreported error';
33
+ return new WP_Error(self::ERROR_GENERIC, 'Unreported error');
34
+ }
35
+ } else {
36
+ $message->error = 'Mail mathod not available';
37
+ return new WP_Error(self::ERROR_FATAL, 'Mail method not available');
38
+ }
39
+ return true;
40
+ }
41
+ }
42
+
43
+ /**
44
+ * Wrapper Mailer for old addons registering the "mail" method (deprecated).
45
+ */
46
+ class NewsletterOldMailerWrapper extends NewsletterMailer {
47
+
48
+ var $mailer;
49
+
50
+ /**
51
+ * Old mailer plugin (actually untyped object)
52
+ * @param object $mailer
53
+ */
54
+ function __construct($mailer) {
55
+ $this->mailer = $mailer;
56
+ // We have not a name, build it from the class name... and of course, no options.
57
+ parent::__construct(strtolower(get_class($mailer)), array());
58
+ $this->description = 'Mailer wrapper for ' . get_class($mailer);
59
+ }
60
+
61
+ /**
62
+ * Only send() needs to be implemented all other method will use the defail base-class implementation
63
+ *
64
+ * @param TNP_Mailer_Message $message
65
+ * @return \WP_Error|boolean
66
+ */
67
+ function send($message) {
68
+ // The old mailer manages itself the from field
69
+ $r = $this->mailer->mail($message->to, $message->subject, array('html' => $message->body, 'text' => $message->body_text), $message->headers);
70
+ if (!$r) {
71
+ if (isset($this->mailer->result)) {
72
+ $message->error = $this->mailer->result;
73
+ return new WP_Error(self::ERROR_GENERIC, $this->mailer->result);
74
+ } else {
75
+ $message->error = 'Unknown error';
76
+ return new WP_Error(self::ERROR_GENERIC, 'Unknown error');
77
+ }
78
+ }
79
+ return true;
80
+ }
81
+ }
82
+
83
+ /**
84
+ * Standard Mailer which uses the wp_mail() function of WP.
85
+ */
86
+ class NewsletterDefaultMailer extends NewsletterMailer {
87
+
88
+ var $filter_active = false;
89
+
90
+ /**
91
+ * Used when the internal SMTP is active
92
+ * @var PHPMailer
93
+ */
94
+ var $mailer = null;
95
+
96
+ /**
97
+ * @var TNP_Mailer_Message
98
+ */
99
+ var $current_message = null;
100
+
101
+ function __construct() {
102
+ parent::__construct('default', Newsletter::instance()->get_options('smtp'));
103
+ }
104
+
105
+ function get_description() {
106
+ // TODO: check if overloaded
107
+ return 'wp_mail() WordPress function (could be extended by a SMTP plugin)';
108
+ }
109
+
110
+ function send($message) {
111
+
112
+ if (!$this->filter_active) {
113
+ add_action('phpmailer_init', function ($mailer) {
114
+ // If there is not a current message, wp_mail() was not called by us
115
+ if (is_null($this->current_message)) {
116
+ return;
117
+ }
118
+
119
+ /* @var $mailer PHPMailer */
120
+ $mailer->Sender = Newsletter::instance()->options['return_path'];
121
+
122
+ if (empty($this->current_message->body_text)) {
123
+ return;
124
+ }
125
+ $mailer->AltBody = $this->current_message->body_text;
126
+ }, 100);
127
+ $this->filter_active = true;
128
+ }
129
+
130
+ $newsletter = Newsletter::instance();
131
+ $wp_mail_headers = array();
132
+ // TODO: Manage the from address
133
+ $wp_mail_headers[] = 'From: "' . $newsletter->options['sender_name'] . '" <' . $newsletter->options['sender_email'] . '>';
134
+
135
+ if (!empty($newsletter->options['reply_to'])) {
136
+ $wp_mail_headers[] = 'Reply-To: ' . $newsletter->options['reply_to'];
137
+ }
138
+
139
+ // Manage from and from name
140
+
141
+ if (!empty($message->headers)) {
142
+ foreach ($message->headers as $key => $value) {
143
+ $wp_mail_headers[] = $key . ': ' . $value;
144
+ }
145
+ }
146
+
147
+ if (!empty($message->body)) {
148
+ $wp_mail_headers[] = 'Content-Type: text/html;charset=UTF-8';
149
+
150
+ $body = $message->body;
151
+ } else if (!empty($message->body_text)) {
152
+ $wp_mail_headers[] = 'Content-Type: text/plain;charset=UTF-8';
153
+ $body = $message->body_text;
154
+ } else {
155
+ $message->error = 'Empty body';
156
+ return new WP_Error(self::ERROR_GENERIC, 'Message format');
157
+ }
158
+
159
+ $this->current_message = $message;
160
+ $r = wp_mail($message->to, $message->subject, $body, $wp_mail_headers);
161
+ $this->current_message = null;
162
+
163
+ if (!$r) {
164
+ $last_error = error_get_last();
165
+ if (is_array($last_error)) {
166
+ $message->error = $last_error['message'];
167
+ if (stripos($message->error, 'Could not instantiate mail function') || stripos($message->error, 'Failed to connect to mailserver')) {
168
+ return new WP_Error(self::ERROR_FATAL, $last_error['message']);
169
+ } else {
170
+ return new WP_Error(self::ERROR_GENERIC, $last_error['message']);
171
+ }
172
+ } else {
173
+ $message->error = 'No error explanation reported';
174
+ return new WP_Error(self::ERROR_GENERIC, 'No error message reported');
175
+ }
176
+ }
177
+ return true;
178
+ }
179
+ }
180
+
181
+ /**
182
+ * Standard Mailer which uses the wp_mail() function of WP.
183
+ */
184
+ class NewsletterDefaultSMTPMailer extends NewsletterMailer {
185
+
186
+ var $mailer = null;
187
+
188
+ function __construct($options) {
189
+ parent::__construct('internal-smtp', $options);
190
+ }
191
+
192
+ function get_description() {
193
+ return 'Internal SMTP (deprecated)';
194
+ }
195
+
196
+ /**
197
+ *
198
+ * @param TNP_Mailer_Message $message
199
+ * @return \WP_Error|boolean
200
+ */
201
+ public function send($message) {
202
+ $logger = $this->get_logger();
203
+ $logger->debug('Start sending to ' . $message->to);
204
+ $mailer = $this->get_mailer();
205
+ $mailer->IsHTML(true);
206
+ $mailer->Body = $message->body;
207
+ $mailer->AltBody = $message->body_text;
208
+ $mailer->Subject = $message->subject;
209
+
210
+ $mailer->ClearCustomHeaders();
211
+ if (!empty($message->headers)) {
212
+ foreach ($message->headers as $key => $value) {
213
+ $mailer->AddCustomHeader($key . ': ' . $value);
214
+ }
215
+ }
216
+
217
+ if ($message->from) {
218
+ $logger->debug('Alternative from available');
219
+ $mailer->setFrom($message->from, $message->from_name);
220
+ }
221
+
222
+ $mailer->ClearAddresses();
223
+ $mailer->AddAddress($message->to);
224
+ $mailer->Send();
225
+
226
+ if ($mailer->IsError()) {
227
+
228
+ $logger->error($mailer->ErrorInfo);
229
+ // If the error is due to SMTP connection, the mailer cannot be reused since it does not clean up the connection
230
+ // on error.
231
+ //$this->mailer = null;
232
+ $message->error = $mailer->ErrorInfo;
233
+ return new WP_Error(self::ERROR_GENERIC, $mailer->ErrorInfo);
234
+ }
235
+
236
+ $logger->debug('Sent ' . $message->to);
237
+ //$logger->error('Time: ' . (microtime(true) - $start) . ' seconds');
238
+ return true;
239
+ }
240
+
241
+ /**
242
+ *
243
+ * @return PHPMailer
244
+ */
245
+ function get_mailer() {
246
+ if ($this->mailer)
247
+ return $this->mailer;
248
+
249
+ $logger = $this->get_logger();
250
+ $logger->info('Setting up PHP mailer');
251
+ require_once ABSPATH . WPINC . '/class-phpmailer.php';
252
+ require_once ABSPATH . WPINC . '/class-smtp.php';
253
+
254
+ $this->mailer = new PHPMailer();
255
+ $this->mailer->IsSMTP();
256
+ $this->mailer->Host = $this->options['host'];
257
+ if (!empty($this->options['port'])) {
258
+ $this->mailer->Port = (int) $this->options['port'];
259
+ }
260
+
261
+ if (!empty($this->options['user'])) {
262
+ $this->mailer->SMTPAuth = true;
263
+ $this->mailer->Username = $this->options['user'];
264
+ $this->mailer->Password = $this->options['pass'];
265
+ }
266
+ $this->mailer->SMTPKeepAlive = true;
267
+ $this->mailer->SMTPSecure = $this->options['secure'];
268
+ $this->mailer->SMTPAutoTLS = false;
269
+
270
+ if ($this->options['ssl_insecure'] == 1) {
271
+ $this->mailer->SMTPOptions = array(
272
+ 'ssl' => array(
273
+ 'verify_peer' => false,
274
+ 'verify_peer_name' => false,
275
+ 'allow_self_signed' => true
276
+ )
277
+ );
278
+ }
279
+
280
+ $newsletter = Newsletter::instance();
281
+
282
+ if (!empty($newsletter->options['content_transfer_encoding'])) {
283
+ $this->mailer->Encoding = $newsletter->options['content_transfer_encoding'];
284
+ } else {
285
+ $this->mailer->Encoding = 'base64';
286
+ }
287
+
288
+ $this->mailer->CharSet = 'UTF-8';
289
+ $this->mailer->From = $newsletter->options['sender_email'];
290
+
291
+ if (!empty($newsletter->options['return_path'])) {
292
+ $this->mailer->Sender = $newsletter->options['return_path'];
293
+ }
294
+ if (!empty($newsletter->options['reply_to'])) {
295
+ $this->mailer->AddReplyTo($newsletter->options['reply_to']);
296
+ }
297
+
298
+ $this->mailer->FromName = $newsletter->options['sender_name'];
299
+
300
+
301
+ return $this->mailer;
302
+ }
303
+ }
304
+
includes/module.php CHANGED
@@ -83,7 +83,7 @@ abstract class TNP_Email {
83
  * @property string $id Theme identifier
84
  * @property string $dir Absolute path to the theme folder
85
  * @property string $name Theme name
86
- * */
87
  class TNP_Theme {
88
 
89
  var $dir;
@@ -131,6 +131,7 @@ class NewsletterAddon {
131
  }
132
 
133
  function upgrade($first_install = false) {
 
134
  }
135
 
136
  function init() {
@@ -162,6 +163,12 @@ class NewsletterAddon {
162
  $this->setup_options();
163
  }
164
 
 
 
 
 
 
 
165
  /**
166
  * @global wpdb $wpdb
167
  * @param string $query
@@ -180,6 +187,292 @@ class NewsletterAddon {
180
 
181
  }
182
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
183
  class NewsletterModule {
184
 
185
  /**
@@ -1976,6 +2269,13 @@ class NewsletterModule {
1976
  return $url;
1977
  }
1978
 
 
 
 
 
 
 
 
1979
  /**
1980
  * Return the current language code. Optionally, if a user is passed and it has a language
1981
  * the user language is returned.
83
  * @property string $id Theme identifier
84
  * @property string $dir Absolute path to the theme folder
85
  * @property string $name Theme name
86
+ */
87
  class TNP_Theme {
88
 
89
  var $dir;
131
  }
132
 
133
  function upgrade($first_install = false) {
134
+
135
  }
136
 
137
  function init() {
163
  $this->setup_options();
164
  }
165
 
166
+ function merge_defaults($defaults) {
167
+ $options = get_option('newsletter_' . $this->name, array());
168
+ $options = array_merge($defaults, $options);
169
+ $this->save_options($options);
170
+ }
171
+
172
  /**
173
  * @global wpdb $wpdb
174
  * @param string $query
187
 
188
  }
189
 
190
+ class NewsletterMailerAddon extends NewsletterAddon {
191
+
192
+ var $enabled = false;
193
+
194
+ function __construct($name, $version = '0.0.0') {
195
+ parent::__construct($name, $version);
196
+ $this->setup_options();
197
+ $this->enabled = !empty($this->options['enabled']);
198
+ }
199
+
200
+ function init() {
201
+ parent::init();
202
+ add_action('newsletter_register_mailer', function () {
203
+ if ($this->enabled) {
204
+ Newsletter::instance()->register_mailer($this->get_mailer());
205
+ }
206
+ });
207
+ }
208
+
209
+ /**
210
+ *
211
+ * @return NewsletterMailer
212
+ */
213
+ function get_mailer() {
214
+ return null;
215
+ }
216
+
217
+ function get_last_run() {
218
+ return get_option('newsletter_' . $this->name . '_last_run', 0);
219
+ }
220
+
221
+ function save_last_run($time) {
222
+ update_option('newsletter_' . $this->name . '_last_run', $time);
223
+ }
224
+
225
+ function save_options($options) {
226
+ parent::save_options($options);
227
+ $this->enabled = !empty($options['enabled']);
228
+ }
229
+
230
+ static function get_test_message($to, $subject = '') {
231
+ $message = new TNP_Mailer_Message();
232
+ $message->to = $to;
233
+ $message->to_name = '';
234
+ $message->body = "<!DOCTYPE html>\n";
235
+ $message->body .= "This is the rich text (HTML) version of a test message.</p>\n";
236
+ $message->body .= "This is a <strong>bold text</strong></p>\n";
237
+ $message->body .= "This is a <a href='http://www.thenewsletterplugin.com'>link to www.thenewsletterplugin.com</a></p>\n";
238
+ $message->body_text = 'This is the TEXT version of a test message. You should see this message only if you email client does not support the rich text (HTML) version.';
239
+ $message->headers['X-Newsletter-Email-Id'] = '0';
240
+ if (empty($subject)) {
241
+ $message->subject = '[' . get_option('blogname') . '] Test message from Newsletter (' . date(DATE_ISO8601) . ')';
242
+ } else {
243
+ $message->subject = $subject;
244
+ }
245
+ $message->from = Newsletter::instance()->options['sender_email'];
246
+ $message->from_name = Newsletter::instance()->options['sender_name'];
247
+ return $message;
248
+ }
249
+
250
+ function get_test_messages($to, $count) {
251
+ $messages = array();
252
+ for ($i = 0; $i < $count; $i++) {
253
+ $messages[] = self::get_test_message($to, '[' . get_option('blogname') . '] Test message ' . ($i + 1) . ' from Newsletter (' . date(DATE_ISO8601) . ')');
254
+ }
255
+ return $messages;
256
+ }
257
+
258
+ }
259
+
260
+ /**
261
+ */
262
+ class NewsletterMailer {
263
+
264
+ const ERROR_GENERIC = '1';
265
+ const ERROR_FATAL = '2';
266
+
267
+ /* @var NewsletterLogger */
268
+
269
+ var $logger;
270
+ var $name;
271
+ var $options;
272
+ private $delta;
273
+ protected $batch_size = 1;
274
+
275
+ public function __construct($name, $options = array()) {
276
+ $this->name = $name;
277
+ $this->options = $options;
278
+ }
279
+
280
+ public function get_name() {
281
+ return $this->name;
282
+ }
283
+
284
+ public function get_description() {
285
+ return $this->name;
286
+ }
287
+
288
+ public function get_batch_size() {
289
+ return $this->batch_size;
290
+ }
291
+
292
+ function send_with_stats($message) {
293
+ $this->delta = microtime(true);
294
+ $r = $this->send($message);
295
+ $this->delta = microtime(true) - $this->delta;
296
+ return $r;
297
+ }
298
+
299
+ /**
300
+ *
301
+ * @param TNP_Mailer_Message $message
302
+ * @return bool|WP_Error
303
+ */
304
+ public function send($message) {
305
+ $message->error = 'No mailing system available';
306
+ return new WP_Error(self::ERROR_FATAL, 'No mailing system available');
307
+ }
308
+
309
+ public function send_batch_with_stats($messages) {
310
+ $this->delta = microtime(true);
311
+ $r = $this->send_batch($messages);
312
+ $this->delta = microtime(true) - $this->delta;
313
+ return $r;
314
+ }
315
+
316
+ function get_capability() {
317
+ return (int) (3600 * $this->batch_size / $this->delta);
318
+ }
319
+
320
+ /**
321
+ *
322
+ * @param TNP_Mailer_Message[] $messages
323
+ * @return bool|WP_Error
324
+ */
325
+ public function send_batch($messages) {
326
+
327
+ // We should not get there is the batch size is one, the caller should use "send()". We can get
328
+ // there if the array of messages counts to one, since could be the last of a series of chunks.
329
+ if ($this->batch_size == 1 || count($messages) == 1) {
330
+ //$this->get_logger()->debug('Caso 1 messaggio');
331
+ $last_result = true;
332
+ foreach ($messages as $message) {
333
+ $r = $this->send($message);
334
+ if (is_wp_error($r)) {
335
+ $last_result = $r;
336
+ }
337
+ }
338
+ return $last_result;
339
+ }
340
+
341
+ // We should always get there
342
+ if (count($messages) <= $this->batch_size) {
343
+ //$this->get_logger()->debug('Caso batch esatto');
344
+ return $this->send_chunk($messages);
345
+ }
346
+
347
+ //$this->get_logger()->debug('Caso bach troppo grande');
348
+ // We should not get here, since it is not optimized
349
+ $chunks = array_chunk($message, $this->batch_size);
350
+ $last_result = true;
351
+ foreach ($chunks as $chunk) {
352
+ $r = $this->send_chunk($chunk);
353
+ if (is_wp_error($r)) {
354
+ $last_result = $r;
355
+ }
356
+ }
357
+ return $last_result;
358
+ }
359
+
360
+ protected function send_chunk($messages) {
361
+ $last_result = true;
362
+ foreach ($messages as $message) {
363
+ $r = $this->send($message);
364
+ if (is_wp_error($r)) {
365
+ $last_result = $r;
366
+ }
367
+ }
368
+ return $last_result;
369
+ }
370
+
371
+ /**
372
+ *
373
+ * @return NewsletterLogger
374
+ */
375
+ function get_logger() {
376
+ if ($this->logger) {
377
+ return $this->logger;
378
+ }
379
+ $this->logger = new NewsletterLogger('mailer-' . $this->name);
380
+ return $this->logger;
381
+ }
382
+
383
+ /**
384
+ *
385
+ * @param TNP_Mailer_Message $message
386
+ * @return bool|WP_Error
387
+ */
388
+ public function enqueue(TNP_Mailer_Message $message) {
389
+ // Optimization when there is no queue
390
+ if ($this->queue_max == 0) {
391
+ $r = $this->send($message);
392
+ return $r;
393
+ }
394
+
395
+ $this->queue[] = $message;
396
+ if (count($this->queue) >= $this->queue_max) {
397
+ return $this->flush();
398
+ }
399
+ return true;
400
+ }
401
+
402
+ public function flush() {
403
+ $undelivered = array();
404
+ foreach ($this->queue as $message) {
405
+ $r = $this->deliver($message);
406
+ if (is_wp_error($r)) {
407
+ $message->error = $r;
408
+ $undelivered[] = $message;
409
+ }
410
+ }
411
+
412
+ $this->queue = array();
413
+
414
+ if ($undelivered) {
415
+ return new WP_Error(self::ERROR_GENERAL, 'Error while flushing messages', $undelivered);
416
+ }
417
+
418
+ return true;
419
+ }
420
+
421
+ /**
422
+ * Original mail function simulation for compatibility.
423
+ * @deprecated
424
+ *
425
+ * @param string $to
426
+ * @param string $subject
427
+ * @param array $message
428
+ * @param array $headers
429
+ * @param bool $enqueue
430
+ * @param type $from Actually ignored
431
+ * @return type
432
+ */
433
+ public function mail($to, $subject, $message, $headers = null, $enqueue = false, $from = false) {
434
+ $mailer_message = new TNP_Mailer_Message();
435
+ $mailer_message->to = $to;
436
+ $mailer_message->subject = $subject;
437
+ $mailer_message->headers = $headers;
438
+ $mailer_message->body = $message['html'];
439
+ $mailer_message->body_text = $message['text'];
440
+
441
+ if ($enqueue) {
442
+ return !is_wp_error($this->enqueue($mailer_message));
443
+ }
444
+ return !is_wp_error($this->send($mailer_message));
445
+ }
446
+
447
+ function save_last_run($time) {
448
+ update_option($this->prefix . '_last_run', $time);
449
+ }
450
+
451
+ function get_last_run() {
452
+ return (int) get_option($this->prefix . '_last_run', 0);
453
+ }
454
+
455
+ }
456
+
457
+ /**
458
+ * @property string $to
459
+ * @property string $subject
460
+ * @property string $body
461
+ * @property array $headers
462
+ * @property string $from
463
+ * @property string $from_name
464
+ */
465
+ class TNP_Mailer_Message {
466
+
467
+ var $to_name = '';
468
+ var $headers = array();
469
+ var $user_id = 0;
470
+ var $email_id = 0;
471
+ var $error = '';
472
+ var $body_text = '';
473
+
474
+ }
475
+
476
  class NewsletterModule {
477
 
478
  /**
2269
  return $url;
2270
  }
2271
 
2272
+ static function clean_eol($text) {
2273
+ $text = str_replace("\r\n", "\n", $text);
2274
+ $text = str_replace("\r", "\n", $text);
2275
+ $text = str_replace("\n", "\r\n", $text);
2276
+ return $text;
2277
+ }
2278
+
2279
  /**
2280
  * Return the current language code. Optionally, if a user is passed and it has a language
2281
  * the user language is returned.
main/main.php CHANGED
@@ -330,13 +330,6 @@ if (!empty($return_path)) {
330
  </td>
331
  </tr>
332
 
333
- <tr>
334
- <th><?php _e('Send email directly', 'newsletter') ?></th>
335
- <td>
336
- <?php $controls->yesno('phpmailer'); ?>
337
- <?php $controls->help('https://www.thenewsletterplugin.com/configuration-tnin-send-email'); ?>
338
- </td>
339
- </tr>
340
  <tr>
341
  <th><?php _e('Email encoding', 'newsletter') ?></th>
342
  <td>
330
  </td>
331
  </tr>
332
 
 
 
 
 
 
 
 
333
  <tr>
334
  <th><?php _e('Email encoding', 'newsletter') ?></th>
335
  <td>
main/smtp.php CHANGED
@@ -23,69 +23,18 @@ if (!$controls->is_action()) {
23
  }
24
 
25
  if ($controls->is_action('test')) {
26
-
27
- require_once ABSPATH . WPINC . '/class-phpmailer.php';
28
- require_once ABSPATH . WPINC . '/class-smtp.php';
29
- $mail = new PHPMailer();
30
- ob_start();
31
- $mail->IsSMTP();
32
- $mail->SMTPDebug = true;
33
- $mail->CharSet = 'UTF-8';
34
- $message = 'This Email is sent by PHPMailer of WordPress';
35
- $mail->IsHTML(false);
36
- $mail->Body = $message;
37
- $mail->From = $module->options['sender_email'];
38
- $mail->FromName = $module->options['sender_name'];
39
- if (!empty($module->options['return_path'])) {
40
- $mail->Sender = $module->options['return_path'];
41
- }
42
- if (!empty($module->options['reply_to'])) {
43
- $mail->AddReplyTo($module->options['reply_to']);
44
- }
45
-
46
- $mail->Subject = '[' . get_option('blogname') . '] SMTP test';
47
-
48
- $mail->Host = $controls->data['host'];
49
- if (!empty($controls->data['port'])) {
50
- $mail->Port = (int) $controls->data['port'];
51
- }
52
-
53
- $mail->SMTPSecure = $controls->data['secure'];
54
- $mail->SMTPAutoTLS = false;
55
 
56
- if ($controls->data['ssl_insecure'] == 1) {
57
- $mail->SMTPOptions = array(
58
- 'ssl' => array(
59
- 'verify_peer' => false,
60
- 'verify_peer_name' => false,
61
- 'allow_self_signed' => true
62
- )
63
- );
64
- }
65
-
66
- if (!empty($controls->data['user'])) {
67
- $mail->SMTPAuth = true;
68
- $mail->Username = $controls->data['user'];
69
- $mail->Password = $controls->data['pass'];
70
- }
71
-
72
- $mail->SMTPKeepAlive = true;
73
- $mail->ClearAddresses();
74
- $mail->AddAddress($controls->data['test_email']);
75
-
76
- $mail->Send();
77
- $mail->SmtpClose();
78
- $debug = htmlspecialchars(ob_get_clean());
79
 
80
- if ($mail->IsError()) {
81
- $controls->errors = '<strong>Connection/email delivery failed.</strong><br>You should contact your provider reporting the SMTP parameter and asking about connection to that SMTP.<br><br>';
82
- $controls->errors = $mail->ErrorInfo;
83
- } else
84
  $controls->messages = 'Success.';
85
-
86
- $controls->messages .= '<textarea style="width:100%; height:200px; font-size:12px; font-family: monospace">';
87
- $controls->messages .= $debug;
88
- $controls->messages .= '</textarea>';
89
  }
90
  }
91
 
23
  }
24
 
25
  if ($controls->is_action('test')) {
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
26
 
27
+ $mailer = new NewsletterDefaultSMTPMailer($controls->data);
28
+ $message = NewsletterMailerAddon::get_test_message($controls->data['test_email']);
29
+
30
+ $r = $mailer->send($message);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
31
 
32
+ if (is_wp_error($r)) {
33
+ $controls->errors = $r->get_error_message();
34
+ } else {
 
35
  $controls->messages = 'Success.';
36
+ }
37
+
 
 
38
  }
39
  }
40
 
main/status.php CHANGED
@@ -75,49 +75,30 @@ if ($controls->is_action('test')) {
75
  $controls->messages .= '<strong>Warning:</strong> you are using as test email the same address configured as sender in main configuration. Test can fail because of that.<br>';
76
  }
77
 
78
- // Newsletter mail
79
- $text = array();
80
- $text['html'] = '<p>This is an <b>HTML</b> test email sent using the sender data set on Newsletter main setting. <a href="https://www.thenewsletterplugin.com">This is a link to an external site</a>.</p>';
81
- $text['text'] = 'This is a textual test email part sent using the sender data set on Newsletter main setting.';
82
- $r = $module->mail($controls->data['test_email'], 'Newsletter test email at ' . date(DATE_ISO8601), $text);
83
-
84
- $controls->messages .= 'Email sent with Newsletter';
85
- if ($module->the_mailer) {
86
- $controls->messages .= ' (with a mailer extension)';
87
- } else if ($module->mail_method) {
88
- $controls->messages .= ' (with a mail delivery extension)';
89
- } else {
90
- $smtp_options = $module->get_smtp_options();
91
-
92
- if (!empty($smtp_options['enabled'])) {
93
- $controls->messages .= ' (with an SMTP)';
94
- }
95
- }
96
- $controls->messages .= ': ';
97
-
98
- if ($r) {
99
  $options['mail'] = 1;
100
  $controls->messages .= '<strong>SUCCESS</strong><br>';
101
  } else {
102
  $options['mail'] = 0;
103
- $options['mail_error'] = $module->mail_last_error;
104
 
105
- $controls->messages .= '<strong>FAILED</strong> (' . $module->mail_last_error . ')<br>';
106
-
107
- if ($module->mail_method) {
108
- $controls->messages .= '- You are using a mail delivery extension. Check and test its configuration.<br>';
109
- } else {
110
- $smtp_options = $module->get_smtp_options();
111
- if (!empty($smtp_options['enabled'])) {
112
- $controls->messages .= '- You are using an SMTP (' . $smtp_options['host'] . '). Check its configuration on main configuration or on SMTP Newsletter extensions if used.<br>';
113
- }
114
- }
115
 
116
  if (!empty($module->options['return_path'])) {
117
- $controls->messages .= '- Try to remove the return path on main settings.<br>';
118
  }
119
 
120
- $controls->messages .= '<a href="https://www.thenewsletterplugin.com/documentation/email-sending-issues" target="_blank"><strong>' . __('Read more', 'newsletter') . '</strong></a>.';
121
 
122
  $parts = explode('@', $module->options['sender_email']);
123
  $sitename = strtolower($_SERVER['SERVER_NAME']);
@@ -125,7 +106,7 @@ if ($controls->is_action('test')) {
125
  $sitename = substr($sitename, 4);
126
  }
127
  if (strtolower($sitename) != strtolower($parts[1])) {
128
- $controls->messages .= '- Try to set on main setting a sender address with the same domain of your blog: ' . $sitename . ' (you are using ' . $module->options['sender_email'] . ')<br>';
129
  }
130
  }
131
  $module->save_options($options, 'status');
@@ -220,6 +201,26 @@ $speed = Newsletter::$instance->options['scheduler_max'];
220
  </td>
221
 
222
  </tr>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
223
  <tr>
224
  <td>Mailing</td>
225
  <td>
75
  $controls->messages .= '<strong>Warning:</strong> you are using as test email the same address configured as sender in main configuration. Test can fail because of that.<br>';
76
  }
77
 
78
+ $message = new TNP_Mailer_Message();
79
+ $message->body = '<p>This is an <b>HTML</b> test email sent using the sender data set on Newsletter main setting. <a href="https://www.thenewsletterplugin.com">This is a link to an external site</a>.</p>';
80
+ $message->body_text = 'This is a textual test email part sent using the sender data set on Newsletter main setting.';
81
+ $message->to = $controls->data['test_email'];
82
+ $message->subject = 'Newsletter test email at ' . date(DATE_ISO8601);
83
+ $message->from = $module->options['sender_email'];
84
+ $message->from_name = $module->options['sender_name'];
85
+
86
+ $r = $module->deliver($message);
87
+
88
+ if (!is_wp_error($r)) {
 
 
 
 
 
 
 
 
 
 
89
  $options['mail'] = 1;
90
  $controls->messages .= '<strong>SUCCESS</strong><br>';
91
  } else {
92
  $options['mail'] = 0;
93
+ $options['mail_error'] = $r->get_error_message();
94
 
95
+ $controls->errors .= '<strong>FAILED</strong> (' . $r->get_error_message() . ')<br>';
 
 
 
 
 
 
 
 
 
96
 
97
  if (!empty($module->options['return_path'])) {
98
+ $controls->errors .= '- Try to remove the return path on main settings.<br>';
99
  }
100
 
101
+ $controls->errors .= '<a href="https://www.thenewsletterplugin.com/documentation/email-sending-issues" target="_blank"><strong>' . __('Read more', 'newsletter') . '</strong></a>.';
102
 
103
  $parts = explode('@', $module->options['sender_email']);
104
  $sitename = strtolower($_SERVER['SERVER_NAME']);
106
  $sitename = substr($sitename, 4);
107
  }
108
  if (strtolower($sitename) != strtolower($parts[1])) {
109
+ $controls->errors .= '- Try to set on main setting a sender address with the same domain of your blog: ' . $sitename . ' (you are using ' . $module->options['sender_email'] . ')<br>';
110
  }
111
  }
112
  $module->save_options($options, 'status');
201
  </td>
202
 
203
  </tr>
204
+ <tr>
205
+ <td>Mailer</td>
206
+ <td>
207
+ &nbsp;
208
+ </td>
209
+ <td>
210
+ <?php
211
+ $mailer = Newsletter::instance()->get_mailer();
212
+ $name = 'Unknown';
213
+ if (is_object($mailer)) {
214
+ if (method_exists($mailer, 'get_description')) {
215
+ $name = $mailer->get_description();
216
+ } else {
217
+ $name = get_class($mailer);
218
+ }
219
+ }
220
+ ?>
221
+
222
+ <?php echo esc_html($name) ?>
223
+ </td>
224
  <tr>
225
  <td>Mailing</td>
226
  <td>
plugin.php CHANGED
@@ -4,7 +4,7 @@
4
  Plugin Name: Newsletter
5
  Plugin URI: https://www.thenewsletterplugin.com/plugins/newsletter
6
  Description: Newsletter is a cool plugin to create your own subscriber list, to send newsletters, to build your business. <strong>Before update give a look to <a href="https://www.thenewsletterplugin.com/category/release">this page</a> to know what's changed.</strong>
7
- Version: 6.2.2
8
  Author: Stefano Lissa & The Newsletter Team
9
  Author URI: https://www.thenewsletterplugin.com
10
  Disclaimer: Use at your own risk. No warranty expressed or implied is provided.
@@ -29,7 +29,7 @@
29
  */
30
 
31
  // Used as dummy parameter on css and js links
32
- define('NEWSLETTER_VERSION', '6.2.2');
33
 
34
  global $newsletter, $wpdb;
35
 
@@ -81,6 +81,7 @@ if (!defined('NEWSLETTER_DEBUG'))
81
  require_once NEWSLETTER_INCLUDES_DIR . '/logger.php';
82
  require_once NEWSLETTER_INCLUDES_DIR . '/store.php';
83
  require_once NEWSLETTER_INCLUDES_DIR . '/module.php';
 
84
  require_once NEWSLETTER_INCLUDES_DIR . '/themes.php';
85
  require_once NEWSLETTER_INCLUDES_DIR . '/TNP.php';
86
 
@@ -157,9 +158,6 @@ class Newsletter extends NewsletterModule {
157
  //add_action('newsletter_extension_versions', array($this, 'hook_newsletter_extension_versions'), 1);
158
  add_action('plugins_loaded', array($this, 'hook_plugins_loaded'));
159
 
160
- // This specific event is created by "Feed by mail" panel on configuration
161
- add_action('shutdown', array($this, 'hook_shutdown'));
162
-
163
  $this->update_cron_stats();
164
 
165
  register_activation_hook(__FILE__, array($this, 'hook_activate'));
@@ -459,9 +457,8 @@ class Newsletter extends NewsletterModule {
459
  echo 'ok';
460
  die();
461
  }
462
-
463
- do_action('newsletter_action', $this->action);
464
 
 
465
  }
466
 
467
  function hook_in_admin_header() {
@@ -585,7 +582,7 @@ class Newsletter extends NewsletterModule {
585
  *
586
  * @global wpdb $wpdb
587
  * @global type $newsletter_feed
588
- * @param type $email
589
  * @param array $users
590
  * @return boolean True if the proccess completed, false if limits was reached. On false the caller should no continue to call it with other emails.
591
  */
@@ -619,6 +616,8 @@ class Newsletter extends NewsletterModule {
619
  $email->query = "select * from " . NEWSLETTER_USERS_TABLE . " where status='C'";
620
  }
621
 
 
 
622
  $email->options = maybe_unserialize($email->options);
623
  $max_emails = apply_filters('newsletter_send_max_emails', $this->max_emails, $email);
624
 
@@ -659,67 +658,76 @@ class Newsletter extends NewsletterModule {
659
  $count = 0;
660
  $result = true;
661
 
662
- foreach ($users as $user) {
663
- $this->logger->debug('send> Processing user ID: ' . $user->id);
664
 
665
- // Before try to send, check the limits.
666
- if (!$test && $this->limits_exceeded()) {
667
- $result = false;
668
- break;
669
- }
670
-
671
- $headers = array('List-Unsubscribe' => '<' . $this->build_action_url('u', $user, $email) . '>');
672
- $headers['Precedence'] = 'bulk';
673
- $headers['X-Newsletter-Email-Id'] = $email->id;
674
 
 
 
 
 
 
 
 
675
 
676
- if (!$test) {
677
- $wpdb->query("update " . NEWSLETTER_EMAILS_TABLE . " set sent=sent+1, last_id=" . $user->id . " where id=" . $email->id . " limit 1");
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
678
  }
 
 
679
 
680
- $user = apply_filters('newsletter_send_user', $user);
681
-
682
- $m = preg_replace('/data-json=".*?"/is', '', $email->message);
683
- $m = preg_replace('/ +/s', ' ', $m);
684
- $m = $this->replace($m, $user, $email);
685
- $mt = $this->replace($email->message_text, $user, $email);
686
-
687
- $m = apply_filters('newsletter_message_html', $m, $email, $user);
688
 
689
- if ($email->track == 1) {
690
- $m = $this->relink($m, $email->id, $user->id, $email->token);
691
- }
692
-
693
- $s = $this->replace($email->subject, $user);
694
- $s = apply_filters('newsletter_message_subject', $s, $email, $user);
695
 
696
- $r = $this->mail($user->email, $s, array('html' => $m, 'text' => $mt), $headers, true);
697
 
698
- $status = $r ? 0 : 1;
 
 
699
 
700
- if (!$test) {
701
- $this->save_sent($user, $email);
702
- }
703
 
704
- $this->email_limit--;
705
- $count++;
706
- }
 
 
 
 
707
 
 
708
 
709
- if ($this->the_mailer != null) {
710
- $this->logger->debug('Flushing and checking errors');
711
- $this->the_mailer->flush();
712
- if (method_exists($this->the_mailer, 'get_errors')) {
713
- $errors = $this->the_mailer->get_errors();
714
- foreach ($errors as $error) {
715
- $this->logger->debug('Error on email ' . $error['email']);
716
- $this->save_sent($error['email'], $email, 1, $error['message']);
717
  }
718
- }
719
 
720
- $this->logger->debug('Clearing errors');
721
- if (method_exists($this->the_mailer, 'get_errors')) {
722
- $this->the_mailer->clear_errors();
723
  }
724
  }
725
 
@@ -737,6 +745,49 @@ class Newsletter extends NewsletterModule {
737
  return $result;
738
  }
739
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
740
  function save_sent($user, $email, $status = 0, $error = '') {
741
  global $wpdb;
742
  //$this->logger->debug('Saving sent data');
@@ -814,170 +865,84 @@ class Newsletter extends NewsletterModule {
814
  }
815
 
816
  /**
817
- *
818
- * @param string $to
819
- * @param string $subject
820
- * @param string|array $message
821
- * @param type $headers
822
- * @return boolean
823
  */
824
- var $mail_method = null;
825
-
826
  function register_mail_method($callable) {
827
- $this->mail_method = $callable;
828
  }
829
 
830
- var $the_mailer = null;
831
-
832
  function register_mailer($mailer) {
833
- $this->the_mailer = $mailer;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
834
  }
835
 
836
- var $mail_last_error = '';
837
 
838
- function mail($to, $subject, $message, $headers = null, $enqueue = false) {
839
- $this->mail_last_error = '';
840
- //$this->logger->debug('mail> To: ' . $to);
841
- //$this->logger->debug('mail> Subject: ' . $subject);
842
  if (empty($subject)) {
843
  $this->logger->error('mail> Subject empty, skipped');
844
  return true;
845
  }
846
 
847
- if (!$headers) {
848
- $headers = array();
849
- }
850
 
851
- $headers['X-Auto-Response-Suppress'] = 'OOF, AutoReply';
 
 
 
852
 
853
  // Message carrige returns and line feeds clean up
854
  if (!is_array($message)) {
855
- $message = str_replace("\r\n", "\n", $message);
856
- $message = str_replace("\r", "\n", $message);
857
- $message = str_replace("\n", "\r\n", $message);
858
  } else {
859
  if (!empty($message['text'])) {
860
- $message['text'] = str_replace("\r\n", "\n", $message['text']);
861
- $message['text'] = str_replace("\r", "\n", $message['text']);
862
- $message['text'] = str_replace("\n", "\r\n", $message['text']);
863
  }
864
 
865
  if (!empty($message['html'])) {
866
- $message['html'] = str_replace("\r\n", "\n", $message['html']);
867
- $message['html'] = str_replace("\r", "\n", $message['html']);
868
- $message['html'] = str_replace("\n", "\r\n", $message['html']);
869
  }
870
  }
871
 
872
- if ($this->the_mailer != null) {
873
- $r = $this->the_mailer->mail($to, $subject, $message, $headers, $enqueue);
874
- if (is_wp_error($r)) {
875
- /* @var $r WP_Error */
876
- $this->mail_last_error = $r->get_error_message();
877
- return false;
878
- }
879
- return true;
880
- }
881
 
 
882
 
883
- if ($this->mail_method != null) {
884
- //$this->logger->debug('mail> alternative mail method found');
885
- return call_user_func($this->mail_method, $to, $subject, $message, $headers);
886
- }
887
-
888
- if ($this->mailer == null) {
889
- $this->mailer_init();
890
- }
891
-
892
- if ($this->mailer == null) {
893
- // If still null, we need to use wp_mail()...
894
-
895
- $wp_mail_headers = array();
896
-
897
- $wp_mail_headers[] = 'From: ' . $this->options['sender_name'] . ' <' . $this->options['sender_email'] . '>';
898
-
899
- if (!empty($this->options['return_path'])) {
900
- $wp_mail_headers[] = 'Return-Path: ' . $this->options['return_path'];
901
- }
902
- if (!empty($this->options['reply_to'])) {
903
- $wp_mail_headers[] = 'Reply-To: ' . $this->options['reply_to'];
904
- }
905
-
906
- if (!is_array($message)) {
907
- $wp_mail_headers[] = 'Content-Type: text/html;charset=UTF-8';
908
- $body = $message;
909
- } else {
910
- // Only html is present?
911
- if (!empty($message['html'])) {
912
- $wp_mail_headers[] = 'Content-Type: text/html;charset=UTF-8';
913
-
914
- $body = $message['html'];
915
- } else if (!empty($message['text'])) {
916
- $wp_mail_headers[] = 'Content-Type: text/plain;charset=UTF-8';
917
- //$this->mailer->IsHTML(false);
918
- $body = $message['text'];
919
- }
920
- }
921
-
922
- if (is_array($headers)) {
923
- foreach ($headers as $key => $value) {
924
- $wp_mail_headers[] = $key . ': ' . $value;
925
- }
926
- }
927
-
928
- $r = wp_mail($to, $subject, $body, $wp_mail_headers);
929
- if (!$r) {
930
- $last_error = error_get_last();
931
- if (is_array($last_error)) {
932
- $this->mail_last_error = $last_error['message'];
933
- }
934
- }
935
- return $r;
936
- }
937
-
938
- // Simple message is asumed to be html
939
- if (!is_array($message)) {
940
- $this->mailer->IsHTML(true);
941
- $this->mailer->Body = $message;
942
- } else {
943
- // Only html is present?
944
- if (empty($message['text'])) {
945
- $this->mailer->IsHTML(true);
946
- $this->mailer->Body = $message['html'];
947
- }
948
- // Only text is present?
949
- else if (empty($message['html'])) {
950
- $this->mailer->IsHTML(false);
951
- $this->mailer->Body = $message['text'];
952
- } else {
953
- $this->mailer->IsHTML(true);
954
- $this->mailer->Body = $message['html'];
955
- $this->mailer->AltBody = $message['text'];
956
- }
957
- }
958
-
959
- $this->mailer->Subject = $subject;
960
-
961
- $this->mailer->ClearCustomHeaders();
962
- if (!empty($headers)) {
963
- foreach ($headers as $key => $value) {
964
- $this->mailer->AddCustomHeader($key . ': ' . $value);
965
- }
966
- }
967
-
968
- $this->mailer->ClearAddresses();
969
- $this->mailer->AddAddress($to);
970
- $this->mailer->Send();
971
-
972
- if ($this->mailer->IsError()) {
973
- $this->mail_last_error = $this->mailer->ErrorInfo;
974
- $this->logger->error('mail> ' . $this->mailer->ErrorInfo);
975
- // If the error is due to SMTP connection, the mailer cannot be reused since it does not clean up the connection
976
- // on error.
977
- $this->mailer = null;
978
- return false;
979
- }
980
- return true;
981
  }
982
 
983
  /**
@@ -989,68 +954,6 @@ class Newsletter extends NewsletterModule {
989
  return $smtp_options;
990
  }
991
 
992
- function mailer_init() {
993
- require_once ABSPATH . WPINC . '/class-phpmailer.php';
994
- require_once ABSPATH . WPINC . '/class-smtp.php';
995
-
996
- $smtp_options = $this->get_smtp_options();
997
-
998
-
999
- if ($smtp_options['enabled'] == 1) {
1000
- $this->mailer = new PHPMailer();
1001
- $this->mailer->IsSMTP();
1002
- $this->mailer->Host = $smtp_options['host'];
1003
- if (!empty($smtp_options['port']))
1004
- $this->mailer->Port = (int) $smtp_options['port'];
1005
-
1006
- if (!empty($smtp_options['user'])) {
1007
- $this->mailer->SMTPAuth = true;
1008
- $this->mailer->Username = $smtp_options['user'];
1009
- $this->mailer->Password = $smtp_options['pass'];
1010
- }
1011
- $this->mailer->SMTPKeepAlive = true;
1012
- $this->mailer->SMTPSecure = $smtp_options['secure'];
1013
- $this->mailer->SMTPAutoTLS = false;
1014
-
1015
- if ($smtp_options['ssl_insecure'] == 1) {
1016
- $this->mailer->SMTPOptions = array(
1017
- 'ssl' => array(
1018
- 'verify_peer' => false,
1019
- 'verify_peer_name' => false,
1020
- 'allow_self_signed' => true
1021
- )
1022
- );
1023
- }
1024
- } else {
1025
- if ($this->options['phpmailer'] == 1) {
1026
- $this->mailer = new PHPMailer();
1027
- $this->mailer->IsMail();
1028
- } else {
1029
- $this->mailer = null;
1030
- return;
1031
- }
1032
- }
1033
-
1034
- if (!empty($this->options['content_transfer_encoding'])) {
1035
- $this->mailer->Encoding = $this->options['content_transfer_encoding'];
1036
- } else {
1037
- $this->mailer->Encoding = 'base64';
1038
- }
1039
-
1040
- $this->mailer->CharSet = 'UTF-8';
1041
- $this->mailer->From = $this->options['sender_email'];
1042
-
1043
- $return_path = $this->options['return_path'];
1044
- if (!empty($return_path)) {
1045
- $this->mailer->Sender = $return_path;
1046
- }
1047
- if (!empty($this->options['reply_to'])) {
1048
- $this->mailer->AddReplyTo($this->options['reply_to']);
1049
- }
1050
-
1051
- $this->mailer->FromName = $this->options['sender_name'];
1052
- }
1053
-
1054
  function hook_deactivate() {
1055
  wp_clear_scheduled_hook('newsletter');
1056
  }
@@ -1058,7 +961,7 @@ class Newsletter extends NewsletterModule {
1058
  function hook_cron_schedules($schedules) {
1059
  $schedules['newsletter'] = array(
1060
  'interval' => NEWSLETTER_CRON_INTERVAL, // seconds
1061
- 'display' => 'Newsletter'
1062
  );
1063
  return $schedules;
1064
  }
@@ -1092,25 +995,20 @@ class Newsletter extends NewsletterModule {
1092
  return $file2;
1093
  }
1094
 
1095
- function hook_shutdown() {
1096
- if ($this->mailer != null)
1097
- $this->mailer->SmtpClose();
1098
- }
1099
-
1100
  function hook_site_transient_update_plugins($value) {
1101
  static $extra_response = array();
1102
-
1103
  //$this->logger->debug('Update plugins transient called');
1104
-
1105
  if (!$value || !is_object($value)) {
1106
  //$this->logger->info('Empty object');
1107
  return $value;
1108
  }
1109
-
1110
  if (!isset($value->response) || !is_array($value->response)) {
1111
  $value->response = array();
1112
  }
1113
-
1114
  if ($extra_response) {
1115
  //$this->logger->debug('Already updated');
1116
  $value->response = array_merge($value->response, $extra_response);
@@ -1118,9 +1016,10 @@ class Newsletter extends NewsletterModule {
1118
  }
1119
 
1120
  $extensions = $this->getTnpExtensions();
1121
-
1122
- if (!$extensions) return $value;
1123
-
 
1124
  foreach ($extensions as $extension) {
1125
  unset($value->response[$extension->wp_slug]);
1126
  unset($value->no_update[$extension->wp_slug]);
@@ -1137,11 +1036,11 @@ class Newsletter extends NewsletterModule {
1137
  //$this->logger->error('No get_plugin_data function available!');
1138
  return $value;
1139
  }
1140
-
1141
  $license_key = $this->get_license_key();
1142
 
1143
  foreach ($extensions as $extension) {
1144
-
1145
  // Patch for names convention
1146
  $extension->plugin = $extension->wp_slug;
1147
 
@@ -1191,9 +1090,9 @@ class Newsletter extends NewsletterModule {
1191
  }
1192
  //$this->logger->debug('Added');
1193
  }
1194
-
1195
  $value->response = array_merge($value->response, $extra_response);
1196
-
1197
  return $value;
1198
  }
1199
 
4
  Plugin Name: Newsletter
5
  Plugin URI: https://www.thenewsletterplugin.com/plugins/newsletter
6
  Description: Newsletter is a cool plugin to create your own subscriber list, to send newsletters, to build your business. <strong>Before update give a look to <a href="https://www.thenewsletterplugin.com/category/release">this page</a> to know what's changed.</strong>
7
+ Version: 6.3.0
8
  Author: Stefano Lissa & The Newsletter Team
9
  Author URI: https://www.thenewsletterplugin.com
10
  Disclaimer: Use at your own risk. No warranty expressed or implied is provided.
29
  */
30
 
31
  // Used as dummy parameter on css and js links
32
+ define('NEWSLETTER_VERSION', '6.3.0');
33
 
34
  global $newsletter, $wpdb;
35
 
81
  require_once NEWSLETTER_INCLUDES_DIR . '/logger.php';
82
  require_once NEWSLETTER_INCLUDES_DIR . '/store.php';
83
  require_once NEWSLETTER_INCLUDES_DIR . '/module.php';
84
+ require_once NEWSLETTER_INCLUDES_DIR . '/mailers.php';
85
  require_once NEWSLETTER_INCLUDES_DIR . '/themes.php';
86
  require_once NEWSLETTER_INCLUDES_DIR . '/TNP.php';
87
 
158
  //add_action('newsletter_extension_versions', array($this, 'hook_newsletter_extension_versions'), 1);
159
  add_action('plugins_loaded', array($this, 'hook_plugins_loaded'));
160
 
 
 
 
161
  $this->update_cron_stats();
162
 
163
  register_activation_hook(__FILE__, array($this, 'hook_activate'));
457
  echo 'ok';
458
  die();
459
  }
 
 
460
 
461
+ do_action('newsletter_action', $this->action);
462
  }
463
 
464
  function hook_in_admin_header() {
582
  *
583
  * @global wpdb $wpdb
584
  * @global type $newsletter_feed
585
+ * @param TNP_Email $email
586
  * @param array $users
587
  * @return boolean True if the proccess completed, false if limits was reached. On false the caller should no continue to call it with other emails.
588
  */
616
  $email->query = "select * from " . NEWSLETTER_USERS_TABLE . " where status='C'";
617
  }
618
 
619
+ // TODO: Ask the max emails per hour/run (to be decided) to the mailer
620
+
621
  $email->options = maybe_unserialize($email->options);
622
  $max_emails = apply_filters('newsletter_send_max_emails', $this->max_emails, $email);
623
 
658
  $count = 0;
659
  $result = true;
660
 
661
+ $mailer = $this->get_mailer();
 
662
 
663
+ // TODO: Reduce the $users to respect the limits
664
+ $batch_size = $mailer->get_batch_size();
 
 
 
 
 
 
 
665
 
666
+ // For batch size == 1 (normal condition) we optimize
667
+ if ($batch_size == 1) {
668
+ foreach ($users as $user) {
669
+ if (!$test && $this->limits_exceeded()) {
670
+ $result = false;
671
+ break;
672
+ }
673
 
674
+ $user = apply_filters('newsletter_send_user', $user);
675
+ $message = $this->build_message($email, $user);
676
+ $r = $mailer->send($message);
677
+ if (!$test) {
678
+ $wpdb->query("update " . NEWSLETTER_EMAILS_TABLE . " set sent=sent+1, last_id=" . $user->id . " where id=" . $email->id . " limit 1");
679
+ $this->save_sent($message->user_id, $email, !empty($message->error) ? 1 : 0, $message->error);
680
+
681
+ // Check the error level
682
+ if (is_wp_error($r) && $r->get_error_code() == NewsletterMailer::ERROR_FATAL) {
683
+ return $r;
684
+ }
685
+ } else {
686
+ if (is_wp_error($r)) return $r;
687
+ }
688
+ // TODO: Review if they're useful
689
+ $this->email_limit--;
690
+ $count++;
691
  }
692
+ } else {
693
+ $chunks = array_chunk($users, $batch_size);
694
 
695
+ foreach ($chunks as $chunk) {
 
 
 
 
 
 
 
696
 
697
+ // Before try to send, check the limits.
698
+ // TODO: Remove when the above todo is implemented
699
+ if (!$test && $this->limits_exceeded()) {
700
+ $result = false;
701
+ break;
702
+ }
703
 
704
+ $messages = array();
705
 
706
+ foreach ($chunk as $user) {
707
+ $this->logger->debug('send> Processing user ID: ' . $user->id);
708
+ $user = apply_filters('newsletter_send_user', $user);
709
 
710
+ $message = $this->build_message($email, $user);
 
 
711
 
712
+ $messages[] = $message;
713
+ if (!$test) {
714
+ $wpdb->query("update " . NEWSLETTER_EMAILS_TABLE . " set sent=sent+1, last_id=" . $user->id . " where id=" . $email->id . " limit 1");
715
+ }
716
+ $this->email_limit--;
717
+ $count++;
718
+ }
719
 
720
+ $r = $mailer->send_batch($messages);
721
 
722
+ if (!$test) {
723
+ foreach ($messages as $message) {
724
+ $this->save_sent($message->user_id, $email, !empty($message->error) ? 1 : 0, $message->error);
725
+ }
726
+ if (is_wp_error($r) && $r->get_error_code() == NewsletterMailer::ERROR_FATAL) {
727
+ return $r;
728
+ }
 
729
  }
 
730
 
 
 
 
731
  }
732
  }
733
 
745
  return $result;
746
  }
747
 
748
+ /**
749
+ *
750
+ * @param TNP_Email $email
751
+ * @param TNP_User $user
752
+ * @return \TNP_Mailer_Message
753
+ */
754
+ function build_message($email, $user) {
755
+
756
+ $message = new TNP_Mailer_Message();
757
+
758
+ $message->to = $user->email;
759
+
760
+ $message->headers = array('List-Unsubscribe' => '<' . $this->build_action_url('u', $user, $email) . '>');
761
+ $message->headers['Precedence'] = 'bulk';
762
+ $message->headers['X-Newsletter-Email-Id'] = $email->id;
763
+ $message->headers['X-Auto-Response-Suppress'] = 'OOF, AutoReply';
764
+ $message->headers = apply_filters('newsletter_message_headers', $message->headers, $email, $user);
765
+
766
+ $message->body = preg_replace('/data-json=".*?"/is', '', $email->message);
767
+ $message->body = preg_replace('/ +/s', ' ', $message->body);
768
+ $message->body = $this->replace($message->body, $user, $email);
769
+ $message->body = apply_filters('newsletter_message_html', $message->body, $email, $user);
770
+
771
+ $message->body_text = $this->replace($email->message_text, $user, $email);
772
+ $message->body_text = apply_filters('newsletter_message_text', $message->body_text, $email, $user);
773
+
774
+ if ($email->track == 1) {
775
+ $message->body = $this->relink($message->body, $email->id, $user->id, $email->token);
776
+ }
777
+
778
+ $message->subject = $this->replace($email->subject, $user);
779
+ $message->subject = apply_filters('newsletter_message_subject', $message->subject, $email, $user);
780
+
781
+ // TODO: Use the $email properties when available
782
+ $message->from = $this->options['sender_email'];
783
+ $message->from_name = $this->options['sender_name'];
784
+
785
+ $message->email_id = $email->id;
786
+ $message->user_id = $user->id;
787
+
788
+ return $message;
789
+ }
790
+
791
  function save_sent($user, $email, $status = 0, $error = '') {
792
  global $wpdb;
793
  //$this->logger->debug('Saving sent data');
865
  }
866
 
867
  /**
868
+ * @deprecated since version 6.0.0
869
+ * @param callback $callable
 
 
 
 
870
  */
 
 
871
  function register_mail_method($callable) {
872
+ $this->mailer = new NewsletterMailMethodWrapper($callable);
873
  }
874
 
 
 
875
  function register_mailer($mailer) {
876
+ //$this->logger->debug($mailer);
877
+ if (!$mailer) return;
878
+ if ($mailer instanceof NewsletterMailer) {
879
+ $this->mailer = $mailer;
880
+ } else {
881
+ $this->logger->debug('Wrapping mailer: ' . get_class($mailer));
882
+ $this->mailer = new NewsletterOldMailerWrapper($mailer);
883
+ }
884
+ }
885
+
886
+ /**
887
+ * Returns the current registered mailer which must be used to send emails.
888
+ *
889
+ * @return NewsletterMailer
890
+ */
891
+ function get_mailer() {
892
+ //die('get mailer');
893
+ if ($this->mailer)
894
+ return $this->mailer;
895
+
896
+ do_action('newsletter_register_mailer');
897
+ if (!$this->mailer) {
898
+ $smtp = $this->get_options('smtp');
899
+ if (!empty($smtp['enabled'])) {
900
+ $this->mailer = new NewsletterDefaultSMTPMailer($smtp);
901
+ } else {
902
+ $this->mailer = new NewsletterDefaultMailer();
903
+ }
904
+ }
905
+ return $this->mailer;
906
+ }
907
+
908
+ function deliver($message) {
909
+ $mailer = $this->get_mailer();
910
+ return $mailer->send($message);
911
  }
912
 
913
+ function mail($to, $subject, $message, $headers = array(), $enqueue = false, $from = false) {
914
 
 
 
 
 
915
  if (empty($subject)) {
916
  $this->logger->error('mail> Subject empty, skipped');
917
  return true;
918
  }
919
 
920
+ $mailer_message = new TNP_Mailer_Message();
921
+ $mailer_message->to = $to;
 
922
 
923
+ if (!empty($headers)) {
924
+ $mailer_message->headers = $headers;
925
+ }
926
+ $mailer_message->headers['X-Auto-Response-Suppress'] = 'OOF, AutoReply';
927
 
928
  // Message carrige returns and line feeds clean up
929
  if (!is_array($message)) {
930
+ $mailer_message->body = $this->clean_eol($message);
 
 
931
  } else {
932
  if (!empty($message['text'])) {
933
+ $mailer_message->body_text = $this->clean_eol($message['text']);
 
 
934
  }
935
 
936
  if (!empty($message['html'])) {
937
+ $mailer_message->body = $this->clean_eol($message['html']);
 
 
938
  }
939
  }
940
 
941
+ $mailer = $this->get_mailer();
 
 
 
 
 
 
 
 
942
 
943
+ $r = $mailer->send($mailer_message);
944
 
945
+ return !is_wp_error($r);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
946
  }
947
 
948
  /**
954
  return $smtp_options;
955
  }
956
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
957
  function hook_deactivate() {
958
  wp_clear_scheduled_hook('newsletter');
959
  }
961
  function hook_cron_schedules($schedules) {
962
  $schedules['newsletter'] = array(
963
  'interval' => NEWSLETTER_CRON_INTERVAL, // seconds
964
+ 'display' => 'Every 5 minutes by Newsletter'
965
  );
966
  return $schedules;
967
  }
995
  return $file2;
996
  }
997
 
 
 
 
 
 
998
  function hook_site_transient_update_plugins($value) {
999
  static $extra_response = array();
1000
+
1001
  //$this->logger->debug('Update plugins transient called');
1002
+
1003
  if (!$value || !is_object($value)) {
1004
  //$this->logger->info('Empty object');
1005
  return $value;
1006
  }
1007
+
1008
  if (!isset($value->response) || !is_array($value->response)) {
1009
  $value->response = array();
1010
  }
1011
+
1012
  if ($extra_response) {
1013
  //$this->logger->debug('Already updated');
1014
  $value->response = array_merge($value->response, $extra_response);
1016
  }
1017
 
1018
  $extensions = $this->getTnpExtensions();
1019
+
1020
+ if (!$extensions)
1021
+ return $value;
1022
+
1023
  foreach ($extensions as $extension) {
1024
  unset($value->response[$extension->wp_slug]);
1025
  unset($value->no_update[$extension->wp_slug]);
1036
  //$this->logger->error('No get_plugin_data function available!');
1037
  return $value;
1038
  }
1039
+
1040
  $license_key = $this->get_license_key();
1041
 
1042
  foreach ($extensions as $extension) {
1043
+
1044
  // Patch for names convention
1045
  $extension->plugin = $extension->wp_slug;
1046
 
1090
  }
1091
  //$this->logger->debug('Added');
1092
  }
1093
+
1094
  $value->response = array_merge($value->response, $extra_response);
1095
+
1096
  return $value;
1097
  }
1098
 
readme.txt CHANGED
@@ -2,7 +2,7 @@
2
  Tags: email, email marketing, newsletter, newsletter subscribers, welcome email, signup forms, contact, lead generation, popup, marketing automation
3
  Requires at least: 3.4.0
4
  Tested up to: 5.2.3
5
- Stable tag: 6.2.2
6
  Requires PHP: 5.6
7
  Contributors: satollo,webagile,michael-travan
8
 
@@ -109,6 +109,14 @@ Thank you, The Newsletter Team
109
 
110
  == Changelog ==
111
 
 
 
 
 
 
 
 
 
112
  = 6.2.2 =
113
 
114
  * Fixed custom blocks style.css loading
@@ -289,6 +297,9 @@ Thank you, The Newsletter Team
289
 
290
  * Reverted back to select2 3.x
291
  * Added last_ip field for better geolocation
 
 
 
292
 
293
  = 5.8.4 =
294
 
2
  Tags: email, email marketing, newsletter, newsletter subscribers, welcome email, signup forms, contact, lead generation, popup, marketing automation
3
  Requires at least: 3.4.0
4
  Tested up to: 5.2.3
5
+ Stable tag: 6.3.0
6
  Requires PHP: 5.6
7
  Contributors: satollo,webagile,michael-travan
8
 
109
 
110
  == Changelog ==
111
 
112
+ = 6.3.0 =
113
+
114
+ * New mailer infrastructure: better compatibility and performance
115
+ * New [TEST] prefix for newsletter tests
116
+ * Fix on composer subject saving
117
+ * General performance improvements
118
+ * Fixed title display in header composer block
119
+
120
  = 6.2.2 =
121
 
122
  * Fixed custom blocks style.css loading
297
 
298
  * Reverted back to select2 3.x
299
  * Added last_ip field for better geolocation
300
+ * Changed the thumbnails folder from wp-content to wp-content/uploads
301
+ * Added a more uniform internal mailer management
302
+ * Improved the mail test on status panel
303
 
304
  = 5.8.4 =
305
 
users/index.php CHANGED
@@ -99,7 +99,7 @@ if ($controls->is_action('search')) {
99
  }
100
 
101
  // Eventually fix the page
102
- if ($controls->data['search_page'] < 0)
103
  $controls->data['search_page'] = 0;
104
  if ($controls->data['search_page'] > $last_page)
105
  $controls->data['search_page'] = $last_page;
99
  }
100
 
101
  // Eventually fix the page
102
+ if (!isset($controls->data['search_page']) || $controls->data['search_page'] < 0)
103
  $controls->data['search_page'] = 0;
104
  if ($controls->data['search_page'] > $last_page)
105
  $controls->data['search_page'] = $last_page;