Newsletter - Version 7.0.9

Version Description

  • [CAPTCHA] Fixed button label translation
  • [DELIVERY] Mailing fatal error management with newsletter stop and reporting
  • [SMTP] Marked obsolete the internal SMTP and made available the free SMTP addon
  • [DELIVERY] Bettere management of delivery fatal errors with a new "error" status for newsletters
  • [GENERAL] New log files panel
  • [IMPORT] Old import panel replaced by the new (really better) import addon (file, copy and paste, bounced addresses import)
  • [NEWSLETTERS] It's now possible to specify the sender name and email per newsletter (thanks to Matthew S.)
Download this release

Release Info

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

Code changes from version 7.0.8 to 7.0.9

admin.css CHANGED
@@ -24,7 +24,7 @@
24
  #tnp-wrap h4,
25
  #tnp-wrap input,
26
  #tnp-wrap select,
27
- #tnp-wrap textarea,
28
  #tnp-wrap button,
29
  #tnp-wrap li,
30
  #tnp-wrap a
@@ -181,7 +181,7 @@
181
  }
182
 
183
  /******************************************************************************
184
- * BODY
185
  ******************************************************************************/
186
 
187
  #tnp-body {
@@ -361,13 +361,15 @@ table.clicks {
361
  border-left: 5px solid #27AE60;
362
  }
363
 
364
- .tnp-notice a {
 
365
  color: #0073aa;
366
  text-decoration: none;
367
  font-weight: bold;
368
  }
369
 
370
- .tnp-notice a.tnp-dismiss {
 
371
  display: block;
372
  position: absolute;
373
  right: 10px;
@@ -1259,10 +1261,14 @@ iframe.tnp-editor-preview-desktop {
1259
  transition: width .6s ease;
1260
  }
1261
 
1262
- .tnp-progress.sent .tnp-progress-bar {
1263
  background-color: green;
1264
  }
1265
 
 
 
 
 
1266
  .tnp-progress-numbers {
1267
  text-align: center;
1268
  color: #666;
@@ -1273,45 +1279,37 @@ iframe.tnp-editor-preview-desktop {
1273
  font-style: italic;
1274
  }
1275
 
1276
- /* Email status label */
1277
- span.tnp-email-status-new {
1278
- background-color: #8E44AD;
1279
  padding: 2px 10px;
1280
  border-radius: 4px;
1281
  color: #fff;
1282
  white-space: nowrap;
1283
  }
1284
 
1285
- span.tnp-email-status-paused {
 
 
 
 
 
1286
  background-color: #95A5A6;
1287
- padding: 2px 10px;
1288
- border-radius: 4px;
1289
- color: #fff;
1290
- white-space: nowrap;
1291
  }
1292
 
1293
- span.tnp-email-status-sending {
1294
- background-color:#27AE60;
1295
- padding: 2px 10px;
1296
- border-radius: 4px;
1297
- color: #fff;
1298
- white-space: nowrap;
1299
  }
1300
 
1301
- span.tnp-email-status-scheduled {
1302
  background-color: #E67E22;
1303
- padding: 2px 10px;
1304
- border-radius: 4px;
1305
- color: #fff;
1306
- white-space: nowrap;
1307
  }
1308
 
1309
- span.tnp-email-status-sent {
1310
  background-color: #95A5A6;
1311
- padding: 2px 10px;
1312
- border-radius: 4px;
1313
- color: #fff;
1314
- white-space: nowrap;
1315
  }
1316
 
1317
  /* Schedule buttons styles */
24
  #tnp-wrap h4,
25
  #tnp-wrap input,
26
  #tnp-wrap select,
27
+ #tnp-wrap textarea,
28
  #tnp-wrap button,
29
  #tnp-wrap li,
30
  #tnp-wrap a
181
  }
182
 
183
  /******************************************************************************
184
+ * BODY
185
  ******************************************************************************/
186
 
187
  #tnp-body {
361
  border-left: 5px solid #27AE60;
362
  }
363
 
364
+ .tnp-notice a,
365
+ .tnp-warning a {
366
  color: #0073aa;
367
  text-decoration: none;
368
  font-weight: bold;
369
  }
370
 
371
+ .tnp-notice a.tnp-dismiss,
372
+ .tnp-warning a.tnp-dismiss{
373
  display: block;
374
  position: absolute;
375
  right: 10px;
1261
  transition: width .6s ease;
1262
  }
1263
 
1264
+ .tnp-progress--sent .tnp-progress-bar {
1265
  background-color: green;
1266
  }
1267
 
1268
+ .tnp-progress--error .tnp-progress-bar {
1269
+ background-color: #E74C3C;
1270
+ }
1271
+
1272
  .tnp-progress-numbers {
1273
  text-align: center;
1274
  color: #666;
1279
  font-style: italic;
1280
  }
1281
 
1282
+ span.tnp-email-status {
1283
+ background-color: #95A5A6;
 
1284
  padding: 2px 10px;
1285
  border-radius: 4px;
1286
  color: #fff;
1287
  white-space: nowrap;
1288
  }
1289
 
1290
+ /* Email status label */
1291
+ span.tnp-email-status.tnp-email-status--new {
1292
+ background-color: #8E44AD;
1293
+ }
1294
+
1295
+ span.tnp-email-status.tnp-email-status--paused {
1296
  background-color: #95A5A6;
 
 
 
 
1297
  }
1298
 
1299
+ span.tnp-email-status.tnp-email-status--sending {
1300
+ background-color: #27AE60;
 
 
 
 
1301
  }
1302
 
1303
+ span.tnp-email-status.tnp-email-status--scheduled {
1304
  background-color: #E67E22;
 
 
 
 
1305
  }
1306
 
1307
+ span.tnp-email-status.tnp-email-status--sent {
1308
  background-color: #95A5A6;
1309
+ }
1310
+
1311
+ span.tnp-email-status.tnp-email-status--error {
1312
+ background-color: #E74C3C;
1313
  }
1314
 
1315
  /* Schedule buttons styles */
emails/edit.php CHANGED
@@ -134,10 +134,10 @@ if ($controls->is_action('test') || $controls->is_action('save') || $controls->i
134
  unset($email['options']['lists_operator']);
135
  unset($email['options']['lists_exclude']);
136
  unset($email['options']['sex']);
137
- for ($i = 1; $i <= 20; $i ++) {
138
  unset($email['options']["profile_$i"]);
139
  }
140
-
141
  // Patch for Geo addon to be solved with a filter
142
  unset($email['options']['countries']);
143
  unset($email['options']['regions']);
@@ -210,7 +210,7 @@ if ($controls->is_action('test') || $controls->is_action('save') || $controls->i
210
 
211
  // Profile fields filter
212
  $profile_clause = array();
213
- for ($i = 1; $i <= 20; $i ++) {
214
  if (isset($email["options"]["profile_$i"]) && count($email["options"]["profile_$i"])) {
215
  $profile_clause[] = 'profile_' . $i . " IN ('" . implode("','", esc_sql($email["options"]["profile_$i"])) . "') ";
216
  }
@@ -263,9 +263,6 @@ if ($controls->is_action('send') || $controls->is_action('schedule')) {
263
  }
264
  }
265
 
266
-
267
-
268
-
269
  if (isset($email['options']['status']) && $email['options']['status'] == 'S') {
270
  $controls->warnings[] = __('This newsletter will be sent to not confirmed subscribers.', 'newsletter');
271
  }
@@ -274,6 +271,10 @@ if (strpos($email['message'], '{profile_url}') === false && strpos($email['messa
274
  $controls->warnings[] = __('The message is missing the subscriber profile or cancellation link.', 'newsletter');
275
  }
276
 
 
 
 
 
277
 
278
  if ($email['status'] != 'sent') {
279
  $subscriber_count = $wpdb->get_var(str_replace('*', 'count(*)', $email['query']));
@@ -322,18 +323,18 @@ if ($email['status'] != 'sent') {
322
  <?php } ?>
323
 
324
  <?php if ($email['status'] != 'sending' && $email['status'] != 'sent') $controls->button_save(); ?>
325
- <?php if ($email['status'] == 'new' ) $controls->button_confirm('send', __('Send now', 'newsletter'), __('Start real delivery?', 'newsletter')); ?>
326
  <?php if ($email['status'] == 'sending') $controls->button_confirm('pause', __('Pause', 'newsletter'), __('Pause the delivery?', 'newsletter')); ?>
327
- <?php if ($email['status'] == 'paused') $controls->button_confirm('continue', __('Continue', 'newsletter'), 'Continue the delivery?'); ?>
328
  <?php if ($email['status'] == 'paused') $controls->button_confirm('abort', __('Stop', 'newsletter'), __('This totally stop the delivery, ok?', 'newsletter')); ?>
329
- <?php if ($email['status'] == 'new' || ( $email['status'] == 'paused' && $email['send_on'] > time() )) { ?>
330
  <a id="tnp-schedule-button" class="button-secondary" href="javascript:tnp_toggle_schedule()"><i class="far fa-clock"></i> <?php _e("Schedule") ?></a>
331
  <span id="tnp-schedule" style="display: none;">
332
  <?php $controls->datetime('send_on') ?>
333
- <?php $controls->button_confirm('schedule', __('Schedule', 'newsletter'), __('Schedule delivery?', 'newsletter')); ?>
334
  <a class="button-secondary tnp-button-cancel" href="javascript:tnp_toggle_schedule()"><?php _e("Cancel") ?></a>
335
  </span>
336
- <?php } ?>
337
  </div>
338
 
339
  <?php $controls->text('subject', null, 'Subject'); ?>
@@ -480,6 +481,27 @@ if ($email['status'] != 'sent') {
480
  <?php $controls->yesno('track'); ?>
481
  </td>
482
  </tr>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
483
  </table>
484
 
485
  <?php do_action('newsletter_emails_edit_other', $module->get_email($email_id), $controls) ?>
134
  unset($email['options']['lists_operator']);
135
  unset($email['options']['lists_exclude']);
136
  unset($email['options']['sex']);
137
+ for ($i = 1; $i <= 20; $i++) {
138
  unset($email['options']["profile_$i"]);
139
  }
140
+
141
  // Patch for Geo addon to be solved with a filter
142
  unset($email['options']['countries']);
143
  unset($email['options']['regions']);
210
 
211
  // Profile fields filter
212
  $profile_clause = array();
213
+ for ($i = 1; $i <= 20; $i++) {
214
  if (isset($email["options"]["profile_$i"]) && count($email["options"]["profile_$i"])) {
215
  $profile_clause[] = 'profile_' . $i . " IN ('" . implode("','", esc_sql($email["options"]["profile_$i"])) . "') ";
216
  }
263
  }
264
  }
265
 
 
 
 
266
  if (isset($email['options']['status']) && $email['options']['status'] == 'S') {
267
  $controls->warnings[] = __('This newsletter will be sent to not confirmed subscribers.', 'newsletter');
268
  }
271
  $controls->warnings[] = __('The message is missing the subscriber profile or cancellation link.', 'newsletter');
272
  }
273
 
274
+ if (TNP_Email::STATUS_ERROR === $email['status'] && isset($email['options']['error_message'])) {
275
+ $controls->errors .= sprintf(__('Stopped by fatal error: %s', 'newsletter'), esc_html($email['options']['error_message']));
276
+ }
277
+
278
 
279
  if ($email['status'] != 'sent') {
280
  $subscriber_count = $wpdb->get_var(str_replace('*', 'count(*)', $email['query']));
323
  <?php } ?>
324
 
325
  <?php if ($email['status'] != 'sending' && $email['status'] != 'sent') $controls->button_save(); ?>
326
+ <?php if ($email['status'] == 'new') $controls->button_confirm('send', __('Send now', 'newsletter'), __('Start real delivery?', 'newsletter')); ?>
327
  <?php if ($email['status'] == 'sending') $controls->button_confirm('pause', __('Pause', 'newsletter'), __('Pause the delivery?', 'newsletter')); ?>
328
+ <?php if ($email['status'] == 'paused' || $email['status'] == 'error') $controls->button_confirm('continue', __('Continue', 'newsletter'), 'Continue the delivery?'); ?>
329
  <?php if ($email['status'] == 'paused') $controls->button_confirm('abort', __('Stop', 'newsletter'), __('This totally stop the delivery, ok?', 'newsletter')); ?>
330
+ <?php if ($email['status'] == 'new' || ( $email['status'] == 'paused' && $email['send_on'] > time() )) { ?>
331
  <a id="tnp-schedule-button" class="button-secondary" href="javascript:tnp_toggle_schedule()"><i class="far fa-clock"></i> <?php _e("Schedule") ?></a>
332
  <span id="tnp-schedule" style="display: none;">
333
  <?php $controls->datetime('send_on') ?>
334
+ <?php $controls->button_confirm('schedule', __('Schedule', 'newsletter'), __('Schedule delivery?', 'newsletter')); ?>
335
  <a class="button-secondary tnp-button-cancel" href="javascript:tnp_toggle_schedule()"><?php _e("Cancel") ?></a>
336
  </span>
337
+ <?php } ?>
338
  </div>
339
 
340
  <?php $controls->text('subject', null, 'Subject'); ?>
481
  <?php $controls->yesno('track'); ?>
482
  </td>
483
  </tr>
484
+ <tr>
485
+ <th><?php _e('Sender email address', 'newsletter') ?></th>
486
+ <td>
487
+ <?php $controls->text_email('options_sender_email', 40); ?>
488
+ <div class="tnpc-hint">
489
+ Original: <?php echo esc_html(Newsletter::instance()->get_sender_email())?>.<br>
490
+ If you use a delivery service, be sure to use a validated email address.
491
+ </div>
492
+ </td>
493
+ </tr>
494
+ <tr>
495
+ <th>
496
+ <?php _e('Sender name', 'newsletter') ?>
497
+ </th>
498
+ <td>
499
+ <?php $controls->text('options_sender_name', 40); ?>
500
+ <div class="tnpc-hint">
501
+ Original: <?php echo esc_html(Newsletter::instance()->get_sender_name())?>
502
+ </div>
503
+ </td>
504
+ </tr>
505
  </table>
506
 
507
  <?php do_action('newsletter_emails_edit_other', $module->get_email($email_id), $controls) ?>
emails/tnp-composer/index-v2.php CHANGED
@@ -25,8 +25,9 @@ $block_options = get_option('newsletter_main');
25
 
26
  $fields = new NewsletterFields($controls);
27
 
28
- $dir = is_rtl()?'rtl':'ltr';
29
- $rev_dir = is_rtl()?'ltr':'rlt';
 
30
  ?>
31
  <script type="text/javascript">
32
  // collapse wp menu
@@ -44,7 +45,7 @@ $rev_dir = is_rtl()?'ltr':'rlt';
44
  #newsletter-builder-area-center-frame-content {
45
  min-height: 300px!important;
46
  }
47
-
48
  #tnpc-subject-wrap th[dir=rtl] {
49
  text-align: left;
50
  }
@@ -64,15 +65,15 @@ $rev_dir = is_rtl()?'ltr':'rlt';
64
  <div id="newsletter-builder-area" class="tnp-builder-column">
65
 
66
  <?php if ($tnpc_show_subject) { ?>
67
- <div id="tnpc-subject-wrap" dir="<?php echo $dir?>">
68
  <table role="presentation" style="width: 100%">
69
  <tr>
70
- <th dir="<?php echo $dir?>">From</th>
71
- <td dir="<?php echo $dir?>"><?php echo esc_html(Newsletter::instance()->options['sender_email']) ?></td>
72
  </tr>
73
  <tr>
74
- <th dir="<?php echo $dir?>">Subject</th>
75
- <td dir="<?php echo $dir?>">
76
  <div id="tnpc-subject">
77
  <?php $this->subject('title'); ?>
78
  </div>
@@ -84,14 +85,14 @@ $rev_dir = is_rtl()?'ltr':'rlt';
84
  </div>
85
  <?php } ?>
86
 
87
- <div id="newsletter-builder-area-center-frame-content" dir="<?php echo $dir?>">
88
 
89
  <!-- Composer content -->
90
 
91
  </div>
92
  </div>
93
 
94
- <div id="newsletter-builder-sidebar" dir="<?php echo is_rtl()?'rtl':'ltr'?>">
95
 
96
  <div class="tnpc-tabs">
97
  <button class="tablinks" onclick="openTab(event, 'tnpc-blocks')" data-tab-id='tnpc-blocks' id="defaultOpen"><?php _e('Blocks', 'newsletter') ?></button>
@@ -132,11 +133,11 @@ $rev_dir = is_rtl()?'ltr':'rlt';
132
  </div>
133
 
134
  <?php //$fields->section('Fonts are applied to new blocks or when refreshed') ?>
135
- <?php $fields->font( 'options_composer_title_font', __( 'Titles font', 'newsletter' ) ) ?>
136
- <?php $fields->font( 'options_composer_text_font', __( 'Text font', 'newsletter' ) ) ?>
137
- <?php $fields->button_style( 'options_composer_button', __( 'Button style', 'newsletter' ) ); ?>
138
 
139
- <?php $fields->textarea('options_preheader', __('Snippet', 'newsletter'), ['description'=>'Show by some email clients as excerpt', 'height'=>'70']) ?>
140
 
141
  <button class="button-secondary" name="apply"><?php _e("Apply", 'newsletter') ?></button>
142
 
25
 
26
  $fields = new NewsletterFields($controls);
27
 
28
+ $dir = is_rtl() ? 'rtl' : 'ltr';
29
+ $rev_dir = is_rtl() ? 'ltr' : 'rlt';
30
+
31
  ?>
32
  <script type="text/javascript">
33
  // collapse wp menu
45
  #newsletter-builder-area-center-frame-content {
46
  min-height: 300px!important;
47
  }
48
+
49
  #tnpc-subject-wrap th[dir=rtl] {
50
  text-align: left;
51
  }
65
  <div id="newsletter-builder-area" class="tnp-builder-column">
66
 
67
  <?php if ($tnpc_show_subject) { ?>
68
+ <div id="tnpc-subject-wrap" dir="<?php echo $dir ?>">
69
  <table role="presentation" style="width: 100%">
70
  <tr>
71
+ <th dir="<?php echo $dir ?>">From</th>
72
+ <td dir="<?php echo $dir ?>"><?php echo esc_html($controls->data['sender_email']) ?></td>
73
  </tr>
74
  <tr>
75
+ <th dir="<?php echo $dir ?>">Subject</th>
76
+ <td dir="<?php echo $dir ?>">
77
  <div id="tnpc-subject">
78
  <?php $this->subject('title'); ?>
79
  </div>
85
  </div>
86
  <?php } ?>
87
 
88
+ <div id="newsletter-builder-area-center-frame-content" dir="<?php echo $dir ?>">
89
 
90
  <!-- Composer content -->
91
 
92
  </div>
93
  </div>
94
 
95
+ <div id="newsletter-builder-sidebar" dir="<?php echo is_rtl() ? 'rtl' : 'ltr' ?>">
96
 
97
  <div class="tnpc-tabs">
98
  <button class="tablinks" onclick="openTab(event, 'tnpc-blocks')" data-tab-id='tnpc-blocks' id="defaultOpen"><?php _e('Blocks', 'newsletter') ?></button>
133
  </div>
134
 
135
  <?php //$fields->section('Fonts are applied to new blocks or when refreshed') ?>
136
+ <?php $fields->font('options_composer_title_font', __('Titles font', 'newsletter')) ?>
137
+ <?php $fields->font('options_composer_text_font', __('Text font', 'newsletter')) ?>
138
+ <?php $fields->button_style('options_composer_button', __('Button style', 'newsletter')); ?>
139
 
140
+ <?php $fields->textarea('options_preheader', __('Snippet', 'newsletter'), ['description' => 'Show by some email clients as excerpt', 'height' => '70']) ?>
141
 
142
  <button class="button-secondary" name="apply"><?php _e("Apply", 'newsletter') ?></button>
143
 
includes/PHPMailerLoader.php CHANGED
@@ -30,6 +30,11 @@ class PHPMailerLoader {
30
 
31
  }
32
 
 
 
 
 
 
33
  public static function make_instance($exceptions = false) {
34
  self::load();
35
 
30
 
31
  }
32
 
33
+ /**
34
+ *
35
+ * @param boolean $exceptions
36
+ * @return \PHPMailer\PHPMailer\PHPMailer
37
+ */
38
  public static function make_instance($exceptions = false) {
39
  self::load();
40
 
includes/composer.php CHANGED
@@ -228,6 +228,17 @@ class TNP_Composer {
228
 
229
  $controls->data['message'] = TNP_Composer::unwrap_email($email->message);
230
  $controls->data['subject'] = $email->subject;
 
 
 
 
 
 
 
 
 
 
 
231
 
232
  $controls->data = array_merge(TNP_Composer::get_global_style_defaults(), $controls->data);
233
  }
228
 
229
  $controls->data['message'] = TNP_Composer::unwrap_email($email->message);
230
  $controls->data['subject'] = $email->subject;
231
+ if (!empty($email->options['sender_email'])) {
232
+ $controls->data['sender_email'] = $email->options['sender_email'];
233
+ } else {
234
+ $controls->data['sender_email'] = Newsletter::instance()->options['sender_email'];
235
+ }
236
+
237
+ if (!empty($email->options['sender_name'])) {
238
+ $controls->data['sender_name'] = $email->options['sender_name'];
239
+ } else {
240
+ $controls->data['sender_name'] = Newsletter::instance()->options['sender_name'];
241
+ }
242
 
243
  $controls->data = array_merge(TNP_Composer::get_global_style_defaults(), $controls->data);
244
  }
includes/mailer.php CHANGED
@@ -198,6 +198,7 @@ class NewsletterMailer {
198
 
199
  /**
200
  * @property string $to
 
201
  * @property string $subject
202
  * @property string $body
203
  * @property array $headers
@@ -214,6 +215,8 @@ class TNP_Mailer_Message {
214
  var $subject = '';
215
  var $body = '';
216
  var $body_text = '';
 
 
217
 
218
  }
219
 
@@ -347,6 +350,11 @@ class NewsletterDefaultMailer extends NewsletterMailer {
347
  }
348
  }
349
 
 
 
 
 
 
350
  function send($message) {
351
 
352
  if (!$this->filter_active) {
@@ -355,9 +363,16 @@ class NewsletterDefaultMailer extends NewsletterMailer {
355
  }
356
 
357
  $newsletter = Newsletter::instance();
358
- $wp_mail_headers = array();
359
- // TODO: Manage the from address
360
- $wp_mail_headers[] = 'From: "' . $newsletter->options['sender_name'] . '" <' . $newsletter->options['sender_email'] . '>';
 
 
 
 
 
 
 
361
 
362
  if (!empty($newsletter->options['reply_to'])) {
363
  $wp_mail_headers[] = 'Reply-To: ' . $newsletter->options['reply_to'];
198
 
199
  /**
200
  * @property string $to
201
+ * @property string $to_name
202
  * @property string $subject
203
  * @property string $body
204
  * @property array $headers
215
  var $subject = '';
216
  var $body = '';
217
  var $body_text = '';
218
+ var $from = '';
219
+ var $from_name = '';
220
 
221
  }
222
 
350
  }
351
  }
352
 
353
+ /**
354
+ *
355
+ * @param TNP_Mailer_Message $message
356
+ * @return \WP_Error|boolean
357
+ */
358
  function send($message) {
359
 
360
  if (!$this->filter_active) {
363
  }
364
 
365
  $newsletter = Newsletter::instance();
366
+ $wp_mail_headers = [];
367
+ if (empty($message->from)) {
368
+ $message->from = $newsletter->options['sender_email'];
369
+ }
370
+
371
+ if (empty($message->from_name)) {
372
+ $message->from_name = $newsletter->options['sender_name'];
373
+ }
374
+
375
+ $wp_mail_headers[] = 'From: "' . $message->from_name . '" <' . $message->from . '>';
376
 
377
  if (!empty($newsletter->options['reply_to'])) {
378
  $wp_mail_headers[] = 'Reply-To: ' . $newsletter->options['reply_to'];
includes/module.php CHANGED
@@ -333,6 +333,7 @@ class TNP_Email {
333
  const STATUS_SENT = 'sent';
334
  const STATUS_SENDING = 'sending';
335
  const STATUS_PAUSED = 'paused';
 
336
 
337
  }
338
 
@@ -860,7 +861,7 @@ class NewsletterModule {
860
  }
861
 
862
  function admin_menu() {
863
-
864
  }
865
 
866
  function add_menu_page($page, $title, $capability = '') {
@@ -925,6 +926,37 @@ class NewsletterModule {
925
  return $list;
926
  }
927
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
928
  /**
929
  * Retrieves an email from DB and unserialize the options.
930
  *
@@ -1059,7 +1091,7 @@ class NewsletterModule {
1059
  }
1060
 
1061
  function show_email_status_label($email) {
1062
- echo '<span class="tnp-email-status-', $this->get_email_status_slug($email), '">', esc_html($this->get_email_status_label($email)), '</span>';
1063
  }
1064
 
1065
  function get_email_progress($email, $format = 'percent') {
@@ -1086,7 +1118,7 @@ class NewsletterModule {
1086
  $percent = $this->get_email_progress($email);
1087
  }
1088
 
1089
- echo '<div class="tnp-progress ', $email->status, '">';
1090
  echo '<div class="tnp-progress-bar" role="progressbar" style="width: ', $percent, '%;">&nbsp;', $percent, '%&nbsp;</div>';
1091
  echo '</div>';
1092
  if ($attrs['numbers']) {
333
  const STATUS_SENT = 'sent';
334
  const STATUS_SENDING = 'sending';
335
  const STATUS_PAUSED = 'paused';
336
+ const STATUS_ERROR = 'error';
337
 
338
  }
339
 
861
  }
862
 
863
  function admin_menu() {
864
+
865
  }
866
 
867
  function add_menu_page($page, $title, $capability = '') {
926
  return $list;
927
  }
928
 
929
+ /**
930
+ * @param string $key
931
+ * @param mixed $value
932
+ * @return TNP_Email[]
933
+ */
934
+ function get_emails_by_field( $key, $value) {
935
+ global $wpdb;
936
+
937
+ $value_placeholder = is_int( $value ) ? '%d' : '%s';
938
+
939
+ $query = $wpdb->prepare( "SELECT * FROM " . NEWSLETTER_EMAILS_TABLE . " WHERE %1s=$value_placeholder ORDER BY id DESC", $key, $value );
940
+
941
+ $email_list = $wpdb->get_results( $query );
942
+
943
+ if ( $wpdb->last_error || empty( $email_list ) ) {
944
+ $this->logger->error( $wpdb->last_error );
945
+
946
+ return [];
947
+ }
948
+
949
+ //Unserialize options
950
+ array_walk( $email_list, function ( $email ) {
951
+ $email->options = maybe_unserialize( $email->options );
952
+ if ( ! is_array( $email->options ) ) {
953
+ $email->options = [];
954
+ }
955
+ } );
956
+
957
+ return $email_list;
958
+ }
959
+
960
  /**
961
  * Retrieves an email from DB and unserialize the options.
962
  *
1091
  }
1092
 
1093
  function show_email_status_label($email) {
1094
+ echo '<span class="tnp-email-status tnp-email-status--', $this->get_email_status_slug($email), '">', esc_html($this->get_email_status_label($email)), '</span>';
1095
  }
1096
 
1097
  function get_email_progress($email, $format = 'percent') {
1118
  $percent = $this->get_email_progress($email);
1119
  }
1120
 
1121
+ echo '<div class="tnp-progress tnp-progress--' . $email->status . '">';
1122
  echo '<div class="tnp-progress-bar" role="progressbar" style="width: ', $percent, '%;">&nbsp;', $percent, '%&nbsp;</div>';
1123
  echo '</div>';
1124
  if ($attrs['numbers']) {
main/smtp.php CHANGED
@@ -1,143 +1,144 @@
1
- <?php
2
- defined('ABSPATH') || exit;
3
-
4
- @include_once NEWSLETTER_INCLUDES_DIR . '/controls.php';
5
- $module = Newsletter::instance();
6
- $controls = new NewsletterControls();
7
-
8
- if (!$controls->is_action()) {
9
- $controls->data = $module->get_options('smtp');
10
- } else {
11
-
12
-
13
- if ($controls->is_action('save')) {
14
-
15
- if ($controls->data['enabled'] && empty($controls->data['host'])) {
16
- $controls->errors = 'The host must be set to enable the SMTP';
17
- }
18
-
19
- if (empty($controls->errors)) {
20
- $module->save_options($controls->data, 'smtp');
21
- $controls->messages .= __('Saved. Remember to test your changes right now!', 'newsletter');
22
- }
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
- $controls->errors .= '<br><a href="https://www.thenewsletterplugin.com/documentation/?p=15170" target="_blank"><strong>' . __('Read more', 'newsletter') . '</strong></a>.';
35
-
36
- } else {
37
- $controls->messages = 'Success.';
38
- }
39
-
40
- }
41
- }
42
-
43
- if (empty($controls->data['enabled']) && !empty($controls->data['host'])) {
44
- $controls->warnings[] = 'SMTP configured but NOT enabled.';
45
- }
46
- ?>
47
-
48
- <div class="wrap" id="tnp-wrap">
49
-
50
- <?php include NEWSLETTER_DIR . '/tnp-header.php'; ?>
51
-
52
- <div id="tnp-heading">
53
-
54
- <h2><?php _e('SMTP Settings', 'newsletter') ?></h2>
55
-
56
- <p>
57
- <i class="fas fa-info-circle"></i> <a href="https://www.thenewsletterplugin.com/extensions" target="_blank">Discover how SMTP services can boost your newsletters!</a>
58
- <!--
59
- <p>SMTP (Simple Mail Transfer Protocol) refers to external delivery services you can use to send emails.</p>
60
- <p>SMTP services are usually more reliable, secure and spam-aware than the standard delivery method available to your blog.</p>
61
- <p>Even better, using the <a href="https://www.thenewsletterplugin.com/extensions">integration extensions</a>, you can benefit of more efficient service connections, bounce detection and other nice features.</p>
62
- -->
63
- </p>
64
-
65
- <p>
66
- <strong>These options can be overridden by extensions which integrates with external
67
- SMTPs (like MailJet, SendGrid, ...) if installed and activated.</strong>
68
- </p>
69
- <p>
70
-
71
- What you need to know to use an external SMTP can be found
72
- <a href="https://www.thenewsletterplugin.com/plugins/newsletter/newsletter-configuration#smtp" target="_blank">here</a>.
73
- <br>
74
- On GoDaddy you should follow this <a href="https://www.thenewsletterplugin.com/godaddy-using-smtp-external-server-shared-hosting" target="_blank">special setup</a>.
75
- </p>
76
- <p>
77
- Consider <a href="https://www.sendinblue.com/?tap_a=30591-fb13f0&tap_s=626735-cdbaad" target="_blank">Sedinblue</a> (aff) for a serious and reliable SMTP service.
78
- </p>
79
-
80
- </div>
81
-
82
- <div id="tnp-body">
83
-
84
- <form method="post" action="">
85
- <?php $controls->init(); ?>
86
-
87
- <table class="form-table">
88
- <tr>
89
- <th>Enable the SMTP?</th>
90
- <td><?php $controls->yesno('enabled'); ?></td>
91
- </tr>
92
- <tr>
93
- <th>SMTP host/port</th>
94
- <td>
95
- host: <?php $controls->text('host', 30); ?>
96
- port: <?php $controls->text('port', 6); ?>
97
- <?php $controls->select('secure', array('' => 'No secure protocol', 'tls' => 'TLS protocol', 'ssl' => 'SSL protocol')); ?>
98
- <p class="description">
99
- Leave port empty for default value (25).<br>
100
- To use GMail, do not set the SMTP here but use a <a href="https://wordpress.org/plugins/search/smtp+gmail/" target="_blank">SMTP plugin which supprts oAuth 2.0</a><br>
101
- On GoDaddy TRY to use "relay-hosting.secureserver.net".
102
- </p>
103
- </td>
104
- </tr>
105
- <tr>
106
- <th>Authentication</th>
107
- <td>
108
- user: <?php $controls->text('user', 30); ?>
109
- password: <?php $controls->password('pass', 30); ?>
110
- <p class="description">
111
- If authentication is not required, leave "user" field blank.
112
- </p>
113
- </td>
114
- </tr>
115
- <tr>
116
- <th>Insecure SSL Connections</th>
117
- <td>
118
- <?php $controls->yesno('ssl_insecure'); ?> <a href="https://www.thenewsletterplugin.com/?p=21989" target="_blank">Read more</a>.
119
- </td>
120
- </tr>
121
- <tr>
122
- <th>Test email address</th>
123
- <td>
124
- <?php $controls->text_email('test_email', 30); ?>
125
- <?php $controls->button('test', 'Send a test email to this address'); ?>
126
- <p class="description">
127
- If the test reports a "connection failed", review your settings and, if correct, contact
128
- your provider to unlock the connection (if possible).
129
- </p>
130
- </td>
131
- </tr>
132
- </table>
133
-
134
- <p>
135
- <?php $controls->button_save(); ?>
136
- </p>
137
-
138
- </form>
139
- </div>
140
-
141
- <?php include NEWSLETTER_DIR . '/tnp-footer.php'; ?>
142
-
143
- </div>
 
1
+ <?php
2
+ defined('ABSPATH') || exit;
3
+
4
+ @include_once NEWSLETTER_INCLUDES_DIR . '/controls.php';
5
+ $module = Newsletter::instance();
6
+ $controls = new NewsletterControls();
7
+
8
+ if (!$controls->is_action()) {
9
+ $controls->data = $module->get_options('smtp');
10
+ } else {
11
+
12
+
13
+ if ($controls->is_action('save') || $controls->is_action('test')) {
14
+
15
+ if ($controls->data['enabled'] && empty($controls->data['host'])) {
16
+ $controls->errors = 'The host must be set to enable the SMTP';
17
+ }
18
+
19
+ if (empty($controls->errors)) {
20
+ $module->save_options($controls->data, 'smtp');
21
+ $controls->add_message_saved();
22
+ }
23
+
24
+ if ($controls->is_action('test')) {
25
+
26
+ $message = NewsletterMailerAddon::get_test_message($controls->data['test_email']);
27
+ $r = (new NewsletterDefaultSMTPMailer($controls->data))->send( $message );
28
+
29
+ if (is_wp_error($r)) {
30
+ $controls->errors = $r->get_error_message();
31
+ $controls->errors .= '<br><a href="https://www.thenewsletterplugin.com/documentation/?p=15170" target="_blank"><strong>' . __('Read more', 'newsletter') . '</strong></a>.';
32
+ } else {
33
+ $controls->messages = 'Success.';
34
+ }
35
+ }
36
+
37
+ }
38
+
39
+ }
40
+
41
+ /*if (empty($controls->data['enabled']) && !empty($controls->data['host'])) {
42
+ $controls->warnings[] = 'SMTP configured but NOT enabled.';
43
+ }*/
44
+
45
+ $is_invalid_configuration = empty( $controls->data['host'] );
46
+ $is_disabled = empty( $controls->data['enabled'] );
47
+
48
+ ?>
49
+
50
+ <div class="wrap" id="tnp-wrap">
51
+
52
+ <?php include NEWSLETTER_DIR . '/tnp-header.php'; ?>
53
+
54
+ <div id="tnp-heading">
55
+
56
+ <h2>SMTP (obsolete)</h2>
57
+ <p>
58
+ This feature is obsolete. Use a third party SMTP plugin or our SMTP addon. <a href="https://www.thenewsletterplugin.com/the-new-smtp-addon" target="_blank">Read our blog post with all you need to know</a>.
59
+ </p>
60
+ </div>
61
+
62
+ <div id="tnp-body">
63
+
64
+ <?php if ( $is_disabled || $is_invalid_configuration ): ?>
65
+ <a href="" id="smtp-show-form"><?php _e( 'Show hidden options', 'newsletter' ) ?></a>
66
+ <script>
67
+ document.getElementById('smtp-show-form').addEventListener('click', function (e) {
68
+ e.preventDefault();
69
+ document.getElementById('smtp-form').classList.toggle('hidden');
70
+ });
71
+ </script>
72
+ <?php endif; ?>
73
+
74
+ <?php $body_classes = ( $is_disabled || $is_invalid_configuration ) ? 'hidden' : '' ?>
75
+ <form method="post"
76
+ action=""
77
+ class="<?php echo $body_classes ?>"
78
+ id="smtp-form">
79
+ <?php $controls->init(); ?>
80
+
81
+ <table class="form-table">
82
+ <tr>
83
+ <th>Enable the SMTP?</th>
84
+ <td><?php $controls->yesno( 'enabled' ); ?></td>
85
+ </tr>
86
+ <tr>
87
+ <th>SMTP host/port</th>
88
+ <td>
89
+ host: <?php $controls->text( 'host', 30 ); ?>
90
+ port: <?php $controls->text( 'port', 6 ); ?>
91
+ <?php $controls->select( 'secure', array(
92
+ '' => 'No secure protocol',
93
+ 'tls' => 'TLS protocol',
94
+ 'ssl' => 'SSL protocol'
95
+ ) ); ?>
96
+ <p class="description">
97
+ Leave port empty for default value (25).<br>
98
+ To use GMail, do not set the SMTP here but use a <a
99
+ href="https://wordpress.org/plugins/search/smtp+gmail/" target="_blank">SMTP plugin
100
+ which supprts oAuth 2.0</a><br>
101
+ On GoDaddy TRY to use "relay-hosting.secureserver.net".
102
+ </p>
103
+ </td>
104
+ </tr>
105
+ <tr>
106
+ <th>Authentication</th>
107
+ <td>
108
+ user: <?php $controls->text( 'user', 30 ); ?>
109
+ password: <?php $controls->password( 'pass', 30 ); ?>
110
+ <p class="description">
111
+ If authentication is not required, leave "user" field blank.
112
+ </p>
113
+ </td>
114
+ </tr>
115
+ <tr>
116
+ <th>Insecure SSL Connections</th>
117
+ <td>
118
+ <?php $controls->yesno( 'ssl_insecure' ); ?> <a
119
+ href="https://www.thenewsletterplugin.com/?p=21989" target="_blank">Read more</a>.
120
+ </td>
121
+ </tr>
122
+ <tr>
123
+ <th>Test email address</th>
124
+ <td>
125
+ <?php $controls->text_email( 'test_email', 30 ); ?>
126
+ <?php $controls->button( 'test', 'Save and send test email' ); ?>
127
+ <p class="description">
128
+ If the test reports a "connection failed", review your settings and, if correct, contact
129
+ your provider to unlock the connection (if possible).
130
+ </p>
131
+ </td>
132
+ </tr>
133
+ </table>
134
+
135
+ <p>
136
+ <?php $controls->button_save(); ?>
137
+ </p>
138
+
139
+ </form>
140
+ </div>
141
+
142
+ <?php include NEWSLETTER_DIR . '/tnp-footer.php'; ?>
143
+
144
+ </div>
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: 7.0.8
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.
@@ -35,7 +35,7 @@ if (version_compare(phpversion(), '5.6', '<')) {
35
  return;
36
  }
37
 
38
- define('NEWSLETTER_VERSION', '7.0.8');
39
 
40
  global $newsletter, $wpdb;
41
 
@@ -154,7 +154,7 @@ class Newsletter extends NewsletterModule {
154
  return $schedules;
155
  }, 1000);
156
 
157
- parent::__construct('main', '1.6.5', null, array('info', 'smtp'));
158
 
159
  $max = $this->options['scheduler_max'];
160
  if (!is_numeric($max)) {
@@ -347,7 +347,7 @@ class Newsletter extends NewsletterModule {
347
  `subject` varchar(255) NOT NULL DEFAULT '',
348
  `message` longtext,
349
  `created` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
350
- `status` enum('new','sending','sent','paused') NOT NULL DEFAULT 'new',
351
  `total` int(11) NOT NULL DEFAULT '0',
352
  `last_id` int(11) NOT NULL DEFAULT '0',
353
  `sent` int(11) NOT NULL DEFAULT '0',
@@ -525,7 +525,7 @@ class Newsletter extends NewsletterModule {
525
 
526
  wp_enqueue_style('tnp-select2', $newsletter_url . '/vendor/select2/css/select2.min.css', [], NEWSLETTER_VERSION);
527
  wp_enqueue_script('tnp-select2', $newsletter_url . '/vendor/select2/js/select2.min.js', [], NEWSLETTER_VERSION);
528
-
529
  wp_enqueue_style('tnp-admin-font', 'https://use.typekit.net/jlj2wjy.css');
530
  wp_enqueue_style('tnp-admin-fontawesome', $newsletter_url . '/vendor/fa/css/all.min.css', [], NEWSLETTER_VERSION);
531
  wp_enqueue_style('tnp-admin-jquery-ui', $newsletter_url . '/vendor/jquery-ui/jquery-ui.min.css', [], NEWSLETTER_VERSION);
@@ -536,7 +536,7 @@ class Newsletter extends NewsletterModule {
536
  wp_enqueue_style('tnp-admin-fields', $newsletter_url . '/css/fields.css', [], NEWSLETTER_VERSION);
537
  wp_enqueue_style('tnp-admin-widgets', $newsletter_url . '/css/widgets.css', [], NEWSLETTER_VERSION);
538
  wp_enqueue_style('tnp-admin-extensions', $newsletter_url . '/css/extensions.css', [], NEWSLETTER_VERSION);
539
-
540
  if (NEWSLETTER_DARK) {
541
  wp_enqueue_style('tnp-admin-dark', $newsletter_url . '/admin-dark.css', ['tnp-admin'], NEWSLETTER_VERSION);
542
  wp_enqueue_style('tnp-admin-controls-dark', $newsletter_url . '/css/controls-dark.css', ['tnp-admin-controls'], NEWSLETTER_VERSION);
@@ -548,7 +548,7 @@ class Newsletter extends NewsletterModule {
548
  'save_to_update_counter' => __('Save the newsletter to update the counter!', 'newsletter')
549
  );
550
  wp_localize_script('tnp-admin', 'tnp_translations', $translations_array);
551
-
552
  wp_enqueue_script('tnp-jquery-vmap', $newsletter_url . '/vendor/jqvmap/jquery.vmap.min.js', ['jquery'], NEWSLETTER_VERSION);
553
  wp_enqueue_script('tnp-jquery-vmap-world', $newsletter_url . '/vendor/jqvmap/jquery.vmap.world.js', ['tnp-jquery-vmap'], NEWSLETTER_VERSION);
554
  wp_enqueue_style('tnp-jquery-vmap', $newsletter_url . '/vendor/jqvmap/jqvmap.min.css', [], NEWSLETTER_VERSION);
@@ -611,7 +611,7 @@ class Newsletter extends NewsletterModule {
611
  $emails = $this->get_results("select * from " . NEWSLETTER_EMAILS_TABLE . " where status='sending' and send_on<" . time() . " order by id asc");
612
  $this->logger->debug(__METHOD__ . '> Emails found in sending status: ' . count($emails));
613
 
614
- foreach ($emails as $email) {
615
  $this->logger->info(__METHOD__ . '> Start newsletter ' . $email->id);
616
  $r = $this->send($email);
617
  if ($this->limits_exceeded()) {
@@ -633,9 +633,13 @@ class Newsletter extends NewsletterModule {
633
  * @global type $newsletter_feed
634
  * @param TNP_Email $email
635
  * @param array $users
636
- * @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.
637
  */
638
  function send($email, $users = null, $test = false) {
 
 
 
 
639
  global $wpdb;
640
 
641
  ignore_user_abort(true);
@@ -651,7 +655,8 @@ class Newsletter extends NewsletterModule {
651
 
652
  $this->logger->info(__METHOD__ . '> Start run for email ' . $email->id);
653
 
654
- // This stops the update of last_id and sent fields since it's not a scheduled delivery but a test or something else (like an autoresponder)
 
655
  $supplied_users = $users != null;
656
 
657
  if ($users == null) {
@@ -661,6 +666,7 @@ class Newsletter extends NewsletterModule {
661
  return false;
662
  }
663
 
 
664
  if (empty($email->query)) {
665
  $email->query = "select * from " . NEWSLETTER_USERS_TABLE . " where status='C'";
666
  }
@@ -668,8 +674,8 @@ class Newsletter extends NewsletterModule {
668
  // TODO: Ask the max emails per hour/run (to be decided) to the mailer
669
 
670
  $email->options = maybe_unserialize($email->options);
 
671
  $max_emails = apply_filters('newsletter_send_max_emails', $this->max_emails, $email);
672
-
673
  $this->logger->debug(__METHOD__ . '> Max emails per run: ' . $max_emails);
674
 
675
  if (empty($max_emails)) {
@@ -677,17 +683,19 @@ class Newsletter extends NewsletterModule {
677
  $max_emails = $this->max_emails;
678
  }
679
 
 
680
  //$query = apply_filters('newsletter_send_query', $email->query, $email);
681
  $query = $email->query;
682
  $query .= " and id>" . $email->last_id . " order by id limit " . $max_emails;
683
 
684
  $this->logger->debug(__METHOD__ . '> Query: ' . $query);
685
 
 
686
  $users = $this->get_results($query);
687
 
688
  $this->logger->debug(__METHOD__ . '> Loaded users: ' . count($users));
689
 
690
- // If there was a database error, do nothing
691
  if ($users === false) {
692
  return new WP_Error('1', 'Unable to query subscribers, check the logs');
693
  }
@@ -716,6 +724,7 @@ class Newsletter extends NewsletterModule {
716
  if ($batch_size == 1) {
717
 
718
  foreach ($users as $user) {
 
719
  if (!$supplied_users && !$test && $this->limits_exceeded()) {
720
  $result = false;
721
  break;
@@ -724,26 +733,39 @@ class Newsletter extends NewsletterModule {
724
  $this->logger->debug(__METHOD__ . '> Processing user ID: ' . $user->id);
725
  $user = apply_filters('newsletter_send_user', $user);
726
  $message = $this->build_message($email, $user);
 
 
727
  $this->save_sent_message($message);
728
 
 
729
  if (!$test) {
730
  $wpdb->query("update " . NEWSLETTER_EMAILS_TABLE . " set sent=sent+1, last_id=" . $user->id . " where id=" . $email->id . " limit 1");
731
  }
732
 
733
  $r = $mailer->send($message);
734
 
 
 
735
  if (!empty($message->error)) {
736
  $this->logger->error($message);
737
  $this->save_sent_message($message);
738
  }
739
 
 
740
  if (is_wp_error($r)) {
741
  $this->logger->error($r);
 
 
 
 
 
 
742
  return $r;
743
  }
744
  }
 
745
  // TODO: Review if they're useful
746
- $this->email_limit--;
747
  $count++;
748
  } else {
749
 
@@ -751,6 +773,9 @@ class Newsletter extends NewsletterModule {
751
 
752
  foreach ($chunks as $chunk) {
753
 
 
 
 
754
  if (!$supplied_users && !$test && $this->limits_exceeded()) {
755
  $result = false;
756
  break;
@@ -782,6 +807,11 @@ class Newsletter extends NewsletterModule {
782
  }
783
 
784
  if (is_wp_error($r)) {
 
 
 
 
 
785
  $this->logger->error($r);
786
  return $r;
787
  }
@@ -790,6 +820,7 @@ class Newsletter extends NewsletterModule {
790
 
791
  $end_time = microtime(true);
792
 
 
793
  if (!$test && $count > 0) {
794
 
795
  NewsletterStatistics::instance()->reset_stats_time($email->id);
@@ -813,6 +844,27 @@ class Newsletter extends NewsletterModule {
813
  return $result;
814
  }
815
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
816
  /**
817
  *
818
  * @param TNP_Email $email
@@ -849,9 +901,17 @@ class Newsletter extends NewsletterModule {
849
  $message->subject = $this->replace($email->subject, $user);
850
  $message->subject = apply_filters('newsletter_message_subject', $message->subject, $email, $user);
851
 
852
- // TODO: Use the $email properties when available
853
- $message->from = $this->options['sender_email'];
854
- $message->from_name = $this->options['sender_name'];
 
 
 
 
 
 
 
 
855
 
856
  $message->email_id = $email->id;
857
  $message->user_id = $user->id;
@@ -1239,6 +1299,14 @@ class Newsletter extends NewsletterModule {
1239
  function has_license() {
1240
  return !empty($this->options['contract_key']);
1241
  }
 
 
 
 
 
 
 
 
1242
 
1243
  /**
1244
  *
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: 7.0.9
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.
35
  return;
36
  }
37
 
38
+ define('NEWSLETTER_VERSION', '7.0.9');
39
 
40
  global $newsletter, $wpdb;
41
 
154
  return $schedules;
155
  }, 1000);
156
 
157
+ parent::__construct('main', '1.6.6', null, array('info', 'smtp'));
158
 
159
  $max = $this->options['scheduler_max'];
160
  if (!is_numeric($max)) {
347
  `subject` varchar(255) NOT NULL DEFAULT '',
348
  `message` longtext,
349
  `created` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
350
+ `status` enum('new','sending','sent','paused','error') NOT NULL DEFAULT 'new',
351
  `total` int(11) NOT NULL DEFAULT '0',
352
  `last_id` int(11) NOT NULL DEFAULT '0',
353
  `sent` int(11) NOT NULL DEFAULT '0',
525
 
526
  wp_enqueue_style('tnp-select2', $newsletter_url . '/vendor/select2/css/select2.min.css', [], NEWSLETTER_VERSION);
527
  wp_enqueue_script('tnp-select2', $newsletter_url . '/vendor/select2/js/select2.min.js', [], NEWSLETTER_VERSION);
528
+
529
  wp_enqueue_style('tnp-admin-font', 'https://use.typekit.net/jlj2wjy.css');
530
  wp_enqueue_style('tnp-admin-fontawesome', $newsletter_url . '/vendor/fa/css/all.min.css', [], NEWSLETTER_VERSION);
531
  wp_enqueue_style('tnp-admin-jquery-ui', $newsletter_url . '/vendor/jquery-ui/jquery-ui.min.css', [], NEWSLETTER_VERSION);
536
  wp_enqueue_style('tnp-admin-fields', $newsletter_url . '/css/fields.css', [], NEWSLETTER_VERSION);
537
  wp_enqueue_style('tnp-admin-widgets', $newsletter_url . '/css/widgets.css', [], NEWSLETTER_VERSION);
538
  wp_enqueue_style('tnp-admin-extensions', $newsletter_url . '/css/extensions.css', [], NEWSLETTER_VERSION);
539
+
540
  if (NEWSLETTER_DARK) {
541
  wp_enqueue_style('tnp-admin-dark', $newsletter_url . '/admin-dark.css', ['tnp-admin'], NEWSLETTER_VERSION);
542
  wp_enqueue_style('tnp-admin-controls-dark', $newsletter_url . '/css/controls-dark.css', ['tnp-admin-controls'], NEWSLETTER_VERSION);
548
  'save_to_update_counter' => __('Save the newsletter to update the counter!', 'newsletter')
549
  );
550
  wp_localize_script('tnp-admin', 'tnp_translations', $translations_array);
551
+
552
  wp_enqueue_script('tnp-jquery-vmap', $newsletter_url . '/vendor/jqvmap/jquery.vmap.min.js', ['jquery'], NEWSLETTER_VERSION);
553
  wp_enqueue_script('tnp-jquery-vmap-world', $newsletter_url . '/vendor/jqvmap/jquery.vmap.world.js', ['tnp-jquery-vmap'], NEWSLETTER_VERSION);
554
  wp_enqueue_style('tnp-jquery-vmap', $newsletter_url . '/vendor/jqvmap/jqvmap.min.css', [], NEWSLETTER_VERSION);
611
  $emails = $this->get_results("select * from " . NEWSLETTER_EMAILS_TABLE . " where status='sending' and send_on<" . time() . " order by id asc");
612
  $this->logger->debug(__METHOD__ . '> Emails found in sending status: ' . count($emails));
613
 
614
+ foreach ($emails as $email) {
615
  $this->logger->info(__METHOD__ . '> Start newsletter ' . $email->id);
616
  $r = $this->send($email);
617
  if ($this->limits_exceeded()) {
633
  * @global type $newsletter_feed
634
  * @param TNP_Email $email
635
  * @param array $users
636
+ * @return boolean|WP_Error True if the process completed, false if limits was reached. On false the caller should no continue to call it with other emails.
637
  */
638
  function send($email, $users = null, $test = false) {
639
+ //TODO proposte:
640
+ // - Separare funzione che spedisce normalmente da quella che spedisce dei test
641
+ // - Utilizzare le eccezioni per evitare di controllare se il risultato della funzione è un errore oppure no
642
+ // - Le eccezioni dovrebbero essere tipizzate
643
  global $wpdb;
644
 
645
  ignore_user_abort(true);
655
 
656
  $this->logger->info(__METHOD__ . '> Start run for email ' . $email->id);
657
 
658
+ // This stops the update of last_id and sent fields since
659
+ // it's not a scheduled delivery but a test or something else (like an autoresponder)
660
  $supplied_users = $users != null;
661
 
662
  if ($users == null) {
666
  return false;
667
  }
668
 
669
+ //If query is empty send to all confirmed subscribers
670
  if (empty($email->query)) {
671
  $email->query = "select * from " . NEWSLETTER_USERS_TABLE . " where status='C'";
672
  }
674
  // TODO: Ask the max emails per hour/run (to be decided) to the mailer
675
 
676
  $email->options = maybe_unserialize($email->options);
677
+ // Retrieve max shipping emails per run
678
  $max_emails = apply_filters('newsletter_send_max_emails', $this->max_emails, $email);
 
679
  $this->logger->debug(__METHOD__ . '> Max emails per run: ' . $max_emails);
680
 
681
  if (empty($max_emails)) {
683
  $max_emails = $this->max_emails;
684
  }
685
 
686
+ // Add limit to query
687
  //$query = apply_filters('newsletter_send_query', $email->query, $email);
688
  $query = $email->query;
689
  $query .= " and id>" . $email->last_id . " order by id limit " . $max_emails;
690
 
691
  $this->logger->debug(__METHOD__ . '> Query: ' . $query);
692
 
693
+ //Retrieve subscribers
694
  $users = $this->get_results($query);
695
 
696
  $this->logger->debug(__METHOD__ . '> Loaded users: ' . count($users));
697
 
698
+ // If there was a database error, return error
699
  if ($users === false) {
700
  return new WP_Error('1', 'Unable to query subscribers, check the logs');
701
  }
724
  if ($batch_size == 1) {
725
 
726
  foreach ($users as $user) {
727
+
728
  if (!$supplied_users && !$test && $this->limits_exceeded()) {
729
  $result = false;
730
  break;
733
  $this->logger->debug(__METHOD__ . '> Processing user ID: ' . $user->id);
734
  $user = apply_filters('newsletter_send_user', $user);
735
  $message = $this->build_message($email, $user);
736
+
737
+ // Save even test emails since people wants to see some stats even for test emails. Stats are reset upon the real "send" of a newsletter
738
  $this->save_sent_message($message);
739
 
740
+ //Se non è un test incremento il contatore delle email spedite. Perchè incremento prima di spedire??
741
  if (!$test) {
742
  $wpdb->query("update " . NEWSLETTER_EMAILS_TABLE . " set sent=sent+1, last_id=" . $user->id . " where id=" . $email->id . " limit 1");
743
  }
744
 
745
  $r = $mailer->send($message);
746
 
747
+ //Perchè dentro al messaggio vado a impostare un errore (viene fatto dentro alla $mailer->send())??? boh
748
+ //in ogni caso, se ho un messaggio di errore loggo e salvo nella sent che la spedizione mi ha dato un errore
749
  if (!empty($message->error)) {
750
  $this->logger->error($message);
751
  $this->save_sent_message($message);
752
  }
753
 
754
+ //Se la send mi ritorna un WP_Error loggo e ritorno al chiamante l'errore
755
  if (is_wp_error($r)) {
756
  $this->logger->error($r);
757
+
758
+ // For fatal error, the newsletter status i changed to error (and the delivery stopped)
759
+ if (!$test && $r->get_error_code() == NewsletterMailer::ERROR_FATAL) {
760
+ $this->set_error_state_of_email($email, $r->get_error_message());
761
+ }
762
+
763
  return $r;
764
  }
765
  }
766
+
767
  // TODO: Review if they're useful
768
+ $this->email_limit--; //Diminuisce il limite delle email?? differenza tra $this->email_limit e $this->max_emails??
769
  $count++;
770
  } else {
771
 
773
 
774
  foreach ($chunks as $chunk) {
775
 
776
+ //Se gli utenti non sono stati forniti esternamente
777
+ //e se non è un test
778
+ //e se è stato superato il limite ALLORA imposto $result-false e interrompo il ciclo
779
  if (!$supplied_users && !$test && $this->limits_exceeded()) {
780
  $result = false;
781
  break;
807
  }
808
 
809
  if (is_wp_error($r)) {
810
+
811
+ if (!$test) {
812
+ $this->set_error_state_of_email($email, $r->get_error_message());
813
+ }
814
+
815
  $this->logger->error($r);
816
  return $r;
817
  }
820
 
821
  $end_time = microtime(true);
822
 
823
+ //Se non sono in test e ho completato con successo delle spedizioni aggiorno i dati di diagnostica
824
  if (!$test && $count > 0) {
825
 
826
  NewsletterStatistics::instance()->reset_stats_time($email->id);
844
  return $result;
845
  }
846
 
847
+ /**
848
+ * @param TNP_Email $email
849
+ */
850
+ private function set_error_state_of_email($email, $message = '') {
851
+ // Handle only message type at the moment
852
+ if ($email->type !== 'message') {
853
+ return;
854
+ }
855
+
856
+ do_action('newsletter_error_on_sending', $email, $message);
857
+
858
+ $edited_email = new TNP_Email();
859
+ $edited_email->id = $email->id;
860
+ $edited_email->status = TNP_Email::STATUS_ERROR;
861
+ $edited_email->options = $email->options;
862
+ $edited_email->options['error_message'] = $message;
863
+
864
+ //If id is present the save function update only the provided fields?!
865
+ $this->save_email($edited_email);
866
+ }
867
+
868
  /**
869
  *
870
  * @param TNP_Email $email
901
  $message->subject = $this->replace($email->subject, $user);
902
  $message->subject = apply_filters('newsletter_message_subject', $message->subject, $email, $user);
903
 
904
+ if (!empty($email->options['sender_email'])) {
905
+ $message->from = $email->options['sender_email'];
906
+ } else {
907
+ $message->from = $this->options['sender_email'];
908
+ }
909
+
910
+ if (!empty($email->options['sender_name'])) {
911
+ $message->from_name = $email->options['sender_name'];
912
+ } else {
913
+ $message->from_name = $this->options['sender_name'];
914
+ }
915
 
916
  $message->email_id = $email->id;
917
  $message->user_id = $user->id;
1299
  function has_license() {
1300
  return !empty($this->options['contract_key']);
1301
  }
1302
+
1303
+ function get_sender_name() {
1304
+ return $this->options['sender_name'];
1305
+ }
1306
+
1307
+ function get_sender_email() {
1308
+ return $this->options['sender_email'];
1309
+ }
1310
 
1311
  /**
1312
  *
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.7
5
- Stable tag: 7.0.8
6
  Requires PHP: 5.6
7
  Contributors: satollo,webagile,michael-travan
8
  License: GPLv2 or later
@@ -34,7 +34,7 @@ We redesigned our drag and drop composer to make your campaign creation even eas
34
  * **Single** And **Double Opt-In** plus privacy checkbox for EU laws compliance
35
  * **Subscribers lists** to fine-target your campaigns
36
  * PHP API and REST API for coders and integrations
37
- * SMTP-Ready
38
  * Customizable Themes
39
  * **Status panel** to check your blog mailing capability and configuration
40
  * **Compatible with every SMTP plugin**: Post SMTP (aka Postman), WP Mail SMTP, Easy WP SMTP, Easy SMTP Mail, WP Mail Bank, ...
@@ -49,11 +49,13 @@ Newsletter is a continuously evolving plugin. Stay tuned following us on [Facebo
49
 
50
  Improve The Newsletter Plugin with these free addons:
51
 
52
- * [WP Registration Integration](https://www.thenewsletterplugin.com/documentation/wpusers-extension) - connects the WordPress standard and custom registration with Newsletter subscription. Optionally imports all registered users as subscribers.
53
- * [Archive](https://www.thenewsletterplugin.com/documentation/archive-extension) - creates a simple blog page which lists all your sent newsletters
54
- * [Locked Content](https://www.thenewsletterplugin.com/documentation/locked-content-extension) - open up your premium content only after subscription
55
- * [Newsletter REST API](https://www.thenewsletterplugin.com/documentation/developers/newsletter-api-2/) - adds a tier of REST api to integrate with the Newsletter core services
56
- * [Sendinblue integration](https://www.thenewsletterplugin.com/documentation/addons/delivery-addons/sendinblue-extension/) - deliver your newsletters with Sendinblue
 
 
57
 
58
  (*easily add them from our [Addons panel](https://www.thenewsletterplugin.com/documentation/install-extensions)*)
59
 
@@ -118,6 +120,16 @@ Thank you, The Newsletter Team
118
 
119
  == Changelog ==
120
 
 
 
 
 
 
 
 
 
 
 
121
  = 7.0.8 =
122
 
123
  * [SUBSCRIBERS] Changed action buttons
@@ -145,6 +157,8 @@ Thank you, The Newsletter Team
145
  = 7.0.5 =
146
 
147
  * [COMPOSER] Hero CTA button not working
 
 
148
 
149
  = 7.0.4 =
150
 
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.7
5
+ Stable tag: 7.0.9
6
  Requires PHP: 5.6
7
  Contributors: satollo,webagile,michael-travan
8
  License: GPLv2 or later
34
  * **Single** And **Double Opt-In** plus privacy checkbox for EU laws compliance
35
  * **Subscribers lists** to fine-target your campaigns
36
  * PHP API and REST API for coders and integrations
37
+ * SMTP-Ready (with free addon)
38
  * Customizable Themes
39
  * **Status panel** to check your blog mailing capability and configuration
40
  * **Compatible with every SMTP plugin**: Post SMTP (aka Postman), WP Mail SMTP, Easy WP SMTP, Easy SMTP Mail, WP Mail Bank, ...
49
 
50
  Improve The Newsletter Plugin with these free addons:
51
 
52
+ * [WP Registration Addon](https://www.thenewsletterplugin.com/documentation/wpusers-extension) - connects the WordPress standard and custom registration with Newsletter subscription. Optionally imports all registered users as subscribers.
53
+ * [Archive Addon](https://www.thenewsletterplugin.com/documentation/archive-extension) - creates a simple blog page which lists all your sent newsletters
54
+ * [Locked Content Addon](https://www.thenewsletterplugin.com/documentation/locked-content-extension) - open up your premium content only after subscription
55
+ * [Newsletter REST API Addon](https://www.thenewsletterplugin.com/documentation/developers/newsletter-api-2/) - adds a tier of REST api to integrate with the Newsletter core services
56
+ * [Sendinblue Addon](https://www.thenewsletterplugin.com/documentation/addons/delivery-addons/sendinblue-extension/) - deliver your newsletters with Sendinblue
57
+ * [SMTP Addon](https://www.thenewsletterplugin.com/documentation/addons/delivery-addons/smtp-extension/) - deliver your newsletters with external SMTP
58
+ * [Advanced Import Addon](https://www.thenewsletterplugin.com/documentation/addons/extended-features/advanced-import/) - import contact from file or copy and paste data with full mapping
59
 
60
  (*easily add them from our [Addons panel](https://www.thenewsletterplugin.com/documentation/install-extensions)*)
61
 
120
 
121
  == Changelog ==
122
 
123
+ = 7.0.9 =
124
+
125
+ * [CAPTCHA] Fixed button label translation
126
+ * [DELIVERY] Mailing fatal error management with newsletter stop and reporting
127
+ * [SMTP] Marked obsolete the internal SMTP and made available the free SMTP addon
128
+ * [DELIVERY] Bettere management of delivery fatal errors with a new "error" status for newsletters
129
+ * [GENERAL] New log files panel
130
+ * [IMPORT] Old import panel replaced by the new (really better) import addon (file, copy and paste, bounced addresses import)
131
+ * [NEWSLETTERS] It's now possible to specify the sender name and email per newsletter (thanks to Matthew S.)
132
+
133
  = 7.0.8 =
134
 
135
  * [SUBSCRIBERS] Changed action buttons
157
  = 7.0.5 =
158
 
159
  * [COMPOSER] Hero CTA button not working
160
+ * Fixed to the hero block button
161
+ * Added support for the SMTP addon
162
 
163
  = 7.0.4 =
164
 
subscription/subscription.php CHANGED
@@ -143,6 +143,7 @@ class NewsletterSubscription extends NewsletterModule {
143
  $options_antibot = $this->get_options('antibot');
144
 
145
  $captcha = !empty($options_antibot['captcha']);
 
146
 
147
  if (!empty($options_antibot['disabled']) || $this->antibot_form_check($captcha)) {
148
 
@@ -166,7 +167,9 @@ class NewsletterSubscription extends NewsletterModule {
166
  $this->show_message('confirmation', $user);
167
  }
168
  } else {
169
- $this->request_to_antibot_form('Subscribe', $captcha);
 
 
170
  }
171
  die();
172
 
@@ -343,10 +346,10 @@ class NewsletterSubscription extends NewsletterModule {
343
  if ($sub == '') {
344
  // For compatibility the options are wrongly named
345
  if ($language) {
346
- $options = get_option('newsletter_' . $language, array());
347
- $options = array_merge(get_option('newsletter', array()), $options);
348
  } else {
349
- $options = get_option('newsletter', array());
350
  }
351
  if (!is_array($options)) {
352
  $options = array();
@@ -358,22 +361,24 @@ class NewsletterSubscription extends NewsletterModule {
358
  if ($language) {
359
  // All that because for unknown reasome, sometime the options are returned as string, maybe a WPML
360
  // interference...
361
- $i18n_options = get_option('newsletter_profile_' . $language, array());
362
- if (!is_array($i18n_options))
363
- $i18n_options = array();
364
- $options = get_option('newsletter_profile', array());
365
- if (!is_array($options))
366
- $options = array();
 
 
367
  $options = array_merge($options, array_filter($i18n_options));
368
  } else {
369
- $options = get_option('newsletter_profile', array());
370
  }
371
  // For compatibility the options are wrongly named
372
  return $options;
373
  }
374
  if ($sub == 'forms') {
375
  // For compatibility the options are wrongly named
376
- return get_option('newsletter_forms', array());
377
  }
378
  return parent::get_options($sub, $language);
379
  }
143
  $options_antibot = $this->get_options('antibot');
144
 
145
  $captcha = !empty($options_antibot['captcha']);
146
+
147
 
148
  if (!empty($options_antibot['disabled']) || $this->antibot_form_check($captcha)) {
149
 
167
  $this->show_message('confirmation', $user);
168
  }
169
  } else {
170
+ $language = isset($_REQUEST['nlang'])?$_REQUEST['nlang']:'';
171
+ $options = $this->get_form_options($language);
172
+ $this->request_to_antibot_form($options['subscribe'], $captcha);
173
  }
174
  die();
175
 
346
  if ($sub == '') {
347
  // For compatibility the options are wrongly named
348
  if ($language) {
349
+ $options = get_option('newsletter_' . $language, []);
350
+ $options = array_merge(get_option('newsletter', []), $options);
351
  } else {
352
+ $options = get_option('newsletter', []);
353
  }
354
  if (!is_array($options)) {
355
  $options = array();
361
  if ($language) {
362
  // All that because for unknown reasome, sometime the options are returned as string, maybe a WPML
363
  // interference...
364
+ $i18n_options = get_option('newsletter_profile_' . $language, []);
365
+ if (!is_array($i18n_options)) {
366
+ $i18n_options = [];
367
+ }
368
+ $options = get_option('newsletter_profile', []);
369
+ if (!is_array($options)) {
370
+ $options = [];
371
+ }
372
  $options = array_merge($options, array_filter($i18n_options));
373
  } else {
374
+ $options = get_option('newsletter_profile', []);
375
  }
376
  // For compatibility the options are wrongly named
377
  return $options;
378
  }
379
  if ($sub == 'forms') {
380
  // For compatibility the options are wrongly named
381
+ return get_option('newsletter_forms', []);
382
  }
383
  return parent::get_options($sub, $language);
384
  }
tnp-header.php CHANGED
@@ -3,7 +3,7 @@ global $current_user, $wpdb;
3
 
4
  defined('ABSPATH') || exit;
5
 
6
- $dismissed = get_option('newsletter_dismissed', array());
7
 
8
  $user_count = Newsletter::instance()->get_user_count();
9
 
@@ -11,19 +11,16 @@ $is_administrator = current_user_can('administrator');
11
 
12
  function newsletter_print_entries($group) {
13
  $entries = apply_filters('newsletter_menu_' . $group, array());
14
- if ($entries) {
15
- foreach ($entries as &$entry) {
16
- echo '<li><a href="';
17
- echo $entry['url'];
18
- echo '">';
19
- echo $entry['label'];
20
- if (!empty($entry['description'])) {
21
- echo '<small>';
22
- echo $entry['description'];
23
- echo '</small>';
24
- }
25
- echo '</a></li>';
26
  }
 
27
  }
28
  }
29
 
@@ -41,11 +38,11 @@ $warning |= empty($status_options['mail']);
41
  </script>
42
 
43
  <?php if (get_option('newsletter_promotion') !== 'june-2020' && time() < gmmktime(0, 0, 0, 7, 15, 2020)) { ?>
44
- <div id="tnp-promotion-bar">
45
- <a href="https://www.thenewsletterplugin.com/premium?utm_source=plugin-bar&utm_campaign=june-2020" onclick="tnp_close_promotion(); return true;" target="_blank">50% discount offer until July, 15. Check it out.</a>
46
- &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
47
- <a href="javascript:void(tnp_close_promotion('june-2020'))">No, thank you!</a>
48
- </div>
49
  <?php } ?>
50
 
51
 
@@ -54,21 +51,39 @@ $warning |= empty($status_options['mail']);
54
  <ul>
55
  <li><a href="#"><i class="fas fa-users"></i> <?php _e('Subscribers', 'newsletter') ?> <i class="fas fa-chevron-down"></i></a>
56
  <ul>
57
- <li><a href="?page=newsletter_users_index"><i class="fas fa-search"></i> <?php _e('Search And Edit', 'newsletter') ?>
58
- <small><?php _e('Add, edit, search', 'newsletter') ?></small></a></li>
59
- <li><a href="?page=newsletter_profile_index"><i class="fas fa-user-circle"></i> <?php _e('Profile page', 'newsletter') ?>
60
- <small><?php _e('The subscriber personal profile editing panel', 'newsletter') ?></small></a></li>
61
- <li><a href="?page=newsletter_users_import"><i class="fas fa-upload"></i> <?php _e('Import', 'newsletter') ?>
62
- <small><?php _e('Import from external sources', 'newsletter') ?></small></a></li>
63
- <li><a href="?page=newsletter_users_export"><i class="fas fa-download"></i> <?php _e('Export', 'newsletter') ?>
64
- <small><?php _e('Export your subscribers list', 'newsletter') ?></small></a></li>
65
- <li><a href="?page=newsletter_users_massive"><i class="fas fa-wrench"></i> <?php _e('Maintenance', 'newsletter') ?>
66
- <small><?php _e('Massive actions: change list, clean up, ...', 'newsletter') ?></small></a></li>
67
- <li><a href="?page=newsletter_users_statistics"><i class="fas fa-chart-bar"></i> <?php _e('Statistics', 'newsletter') ?>
68
- <small><?php _e('All about your subscribers', 'newsletter') ?></small></a></li>
69
- <?php
70
- newsletter_print_entries('subscribers');
71
- ?>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
72
  </ul>
73
  </li>
74
  <li><a href="#"><i class="fas fa-list"></i> <?php _e('List Building', 'newsletter') ?> <i class="fas fa-chevron-down"></i></a>
@@ -82,18 +97,17 @@ $warning |= empty($status_options['mail']);
82
  <a href="?page=newsletter_subscription_options"><i class="fas fa-sign-in-alt"></i> <?php _e('Subscription', 'newsletter') ?>
83
  <small><?php _e('The subscription process in detail', 'newsletter') ?></small></a>
84
  </li>
85
-
86
  <li>
87
  <a href="?page=newsletter_subscription_lists"><i class="fas fa-th-list"></i> <?php _e('Lists', 'newsletter') ?>
88
  <small><?php _e('Profile the subscribers for a better targeting', 'newsletter') ?></small></a>
89
  </li>
90
-
91
  <li>
92
  <a href="?page=newsletter_subscription_antibot"><i class="fas fa-lock"></i> <?php _e('Security', 'newsletter') ?>
93
  <small><?php _e('Spam subscriptions control', 'newsletter') ?></small></a>
94
  </li>
95
 
96
-
97
  <li>
98
  <a href="?page=newsletter_unsubscription_index"><i class="fas fa-sign-out-alt"></i> <?php _e('Unsubscription', 'newsletter') ?>
99
  <small><?php _e('How to give the last goodbye (or avoid it!)', 'newsletter') ?></small></a>
@@ -104,14 +118,20 @@ $warning |= empty($status_options['mail']);
104
  ?>
105
  </ul>
106
  </li>
107
-
108
  <li>
109
  <a href="#"><i class="fas fa-newspaper"></i> <?php _e('Newsletters', 'newsletter') ?> <i class="fas fa-chevron-down"></i></a>
110
  <ul>
111
- <li><a href="?page=newsletter_emails_composer"><i class="fas fa-plus"></i> <?php _e('Create newsletter', 'newsletter') ?>
112
- <small><?php _e('Start your new campaign', 'newsletter') ?></small></a></li>
113
- <li><a href="?page=newsletter_emails_index"><i class="fas fa-newspaper"></i> <?php _e('Newsletters', 'newsletter') ?>
114
- <small><?php _e('The classic "write & send" newsletters', 'newsletter') ?></small></a></li>
 
 
 
 
 
 
115
  <li>
116
  <a href="<?php echo NewsletterStatistics::instance()->get_index_url() ?>"><i class="fas fa-chart-bar"></i> <?php _e('Statistics', 'newsletter') ?>
117
  <small><?php _e('Tracking configuration and basic data', 'newsletter') ?></small></a>
@@ -121,26 +141,29 @@ $warning |= empty($status_options['mail']);
121
  ?>
122
  </ul>
123
  </li>
124
-
125
  <li>
126
  <a href="#"><i class="fas fa-cog"></i> <?php _e('Settings', 'newsletter') ?> <i class="fas fa-chevron-down"></i></a>
127
  <ul>
128
  <?php if ($is_administrator) { ?>
129
- <li>
130
- <a href="?page=newsletter_main_main"><i class="fas fa-cogs"></i> <?php _e('General Settings', 'newsletter') ?>
131
- <small><?php _e('Delivery speed, sender details, ...', 'newsletter') ?></small></a>
132
- </li>
133
- <?php if (!class_exists('NewsletterSmtp')) { ?>
134
  <li>
135
- <a href="?page=newsletter_main_smtp"><i class="fas fa-server"></i> <?php _e('SMTP', 'newsletter') ?>
136
- <small><?php _e('External mail server', 'newsletter') ?></small>
137
- </a>
138
  </li>
 
 
 
 
 
 
 
139
  <?php } ?>
140
- <?php } ?>
141
-
142
- <li><a href="?page=newsletter_main_info"><i class="fas fa-info"></i> <?php _e('Company Info', 'newsletter') ?>
143
- <small><?php _e('Social, address, logo and general info', 'newsletter') ?></small></a></li>
 
 
144
  <li>
145
  <a href="?page=newsletter_subscription_template"><i class="fas fa-file-alt"></i> <?php _e('Messages Template', 'newsletter') ?>
146
  <small><?php _e('Change the look of your service emails', 'newsletter') ?></small></a>
@@ -153,55 +176,55 @@ $warning |= empty($status_options['mail']);
153
  </li>
154
 
155
  <?php if ($is_administrator) { ?>
156
- <li>
157
- <a href="?page=newsletter_main_status"><i class="fas fa-thermometer"></i> <?php _e('Status', 'newsletter') ?>
158
- <?php if ($warning) { ?>
159
- <i class="fas fa-exclamation-triangle" style="color: red;"></i>
160
- <?php } ?>
161
- </a>
162
- <ul>
163
- <li>
164
- <a href="?page=newsletter_main_logs"><i class="fas fa-file"></i> <?php _e('Logs', 'newsletter') ?>
165
- <small><?php _e('Plugin and addons logs', 'newsletter') ?></small></a>
166
- </li>
167
- </ul>
168
- </li>
169
  <?php } ?>
170
-
171
- <?php
172
- $license_data = Newsletter::instance()->get_license_data();
173
- $premium_url = 'https://www.thenewsletterplugin.com/premium?utm_source=plugin&utm_medium=link&utm_campaign=header&utm_content=' . urlencode($_GET['page']);
174
  ?>
175
 
176
  <?php if (empty($license_data)) { ?>
177
- <li class="tnp-professional-extensions-button"><a href="<?php echo $premium_url?>" target="_blank">
178
- <i class="fas fa-trophy"></i> <?php _e('Get Professional Addons', 'newsletter') ?></a>
179
  </li>
180
  <?php } elseif (is_wp_error($license_data)) { ?>
181
  <li class="tnp-professional-extensions-button-red">
182
  <a href="?page=newsletter_main_main"><i class="fas fa-hand-paper" style="color: white"></i> <?php _e('Unable to check', 'newsletter') ?></a>
183
  </li>
184
-
185
  <?php } elseif ($license_data->expire == 0) { ?>
186
-
187
- <li class="tnp-professional-extensions-button"><a href="<?php echo $premium_url?>" target="_blank">
188
- <i class="fas fa-trophy"></i> <?php _e('Get Professional Addons', 'newsletter') ?></a>
189
  </li>
190
-
191
  <?php } elseif ($license_data->expire < time()) { ?>
192
-
193
  <li class="tnp-professional-extensions-button-red">
194
  <a href="?page=newsletter_main_main"><i class="fas fa-hand-paper" style="color: white"></i> <?php _e('License expired', 'newsletter') ?></a>
195
  </li>
196
-
197
  <?php } elseif ($license_data->expire >= time()) { ?>
198
-
199
- <?php $p = class_exists('NewsletterExtensions')?'newsletter_extensions_index':'newsletter_main_extensions'; ?>
200
  <li class="tnp-professional-extensions-button">
201
- <a href="?page=<?php echo $p?>"><i class="fas fa-check-square"></i> <?php _e('License active', 'newsletter') ?></a>
202
  </li>
203
-
204
-
205
  <?php } ?>
206
  </ul>
207
  </div>
@@ -214,7 +237,7 @@ $warning |= empty($status_options['mail']);
214
  $content = get_post_field('post_content', Newsletter::instance()->options['page']);
215
  // With and without attributes
216
  if (strpos($content, '[newsletter]') === false && strpos($content, '[newsletter ') === false) {
217
- ?>
218
  <div class="tnp-notice">
219
  <a href="<?php echo $_SERVER['REQUEST_URI'] . '&noheader=1&dismiss=newsletter-shortcode' ?>" class="tnp-dismiss">&times;</a>
220
  The Newsletter dedicated page does not contain the [newsletter] shortcode. If you're using a visual composer it could be ok.
@@ -262,13 +285,14 @@ $warning |= empty($status_options['mail']);
262
  </div>
263
  <?php } ?>
264
 
265
- <?php if (!defined('NEWSLETTER_CRON_WARNINGS') || NEWSLETTER_CRON_WARNINGS) {
266
- $x = wp_next_scheduled('newsletter');
267
- if ($x === false) {
268
- echo '<div class="tnpc-warning">The Newsletter delivery engine is off (it should never be off). Deactivate and reactivate the Newsletter plugin.</div>';
269
- } else if (time() - $x > 900) {
270
- echo '<div class="tnpc-warning">The WP scheduler doesn\'t seem to be running correctly for Newsletter. <a href="https://www.thenewsletterplugin.com/documentation/?p=6128" target="_blank"><strong>Read this page to solve the problem</strong></a>.</div>';
271
- } else {
 
272
  // if (empty($this->options['disable_cron_notice'])) {
273
  // $cron_data = get_option('newsletter_diagnostic_cron_data');
274
  // if ($cron_data && $cron_data['mean'] > 500) {
@@ -278,7 +302,24 @@ $warning |= empty($status_options['mail']);
278
  }
279
  }
280
  ?>
281
-
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
282
  <div id="tnp-notification">
283
  <?php
284
  if (isset($controls)) {
3
 
4
  defined('ABSPATH') || exit;
5
 
6
+ $dismissed = get_option('newsletter_dismissed', []);
7
 
8
  $user_count = Newsletter::instance()->get_user_count();
9
 
11
 
12
  function newsletter_print_entries($group) {
13
  $entries = apply_filters('newsletter_menu_' . $group, array());
14
+ if (!$entries) {
15
+ return;
16
+ }
17
+
18
+ foreach ($entries as &$entry) {
19
+ echo '<li><a href="', $entry['url'], '">', $entry['label'];
20
+ if (!empty($entry['description'])) {
21
+ echo '<small>', $entry['description'], '</small>';
 
 
 
 
22
  }
23
+ echo '</a></li>';
24
  }
25
  }
26
 
38
  </script>
39
 
40
  <?php if (get_option('newsletter_promotion') !== 'june-2020' && time() < gmmktime(0, 0, 0, 7, 15, 2020)) { ?>
41
+ <div id="tnp-promotion-bar">
42
+ <a href="https://www.thenewsletterplugin.com/premium?utm_source=plugin-bar&utm_campaign=june-2020" onclick="tnp_close_promotion(); return true;" target="_blank">50% discount offer until July, 15. Check it out.</a>
43
+ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
44
+ <a href="javascript:void(tnp_close_promotion('june-2020'))">No, thank you!</a>
45
+ </div>
46
  <?php } ?>
47
 
48
 
51
  <ul>
52
  <li><a href="#"><i class="fas fa-users"></i> <?php _e('Subscribers', 'newsletter') ?> <i class="fas fa-chevron-down"></i></a>
53
  <ul>
54
+ <li>
55
+ <a href="?page=newsletter_users_index"><i class="fas fa-search"></i> <?php _e('Search And Edit', 'newsletter') ?>
56
+ <small><?php _e('Add, edit, search', 'newsletter') ?></small></a>
57
+ </li>
58
+
59
+ <li>
60
+ <a href="?page=newsletter_profile_index"><i class="fas fa-user-circle"></i> <?php _e('Profile page', 'newsletter') ?>
61
+ <small><?php _e('The subscriber personal profile editing panel', 'newsletter') ?></small></a>
62
+ </li>
63
+
64
+ <?php if (!class_exists('NewsletterImport')) { ?>
65
+ <li>
66
+ <a href="?page=newsletter_users_import"><i class="fas fa-upload"></i> <?php _e('Import', 'newsletter') ?>
67
+ <small><?php _e('Import from external sources', 'newsletter') ?></small></a>
68
+ </li>
69
+ <?php } ?>
70
+
71
+ <li>
72
+ <a href="?page=newsletter_users_export"><i class="fas fa-download"></i> <?php _e('Export', 'newsletter') ?>
73
+ <small><?php _e('Export your subscribers list', 'newsletter') ?></small></a>
74
+ </li>
75
+
76
+ <li>
77
+ <a href="?page=newsletter_users_massive"><i class="fas fa-wrench"></i> <?php _e('Maintenance', 'newsletter') ?>
78
+ <small><?php _e('Massive actions: change list, clean up, ...', 'newsletter') ?></small></a>
79
+ </li>
80
+
81
+ <li>
82
+ <a href="?page=newsletter_users_statistics"><i class="fas fa-chart-bar"></i> <?php _e('Statistics', 'newsletter') ?>
83
+ <small><?php _e('All about your subscribers', 'newsletter') ?></small></a>
84
+ </li>
85
+
86
+ <?php newsletter_print_entries('subscribers') ?>
87
  </ul>
88
  </li>
89
  <li><a href="#"><i class="fas fa-list"></i> <?php _e('List Building', 'newsletter') ?> <i class="fas fa-chevron-down"></i></a>
97
  <a href="?page=newsletter_subscription_options"><i class="fas fa-sign-in-alt"></i> <?php _e('Subscription', 'newsletter') ?>
98
  <small><?php _e('The subscription process in detail', 'newsletter') ?></small></a>
99
  </li>
100
+
101
  <li>
102
  <a href="?page=newsletter_subscription_lists"><i class="fas fa-th-list"></i> <?php _e('Lists', 'newsletter') ?>
103
  <small><?php _e('Profile the subscribers for a better targeting', 'newsletter') ?></small></a>
104
  </li>
105
+
106
  <li>
107
  <a href="?page=newsletter_subscription_antibot"><i class="fas fa-lock"></i> <?php _e('Security', 'newsletter') ?>
108
  <small><?php _e('Spam subscriptions control', 'newsletter') ?></small></a>
109
  </li>
110
 
 
111
  <li>
112
  <a href="?page=newsletter_unsubscription_index"><i class="fas fa-sign-out-alt"></i> <?php _e('Unsubscription', 'newsletter') ?>
113
  <small><?php _e('How to give the last goodbye (or avoid it!)', 'newsletter') ?></small></a>
118
  ?>
119
  </ul>
120
  </li>
121
+
122
  <li>
123
  <a href="#"><i class="fas fa-newspaper"></i> <?php _e('Newsletters', 'newsletter') ?> <i class="fas fa-chevron-down"></i></a>
124
  <ul>
125
+ <li>
126
+ <a href="?page=newsletter_emails_composer"><i class="fas fa-plus"></i> <?php _e('Create newsletter', 'newsletter') ?>
127
+ <small><?php _e('Start your new campaign', 'newsletter') ?></small></a>
128
+ </li>
129
+
130
+ <li>
131
+ <a href="?page=newsletter_emails_index"><i class="fas fa-newspaper"></i> <?php _e('Newsletters', 'newsletter') ?>
132
+ <small><?php _e('The classic "write & send" newsletters', 'newsletter') ?></small></a>
133
+ </li>
134
+
135
  <li>
136
  <a href="<?php echo NewsletterStatistics::instance()->get_index_url() ?>"><i class="fas fa-chart-bar"></i> <?php _e('Statistics', 'newsletter') ?>
137
  <small><?php _e('Tracking configuration and basic data', 'newsletter') ?></small></a>
141
  ?>
142
  </ul>
143
  </li>
144
+
145
  <li>
146
  <a href="#"><i class="fas fa-cog"></i> <?php _e('Settings', 'newsletter') ?> <i class="fas fa-chevron-down"></i></a>
147
  <ul>
148
  <?php if ($is_administrator) { ?>
 
 
 
 
 
149
  <li>
150
+ <a href="?page=newsletter_main_main"><i class="fas fa-cogs"></i> <?php _e('General Settings', 'newsletter') ?>
151
+ <small><?php _e('Delivery speed, sender details, ...', 'newsletter') ?></small></a>
 
152
  </li>
153
+ <?php if (!class_exists('NewsletterSmtp')) { ?>
154
+ <li>
155
+ <a href="?page=newsletter_main_smtp"><i class="fas fa-server"></i> <?php _e('SMTP', 'newsletter') ?>
156
+ <small><?php _e('External mail server', 'newsletter') ?></small>
157
+ </a>
158
+ </li>
159
+ <?php } ?>
160
  <?php } ?>
161
+
162
+ <li>
163
+ <a href="?page=newsletter_main_info"><i class="fas fa-info"></i> <?php _e('Company Info', 'newsletter') ?>
164
+ <small><?php _e('Social, address, logo and general info', 'newsletter') ?></small></a>
165
+ </li>
166
+
167
  <li>
168
  <a href="?page=newsletter_subscription_template"><i class="fas fa-file-alt"></i> <?php _e('Messages Template', 'newsletter') ?>
169
  <small><?php _e('Change the look of your service emails', 'newsletter') ?></small></a>
176
  </li>
177
 
178
  <?php if ($is_administrator) { ?>
179
+ <li>
180
+ <a href="?page=newsletter_main_status"><i class="fas fa-thermometer"></i> <?php _e('Status', 'newsletter') ?>
181
+ <?php if ($warning) { ?>
182
+ <i class="fas fa-exclamation-triangle" style="color: red;"></i>
183
+ <?php } ?>
184
+ </a>
185
+ <ul>
186
+ <li>
187
+ <a href="?page=newsletter_main_logs"><i class="fas fa-file"></i> <?php _e('Logs', 'newsletter') ?>
188
+ <small><?php _e('Plugin and addons logs', 'newsletter') ?></small></a>
189
+ </li>
190
+ </ul>
191
+ </li>
192
  <?php } ?>
193
+
194
+ <?php
195
+ $license_data = Newsletter::instance()->get_license_data();
196
+ $premium_url = 'https://www.thenewsletterplugin.com/premium?utm_source=plugin&utm_medium=link&utm_campaign=header&utm_content=' . urlencode($_GET['page']);
197
  ?>
198
 
199
  <?php if (empty($license_data)) { ?>
200
+ <li class="tnp-professional-extensions-button"><a href="<?php echo $premium_url ?>" target="_blank">
201
+ <i class="fas fa-trophy"></i> <?php _e('Get Professional Addons', 'newsletter') ?></a>
202
  </li>
203
  <?php } elseif (is_wp_error($license_data)) { ?>
204
  <li class="tnp-professional-extensions-button-red">
205
  <a href="?page=newsletter_main_main"><i class="fas fa-hand-paper" style="color: white"></i> <?php _e('Unable to check', 'newsletter') ?></a>
206
  </li>
207
+
208
  <?php } elseif ($license_data->expire == 0) { ?>
209
+
210
+ <li class="tnp-professional-extensions-button"><a href="<?php echo $premium_url ?>" target="_blank">
211
+ <i class="fas fa-trophy"></i> <?php _e('Get Professional Addons', 'newsletter') ?></a>
212
  </li>
213
+
214
  <?php } elseif ($license_data->expire < time()) { ?>
215
+
216
  <li class="tnp-professional-extensions-button-red">
217
  <a href="?page=newsletter_main_main"><i class="fas fa-hand-paper" style="color: white"></i> <?php _e('License expired', 'newsletter') ?></a>
218
  </li>
219
+
220
  <?php } elseif ($license_data->expire >= time()) { ?>
221
+
222
+ <?php $p = class_exists('NewsletterExtensions') ? 'newsletter_extensions_index' : 'newsletter_main_extensions'; ?>
223
  <li class="tnp-professional-extensions-button">
224
+ <a href="?page=<?php echo $p ?>"><i class="fas fa-check-square"></i> <?php _e('License active', 'newsletter') ?></a>
225
  </li>
226
+
227
+
228
  <?php } ?>
229
  </ul>
230
  </div>
237
  $content = get_post_field('post_content', Newsletter::instance()->options['page']);
238
  // With and without attributes
239
  if (strpos($content, '[newsletter]') === false && strpos($content, '[newsletter ') === false) {
240
+ ?>
241
  <div class="tnp-notice">
242
  <a href="<?php echo $_SERVER['REQUEST_URI'] . '&noheader=1&dismiss=newsletter-shortcode' ?>" class="tnp-dismiss">&times;</a>
243
  The Newsletter dedicated page does not contain the [newsletter] shortcode. If you're using a visual composer it could be ok.
285
  </div>
286
  <?php } ?>
287
 
288
+ <?php
289
+ if (!defined('NEWSLETTER_CRON_WARNINGS') || NEWSLETTER_CRON_WARNINGS) {
290
+ $x = wp_next_scheduled('newsletter');
291
+ if ($x === false) {
292
+ echo '<div class="tnpc-warning">The Newsletter delivery engine is off (it should never be off). Deactivate and reactivate the Newsletter plugin.</div>';
293
+ } else if (time() - $x > 900) {
294
+ echo '<div class="tnpc-warning">The WP scheduler doesn\'t seem to be running correctly for Newsletter. <a href="https://www.thenewsletterplugin.com/documentation/?p=6128" target="_blank"><strong>Read this page to solve the problem</strong></a>.</div>';
295
+ } else {
296
  // if (empty($this->options['disable_cron_notice'])) {
297
  // $cron_data = get_option('newsletter_diagnostic_cron_data');
298
  // if ($cron_data && $cron_data['mean'] > 500) {
302
  }
303
  }
304
  ?>
305
+
306
+ <?php
307
+ if ( $_GET['page'] !== 'newsletter_emails_edit' ) {
308
+
309
+ $last_failed_newsletters = Newsletter::instance()->get_emails_by_field( 'status', TNP_Email::STATUS_ERROR );
310
+
311
+ foreach ( $last_failed_newsletters as $newsletter ) {
312
+ echo '<div class="tnpc-error">';
313
+ printf(__('Newsletter "%s" stopped by fatal error.', 'newsletter'), esc_html( $newsletter->subject ));
314
+ echo '&nbsp;';
315
+ $c = new NewsletterControls();
316
+ $c->btn_link('?page=newsletter_emails_edit&id=' . $newsletter->id, __('Check', 'newsletter'));
317
+ echo '</div>';
318
+ }
319
+
320
+ }
321
+ ?>
322
+
323
  <div id="tnp-notification">
324
  <?php
325
  if (isset($controls)) {