Newsletter - Version 7.1.9

Version Description

  • [GENERAL] Removed the encodign defatlt to Base 64 when not specified since it seems incompatible with some SMTP plugins
  • [GENERAL] Review some controls layout and behavior
  • [DEBUG] Improved logging on database errors
  • [GENERAL] Added TikTok, Discord and Twitch socials
  • [GENERAL] Fixed odd error reported related to the cron call statistics collection
  • [DEBUG] Added a delivery diagnostic panel
Download this release

Release Info

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

Code changes from version 7.1.8 to 7.1.9

admin.css CHANGED
@@ -195,6 +195,7 @@
195
  #tnp-body h4,
196
  #tnp-body p {
197
  color: #fff;
 
198
  }
199
 
200
  #tnp-body h3 {
@@ -953,7 +954,7 @@ span.wp-media-buttons-icon:before {
953
  color: #fff;
954
  }
955
 
956
- #tnp-status-table .tnp-ok {
957
  font-weight: bold;
958
  color: white;
959
  font-size: 14px;
@@ -965,7 +966,7 @@ span.wp-media-buttons-icon:before {
965
  text-align: center;
966
  }
967
 
968
- #tnp-status-table .tnp-ko {
969
  font-weight: bold;
970
  color: white;
971
  font-size: 14px;
@@ -977,7 +978,7 @@ span.wp-media-buttons-icon:before {
977
  text-align: center;
978
  }
979
 
980
- #tnp-status-table .tnp-maybe {
981
  font-weight: bold;
982
  color: white;
983
  font-size: 14px;
195
  #tnp-body h4,
196
  #tnp-body p {
197
  color: #fff;
198
+ font-weight: normal;
199
  }
200
 
201
  #tnp-body h3 {
954
  color: #fff;
955
  }
956
 
957
+ .tnp-ok {
958
  font-weight: bold;
959
  color: white;
960
  font-size: 14px;
966
  text-align: center;
967
  }
968
 
969
+ .tnp-ko {
970
  font-weight: bold;
971
  color: white;
972
  font-size: 14px;
978
  text-align: center;
979
  }
980
 
981
+ .tnp-maybe {
982
  font-weight: bold;
983
  color: white;
984
  font-size: 14px;
css/controls.css CHANGED
@@ -69,11 +69,6 @@
69
  border-collapse: collapse;
70
  }
71
 
72
- #tnp-body .form-table table thead th {
73
- text-align: left;
74
- font-weight: bold;
75
- }
76
-
77
  #tnp-body .form-table td table th {
78
  background-color: transparent;
79
  text-align: right;
@@ -92,6 +87,20 @@
92
  vertical-align: middle;
93
  }
94
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
95
  /* Fix for select 2 */
96
  #tnp-body .form-table td ul {
97
  margin-left: 0;
@@ -112,6 +121,22 @@
112
  overflow: hidden;
113
  }
114
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
115
 
116
  /* Hint text after a field */
117
  .tnpc-hint, p.description {
69
  border-collapse: collapse;
70
  }
71
 
 
 
 
 
 
72
  #tnp-body .form-table td table th {
73
  background-color: transparent;
74
  text-align: right;
87
  vertical-align: middle;
88
  }
89
 
90
+ #tnp-body .form-table td table.widefat th {
91
+ background-color: transparent;
92
+ text-align: left;
93
+ width: auto;
94
+ padding: 5px;
95
+ font-weight: normal;
96
+ }
97
+
98
+ #tnp-body .form-table td table.widefat td {
99
+ background-color: transparent;
100
+ padding: 5px;
101
+ vertical-align: middle;
102
+ }
103
+
104
  /* Fix for select 2 */
105
  #tnp-body .form-table td ul {
106
  margin-left: 0;
121
  overflow: hidden;
122
  }
123
 
124
+ .tnpc-lists label {
125
+ display: block;
126
+ padding: 5px 0;
127
+ }
128
+
129
+ .tnpc-lists label span {
130
+ border-radius: 3px;
131
+ color: #fff;
132
+ background-color: #aaa;
133
+ display: inline-block;
134
+ padding: 1px 5px;
135
+ min-width: 2em;
136
+ font-size: .9em;
137
+ text-align: center;
138
+ }
139
+
140
 
141
  /* Hint text after a field */
142
  .tnpc-hint, p.description {
css/fields.css CHANGED
@@ -49,6 +49,12 @@
49
  float: left;
50
  }
51
 
 
 
 
 
 
 
52
  .tnp-section {
53
 
54
  }
@@ -65,6 +71,10 @@
65
  margin-bottom: 10px;
66
  }
67
 
 
 
 
 
68
  .tnp-field label.tnp-label, .tnp-field-row label.tnp-row-label {
69
  display: block;
70
  font-size: 12px;
49
  float: left;
50
  }
51
 
52
+ .tnp-field-box {
53
+ padding: 10px;
54
+ background-color: #eee !important;
55
+ border: 1px solid #bbb;
56
+ }
57
+
58
  .tnp-section {
59
 
60
  }
71
  margin-bottom: 10px;
72
  }
73
 
74
+ .tnp-field select.tnp-small {
75
+ font-size: .9em;
76
+ }
77
+
78
  .tnp-field label.tnp-label, .tnp-field-row label.tnp-row-label {
79
  display: block;
80
  font-size: 12px;
emails/blocks/posts/options.php CHANGED
@@ -14,76 +14,83 @@ if (class_exists('NewsletterExtensions')) {
14
 
15
  <?php if ($context['type'] == 'automated') { ?>
16
 
17
- <?php $fields->select('automated_disabled', '', ['' => 'Check for new posts since last newsletter', '1' => 'Do not check for new posts']) ?>
 
 
 
 
 
18
 
19
  <div class="tnp-field-row">
20
  <div class="tnp-field-col-2">
21
- <?php
22
- $fields->select('automated_include', __('If there are new posts', 'newsletter'),
23
- [
24
- 'new' => __('Include only new posts', 'newsletter'),
25
- 'max' => __('Include specified max posts', 'newsletter')
26
- ],
27
- ['description' => ''])
28
- ?>
29
  </div>
30
  <div class="tnp-field-col-2">
31
- <?php
32
- $fields->select('automated', __('If there are not new posts', 'newsletter'),
33
- [
34
- '' => 'Show the message below',
35
- '1' => 'Do not send the newsletter',
36
- '2' => 'Remove this block'
37
- ],
38
- ['description' => ''])
39
- ?>
40
- <?php $fields->text('automated_no_contents', null, ['placeholder'=>'No new posts message']) ?>
41
  </div>
42
  </div>
43
-
 
44
  <?php } ?>
45
 
46
 
47
- <?php $fields->select( 'layout', __( 'Layout', 'newsletter' ),
48
- array(
49
- 'one' => __( 'One column', 'newsletter' ),
50
- 'one-2' => __( 'One column variant', 'newsletter' ),
51
- 'two' => __( 'Two columns', 'newsletter' ),
52
- 'big-image' => __( 'One column, big image', 'newsletter' ),
53
- 'full-post' => __( 'Full post', 'newsletter' )
54
- ) )
55
- ?>
56
-
 
57
 
58
  <div class="tnp-field-row">
59
  <label class="tnp-row-label"><?php _e('Post info', 'newsletter') ?></label>
60
  <div class="tnp-field-col-3">
61
- <?php $fields->checkbox('show_date', __('Show date', 'newsletter')) ?>
62
  </div>
63
  <div class="tnp-field-col-3">
64
- <?php $fields->checkbox('show_author', __('Show author', 'newsletter')) ?>
65
  </div>
66
  <div class="tnp-field-col-3">
67
- <?php $fields->checkbox( 'show_image', __( 'Show image', 'newsletter' ) ) ?>
68
  </div>
69
  <div style="clear: both"></div>
70
  </div>
71
 
72
  <div class="tnp-field-row">
73
  <div class="tnp-field-col-2">
74
- <?php $fields->select_number('max', __('Max posts', 'newsletter'), 1, 40); ?>
75
  </div>
76
  <div class="tnp-field-col-2">
77
- <?php $fields->select_number('post_offset', __('Posts offset', 'newsletter'), 0, 20); ?>
78
  </div>
79
  </div>
80
 
81
  <div class="tnp-field-row">
82
  <div class="tnp-field-col-2">
83
- <?php $fields->number( 'excerpt_length', __( 'Excerpt words', 'newsletter' ), array( 'min' => 0 ) ); ?>
84
  </div>
85
  <div class="tnp-field-col-2">
86
- <?php $fields->yesno( 'show_read_more_button', 'Show read more button' ) ?>
87
  </div>
88
  <div style="clear: both"></div>
89
  </div>
@@ -95,14 +102,16 @@ if (class_exists('NewsletterExtensions')) {
95
  <?php $fields->text('tags', __('Tags', 'newsletter'), ['description' => __('Comma separated')]); ?>
96
 
97
  <?php $fields->section(__('Styles', 'newsletter')) ?>
98
- <?php $fields->font( 'title_font', __( 'Title font', 'newsletter' ), ['family_default'=>true, 'size_default'=>true, 'weight_default'=>true] ) ?>
99
- <?php $fields->font( 'font', __( 'Excerpt font', 'newsletter' ), ['family_default'=>true, 'size_default'=>true, 'weight_default'=>true] ) ?>
100
- <?php $fields->button( 'button', __( 'Read more button', 'newsletter' ), [
101
- 'url' => false,
102
- 'family_default' => true,
103
- 'size_default' => true,
104
- 'weight_default' => true
105
- ] ) ?>
 
 
106
 
107
  <?php $fields->block_commons() ?>
108
 
14
 
15
  <?php if ($context['type'] == 'automated') { ?>
16
 
17
+ <div class="tnp-field-box">
18
+ <p>
19
+ <strong>AUTOMATED</strong><br>
20
+ While composing all posts are shown while on sending posts are extrated following the rules below.
21
+ </p>
22
+ <?php $fields->select('automated_disabled', '', ['' => 'Use the last newsletter date and...', '1' => 'Do not consider the last newsletter']) ?>
23
 
24
  <div class="tnp-field-row">
25
  <div class="tnp-field-col-2">
26
+ <?php
27
+ $fields->select('automated_include', __('If there are new posts', 'newsletter'),
28
+ [
29
+ 'new' => __('Include only new posts', 'newsletter'),
30
+ 'max' => __('Include specified max posts', 'newsletter')
31
+ ],
32
+ ['description' => '', 'class' => 'tnp-small'])
33
+ ?>
34
  </div>
35
  <div class="tnp-field-col-2">
36
+ <?php
37
+ $fields->select('automated', __('If there are not new posts', 'newsletter'),
38
+ [
39
+ '' => 'Show the message below',
40
+ '1' => 'Do not send the newsletter',
41
+ '2' => 'Remove this block'
42
+ ],
43
+ ['description' => '', 'class' => 'tnp-small'])
44
+ ?>
45
+ <?php $fields->text('automated_no_contents', null, ['placeholder' => 'No new posts message']) ?>
46
  </div>
47
  </div>
48
+ <div style="clear: both"></div>
49
+ </div>
50
  <?php } ?>
51
 
52
 
53
+ <?php
54
+ $fields->select('layout', __('Layout', 'newsletter'),
55
+ [
56
+ 'one' => __('One column', 'newsletter'),
57
+ 'one-2' => __('One column variant', 'newsletter'),
58
+ 'two' => __('Two columns', 'newsletter'),
59
+ 'big-image' => __('One column, big image', 'newsletter'),
60
+ 'full-post' => __('Full post', 'newsletter')
61
+ ])
62
+ ?>
63
+
64
 
65
  <div class="tnp-field-row">
66
  <label class="tnp-row-label"><?php _e('Post info', 'newsletter') ?></label>
67
  <div class="tnp-field-col-3">
68
+ <?php $fields->checkbox('show_date', __('Show date', 'newsletter')) ?>
69
  </div>
70
  <div class="tnp-field-col-3">
71
+ <?php $fields->checkbox('show_author', __('Show author', 'newsletter')) ?>
72
  </div>
73
  <div class="tnp-field-col-3">
74
+ <?php $fields->checkbox('show_image', __('Show image', 'newsletter')) ?>
75
  </div>
76
  <div style="clear: both"></div>
77
  </div>
78
 
79
  <div class="tnp-field-row">
80
  <div class="tnp-field-col-2">
81
+ <?php $fields->select_number('max', __('Max posts', 'newsletter'), 1, 40); ?>
82
  </div>
83
  <div class="tnp-field-col-2">
84
+ <?php $fields->select_number('post_offset', __('Posts offset', 'newsletter'), 0, 20); ?>
85
  </div>
86
  </div>
87
 
88
  <div class="tnp-field-row">
89
  <div class="tnp-field-col-2">
90
+ <?php $fields->number('excerpt_length', __('Excerpt words', 'newsletter'), array('min' => 0)); ?>
91
  </div>
92
  <div class="tnp-field-col-2">
93
+ <?php $fields->yesno('show_read_more_button', 'Show read more button') ?>
94
  </div>
95
  <div style="clear: both"></div>
96
  </div>
102
  <?php $fields->text('tags', __('Tags', 'newsletter'), ['description' => __('Comma separated')]); ?>
103
 
104
  <?php $fields->section(__('Styles', 'newsletter')) ?>
105
+ <?php $fields->font('title_font', __('Title font', 'newsletter'), ['family_default' => true, 'size_default' => true, 'weight_default' => true]) ?>
106
+ <?php $fields->font('font', __('Excerpt font', 'newsletter'), ['family_default' => true, 'size_default' => true, 'weight_default' => true]) ?>
107
+ <?php
108
+ $fields->button('button', __('Read more button', 'newsletter'), [
109
+ 'url' => false,
110
+ 'family_default' => true,
111
+ 'size_default' => true,
112
+ 'weight_default' => true
113
+ ])
114
+ ?>
115
 
116
  <?php $fields->block_commons() ?>
117
 
emails/blocks/social/block.php CHANGED
@@ -19,7 +19,7 @@ $options = array_merge($defaults, $options);
19
 
20
  $social_icon_url = plugins_url('newsletter') . '/emails/themes/default/images';
21
 
22
- $socials = ['facebook', 'twitter', 'pinterest', 'linkedin', 'tumblr', 'youtube', 'soundcloud', 'instagram', 'vimeo', 'telegram', 'vk'];
23
 
24
  $valid_socials = [];
25
  foreach ($socials as &$social) {
19
 
20
  $social_icon_url = plugins_url('newsletter') . '/emails/themes/default/images';
21
 
22
+ $socials = ['facebook', 'twitter', 'pinterest', 'linkedin', 'tumblr', 'youtube', 'soundcloud', 'instagram', 'vimeo', 'telegram', 'vk', 'discord', 'tiktok', 'twitch'];
23
 
24
  $valid_socials = [];
25
  foreach ($socials as &$social) {
emails/themes/default/images/discord.png ADDED
Binary file
emails/themes/default/images/tiktok.png ADDED
Binary file
emails/themes/default/images/twitch.png ADDED
Binary file
emails/tnp-composer/_css/newsletter-builder-v2.css CHANGED
@@ -681,7 +681,7 @@ iframe#tnpc-mobile-preview {
681
  margin-top: 0;
682
  }
683
 
684
- #tnpc-block-options-form, #tnpc-block-options-form p {
685
  color: #444;
686
  background-color: #ECF0F1 !important;
687
  }
681
  margin-top: 0;
682
  }
683
 
684
+ #tnpc-block-options-form {
685
  color: #444;
686
  background-color: #ECF0F1 !important;
687
  }
includes/controls.php CHANGED
@@ -308,6 +308,10 @@ class NewsletterControls {
308
  $time = gmmktime((int) $_REQUEST[$name . '_hour'], 0, 0, (int) $_REQUEST[$name . '_month'], (int) $_REQUEST[$name . '_day'], (int) $_REQUEST[$name . '_year']);
309
  $time -= get_option('gmt_offset') * 3600;
310
  $this->data[$name] = $time;
 
 
 
 
311
  }
312
  }
313
  }
@@ -866,8 +870,8 @@ class NewsletterControls {
866
  if (!empty($attrs['data'])) {
867
  $onclick .= "this.form.btn.value='" . esc_attr(esc_js($attrs['data'])) . "';";
868
  }
869
- if (!empty($attrs['confirm'])) {
870
- if (is_string($attrs['confirm'])) {
871
  $onclick .= "if (!confirm('" . esc_attr(esc_js($attrs['confirm'])) . "')) return false;";
872
  } else {
873
  $onclick .= "if (!confirm('" . esc_attr(esc_js(__('Proceed?', 'newsletter'))) . "')) return false;";
@@ -1159,14 +1163,19 @@ class NewsletterControls {
1159
  * Creates a checkbox named $name and checked if the internal data contains under
1160
  * the key $name an array containig the passed value.
1161
  */
1162
- function checkbox_group($name, $value, $label = '') {
 
1163
  echo '<label><input type="checkbox" id="' . esc_attr($name) . '" name="options[' . esc_attr($name) . '][]" value="' . esc_attr($value) . '"';
1164
  if (isset($this->data[$name]) && is_array($this->data[$name]) && array_search($value, $this->data[$name]) !== false) {
1165
  echo ' checked';
1166
  }
1167
  echo '>';
1168
  if ($label != '') {
1169
- echo esc_html($label);
 
 
 
 
1170
  }
1171
  echo '</label>';
1172
  }
@@ -1227,6 +1236,16 @@ class NewsletterControls {
1227
  }
1228
  echo '<div style="clear: both"></div>';
1229
  }
 
 
 
 
 
 
 
 
 
 
1230
 
1231
  function lists_checkboxes($name = 'lists') {
1232
  $this->preferences_group($name);
@@ -1241,14 +1260,10 @@ class NewsletterControls {
1241
 
1242
  $lists = Newsletter::instance()->get_lists();
1243
 
1244
- echo '<div class="newsletter-preferences-group">';
1245
  foreach ($lists as $list) {
1246
-
1247
- echo '<div class="newsletter-preferences-item">';
1248
- $this->checkbox_group($name, $list->id, '(' . $list->id . ') ' . esc_html($list->name));
1249
- echo '</div>';
1250
  }
1251
- echo '<div style="clear: both"></div>';
1252
  echo '<a href="https://www.thenewsletterplugin.com/documentation/newsletter-lists" target="_blank">'
1253
  . 'Click here to read more about lists.'
1254
  . '</a>';
308
  $time = gmmktime((int) $_REQUEST[$name . '_hour'], 0, 0, (int) $_REQUEST[$name . '_month'], (int) $_REQUEST[$name . '_day'], (int) $_REQUEST[$name . '_year']);
309
  $time -= get_option('gmt_offset') * 3600;
310
  $this->data[$name] = $time;
311
+ continue;
312
+ }
313
+ if ($type === 'array') {
314
+ if (!isset($this->data[$name])) $this->data[$name] = [];
315
  }
316
  }
317
  }
870
  if (!empty($attrs['data'])) {
871
  $onclick .= "this.form.btn.value='" . esc_attr(esc_js($attrs['data'])) . "';";
872
  }
873
+ if (isset($attrs['confirm'])) {
874
+ if (!empty($attrs['confirm'])) {
875
  $onclick .= "if (!confirm('" . esc_attr(esc_js($attrs['confirm'])) . "')) return false;";
876
  } else {
877
  $onclick .= "if (!confirm('" . esc_attr(esc_js(__('Proceed?', 'newsletter'))) . "')) return false;";
1163
  * Creates a checkbox named $name and checked if the internal data contains under
1164
  * the key $name an array containig the passed value.
1165
  */
1166
+ function checkbox_group($name, $value, $label = '', $attrs = []) {
1167
+ $attrs = wp_parse_args($attrs, ['label_escape'=>true]);
1168
  echo '<label><input type="checkbox" id="' . esc_attr($name) . '" name="options[' . esc_attr($name) . '][]" value="' . esc_attr($value) . '"';
1169
  if (isset($this->data[$name]) && is_array($this->data[$name]) && array_search($value, $this->data[$name]) !== false) {
1170
  echo ' checked';
1171
  }
1172
  echo '>';
1173
  if ($label != '') {
1174
+ if ($attrs['label_escape']) {
1175
+ echo esc_html($label);
1176
+ } else {
1177
+ echo $label;
1178
+ }
1179
  }
1180
  echo '</label>';
1181
  }
1236
  }
1237
  echo '<div style="clear: both"></div>';
1238
  }
1239
+
1240
+ /** A list of all lists defined each one with a checkbox to select it. An array
1241
+ * of ID of all checked lists is submitted.
1242
+ *
1243
+ * @param string $name
1244
+ */
1245
+ function lists($name = 'lists') {
1246
+ echo '<input type="hidden" name="tnp_fields[' . esc_attr($name) . ']" value="array">';
1247
+ $this->preferences_group($name);
1248
+ }
1249
 
1250
  function lists_checkboxes($name = 'lists') {
1251
  $this->preferences_group($name);
1260
 
1261
  $lists = Newsletter::instance()->get_lists();
1262
 
1263
+ echo '<div class="tnpc-lists">';
1264
  foreach ($lists as $list) {
1265
+ $this->checkbox_group($name, $list->id, '<span>' . $list->id . '</span> ' . esc_html($list->name), ['label_escape'=>false]);
 
 
 
1266
  }
 
1267
  echo '<a href="https://www.thenewsletterplugin.com/documentation/newsletter-lists" target="_blank">'
1268
  . 'Click here to read more about lists.'
1269
  . '</a>';
includes/fields.php CHANGED
@@ -215,12 +215,15 @@ class NewsletterFields {
215
  * @param type $attrs
216
  */
217
  public function select($name, $label = '', $options = [], $attrs = []) {
218
- $attrs = $this->_merge_attrs($attrs, ['reload' => false, 'after-rendering' => '']);
219
  $this->_open();
220
  $this->_label($label);
221
  $value = $this->controls->get_value($name);
222
 
223
  echo '<select id="', $this->_id($name), '" name="', $this->_name($name), '"';
 
 
 
224
  if ($attrs['reload']) {
225
  echo ' onchange="tnpc_reload_options(event)"';
226
  }
215
  * @param type $attrs
216
  */
217
  public function select($name, $label = '', $options = [], $attrs = []) {
218
+ $attrs = $this->_merge_attrs($attrs, ['reload' => false, 'after-rendering' => '', 'class' => '']);
219
  $this->_open();
220
  $this->_label($label);
221
  $value = $this->controls->get_value($name);
222
 
223
  echo '<select id="', $this->_id($name), '" name="', $this->_name($name), '"';
224
+ if ($attrs['class']) {
225
+ echo ' class="', esc_attr($attrs['class']), '"';
226
+ }
227
  if ($attrs['reload']) {
228
  echo ' onchange="tnpc_reload_options(event)"';
229
  }
includes/mailer.php CHANGED
@@ -337,7 +337,8 @@ class NewsletterDefaultMailer extends NewsletterMailer {
337
  if (!empty($newsletter->options['content_transfer_encoding'])) {
338
  $mailer->Encoding = $newsletter->options['content_transfer_encoding'];
339
  } else {
340
- $mailer->Encoding = 'base64';
 
341
  }
342
  }
343
 
337
  if (!empty($newsletter->options['content_transfer_encoding'])) {
338
  $mailer->Encoding = $newsletter->options['content_transfer_encoding'];
339
  } else {
340
+ // Setting and encoding sometimes conflict with SMTP plugins
341
+ //$mailer->Encoding = 'base64';
342
  }
343
  }
344
 
includes/module.php CHANGED
@@ -258,6 +258,19 @@ class TNP_Subscription_Data {
258
  $subscriber->$key = $value;
259
  }
260
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
261
 
262
  }
263
 
258
  $subscriber->$key = $value;
259
  }
260
  }
261
+
262
+ /** Sets to active a set of lists. Accepts incorrect data (and ignores it).
263
+ *
264
+ * @param array $list_ids Array of list IDs
265
+ */
266
+ function add_lists($list_ids) {
267
+ if (empty($list_ids) || !is_array($list_ids)) return;
268
+ foreach ($list_ids as $list_id) {
269
+ $list_id = (int)$list_id;
270
+ if ($list_id < 0 || $list_id > NEWSLETTER_LIST_MAX) continue;
271
+ $this->lists[$list_id] = 1;
272
+ }
273
+ }
274
 
275
  }
276
 
includes/store.php CHANGED
@@ -133,6 +133,7 @@ class NewsletterStore {
133
  if ($r === false) {
134
  $this->logger->fatal($wpdb->last_error);
135
  $this->logger->fatal($wpdb->last_query);
 
136
  die('Database error. If you were saving a newsletter try a table upgrade from the status panel.');
137
  }
138
  }
@@ -142,6 +143,7 @@ class NewsletterStore {
142
  if ($r === false) {
143
  $this->logger->fatal($wpdb->last_error);
144
  $this->logger->fatal($wpdb->last_query);
 
145
  die('Database error. If you were saving a newsletter try a table upgrade from the status panel.');
146
  }
147
  $id = $wpdb->insert_id;
133
  if ($r === false) {
134
  $this->logger->fatal($wpdb->last_error);
135
  $this->logger->fatal($wpdb->last_query);
136
+ $this->logger->debug($data);
137
  die('Database error. If you were saving a newsletter try a table upgrade from the status panel.');
138
  }
139
  }
143
  if ($r === false) {
144
  $this->logger->fatal($wpdb->last_error);
145
  $this->logger->fatal($wpdb->last_query);
146
+ $this->logger->debug($data);
147
  die('Database error. If you were saving a newsletter try a table upgrade from the status panel.');
148
  }
149
  $id = $wpdb->insert_id;
main/delivery.php ADDED
@@ -0,0 +1,221 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /* @var $this Newsletter */
3
+ /* @var $wpdb wpdb */
4
+
5
+ defined('ABSPATH') || exit;
6
+
7
+ include_once NEWSLETTER_INCLUDES_DIR . '/controls.php';
8
+ $controls = new NewsletterControls();
9
+
10
+ if ($controls->is_action('test')) {
11
+
12
+ if (!NewsletterModule::is_email($controls->data['test_email'])) {
13
+ $controls->errors = 'The test email address is not set or is not correct.';
14
+ }
15
+
16
+ if (empty($controls->errors)) {
17
+
18
+ $options = $controls->data;
19
+
20
+ if ($controls->data['test_email'] == $this->options['sender_email']) {
21
+ $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>';
22
+ }
23
+
24
+ $message = NewsletterMailerAddon::get_test_message($controls->data['test_email'], 'Newsletter test email at ' . date(DATE_ISO8601));
25
+
26
+ $r = $this->deliver($message);
27
+
28
+ if (!is_wp_error($r)) {
29
+ $options['mail'] = 1;
30
+ $controls->messages .= '<strong>SUCCESS</strong><br>';
31
+ $controls->messages .= 'Anyway if the message does not appear the mailbox (check even the spam folder) you can ';
32
+ $controls->messages .= '<a href="https://www.thenewsletterplugin.com/documentation/?p=15170" target="_blank"><strong>read more here</strong></a>.';
33
+ } else {
34
+ $options['mail'] = 0;
35
+ $options['mail_error'] = $r->get_error_message();
36
+
37
+ $controls->errors .= '<strong>FAILED</strong> (' . $r->get_error_message() . ')<br>';
38
+
39
+ if (!empty($this->options['return_path'])) {
40
+ $controls->errors .= '- Try to remove the return path on main settings.<br>';
41
+ }
42
+
43
+ $controls->errors .= '<a href="https://www.thenewsletterplugin.com/documentation/?p=15170" target="_blank"><strong>' . __('Read more', 'newsletter') . '</strong></a>.';
44
+
45
+ $parts = explode('@', $this->options['sender_email']);
46
+ $sitename = strtolower($_SERVER['SERVER_NAME']);
47
+ if (substr($sitename, 0, 4) == 'www.') {
48
+ $sitename = substr($sitename, 4);
49
+ }
50
+ if (strtolower($sitename) != strtolower($parts[1])) {
51
+ $controls->errors .= '- Try to set on main setting a sender address with the same domain of your blog: ' . $sitename . ' (you are using ' . $this->options['sender_email'] . ')<br>';
52
+ }
53
+ }
54
+ $this->save_options($options, 'status');
55
+ }
56
+ }
57
+
58
+ $options = $this->get_options('status');
59
+
60
+ $mailer = Newsletter::instance()->get_mailer();
61
+ $functions = tnp_get_hook_functions('phpmailer_init');
62
+ $icon = 'fas fa-plug';
63
+ if ($mailer instanceof NewsletterDefaultMailer) {
64
+ $mailer_name = 'Wordpress';
65
+ $service_name = 'Hosting Provider';
66
+ if (!empty($functions)) {
67
+ $mailer_name .= '<br>(see below)';
68
+ $service_name .= '<br>(see below)';
69
+ }
70
+ $icon = 'fab fa-wordpress';
71
+ } else if ($mailer instanceof NewsletterDefaultSMTPMailer) {
72
+ $mailer_name = 'Internal SMTP';
73
+ $service_name = 'SMTP Provider';
74
+ } else {
75
+ $mailer_name = 'Unknown';
76
+ $service_name = 'Unknown';
77
+ if (is_object($mailer)) {
78
+ if (method_exists($mailer, 'get_description')) {
79
+ $mailer_name = esc_html($mailer->get_description());
80
+ $service_name = esc_html(ucfirst($mailer->get_name()));
81
+ } else {
82
+ $mailer_name = esc_html(get_class($mailer));
83
+ $service_name = $mailer_name;
84
+ }
85
+ }
86
+ }
87
+
88
+ function tnp_get_hook_functions($tag) {
89
+ global $wp_filter;
90
+ if (isset($wp_filter)) {
91
+ $b = '';
92
+ foreach ($wp_filter[$tag]->callbacks as $priority => $functions) {
93
+
94
+ foreach ($functions as $function) {
95
+ //var_dump($function);
96
+ $b .= '[' . $priority . '] ';
97
+ if (is_array($function['function'])) {
98
+ if (is_object($function['function'][0])) {
99
+ $b .= get_class($function['function'][0]) . '::' . $function['function'][1];
100
+ } else {
101
+ $b .= $function['function'][0] . '::' . $function['function'][1];
102
+ }
103
+ } else {
104
+ if (is_object($function['function'])) {
105
+ $fn = new ReflectionFunction($function['function']);
106
+ $b .= get_class($fn->getClosureThis()) . '(closure)';
107
+ } else {
108
+ $b .= $function['function'];
109
+ }
110
+ }
111
+ $b .= "<br>";
112
+ }
113
+ }
114
+ }
115
+ return $b;
116
+ }
117
+
118
+ $speed = Newsletter::$instance->options['scheduler_max'];
119
+ ?>
120
+ <style>
121
+ .tnp-flow {
122
+ margin-top: 30px;
123
+ }
124
+ .tnp-flow div {
125
+ display: inline-block;
126
+ vertical-align: middle;
127
+ color: #fff;
128
+ text-align: center;
129
+ margin: 0 20px;
130
+ padding: 1em;
131
+ }
132
+ .tnp-flow div i {
133
+ font-size: 50px;
134
+ }
135
+ .tnp-flow div.tnp-arrow {
136
+ font-size: 40px;
137
+ color: #bbb;
138
+ padding: 0;
139
+ margin: 0;
140
+ }
141
+ .tnp-mail, .tnp-addon, .tnp-service {
142
+ height: 150px;
143
+ width: 150px;
144
+ border: 1px solid #fff;
145
+ }
146
+ </style>
147
+
148
+ <div class="wrap tnp-main-status" id="tnp-wrap">
149
+
150
+ <?php include NEWSLETTER_DIR . '/tnp-header.php'; ?>
151
+
152
+ <div id="tnp-heading">
153
+
154
+ <h2><?php _e('Email Delivery', 'newsletter') ?></h2>
155
+
156
+ </div>
157
+
158
+ <div id="tnp-body">
159
+ <form method="post" action="">
160
+ <?php $controls->init(); ?>
161
+ <h3>Mailing test</h3>
162
+
163
+ <p>
164
+ <?php $controls->text_email('test_email') ?> <?php $controls->button('test', __('Send a test message')) ?>
165
+ <?php if (empty($options['mail'])) { ?>
166
+ <span class="tnp-ko">KO</span>
167
+ <?php } else { ?>
168
+ <span class="tnp-ok">OK</span>
169
+ <?php } ?>
170
+ </p>
171
+
172
+ <p>
173
+ <?php if (empty($options['mail'])) { ?>
174
+ <?php if (empty($options['mail_error'])) { ?>
175
+ <p>A test has never run.</p>
176
+ <?php } else { ?>
177
+ <p>Last test failed with error "<?php echo esc_html($options['mail_error']) ?>".</p>
178
+
179
+ <?php } ?>
180
+ <?php } else { ?>
181
+ <p>Last test was successful. If you didn't receive the test email:</p>
182
+ <ol style="color: #fff">
183
+ <li>If you're using an third party SMTP plugin, do a test from that plugin configuration panel</li>
184
+ <li>If you're using a Newsletter Delivery Addon, do a test from that addon configuration panel</li>
185
+ <li>If previous points do not apply to you, ask for support to your provider reporting the emails from your blog are not delivered</li>
186
+ </ol>
187
+ <?php } ?>
188
+ <p><a href="https://www.thenewsletterplugin.com/documentation/email-sending-issues" target="_blank">Read more to solve your issues, if any</a></p>
189
+
190
+
191
+ </form>
192
+
193
+ <h3>
194
+ How are messages delivered by Newsletter to your subscribers?
195
+ </h3>
196
+
197
+ <div class="tnp-flow">
198
+ <div class="tnp-mail"><i class="fas fa-envelope"></i><br><br>Messages<br>
199
+ (max: <?php echo esc_html($speed) ?> emails per hour)
200
+ </div>
201
+ <div class="tnp-arrow">&rightarrow;</div>
202
+ <div class="tnp-addon"><i class="<?php echo $icon ?>"></i><br><br><?php echo $mailer_name ?></div>
203
+ <div class="tnp-arrow">&rightarrow;</div>
204
+ <div class="tnp-service"><i class="fas fa-cog"></i><br><br>
205
+ <?php echo $service_name ?>
206
+ </div>
207
+ <div class="tnp-arrow">&rightarrow;</div>
208
+ <div class="tnp-user"><i class="fas fa-user"></i></div>
209
+ </div>
210
+
211
+
212
+ <?php if (!empty($functions)) { ?>
213
+ <br><br>
214
+ <h3>Functions that are changing the default WordPress delivery system</h3>
215
+ <p><?php echo $functions ?></p>
216
+ <?php } ?>
217
+
218
+
219
+ </div>
220
+ <?php include NEWSLETTER_DIR . '/tnp-footer.php'; ?>
221
+ </div>
main/info.php CHANGED
@@ -157,13 +157,31 @@ if (!$controls->is_action()) {
157
  <tr>
158
  <th>Telegram URL</th>
159
  <td>
160
- <?php $controls->text('telegram_url', 40); ?>
161
  </td>
162
  </tr>
163
  <tr>
164
  <th>VK URL</th>
165
  <td>
166
- <?php $controls->text('vk_url', 40); ?>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
167
  </td>
168
  </tr>
169
  </table>
157
  <tr>
158
  <th>Telegram URL</th>
159
  <td>
160
+ <?php $controls->text('telegram_url', 40); ?>
161
  </td>
162
  </tr>
163
  <tr>
164
  <th>VK URL</th>
165
  <td>
166
+ <?php $controls->text('vk_url', 40); ?>
167
+ </td>
168
+ </tr>
169
+ <tr>
170
+ <th>Twitch</th>
171
+ <td>
172
+ <?php $controls->text('twitch_url', 40); ?>
173
+ </td>
174
+ </tr>
175
+ <tr>
176
+ <th>Discord</th>
177
+ <td>
178
+ <?php $controls->text('discord_url', 40); ?>
179
+ </td>
180
+ </tr>
181
+ <tr>
182
+ <th>TikTok</th>
183
+ <td>
184
+ <?php $controls->text('tiktok_url', 40); ?>
185
  </td>
186
  </tr>
187
  </table>
main/status.php CHANGED
@@ -63,7 +63,7 @@ if ($controls->is_action('conversion')) {
63
  $controls->errors .= 'It was not possible to run the conversion for the table ' . NEWSLETTER_EMAILS_TABLE . ' - ';
64
  $controls->errors .= $wpdb->last_error . '<br>';
65
  }
66
- $controls->messages = 'Done.';
67
  } else {
68
  $controls->errors = 'Table conversion function not available';
69
  }
@@ -124,14 +124,14 @@ if ($controls->is_action('test')) {
124
  }
125
  }
126
 
127
- if ($controls->is_action( 'stats_email_column_upgrade') ) {
128
- $this->query( "alter table " . NEWSLETTER_STATS_TABLE . " drop index email_id" );
129
- $this->query( "alter table " . NEWSLETTER_STATS_TABLE . " drop index user_id" );
130
- $this->query( "alter table `" . NEWSLETTER_STATS_TABLE . "` modify column `email_id` int(11) not null default 0" );
131
- $this->query( "create index email_id on " . NEWSLETTER_STATS_TABLE . " (email_id)" );
132
- $this->query( "create index user_id on " . NEWSLETTER_STATS_TABLE . " (user_id)" );
133
- $controls->add_message_done();
134
- update_option('newsletter_stats_email_column_upgraded', true);
135
  }
136
 
137
  $options = $this->get_options('status');
@@ -156,6 +156,14 @@ function tnp_status_print_flag($condition) {
156
  break;
157
  }
158
  }
 
 
 
 
 
 
 
 
159
  ?>
160
  <style>
161
  table.widefat tbody tr>td:first-child {
@@ -178,7 +186,8 @@ function tnp_status_print_flag($condition) {
178
  <form method="post" action="">
179
  <?php $controls->init(); ?>
180
 
181
- <h3>Mailing test</h3>
 
182
  <table class="widefat" id="tnp-status-table">
183
 
184
  <thead>
@@ -187,42 +196,153 @@ function tnp_status_print_flag($condition) {
187
  <th><?php _e('Status', 'newsletter') ?></th>
188
  <th>Action</th>
189
  </tr>
 
190
  </thead>
191
 
192
  <tbody>
 
193
  <tr>
194
- <td>Mailing</td>
195
  <td>
196
- <?php if (empty($options['mail'])) { ?>
197
- <span class="tnp-ko">KO</span>
 
 
 
 
 
198
  <?php } else { ?>
199
- <span class="tnp-ok">OK</span>
200
  <?php } ?>
 
201
 
 
 
 
 
 
202
  </td>
203
  <td>
204
- <?php if (empty($options['mail'])) { ?>
205
- <?php if (empty($options['mail_error'])) { ?>
206
- A test has never run.
207
- <?php } else { ?>
208
- Last test failed with error "<?php echo esc_html($options['mail_error']) ?>".
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
209
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
210
  <?php } ?>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
211
  <?php } else { ?>
212
- Last test was successful. If you didn't receive the test email:
213
- <ol>
214
- <li>If you set the Newsletter SMTP, do a test from that panel</li>
215
- <li>If you're using a integration extension do a test from its configuration panel</li>
216
- <li>If previous points do not apply to you, ask for support to your provider reporting the emails from your blog are not delivered</li>
217
- </ol>
218
  <?php } ?>
219
- <br>
220
- <a href="https://www.thenewsletterplugin.com/documentation/email-sending-issues" target="_blank">Read more to solve your issues, if any</a>.
221
- <br>
222
- Email: <?php $controls->text_email('test_email') ?> <?php $controls->button('test', __('Send a test message')) ?>
223
  </td>
224
-
225
  </tr>
 
226
  </tbody>
227
  </table>
228
 
@@ -333,43 +453,7 @@ function tnp_status_print_flag($condition) {
333
  </td>
334
 
335
  </tr>
336
- <tr>
337
- <td>Delivering</td>
338
- <td>
339
- &nbsp;
340
- </td>
341
- <td>
342
- <?php if (count($emails)) { ?>
343
- Delivering <?php echo count($emails) ?> newsletters to about <?php echo $queued ?> recipients.
344
- At speed of <?php echo $speed ?> emails per hour it will take <?php printf('%.1f', $queued / $speed) ?> hours to finish.
345
 
346
- <?php } else { ?>
347
- Nothing delivering right now
348
- <?php } ?>
349
- </td>
350
-
351
- </tr>
352
- <tr>
353
- <td>Mailer</td>
354
- <td>
355
- &nbsp;
356
- </td>
357
- <td>
358
- <?php
359
- $mailer = Newsletter::instance()->get_mailer();
360
- $name = 'Unknown';
361
- if (is_object($mailer)) {
362
- if (method_exists($mailer, 'get_description')) {
363
- $name = $mailer->get_description();
364
- } else {
365
- $name = get_class($mailer);
366
- }
367
- }
368
- ?>
369
-
370
- <?php echo esc_html($name) ?>
371
- </td>
372
- </tr>
373
 
374
 
375
 
@@ -438,37 +522,7 @@ function tnp_status_print_flag($condition) {
438
 
439
 
440
 
441
- <tr>
442
- <?php
443
- $time = wp_next_scheduled('newsletter');
444
- $res = true;
445
- $condition = 1;
446
- if ($time === false) {
447
- $res = false;
448
- $condition = 0;
449
- }
450
- $delta = $time - time();
451
- if ($delta <= -600) {
452
- $res = false;
453
- $condition = 0;
454
- }
455
- ?>
456
- <td>Newsletter delivery engine job</td>
457
- <td>
458
- <?php tnp_status_print_flag($condition) ?>
459
- </td>
460
- <td>
461
- <?php if ($time === false) { ?>
462
- No next execution is planned.
463
- <?php $controls->button('reschedule', 'Reset') ?>
464
- <?php } else if ($delta <= -600) { ?>
465
- The scheduler is very late: <?php echo $delta ?> seconds (<a href="https://www.thenewsletterplugin.com/plugins/newsletter/newsletter-delivery-engine" target="_blank">read more</a>)
466
- <?php $controls->button('trigger', 'Trigger') ?>
467
- <?php } else { ?>
468
- Next execution is planned in <?php echo $delta ?> seconds (negative values are ok).
469
- <?php } ?>
470
- </td>
471
- </tr>
472
 
473
  <?php
474
  $schedules = wp_get_schedules();
@@ -584,81 +638,9 @@ function tnp_status_print_flag($condition) {
584
  </tr>
585
 
586
 
587
- <?php
588
- // Send calls stats
589
- $send_calls = get_option('newsletter_diagnostic_send_calls', array());
590
- if (count($send_calls)) {
591
- $send_max = 0;
592
- $send_min = PHP_INT_MAX;
593
- $send_total_time = 0;
594
- $send_total_emails = 0;
595
- $send_completed = 0;
596
- for ($i = 0; $i < count($send_calls); $i++) {
597
- if (empty($send_calls[$i][2]))
598
- continue;
599
 
600
- $delta = $send_calls[$i][1] - $send_calls[$i][0];
601
- $send_total_time += $delta;
602
- $send_total_emails += $send_calls[$i][2];
603
- $send_mean = $delta / $send_calls[$i][2];
604
- if ($send_min > $send_mean) {
605
- $send_min = $send_mean;
606
- }
607
- if ($send_max < $send_mean) {
608
- $send_max = $send_mean;
609
- }
610
- if (isset($send_calls[$i][3]) && $send_calls[$i][3]) {
611
- $send_completed++;
612
- }
613
- }
614
- $send_mean = $send_total_time / $send_total_emails;
615
- ?>
616
- <tr>
617
- <td>
618
- Send details
619
- </td>
620
- <td>
621
- <?php if ($send_mean > 1) { ?>
622
- <span class="tnp-ko">KO</span>
623
- <?php } else { ?>
624
- <span class="tnp-ok">OK</span>
625
- <?php } ?>
626
- </td>
627
- <td>
628
- <?php if ($send_mean > 1) { ?>
629
- <strong>Sending an email is taking more than 1 second, rather slow.</strong>
630
- <a href="https://www.thenewsletterplugin.com/documentation/status-panel#status-performance" target="_blank">Read more</a>.
631
- <?php } ?>
632
- Average time to send an email: <?php echo sprintf("%.2f", $send_mean) ?> seconds<br>
633
- <?php if ($send_mean > 0) { ?>
634
- Max speed: <?php echo sprintf("%.2f", 1.0 / $send_mean * 3600) ?> emails per hour<br>
635
- <?php } ?>
636
-
637
- Max mean time measured: <?php echo sprintf("%.2f", $send_max) ?> seconds<br>
638
- Min mean time measured: <?php echo sprintf("%.2f", $send_min) ?> seconds<br>
639
- Total email in the sample: <?php echo $send_total_emails ?><br>
640
- Runs in the sample: <?php echo count($send_calls); ?><br>
641
- Runs prematurely interrupted: <?php echo sprintf("%.2f", (count($send_calls) - $send_completed) * 100.0 / count($send_calls)) ?>%<br>
642
- <br>
643
- <?php $controls->button_reset('reset_send_stats')?>
644
- </td>
645
- </tr>
646
- <?php } else { ?>
647
- <tr>
648
- <td>
649
- Send details
650
- </td>
651
- <td>
652
- <span class="tnp-maybe">MAYBE</span>
653
- </td>
654
- <td>
655
- No data avaiable. Send a newsletter to collect some sending statistics.
656
- </td>
657
- </tr>
658
- <?php } ?>
659
 
660
 
661
-
662
 
663
 
664
 
@@ -770,7 +752,7 @@ function tnp_status_print_flag($condition) {
770
  </tbody>
771
  </table>
772
 
773
-
774
  <h3>WordPress Scheduler/Cron</h3>
775
 
776
  <table class="widefat" id="tnp-status-table">
@@ -782,7 +764,7 @@ function tnp_status_print_flag($condition) {
782
  </tr>
783
  </thead>
784
  <tbody>
785
- <tr>
786
  <?php
787
  $condition = (defined('NEWSLETTER_CRON_WARNINGS') && !NEWSLETTER_CRON_WARNINGS) ? 2 : 1;
788
  ?>
@@ -1147,6 +1129,18 @@ function tnp_status_print_flag($condition) {
1147
  <?php } ?>
1148
  </td>
1149
  </tr>
 
 
 
 
 
 
 
 
 
 
 
 
1150
 
1151
 
1152
  <?php
@@ -1210,26 +1204,26 @@ function tnp_status_print_flag($condition) {
1210
  $res = $wpdb->query("drop table if exists {$wpdb->prefix}newsletter_test");
1211
  ?>
1212
 
1213
- <?php if ( ! get_option( 'newsletter_stats_email_column_upgraded', false ) ) { ?>
1214
- <?php
1215
- $data_type = $wpdb->get_var(
1216
- $wpdb->prepare( 'SELECT DATA_TYPE FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_SCHEMA = %s AND TABLE_NAME = %s AND COLUMN_NAME = %s',
1217
- DB_NAME, NEWSLETTER_STATS_TABLE, 'email_id' ) );
1218
- $to_upgrade = strtoupper( $data_type ) == 'INT' ? false : true;
1219
- ?>
1220
- <?php if ( $to_upgrade ) { ?>
1221
  <tr>
1222
  <td>Database stats table upgrade</td>
1223
- <td><?php tnp_status_print_flag( 0 ) ?></td>
1224
- <td><?php $controls->button( 'stats_email_column_upgrade', 'Stats table upgrade' ) ?></td>
1225
  </tr>
1226
- <?php } ?>
1227
  <?php } ?>
1228
 
1229
  </tbody>
1230
  </table>
1231
-
1232
- <h3>3rd party plugins</h3>
1233
  <table class="widefat" id="tnp-status-table">
1234
  <thead>
1235
  <tr>
@@ -1240,19 +1234,19 @@ function tnp_status_print_flag($condition) {
1240
  </thead>
1241
  <tbody>
1242
  <?php if (is_plugin_active('plugin-load-filter/plugin-load-filter.php')) { ?>
1243
- <tr>
1244
- <td><a href="https://wordpress.org/plugins/plugin-load-filter/" target="_blank">Plugin load filter</a></td>
1245
- <td>
1246
- <span class="tnp-maybe">MAY BE</span>
1247
- </td>
1248
- <td>
1249
- Be sure Newsletter is set as active in EVERY context.
1250
- </td>
1251
- </tr>
1252
  <?php } ?>
1253
  </tbody>
1254
  </table>
1255
-
1256
  <h3>General parameters</h3>
1257
  <table class="widefat" id="tnp-parameters-table">
1258
  <thead>
63
  $controls->errors .= 'It was not possible to run the conversion for the table ' . NEWSLETTER_EMAILS_TABLE . ' - ';
64
  $controls->errors .= $wpdb->last_error . '<br>';
65
  }
66
+ $controls->messages .= 'Done.';
67
  } else {
68
  $controls->errors = 'Table conversion function not available';
69
  }
124
  }
125
  }
126
 
127
+ if ($controls->is_action('stats_email_column_upgrade')) {
128
+ $this->query("alter table " . NEWSLETTER_STATS_TABLE . " drop index email_id");
129
+ $this->query("alter table " . NEWSLETTER_STATS_TABLE . " drop index user_id");
130
+ $this->query("alter table `" . NEWSLETTER_STATS_TABLE . "` modify column `email_id` int(11) not null default 0");
131
+ $this->query("create index email_id on " . NEWSLETTER_STATS_TABLE . " (email_id)");
132
+ $this->query("create index user_id on " . NEWSLETTER_STATS_TABLE . " (user_id)");
133
+ $controls->add_message_done();
134
+ update_option('newsletter_stats_email_column_upgraded', true);
135
  }
136
 
137
  $options = $this->get_options('status');
156
  break;
157
  }
158
  }
159
+
160
+ class TNP_WPDB extends wpdb {
161
+ public function get_table_charset($table) {
162
+ return parent::get_table_charset($table);
163
+ }
164
+ }
165
+
166
+ $tnp_wpdb = new TNP_WPDB(DB_USER, DB_PASSWORD, DB_NAME, DB_HOST);
167
  ?>
168
  <style>
169
  table.widefat tbody tr>td:first-child {
186
  <form method="post" action="">
187
  <?php $controls->init(); ?>
188
 
189
+
190
+ <h3>Delivery</h3>
191
  <table class="widefat" id="tnp-status-table">
192
 
193
  <thead>
196
  <th><?php _e('Status', 'newsletter') ?></th>
197
  <th>Action</th>
198
  </tr>
199
+
200
  </thead>
201
 
202
  <tbody>
203
+
204
  <tr>
205
+ <td>Delivering</td>
206
  <td>
207
+ &nbsp;
208
+ </td>
209
+ <td>
210
+ <?php if (count($emails)) { ?>
211
+ Delivering <?php echo count($emails) ?> newsletters to about <?php echo $queued ?> recipients.
212
+ At speed of <?php echo $speed ?> emails per hour it will take <?php printf('%.1f', $queued / $speed) ?> hours to finish.
213
+
214
  <?php } else { ?>
215
+ Nothing delivering right now
216
  <?php } ?>
217
+ </td>
218
 
219
+ </tr>
220
+ <tr>
221
+ <td>Mailer</td>
222
+ <td>
223
+ &nbsp;
224
  </td>
225
  <td>
226
+ <?php
227
+ $mailer = Newsletter::instance()->get_mailer();
228
+ $name = 'Unknown';
229
+ if (is_object($mailer)) {
230
+ if (method_exists($mailer, 'get_description')) {
231
+ $name = $mailer->get_description();
232
+ } else {
233
+ $name = get_class($mailer);
234
+ }
235
+ }
236
+ ?>
237
+
238
+ <?php echo esc_html($name) ?>
239
+ </td>
240
+ </tr>
241
+ <?php
242
+ // Send calls stats
243
+ $send_calls = get_option('newsletter_diagnostic_send_calls', array());
244
+ if (count($send_calls)) {
245
+ $send_max = 0;
246
+ $send_min = PHP_INT_MAX;
247
+ $send_total_time = 0;
248
+ $send_total_emails = 0;
249
+ $send_completed = 0;
250
+ for ($i = 0; $i < count($send_calls); $i++) {
251
+ if (empty($send_calls[$i][2]))
252
+ continue;
253
 
254
+ $delta = $send_calls[$i][1] - $send_calls[$i][0];
255
+ $send_total_time += $delta;
256
+ $send_total_emails += $send_calls[$i][2];
257
+ $send_mean = $delta / $send_calls[$i][2];
258
+ if ($send_min > $send_mean) {
259
+ $send_min = $send_mean;
260
+ }
261
+ if ($send_max < $send_mean) {
262
+ $send_max = $send_mean;
263
+ }
264
+ if (isset($send_calls[$i][3]) && $send_calls[$i][3]) {
265
+ $send_completed++;
266
+ }
267
+ }
268
+ $send_mean = $send_total_time / $send_total_emails;
269
+ ?>
270
+ <tr>
271
+ <td>
272
+ Send details
273
+ </td>
274
+ <td>
275
+ <?php if ($send_mean > 1) { ?>
276
+ <span class="tnp-ko">KO</span>
277
+ <?php } else { ?>
278
+ <span class="tnp-ok">OK</span>
279
+ <?php } ?>
280
+ </td>
281
+ <td>
282
+ <?php if ($send_mean > 1) { ?>
283
+ <strong>Sending an email is taking more than 1 second, rather slow.</strong>
284
+ <a href="https://www.thenewsletterplugin.com/documentation/status-panel#status-performance" target="_blank">Read more</a>.
285
  <?php } ?>
286
+ Average time to send an email: <?php echo sprintf("%.2f", $send_mean) ?> seconds<br>
287
+ <?php if ($send_mean > 0) { ?>
288
+ Max speed: <?php echo sprintf("%.2f", 1.0 / $send_mean * 3600) ?> emails per hour<br>
289
+ <?php } ?>
290
+
291
+ Max mean time measured: <?php echo sprintf("%.2f", $send_max) ?> seconds<br>
292
+ Min mean time measured: <?php echo sprintf("%.2f", $send_min) ?> seconds<br>
293
+ Total email in the sample: <?php echo $send_total_emails ?><br>
294
+ Runs in the sample: <?php echo count($send_calls); ?><br>
295
+ Runs prematurely interrupted: <?php echo sprintf("%.2f", (count($send_calls) - $send_completed) * 100.0 / count($send_calls)) ?>%<br>
296
+ <br>
297
+ <?php $controls->button_reset('reset_send_stats') ?>
298
+ </td>
299
+ </tr>
300
+ <?php } else { ?>
301
+ <tr>
302
+ <td>
303
+ Send details
304
+ </td>
305
+ <td>
306
+ <span class="tnp-maybe">MAYBE</span>
307
+ </td>
308
+ <td>
309
+ No data avaiable. Send a newsletter to collect some sending statistics.
310
+ </td>
311
+ </tr>
312
+ <?php } ?>
313
+
314
+ <tr>
315
+ <?php
316
+ $time = wp_next_scheduled('newsletter');
317
+ $res = true;
318
+ $condition = 1;
319
+ if ($time === false) {
320
+ $res = false;
321
+ $condition = 0;
322
+ }
323
+ $delta = $time - time();
324
+ if ($delta <= -600) {
325
+ $res = false;
326
+ $condition = 0;
327
+ }
328
+ ?>
329
+ <td>Newsletter delivery engine job</td>
330
+ <td>
331
+ <?php tnp_status_print_flag($condition) ?>
332
+ </td>
333
+ <td>
334
+ <?php if ($time === false) { ?>
335
+ No next execution is planned.
336
+ <?php $controls->button('reschedule', 'Reset') ?>
337
+ <?php } else if ($delta <= -600) { ?>
338
+ The scheduler is very late: <?php echo $delta ?> seconds (<a href="https://www.thenewsletterplugin.com/plugins/newsletter/newsletter-delivery-engine" target="_blank">read more</a>)
339
+ <?php $controls->button('trigger', 'Trigger') ?>
340
  <?php } else { ?>
341
+ Next execution is planned in <?php echo $delta ?> seconds (negative values are ok).
 
 
 
 
 
342
  <?php } ?>
 
 
 
 
343
  </td>
 
344
  </tr>
345
+
346
  </tbody>
347
  </table>
348
 
453
  </td>
454
 
455
  </tr>
 
 
 
 
 
 
 
 
 
456
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
457
 
458
 
459
 
522
 
523
 
524
 
525
+
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
526
 
527
  <?php
528
  $schedules = wp_get_schedules();
638
  </tr>
639
 
640
 
 
 
 
 
 
 
 
 
 
 
 
 
641
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
642
 
643
 
 
644
 
645
 
646
 
752
  </tbody>
753
  </table>
754
 
755
+
756
  <h3>WordPress Scheduler/Cron</h3>
757
 
758
  <table class="widefat" id="tnp-status-table">
764
  </tr>
765
  </thead>
766
  <tbody>
767
+ <tr>
768
  <?php
769
  $condition = (defined('NEWSLETTER_CRON_WARNINGS') && !NEWSLETTER_CRON_WARNINGS) ? 2 : 1;
770
  ?>
1129
  <?php } ?>
1130
  </td>
1131
  </tr>
1132
+
1133
+ <tr>
1134
+ <td>get_table_charset()</td>
1135
+ <td>
1136
+
1137
+ </td>
1138
+ <td>
1139
+ <?php echo esc_html(NEWSLETTER_USERS_TABLE), ': ', esc_html($tnp_wpdb->get_table_charset(NEWSLETTER_USERS_TABLE))?>
1140
+ </td>
1141
+ </tr>
1142
+
1143
+
1144
 
1145
 
1146
  <?php
1204
  $res = $wpdb->query("drop table if exists {$wpdb->prefix}newsletter_test");
1205
  ?>
1206
 
1207
+ <?php if (!get_option('newsletter_stats_email_column_upgraded', false)) { ?>
1208
+ <?php
1209
+ $data_type = $wpdb->get_var(
1210
+ $wpdb->prepare('SELECT DATA_TYPE FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_SCHEMA = %s AND TABLE_NAME = %s AND COLUMN_NAME = %s',
1211
+ DB_NAME, NEWSLETTER_STATS_TABLE, 'email_id'));
1212
+ $to_upgrade = strtoupper($data_type) == 'INT' ? false : true;
1213
+ ?>
1214
+ <?php if ($to_upgrade) { ?>
1215
  <tr>
1216
  <td>Database stats table upgrade</td>
1217
+ <td><?php tnp_status_print_flag(0) ?></td>
1218
+ <td><?php $controls->button('stats_email_column_upgrade', 'Stats table upgrade') ?></td>
1219
  </tr>
1220
+ <?php } ?>
1221
  <?php } ?>
1222
 
1223
  </tbody>
1224
  </table>
1225
+
1226
+ <h3>3rd party plugins</h3>
1227
  <table class="widefat" id="tnp-status-table">
1228
  <thead>
1229
  <tr>
1234
  </thead>
1235
  <tbody>
1236
  <?php if (is_plugin_active('plugin-load-filter/plugin-load-filter.php')) { ?>
1237
+ <tr>
1238
+ <td><a href="https://wordpress.org/plugins/plugin-load-filter/" target="_blank">Plugin load filter</a></td>
1239
+ <td>
1240
+ <span class="tnp-maybe">MAY BE</span>
1241
+ </td>
1242
+ <td>
1243
+ Be sure Newsletter is set as active in EVERY context.
1244
+ </td>
1245
+ </tr>
1246
  <?php } ?>
1247
  </tbody>
1248
  </table>
1249
+
1250
  <h3>General parameters</h3>
1251
  <table class="widefat" id="tnp-parameters-table">
1252
  <thead>
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.1.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.1.8');
39
 
40
  global $newsletter, $wpdb;
41
 
@@ -275,7 +275,8 @@ class Newsletter extends NewsletterModule {
275
 
276
  function update_cron_stats() {
277
  if (defined('DOING_CRON') && DOING_CRON) {
278
- $calls = get_option('newsletter_diagnostic_cron_calls', array());
 
279
  $calls[] = time();
280
  if (count($calls) > self::MAX_CRON_SAMPLES) {
281
  array_shift($calls);
@@ -473,6 +474,7 @@ class Newsletter extends NewsletterModule {
473
  $this->add_menu_page('main', __('Settings and More', 'newsletter'));
474
  $this->add_admin_page('smtp', 'SMTP');
475
  $this->add_admin_page('status', __('Status', 'newsletter'));
 
476
  $this->add_admin_page('logs', __('Logs', 'newsletter'));
477
  $this->add_admin_page('diagnostic', __('Diagnostic', 'newsletter'));
478
  $this->add_admin_page('test', __('Test', 'newsletter'));
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.1.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.1.9');
39
 
40
  global $newsletter, $wpdb;
41
 
275
 
276
  function update_cron_stats() {
277
  if (defined('DOING_CRON') && DOING_CRON) {
278
+ $calls = get_option('newsletter_diagnostic_cron_calls', []);
279
+ if (!is_array($calls)) $calls = []; // Protection agains scrambled options or bad written caching DB caching plugin
280
  $calls[] = time();
281
  if (count($calls) > self::MAX_CRON_SAMPLES) {
282
  array_shift($calls);
474
  $this->add_menu_page('main', __('Settings and More', 'newsletter'));
475
  $this->add_admin_page('smtp', 'SMTP');
476
  $this->add_admin_page('status', __('Status', 'newsletter'));
477
+ $this->add_admin_page('delivery', __('Delivery Diagnostic', 'newsletter'));
478
  $this->add_admin_page('logs', __('Logs', 'newsletter'));
479
  $this->add_admin_page('diagnostic', __('Diagnostic', 'newsletter'));
480
  $this->add_admin_page('test', __('Test', 'newsletter'));
readme.txt CHANGED
@@ -1,8 +1,8 @@
1
  === Newsletter ===
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.2
5
- Stable tag: 7.1.8
6
  Requires PHP: 5.6
7
  Contributors: satollo,webagile,michael-travan
8
  License: GPLv2 or later
@@ -106,8 +106,7 @@ Premium Users with an active license have access to one-to-one support via our [
106
 
107
  == Frequently Asked Questions ==
108
 
109
- See the [Newsletter FAQ](https://www.thenewsletterplugin.com/plugins/newsletter/newsletter-faq) or the
110
- [Newsletter Forum](https://www.thenewsletterplugin.com/forums) to ask for help.
111
 
112
  For documentation start from [Newsletter documentation](https://www.thenewsletterplugin.com/documentation).
113
 
@@ -121,6 +120,15 @@ Thank you, The Newsletter Team
121
 
122
  == Changelog ==
123
 
 
 
 
 
 
 
 
 
 
124
  = 7.1.8 =
125
 
126
  * Fixed alignment of single big image on Outlook Android
1
  === Newsletter ===
2
+ Tags: newsletter, email marketing, welcome email, signup forms, contact, lead generation, marketing automation
3
  Requires at least: 3.4.0
4
  Tested up to: 5.7.2
5
+ Stable tag: 7.1.9
6
  Requires PHP: 5.6
7
  Contributors: satollo,webagile,michael-travan
8
  License: GPLv2 or later
106
 
107
  == Frequently Asked Questions ==
108
 
109
+ See the [Newsletter Forum](https://www.thenewsletterplugin.com/forums) to ask for help.
 
110
 
111
  For documentation start from [Newsletter documentation](https://www.thenewsletterplugin.com/documentation).
112
 
120
 
121
  == Changelog ==
122
 
123
+ = 7.1.9 =
124
+
125
+ * [GENERAL] Removed the encodign defatlt to Base 64 when not specified since it seems incompatible with some SMTP plugins
126
+ * [GENERAL] Review some controls layout and behavior
127
+ * [DEBUG] Improved logging on database errors
128
+ * [GENERAL] Added TikTok, Discord and Twitch socials
129
+ * [GENERAL] Fixed odd error reported related to the cron call statistics collection
130
+ * [DEBUG] Added a delivery diagnostic panel
131
+
132
  = 7.1.8 =
133
 
134
  * Fixed alignment of single big image on Outlook Android
subscription/subscription.php CHANGED
@@ -1416,7 +1416,7 @@ class NewsletterSubscription extends NewsletterModule {
1416
  // All lists
1417
  if ($name == 'lists' || $name == 'preferences') {
1418
  $lists = $this->get_lists_for_subscription($language);
1419
- if (isset($attrs['layout']) && $attrs['layout'] === 'dropdown') {
1420
 
1421
  $buffer .= '<div class="tnp-field tnp-lists">';
1422
  // There is not a default "label" for the block of lists, so it can only be specified in the shortcode attrs as "label"
1416
  // All lists
1417
  if ($name == 'lists' || $name == 'preferences') {
1418
  $lists = $this->get_lists_for_subscription($language);
1419
+ if (!empty($lists) && isset($attrs['layout']) && $attrs['layout'] === 'dropdown') {
1420
 
1421
  $buffer .= '<div class="tnp-field tnp-lists">';
1422
  // There is not a default "label" for the block of lists, so it can only be specified in the shortcode attrs as "label"
tnp-header.php CHANGED
@@ -187,6 +187,10 @@ $warning |= empty($status_options['mail']);
187
  <a href="<?php echo admin_url('site-health.php')?> "><i class="fas fa-file"></i> <?php _e('Site health') ?>
188
  <small><?php _e('WP native site health checks', 'newsletter') ?></small></a>
189
  </li>
 
 
 
 
190
  <li>
191
  <a href="?page=newsletter_main_status"><i class="fas fa-file"></i> <?php _e('Status', 'newsletter') ?>
192
  <small><?php _e('Checks and parameters', 'newsletter') ?></small></a>
187
  <a href="<?php echo admin_url('site-health.php')?> "><i class="fas fa-file"></i> <?php _e('Site health') ?>
188
  <small><?php _e('WP native site health checks', 'newsletter') ?></small></a>
189
  </li>
190
+ <li>
191
+ <a href="?page=newsletter_main_delivery"><i class="fas fa-file"></i> <?php _e('Delivery Diagnostic', 'newsletter') ?>
192
+ <small><?php _e('Delivery analysis and test', 'newsletter') ?></small></a>
193
+ </li>
194
  <li>
195
  <a href="?page=newsletter_main_status"><i class="fas fa-file"></i> <?php _e('Status', 'newsletter') ?>
196
  <small><?php _e('Checks and parameters', 'newsletter') ?></small></a>