Newsletter - Version 6.4.1

Version Description

  • Added statistics shortcut for sent newsletters
  • Fixed unsubscription from email tracking
  • Password field in smtp configuration
  • Small fixes to header block
  • Fixed the subject on online newsletter view
  • Fixed the subject ideas popup X button
Download this release

Release Info

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

Code changes from version 6.3.9 to 6.4.1

emails/blocks/header/block.php CHANGED
@@ -11,10 +11,10 @@ $default_options = array(
11
  'font_color' => '#444444',
12
  'font_weight' => 'normal',
13
  'block_background' => '#ffffff',
14
- 'block_padding_top'=>15,
15
- 'block_padding_bottom'=>15,
16
- 'block_padding_left'=>15,
17
- 'block_padding_right'=>15
18
  );
19
  $options = array_merge($default_options, $options);
20
 
@@ -28,46 +28,60 @@ if (empty($info['header_logo']['id'])) {
28
  }
29
 
30
  $empty = empty($info['header_logo']['id']) && empty($info['header_sub']) && empty($info['header_title']);
31
-
32
  ?>
33
 
34
  <?php if ($empty) { ?>
35
- <p>Please, set your company info.</p>
36
  <?php } else { ?>
37
- <style>
38
- .header-text {
39
- padding: 10px;
40
- text-align: right;
41
- font-size: <?php echo $options['font_size'] ?>px;
42
- font-family: <?php echo $options['font_family'] ?>;
43
- font-weight: <?php echo $options['font_weight'] ?>;
44
- color: <?php echo $options['font_color'] ?>;
45
- }
46
- .header-logo {
47
- font-family: <?php echo $options['font_family'] ?>;
48
- font-size: <?php echo $options['font_size']*1.1 ?>px;
49
- line-height: normal;
50
- font-weight: <?php echo $options['font_weight'] ?>;
51
- color: <?php echo $options['font_color'] ?>;
52
- }
53
- </style>
 
 
 
 
 
 
 
 
 
 
 
 
54
 
55
  <table border="0" cellpadding="0" cellspacing="0" width="100%">
56
  <tr>
57
- <?php if ( $image ) { ?>
58
- <td align="left" width="50%" inline-class="header-logo">
59
- <a href="#" target="_blank">
60
- <img alt="<?php echo esc_attr( $info['header_title'] ) ?>" src="<?php echo $image ?>"
61
- style="display: block; max-width: 100%" border="0">
62
- </a>
63
- <?php } else { ?>
64
- <td align="left" width="50%" inline-class="heading-text"
65
- style="padding: 5px; font-size: 24px; font-family: Helvetica, Arial, sans-serif; font-weight: bold; color: #444444;">
66
- <?php echo esc_attr( $info['header_title'] ) ?>
67
- <?php } ?>
68
- </td>
 
 
 
69
  <td width="50%" align="right" class="mobile-hide" inline-class="header-text">
70
- <?php echo $info['header_sub'] ?>
71
  </td>
72
  </tr>
73
  </table>
11
  'font_color' => '#444444',
12
  'font_weight' => 'normal',
13
  'block_background' => '#ffffff',
14
+ 'block_padding_top' => 15,
15
+ 'block_padding_bottom' => 15,
16
+ 'block_padding_left' => 15,
17
+ 'block_padding_right' => 15
18
  );
19
  $options = array_merge($default_options, $options);
20
 
28
  }
29
 
30
  $empty = empty($info['header_logo']['id']) && empty($info['header_sub']) && empty($info['header_title']);
 
31
  ?>
32
 
33
  <?php if ($empty) { ?>
34
+ <p>Please, set your company info.</p>
35
  <?php } else { ?>
36
+ <style>
37
+ .header-text {
38
+ padding: 10px;
39
+ font-size: <?php echo $options['font_size'] ?>px;
40
+ font-family: <?php echo $options['font_family'] ?>;
41
+ font-weight: <?php echo $options['font_weight'] ?>;
42
+ color: <?php echo $options['font_color'] ?>;
43
+ text-decoration: none;
44
+ line-height: normal;
45
+ }
46
+ .header-title {
47
+ font-size: <?php echo $options['font_size'] * 1.2 ?>px;
48
+ font-family: <?php echo $options['font_family'] ?>;
49
+ font-weight: <?php echo $options['font_weight'] ?>;
50
+ color: <?php echo $options['font_color'] ?>;
51
+ text-decoration: none;
52
+ line-height: normal;
53
+ }
54
+ .header-logo {
55
+ font-family: <?php echo $options['font_family'] ?>;
56
+ line-height: normal;
57
+ font-weight: <?php echo $options['font_weight'] ?>;
58
+ color: <?php echo $options['font_color'] ?>;
59
+ }
60
+ .header-logo-img {
61
+ display: block;
62
+ max-width: 100%
63
+ }
64
+ </style>
65
 
66
  <table border="0" cellpadding="0" cellspacing="0" width="100%">
67
  <tr>
68
+ <?php if ($image) { ?>
69
+ <td align="left" width="50%" inline-class="header-logo">
70
+ <a href="<?php echo home_url() ?>" target="_blank">
71
+ <img alt="<?php echo esc_attr($info['header_title']) ?>" src="<?php echo $image ?>" class="header-logo-img" border="0">
72
+ </a>
73
+ </td>
74
+ <?php } else { ?>
75
+ <td align="left" width="50%" inline-class="header-logo">
76
+ <a href="<?php echo home_url() ?>" target="_blank" class="header-title">
77
+ <?php echo esc_attr($info['header_title']) ?>
78
+ </a>
79
+ </td>
80
+ <?php } ?>
81
+
82
+
83
  <td width="50%" align="right" class="mobile-hide" inline-class="header-text">
84
+ <?php echo $info['header_sub'] ?>
85
  </td>
86
  </tr>
87
  </table>
emails/blocks/posts/block.php CHANGED
@@ -91,6 +91,8 @@ $button_color = $options['button_font_color'];
91
 
92
  $alternative = plugins_url('newsletter') . '/emails/blocks/posts/images/blank.png';
93
  $alternative_2 = plugins_url('newsletter') . '/emails/blocks/posts/images/blank-240x160.png';
 
 
94
  ?>
95
 
96
  <?php if ($options['layout'] == 'one') { ?>
91
 
92
  $alternative = plugins_url('newsletter') . '/emails/blocks/posts/images/blank.png';
93
  $alternative_2 = plugins_url('newsletter') . '/emails/blocks/posts/images/blank-240x160.png';
94
+
95
+ remove_all_filters('excerpt_more');
96
  ?>
97
 
98
  <?php if ($options['layout'] == 'one') { ?>
emails/blocks/posts/options.php CHANGED
@@ -24,7 +24,7 @@
24
 
25
  <?php $fields->checkbox('show_date', __('Show date', 'newsletter')) ?>
26
 
27
- <?php $fields->select_number('max', __('Max posts', 'newsletter'), 1, 20); ?>
28
 
29
  <?php $fields->language(); ?>
30
 
24
 
25
  <?php $fields->checkbox('show_date', __('Show date', 'newsletter')) ?>
26
 
27
+ <?php $fields->select_number('max', __('Max posts', 'newsletter'), 1, 40); ?>
28
 
29
  <?php $fields->language(); ?>
30
 
emails/subjects.php CHANGED
@@ -22,7 +22,7 @@
22
  });
23
 
24
  jQuery(".tnp-popup-close").click(function () {
25
- $(this).parent().parent().hide();
26
 
27
  });
28
  });
22
  });
23
 
24
  jQuery(".tnp-popup-close").click(function () {
25
+ jQuery(this).parent().parent().hide();
26
 
27
  });
28
  });
emails/tnp-composer/_scripts/newsletter-builder.js CHANGED
@@ -293,7 +293,7 @@ function tnpc_save(form) {
293
 
294
  let css = jQuery.trim(form.elements["options[css]"].value);
295
 
296
- let export_content = '<!DOCTYPE html>\n<html>\n<head>\n<title>{subject}</title>\n<meta charset="utf-8">\n<meta name="viewport" content="width=device-width, initial-scale=1">\n<meta http-equiv="X-UA-Compatible" content="IE=edge">\n';
297
  export_content += '<style type="text/css">' + css + '</style>';
298
  export_content += '</head>\n<body style="margin: 0; padding: 0;">\n';
299
  export_content += preload_export_html;
293
 
294
  let css = jQuery.trim(form.elements["options[css]"].value);
295
 
296
+ let export_content = '<!DOCTYPE html>\n<html>\n<head>\n<title>{email_subject}</title>\n<meta charset="utf-8">\n<meta name="viewport" content="width=device-width, initial-scale=1">\n<meta http-equiv="X-UA-Compatible" content="IE=edge">\n';
297
  export_content += '<style type="text/css">' + css + '</style>';
298
  export_content += '</head>\n<body style="margin: 0; padding: 0;">\n';
299
  export_content += preload_export_html;
images/donate.png DELETED
Binary file
includes/TNP.php CHANGED
@@ -16,286 +16,297 @@
16
  * @author roby
17
  */
18
  class TNP {
19
- /*
20
- * The full process of subscription
21
- */
22
-
23
- public static function subscribe($params) {
24
-
25
- $newsletter = Newsletter::instance();
26
- $subscription = NewsletterSubscription::instance();
27
-
28
- // default params
29
- $defaults = array('send_emails' => true);
30
- $params = array_merge ($defaults, $params);
31
-
32
- // Messages
33
- $options = get_option('newsletter', array());
34
-
35
- // Form field configuration
36
- $options_profile = get_option('newsletter_profile', array());
37
-
38
- $optin = (int) $options['noconfirmation']; // 0 - double, 1 - single
39
-
40
- $email = $newsletter->normalize_email(stripslashes($params['email']));
41
-
42
- // Should never reach this point without a valid email address
43
- if ($email == null) {
44
- return new WP_Error('-1', 'Email address not valid', array('status' => 400));
45
- }
46
-
47
- $user = $newsletter->get_user($email);
48
-
49
- if ($user != null) {
50
-
51
- $newsletter->logger->info('Subscription of an address with status ' . $user->status);
52
-
53
- // Bounced
54
- if ($user->status == 'B') {
55
- return new WP_Error('-1', 'Bounced address', array('status' => 400));
56
- }
57
-
58
- // If asked to put in confirmed status, do not check further
59
- if ($params['status'] != 'C' && $optin == 0) {
60
-
61
- // Already confirmed
62
- //if ($optin == 0 && $user->status == 'C') {
63
- if ($user->status == 'C') {
64
-
65
- set_transient($user->id . '-' . $user->token, $params, 3600 * 48);
66
- $subscription->set_updated($user);
67
-
68
- // A second subscription always require confirmation otherwise anywan can change other users' data
69
- $user->status = 'S';
70
- $subscription->send_activation_email($user);
71
-
72
- return $user;
73
- }
74
- }
75
- }
76
-
77
- if ($user != null) {
78
- $newsletter->logger->info("Email address subscribed but not confirmed");
79
- $user = array('id' => $user->id);
80
- } else {
81
- $newsletter->logger->info("New email address");
82
- }
83
-
84
- if ($optin) {
85
- $params['status'] = 'C';
86
- } else {
87
- $params['status'] = 'S';
88
- }
89
-
90
- // Lists
91
-
92
- if (!isset($params['lists']) || !is_array($params['lists'])) {
93
- $params['lists'] = array();
94
- }
95
-
96
- // Public lists: rebuild the array keeping only the valid lists
97
- $lists = $newsletter->get_lists_public();
98
-
99
- // Public list IDs
100
- $public_lists = array();
101
- foreach ($lists as $list) {
102
- $public_lists[] = $list->id;
103
- }
104
-
105
- // Keep only the public lists
106
- $params['lists'] = array_intersect($public_lists, $params['lists']);
107
-
108
- // Pre assigned lists
109
- $lists = $newsletter->get_lists();
110
- foreach ($lists as $list) {
111
- if ($list->forced) {
112
- $params['lists'][] = $list->id;
113
- }
114
- }
115
-
116
- apply_filters('newsletter_api_subscribe', $params);
117
-
118
- $user = TNP::add_subscriber($params);
119
-
120
- if (is_wp_error($user)) {
121
- return ($user);
122
- }
123
-
124
- // Notification to admin (only for new confirmed subscriptions)
125
- if ($user->status == 'C') {
126
- do_action('newsletter_user_confirmed', $user);
127
- $subscription->notify_admin($user, 'Newsletter subscription');
128
- setcookie('newsletter', $user->id . '-' . $user->token, time() + 60 * 60 * 24 * 365, '/');
129
- }
130
-
131
- // skip messages if send_emails = false
132
- if (!$params['send_emails']) {
133
- return $user;
134
- }
135
-
136
- $message_type = ($user->status == 'C') ? 'confirmed' : 'confirmation';
137
- $subscription->send_message($message_type, $user);
138
-
139
- return $user;
140
- }
141
-
142
- /*
143
- * The UNsubscription
144
- */
145
-
146
- public static function unsubscribe($params) {
147
-
148
- $newsletter = Newsletter::instance();
149
- $user = $newsletter->get_user($params['email']);
 
 
 
 
 
 
 
 
150
 
151
  // $newsletter->logger->debug($params);
152
 
153
- if (!$user) {
154
- return new WP_Error('-1', 'Email address not found', array('status' => 404));
155
- }
 
 
 
 
 
 
 
 
 
 
 
156
 
157
- if ($user->status == 'U') {
158
- return $user;
159
- }
160
 
161
- $user = $newsletter->set_user_status($user, 'U');
 
 
162
 
163
- if (empty(NewsletterSubscription::instance()->options['unsubscribed_disabled'])) {
164
- $newsletter->mail($user->email, $newsletter->replace(NewsletterSubscription::instance()->options['unsubscribed_subject'], $user), $newsletter->replace(NewsletterSubscription::instance()->options['unsubscribed_message'], $user));
165
- }
166
- NewsletterSubscription::instance()->notify_admin($user, 'Newsletter unsubscription');
167
 
168
- return $user;
169
- }
170
 
171
- /*
172
- * Adds a subscriber if not already in
173
- */
174
 
175
- public static function add_subscriber($params) {
 
 
176
 
177
- $newsletter = Newsletter::instance();
178
 
179
- $email = $newsletter->normalize_email(stripslashes($params['email']));
 
 
180
 
181
- if (!$email) {
182
- return new WP_Error('-1', 'Email address not valid', array('status' => 400));
183
- }
184
 
185
- $user = $newsletter->get_user($email);
 
 
186
 
187
- if ($user) {
188
- return new WP_Error('-1', 'Email address already exists', array('status' => 400));
189
- }
190
 
191
- $user = array('email' => $email);
 
 
192
 
193
- if (isset($params['name'])) {
194
- $user['name'] = $newsletter->normalize_name(stripslashes($params['name']));
195
- }
 
 
196
 
197
- if (isset($params['surname'])) {
198
- $user['surname'] = $newsletter->normalize_name(stripslashes($params['surname']));
199
- }
 
 
 
 
200
 
201
- if (!empty($params['gender'])) {
202
- $user['sex'] = $newsletter->normalize_sex($params['gender']);
203
- }
204
 
205
- if (isset($params['profile']) && is_array($params['profile'])) {
206
- foreach ($params['profile'] as $key => $value) {
207
- $user['profile_' . $key] = trim(stripslashes($value));
208
- }
209
- }
210
 
211
- // Lists (an arrayunder the key "lists")
212
- // Preferences (field names are nl[] and values the list number so special forms with radio button can work)
213
- if (isset($params['lists']) && is_array($params['lists'])) {
214
- foreach ($params['lists'] as $list_id) {
215
- $user['list_' . ((int)$list_id)] = 1;
216
- }
217
- }
218
 
 
219
 
220
- if (!empty($params['status'])) {
221
- $user['status'] = $params['status'];
222
- } else {
223
- $user['status'] = 'C';
224
- }
225
 
226
- $user['token'] = $newsletter->get_token();
227
- $user['updated'] = time();
228
-
229
- $user['ip'] = Newsletter::get_remote_ip();
230
 
231
- $user = $newsletter->save_user($user);
 
 
232
 
233
- return $user;
234
- }
235
 
236
- /*
237
- * Subscribers list
238
- */
239
 
240
- public static function subscribers($params) {
 
241
 
242
- global $wpdb;
243
- $newsletter = Newsletter::instance();
 
244
 
245
- $items_per_page = 20;
246
- $where = "";
247
 
248
- $query = "select name, email from " . NEWSLETTER_USERS_TABLE . ' ' . $where . " order by id desc";
249
- $query .= " limit 0," . $items_per_page;
250
- $list = $wpdb->get_results($query);
251
 
252
- return $list;
253
- }
254
 
255
- /*
256
- * Deletes a subscriber
257
- */
258
 
259
- public static function delete_subscriber($params) {
260
 
261
- global $wpdb;
262
- $newsletter = Newsletter::instance();
 
263
 
264
- $user = $newsletter->get_user($params['email']);
 
 
 
265
 
266
- if (!$user) {
267
- return new WP_Error('-1', 'Email address not found', array('status' => 404));
268
- }
269
 
270
- if ($wpdb->query($wpdb->prepare("delete from " . NEWSLETTER_USERS_TABLE . " where id=%d", (int) $user->id))) {
271
- return "OK";
272
- } else {
273
- $newsletter->logger->debug($wpdb->last_query);
274
- return new WP_Error('-1', $wpdb->last_error, array('status' => 400));
275
- }
276
- }
277
 
278
- /*
279
- * Newsletters list
280
- */
281
 
282
- public static function newsletters($params) {
 
283
 
284
- global $wpdb;
285
- $newsletter = Newsletter::instance();
286
 
287
- $list = $wpdb->get_results("SELECT id, subject, created, status, total, sent, send_on FROM " . NEWSLETTER_EMAILS_TABLE . " ORDER BY id DESC LIMIT 10", OBJECT);
 
288
 
289
- if ($wpdb->last_error) {
290
- $newsletter->logger->error($wpdb->last_error);
291
- return false;
292
- }
293
 
294
- if (empty($list)) {
295
- return array();
296
- }
297
 
298
- return $list;
299
- }
300
 
301
  }
16
  * @author roby
17
  */
18
  class TNP {
19
+ /*
20
+ * The full process of subscription
21
+ */
22
+
23
+ public static function subscribe( $params ) {
24
+
25
+ $newsletter = Newsletter::instance();
26
+ $subscription = NewsletterSubscription::instance();
27
+
28
+ // default params
29
+ $defaults = array( 'send_emails' => true );
30
+ $params = array_merge( $defaults, $params );
31
+
32
+ // Messages
33
+ $options = get_option( 'newsletter', array() );
34
+
35
+ // Form field configuration
36
+ $options_profile = get_option( 'newsletter_profile', array() );
37
+
38
+ $optin = (int) $options['noconfirmation']; // 0 - double, 1 - single
39
+
40
+ $email = $newsletter->normalize_email( stripslashes( $params['email'] ) );
41
+
42
+ // Should never reach this point without a valid email address
43
+ if ( $email == null ) {
44
+ return new WP_Error( '-1', 'Email address not valid', array( 'status' => 400 ) );
45
+ }
46
+
47
+ $user = $newsletter->get_user( $email );
48
+
49
+ if ( $user != null ) {
50
+
51
+ $newsletter->logger->info( 'Subscription of an address with status ' . $user->status );
52
+
53
+ // Bounced
54
+ if ( $user->status == 'B' ) {
55
+ return new WP_Error( '-1', 'Bounced address', array( 'status' => 400 ) );
56
+ }
57
+
58
+ // If asked to put in confirmed status, do not check further
59
+ if ( $params['status'] != 'C' && $optin == 0 ) {
60
+
61
+ // Already confirmed
62
+ //if ($optin == 0 && $user->status == 'C') {
63
+ if ( $user->status == 'C' ) {
64
+
65
+ set_transient( $user->id . '-' . $user->token, $params, 3600 * 48 );
66
+ $subscription->set_updated( $user );
67
+
68
+ // A second subscription always require confirmation otherwise anywan can change other users' data
69
+ $user->status = 'S';
70
+ $subscription->send_activation_email( $user );
71
+
72
+ return $user;
73
+ }
74
+ }
75
+ }
76
+
77
+ if ( $user != null ) {
78
+ $newsletter->logger->info( "Email address subscribed but not confirmed" );
79
+ $user = array( 'id' => $user->id );
80
+ } else {
81
+ $newsletter->logger->info( "New email address" );
82
+ }
83
+
84
+ if ( $optin ) {
85
+ $params['status'] = 'C';
86
+ } else {
87
+ $params['status'] = 'S';
88
+ }
89
+
90
+ // Lists
91
+
92
+ if ( ! isset( $params['lists'] ) || ! is_array( $params['lists'] ) ) {
93
+ $params['lists'] = array();
94
+ }
95
+
96
+ // Public lists: rebuild the array keeping only the valid lists
97
+ $lists = $newsletter->get_lists_public();
98
+
99
+ // Public list IDs
100
+ $public_lists = array();
101
+ foreach ( $lists as $list ) {
102
+ $public_lists[] = $list->id;
103
+ }
104
+
105
+ // Keep only the public lists
106
+ $params['lists'] = array_intersect( $public_lists, $params['lists'] );
107
+
108
+ // Pre assigned lists
109
+ $lists = $newsletter->get_lists();
110
+ foreach ( $lists as $list ) {
111
+ if ( $list->forced ) {
112
+ $params['lists'][] = $list->id;
113
+ }
114
+ }
115
+
116
+ // Keep only the public profile fields
117
+ for ( $i = 1; $i <= NEWSLETTER_PROFILE_MAX; $i ++ ) {
118
+ // If the profile cannot be set by subscriber, skip it.
119
+ if ( $subscription->options_profile[ 'profile_' . $i . '_status' ] == 0 ) {
120
+ unset( $params[ 'profile_' . $i ] );
121
+ }
122
+ }
123
+
124
+ apply_filters( 'newsletter_api_subscribe', $params );
125
+
126
+ $user = TNP::add_subscriber( $params );
127
+
128
+ if ( is_wp_error( $user ) ) {
129
+ return ( $user );
130
+ }
131
+
132
+ // Notification to admin (only for new confirmed subscriptions)
133
+ if ( $user->status == 'C' ) {
134
+ do_action( 'newsletter_user_confirmed', $user );
135
+ $subscription->notify_admin( $user, 'Newsletter subscription' );
136
+ setcookie( 'newsletter', $user->id . '-' . $user->token, time() + 60 * 60 * 24 * 365, '/' );
137
+ }
138
+
139
+ // skip messages if send_emails = false
140
+ if ( ! $params['send_emails'] ) {
141
+ return $user;
142
+ }
143
+
144
+ $message_type = ( $user->status == 'C' ) ? 'confirmed' : 'confirmation';
145
+ $subscription->send_message( $message_type, $user );
146
+
147
+ return null;
148
+ }
149
+
150
+ /*
151
+ * The UNsubscription
152
+ */
153
+
154
+ public static function unsubscribe( $params ) {
155
+
156
+ $newsletter = Newsletter::instance();
157
+ $user = $newsletter->get_user( $params['email'] );
158
 
159
  // $newsletter->logger->debug($params);
160
 
161
+ if ( ! $user ) {
162
+ return new WP_Error( '-1', 'Email address not found', array( 'status' => 404 ) );
163
+ }
164
+
165
+ if ( $user->status == 'U' ) {
166
+ return $user;
167
+ }
168
+
169
+ $user = $newsletter->set_user_status( $user, 'U' );
170
+
171
+ if ( empty( NewsletterSubscription::instance()->options['unsubscribed_disabled'] ) ) {
172
+ $newsletter->mail( $user->email, $newsletter->replace( NewsletterSubscription::instance()->options['unsubscribed_subject'], $user ), $newsletter->replace( NewsletterSubscription::instance()->options['unsubscribed_message'], $user ) );
173
+ }
174
+ NewsletterSubscription::instance()->notify_admin( $user, 'Newsletter unsubscription' );
175
 
176
+ return $user;
177
+ }
 
178
 
179
+ /*
180
+ * Adds a subscriber if not already in
181
+ */
182
 
183
+ public static function add_subscriber( $params ) {
 
 
 
184
 
185
+ $newsletter = Newsletter::instance();
186
+ $subscription = NewsletterSubscription::instance();
187
 
188
+ $email = $newsletter->normalize_email( stripslashes( $params['email'] ) );
 
 
189
 
190
+ if ( ! $email ) {
191
+ return new WP_Error( '-1', 'Email address not valid', array( 'status' => 400 ) );
192
+ }
193
 
194
+ $user = $newsletter->get_user( $email );
195
 
196
+ if ( $user ) {
197
+ return new WP_Error( '-1', 'Email address already exists', array( 'status' => 400 ) );
198
+ }
199
 
200
+ $user = array( 'email' => $email );
 
 
201
 
202
+ if ( isset( $params['name'] ) ) {
203
+ $user['name'] = $newsletter->normalize_name( stripslashes( $params['name'] ) );
204
+ }
205
 
206
+ if ( isset( $params['surname'] ) ) {
207
+ $user['surname'] = $newsletter->normalize_name( stripslashes( $params['surname'] ) );
208
+ }
209
 
210
+ if ( ! empty( $params['gender'] ) ) {
211
+ $user['sex'] = $newsletter->normalize_sex( $params['gender'] );
212
+ }
213
 
214
+ for ( $i = 1; $i <= NEWSLETTER_PROFILE_MAX; $i ++ ) {
215
+ if ( isset( $params[ 'profile_' . $i ] ) ) {
216
+ $user[ 'profile_' . $i ] = trim( stripslashes( $params[ 'profile_' . $i ] ) );
217
+ }
218
+ }
219
 
220
+ // Lists (an array under the key "lists")
221
+ // Preferences (field names are nl[] and values the list number so special forms with radio button can work)
222
+ if ( isset( $params['lists'] ) && is_array( $params['lists'] ) ) {
223
+ foreach ( $params['lists'] as $list_id ) {
224
+ $user[ 'list_' . ( (int) $list_id ) ] = 1;
225
+ }
226
+ }
227
 
 
 
 
228
 
229
+ if ( ! empty( $params['status'] ) ) {
230
+ $user['status'] = $params['status'];
231
+ } else {
232
+ $user['status'] = 'C';
233
+ }
234
 
235
+ $user['token'] = $newsletter->get_token();
236
+ $user['updated'] = time();
 
 
 
 
 
237
 
238
+ $user['ip'] = Newsletter::get_remote_ip();
239
 
240
+ $user = $newsletter->save_user( $user );
 
 
 
 
241
 
242
+ return $user;
243
+ }
 
 
244
 
245
+ /*
246
+ * Subscribers list
247
+ */
248
 
249
+ public static function subscribers( $params ) {
 
250
 
251
+ global $wpdb;
252
+ $newsletter = Newsletter::instance();
 
253
 
254
+ $items_per_page = 20;
255
+ $where = "";
256
 
257
+ $query = "select name, email from " . NEWSLETTER_USERS_TABLE . ' ' . $where . " order by id desc";
258
+ $query .= " limit 0," . $items_per_page;
259
+ $list = $wpdb->get_results( $query );
260
 
261
+ return $list;
262
+ }
263
 
264
+ /*
265
+ * Deletes a subscriber
266
+ */
267
 
268
+ public static function delete_subscriber( $params ) {
 
269
 
270
+ global $wpdb;
271
+ $newsletter = Newsletter::instance();
 
272
 
273
+ $user = $newsletter->get_user( $params['email'] );
274
 
275
+ if ( ! $user ) {
276
+ return new WP_Error( '-1', 'Email address not found', array( 'status' => 404 ) );
277
+ }
278
 
279
+ if ( $wpdb->query( $wpdb->prepare( "delete from " . NEWSLETTER_USERS_TABLE . " where id=%d", (int) $user->id ) ) ) {
280
+ return "OK";
281
+ } else {
282
+ $newsletter->logger->debug( $wpdb->last_query );
283
 
284
+ return new WP_Error( '-1', $wpdb->last_error, array( 'status' => 400 ) );
285
+ }
286
+ }
287
 
288
+ /*
289
+ * Newsletters list
290
+ */
 
 
 
 
291
 
292
+ public static function newsletters( $params ) {
 
 
293
 
294
+ global $wpdb;
295
+ $newsletter = Newsletter::instance();
296
 
297
+ $list = $wpdb->get_results( "SELECT id, subject, created, status, total, sent, send_on FROM " . NEWSLETTER_EMAILS_TABLE . " ORDER BY id DESC LIMIT 10", OBJECT );
 
298
 
299
+ if ( $wpdb->last_error ) {
300
+ $newsletter->logger->error( $wpdb->last_error );
301
 
302
+ return false;
303
+ }
 
 
304
 
305
+ if ( empty( $list ) ) {
306
+ return array();
307
+ }
308
 
309
+ return $list;
310
+ }
311
 
312
  }
includes/controls.php CHANGED
@@ -741,6 +741,15 @@ class NewsletterControls {
741
  echo $minutes . ' minutes ';
742
  }
743
  }
 
 
 
 
 
 
 
 
 
744
 
745
  function text($name, $size = 20, $placeholder = '') {
746
  $value = $this->get_value($name);
741
  echo $minutes . ' minutes ';
742
  }
743
  }
744
+
745
+ function password($name, $size = 20, $placeholder = '') {
746
+ $value = $this->get_value($name);
747
+ echo '<input id="options-', esc_attr($name), '" placeholder="' . esc_attr($placeholder) . '" name="options[' . $name . ']" type="password" autocomplete="off" ';
748
+ if (!empty($size)) {
749
+ echo 'size="' . $size . '" ';
750
+ }
751
+ echo 'value="', esc_attr($value), '">';
752
+ }
753
 
754
  function text($name, $size = 20, $placeholder = '') {
755
  $value = $this->get_value($name);
includes/fields.php CHANGED
@@ -264,9 +264,9 @@ class NewsletterFields {
264
  'author' => '',
265
  'author_name' => '',
266
  'post_status' => 'publish',
267
- 'suppress_filters' => true,
268
  'last_post_option'=>false
269
- )), $args);
270
  $args['filters']['posts_per_page'] = $count;
271
 
272
  $posts = get_posts($args['filters']);
264
  'author' => '',
265
  'author_name' => '',
266
  'post_status' => 'publish',
267
+ 'suppress_filters' => true),
268
  'last_post_option'=>false
269
+ ), $args);
270
  $args['filters']['posts_per_page'] = $count;
271
 
272
  $posts = get_posts($args['filters']);
includes/logger.php CHANGED
@@ -2,7 +2,7 @@
2
  defined('ABSPATH') || exit;
3
 
4
  if (!defined('NEWSLETTER_LOG_DIR')) {
5
- define('NEWSLETTER_LOG_DIR', WP_CONTENT_DIR . '/logs/newsletter/');
6
  }
7
 
8
  class NewsletterLogger {
2
  defined('ABSPATH') || exit;
3
 
4
  if (!defined('NEWSLETTER_LOG_DIR')) {
5
+ define('NEWSLETTER_LOG_DIR', WP_CONTENT_DIR . '/logs/newsletter');
6
  }
7
 
8
  class NewsletterLogger {
includes/mailers.php CHANGED
@@ -38,6 +38,7 @@ class NewsletterMailMethodWrapper extends NewsletterMailer {
38
  }
39
  return true;
40
  }
 
41
  }
42
 
43
  /**
@@ -78,6 +79,7 @@ class NewsletterOldMailerWrapper extends NewsletterMailer {
78
  }
79
  return true;
80
  }
 
81
  }
82
 
83
  /**
@@ -86,18 +88,13 @@ class NewsletterOldMailerWrapper extends NewsletterMailer {
86
  class NewsletterDefaultMailer extends NewsletterMailer {
87
 
88
  var $filter_active = false;
89
-
90
- /**
91
- * Used when the internal SMTP is active
92
- * @var PHPMailer
93
- */
94
- var $mailer = null;
95
 
96
  /**
 
97
  * @var TNP_Mailer_Message
98
  */
99
  var $current_message = null;
100
-
101
  function __construct() {
102
  parent::__construct('default', Newsletter::instance()->get_options('smtp'));
103
  }
@@ -107,30 +104,31 @@ class NewsletterDefaultMailer extends NewsletterMailer {
107
  return 'wp_mail() WordPress function (could be extended by a SMTP plugin)';
108
  }
109
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
110
  function send($message) {
111
 
112
  if (!$this->filter_active) {
113
- add_action('phpmailer_init', function ($mailer) {
114
- $newsletter = Newsletter::instance();
115
- if (!empty($newsletter->options['content_transfer_encoding'])) {
116
- $mailer->Encoding = $newsletter->options['content_transfer_encoding'];
117
- } else {
118
- $mailer->Encoding = 'base64';
119
- }
120
-
121
- // If there is not a current message, wp_mail() was not called by us
122
- if (is_null($this->current_message)) {
123
- return;
124
- }
125
-
126
- /* @var $mailer PHPMailer */
127
- $mailer->Sender = $newsletter->options['return_path'];
128
-
129
- if (!empty($this->current_message->body) && !empty($this->current_message->body_text)) {
130
- $mailer->AltBody = $this->current_message->body_text;
131
- }
132
-
133
- }, 100);
134
  $this->filter_active = true;
135
  }
136
 
@@ -142,7 +140,7 @@ class NewsletterDefaultMailer extends NewsletterMailer {
142
  if (!empty($newsletter->options['reply_to'])) {
143
  $wp_mail_headers[] = 'Reply-To: ' . $newsletter->options['reply_to'];
144
  }
145
-
146
  // Manage from and from name
147
 
148
  if (!empty($message->headers)) {
@@ -161,11 +159,11 @@ class NewsletterDefaultMailer extends NewsletterMailer {
161
  $message->error = 'Empty body';
162
  return new WP_Error(self::ERROR_GENERIC, 'Message format');
163
  }
164
-
165
  $this->current_message = $message;
166
  $r = wp_mail($message->to, $message->subject, $body, $wp_mail_headers);
167
  $this->current_message = null;
168
-
169
  if (!$r) {
170
  $last_error = error_get_last();
171
  if (is_array($last_error)) {
@@ -182,6 +180,7 @@ class NewsletterDefaultMailer extends NewsletterMailer {
182
  }
183
  return true;
184
  }
 
185
  }
186
 
187
  /**
@@ -190,7 +189,7 @@ class NewsletterDefaultMailer extends NewsletterMailer {
190
  class NewsletterDefaultSMTPMailer extends NewsletterMailer {
191
 
192
  var $mailer = null;
193
-
194
  function __construct($options) {
195
  parent::__construct('internal-smtp', $options);
196
  }
@@ -208,7 +207,7 @@ class NewsletterDefaultSMTPMailer extends NewsletterMailer {
208
  $logger = $this->get_logger();
209
  $logger->debug('Start sending to ' . $message->to);
210
  $mailer = $this->get_mailer();
211
-
212
  if (!empty($message->body)) {
213
  $mailer->IsHTML(true);
214
  $mailer->Body = $message->body;
@@ -218,7 +217,7 @@ class NewsletterDefaultSMTPMailer extends NewsletterMailer {
218
  $mailer->Body = $message->body_text;
219
  $mailer->AltBody = '';
220
  }
221
-
222
  $mailer->Subject = $message->subject;
223
 
224
  $mailer->ClearCustomHeaders();
@@ -235,7 +234,7 @@ class NewsletterDefaultSMTPMailer extends NewsletterMailer {
235
  $newsletter = Newsletter::instance();
236
  $mailer->setFrom($newsletter->options['sender_email'], $newsletter->options['sender_name']);
237
  }
238
-
239
  $mailer->ClearAddresses();
240
  $mailer->AddAddress($message->to);
241
  $mailer->Send();
@@ -249,7 +248,7 @@ class NewsletterDefaultSMTPMailer extends NewsletterMailer {
249
  $message->error = $mailer->ErrorInfo;
250
  return new WP_Error(self::ERROR_GENERIC, $mailer->ErrorInfo);
251
  }
252
-
253
  $logger->debug('Sent ' . $message->to);
254
  //$logger->error('Time: ' . (microtime(true) - $start) . ' seconds');
255
  return true;
@@ -318,5 +317,5 @@ class NewsletterDefaultSMTPMailer extends NewsletterMailer {
318
 
319
  return $this->mailer;
320
  }
321
- }
322
 
 
38
  }
39
  return true;
40
  }
41
+
42
  }
43
 
44
  /**
79
  }
80
  return true;
81
  }
82
+
83
  }
84
 
85
  /**
88
  class NewsletterDefaultMailer extends NewsletterMailer {
89
 
90
  var $filter_active = false;
 
 
 
 
 
 
91
 
92
  /**
93
+ * Static to be accessed in the hook: on some installation the object $this is not working, we're still trying to understand why
94
  * @var TNP_Mailer_Message
95
  */
96
  var $current_message = null;
97
+
98
  function __construct() {
99
  parent::__construct('default', Newsletter::instance()->get_options('smtp'));
100
  }
104
  return 'wp_mail() WordPress function (could be extended by a SMTP plugin)';
105
  }
106
 
107
+ function fix_mailer($mailer) {
108
+ $newsletter = Newsletter::instance();
109
+ if (!empty($newsletter->options['content_transfer_encoding'])) {
110
+ $mailer->Encoding = $newsletter->options['content_transfer_encoding'];
111
+ } else {
112
+ $mailer->Encoding = 'base64';
113
+ }
114
+
115
+ // If there is not a current message, wp_mail() was not called by us
116
+ if (is_null($this->current_message)) {
117
+ return;
118
+ }
119
+
120
+ /* @var $mailer PHPMailer */
121
+ $mailer->Sender = $newsletter->options['return_path'];
122
+
123
+ if (!empty($this->current_message->current_message->body) && !empty($this->current_message->current_message->body_text)) {
124
+ $mailer->AltBody = $this->current_message->current_message->body_text;
125
+ }
126
+ }
127
+
128
  function send($message) {
129
 
130
  if (!$this->filter_active) {
131
+ add_action('phpmailer_init', array($this, 'fix_mailer'), 100);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
132
  $this->filter_active = true;
133
  }
134
 
140
  if (!empty($newsletter->options['reply_to'])) {
141
  $wp_mail_headers[] = 'Reply-To: ' . $newsletter->options['reply_to'];
142
  }
143
+
144
  // Manage from and from name
145
 
146
  if (!empty($message->headers)) {
159
  $message->error = 'Empty body';
160
  return new WP_Error(self::ERROR_GENERIC, 'Message format');
161
  }
162
+
163
  $this->current_message = $message;
164
  $r = wp_mail($message->to, $message->subject, $body, $wp_mail_headers);
165
  $this->current_message = null;
166
+
167
  if (!$r) {
168
  $last_error = error_get_last();
169
  if (is_array($last_error)) {
180
  }
181
  return true;
182
  }
183
+
184
  }
185
 
186
  /**
189
  class NewsletterDefaultSMTPMailer extends NewsletterMailer {
190
 
191
  var $mailer = null;
192
+
193
  function __construct($options) {
194
  parent::__construct('internal-smtp', $options);
195
  }
207
  $logger = $this->get_logger();
208
  $logger->debug('Start sending to ' . $message->to);
209
  $mailer = $this->get_mailer();
210
+
211
  if (!empty($message->body)) {
212
  $mailer->IsHTML(true);
213
  $mailer->Body = $message->body;
217
  $mailer->Body = $message->body_text;
218
  $mailer->AltBody = '';
219
  }
220
+
221
  $mailer->Subject = $message->subject;
222
 
223
  $mailer->ClearCustomHeaders();
234
  $newsletter = Newsletter::instance();
235
  $mailer->setFrom($newsletter->options['sender_email'], $newsletter->options['sender_name']);
236
  }
237
+
238
  $mailer->ClearAddresses();
239
  $mailer->AddAddress($message->to);
240
  $mailer->Send();
248
  $message->error = $mailer->ErrorInfo;
249
  return new WP_Error(self::ERROR_GENERIC, $mailer->ErrorInfo);
250
  }
251
+
252
  $logger->debug('Sent ' . $message->to);
253
  //$logger->error('Time: ' . (microtime(true) - $start) . ' seconds');
254
  return true;
317
 
318
  return $this->mailer;
319
  }
 
320
 
321
+ }
includes/module.php CHANGED
@@ -118,16 +118,6 @@ class NewsletterAddon {
118
  }
119
  add_action('newsletter_init', array($this, 'init'));
120
 
121
- if (is_admin()) {
122
- if (!class_exists('NewsletterExtensions')) {
123
- add_filter('plugin_row_meta', function ($plugin_meta, $plugin_file) {
124
- if ($plugin_file === 'newsletter-' . $this->name . '/' . $this->name . '.php') {
125
- $plugin_meta[] = '<a href="admin.php?page=newsletter_main_extensions" style="font-weight: bold">Newsletter Addons Manager required</a>';
126
- }
127
- return $plugin_meta;
128
- }, 10, 2);
129
- }
130
- }
131
  }
132
 
133
  function upgrade($first_install = false) {
@@ -269,7 +259,6 @@ class NewsletterMailer {
269
  const ERROR_FATAL = '2';
270
 
271
  /* @var NewsletterLogger */
272
-
273
  var $logger;
274
  var $name;
275
  var $options;
@@ -2057,6 +2046,8 @@ class NewsletterModule {
2057
  $text = str_replace('{email_id}', $email->id, $text);
2058
  $text = str_replace('{email_key}', $nek, $text);
2059
  $text = str_replace('{email_subject}', $email->subject, $text);
 
 
2060
  $text = $this->replace_url($text, 'EMAIL_URL', $this->build_action_url('v', $user) . '&id=' . $email->id);
2061
  }
2062
 
118
  }
119
  add_action('newsletter_init', array($this, 'init'));
120
 
 
 
 
 
 
 
 
 
 
 
121
  }
122
 
123
  function upgrade($first_install = false) {
259
  const ERROR_FATAL = '2';
260
 
261
  /* @var NewsletterLogger */
 
262
  var $logger;
263
  var $name;
264
  var $options;
2046
  $text = str_replace('{email_id}', $email->id, $text);
2047
  $text = str_replace('{email_key}', $nek, $text);
2048
  $text = str_replace('{email_subject}', $email->subject, $text);
2049
+ // Deprecated
2050
+ $text = str_replace('{subject}', $email->subject, $text);
2051
  $text = $this->replace_url($text, 'EMAIL_URL', $this->build_action_url('v', $user) . '&id=' . $email->id);
2052
  }
2053
 
main/index.php CHANGED
@@ -20,6 +20,7 @@ if ( $controls->is_action( 'feed_disable' ) ) {
20
  }
21
 
22
  $emails_module = NewsletterEmails::instance();
 
23
  $emails = $wpdb->get_results( "select * from " . NEWSLETTER_EMAILS_TABLE . " where type='message' order by id desc limit 5" );
24
 
25
  $users_module = NewsletterUsers::instance();
@@ -33,9 +34,9 @@ $last_email = $wpdb->get_row(
33
 
34
  if ( $last_email ) {
35
  $last_email_sent = $last_email->sent;
36
- $last_email_opened = NewsletterStatistics::instance()->get_open_count( $last_email->id );
37
  $last_email_notopened = $last_email_sent - $last_email_opened;
38
- $last_email_clicked = NewsletterStatistics::instance()->get_click_count( $last_email->id );
39
  $last_email_opened -= $last_email_clicked;
40
 
41
  $overall_sent = $wpdb->get_var( "select sum(sent) from " . NEWSLETTER_EMAILS_TABLE . " where type='message' and status in ('sent', 'sending')" );
@@ -302,16 +303,16 @@ $labels = array_reverse( $labels );
302
  ?>
303
  </td>
304
  <td>
305
-
306
- <?php $emails_module->show_email_status_label( $email ) ?>
307
  </td>
308
  <td>
309
  <?php $emails_module->show_email_progress_bar( $email, array( 'scheduled' => true ) ) ?>
310
  </td>
311
-
312
- <td style="white-space:nowrap">
313
- <?php echo $emails_module->get_edit_button($email) ?>
314
- </td>
 
315
  </tr>
316
  <?php } ?>
317
  </table>
20
  }
21
 
22
  $emails_module = NewsletterEmails::instance();
23
+ $statistics_module = NewsletterStatistics::instance();
24
  $emails = $wpdb->get_results( "select * from " . NEWSLETTER_EMAILS_TABLE . " where type='message' order by id desc limit 5" );
25
 
26
  $users_module = NewsletterUsers::instance();
34
 
35
  if ( $last_email ) {
36
  $last_email_sent = $last_email->sent;
37
+ $last_email_opened = $statistics_module->get_open_count( $last_email->id );
38
  $last_email_notopened = $last_email_sent - $last_email_opened;
39
+ $last_email_clicked = $statistics_module->get_click_count( $last_email->id );
40
  $last_email_opened -= $last_email_clicked;
41
 
42
  $overall_sent = $wpdb->get_var( "select sum(sent) from " . NEWSLETTER_EMAILS_TABLE . " where type='message' and status in ('sent', 'sending')" );
303
  ?>
304
  </td>
305
  <td>
306
+ <?php $emails_module->show_email_status_label( $email ) ?>
 
307
  </td>
308
  <td>
309
  <?php $emails_module->show_email_progress_bar( $email, array( 'scheduled' => true ) ) ?>
310
  </td>
311
+ <td style="white-space:nowrap"><?php if ($email->status == 'sent') {
312
+ echo '<a class="button-primary" href="' . $statistics_module->get_statistics_url($email->id) . '"><i class="fa fa-chart-bar"></i> ' . __('Statistics', 'newsletter') . '</a>';
313
+ } else {
314
+ echo $emails_module->get_edit_button($email);
315
+ } ?></td>
316
  </tr>
317
  <?php } ?>
318
  </table>
main/main.php CHANGED
@@ -53,6 +53,7 @@ if (!$controls->is_action()) {
53
 
54
  //$module->hook_newsletter_extension_versions(true);
55
  delete_transient("tnp_extensions_json");
 
56
  }
57
 
58
  if ($controls->is_action('create')) {
@@ -78,48 +79,20 @@ if (!$controls->is_action()) {
78
  }
79
  }
80
 
81
- /* TODO switch to check_license function */
82
 
83
- if (!empty($controls->data['contract_key']) || defined('NEWSLETTER_LICENSE_KEY')) {
84
-
85
- if (defined('NEWSLETTER_LICENSE_KEY')) {
86
- $license_key = NEWSLETTER_LICENSE_KEY;
87
- } else {
88
- $license_key = $controls->data['contract_key'];
89
- }
90
-
91
- $response = wp_remote_get('http://www.thenewsletterplugin.com/wp-content/plugins/file-commerce-pro/license-check.php?k=' . urlencode($license_key), array('sslverify' => false));
92
-
93
- if (is_wp_error($response)) {
94
- /* @var $response WP_Error */
95
- $controls->errors .= 'It seems that your blog cannot contact the license validator. Ask your provider to unlock the HTTP/HTTPS connections to www.thenewsletterplugin.com<br>';
96
- $controls->errors .= esc_html($response->get_error_code()) . ' - ' . esc_html($response->get_error_message());
97
- $controls->data['licence_expires'] = '';
98
- } else {
99
- if (wp_remote_retrieve_response_code($response) != 200) {
100
- $controls->errors .= '[' . wp_remote_retrieve_response_code($response) . '] The license validator returned an error, please check your <a href="https://www.thenewsletterplugin.com/account">license code and status</a>, thank you.';
101
- $controls->errors .= '<br>You can anyway download the professional addons from https://www.thenewsletterplugin.com if your license is valid.';
102
- $controls->data['licence_expires'] = '';
103
  } else {
104
- $expires = json_decode(wp_remote_retrieve_body($response));
105
-
106
- if (!empty($expires->message)) {
107
- $controls->errors = $expires->message;
108
- } else {
109
- $controls->data['licence_expires'] = $expires->expire;
110
-
111
- if ($expires->expire == -1) {
112
- $controls->messages = 'Your FREE license is valid';
113
- } elseif ($expires->expire >= time()) {
114
- $controls->messages = 'Your license is valid and expires on ' . esc_html(date('Y-m-d', $expires->expire));
115
- } else {
116
- $controls->messages = 'Your license is expired on ' . esc_html(date('Y-m-d', $expires->expire));
117
- }
118
- }
119
  }
120
-
121
  }
122
- $module->merge_options($controls->data);
123
  }
124
 
125
  $return_path = $module->options['return_path'];
53
 
54
  //$module->hook_newsletter_extension_versions(true);
55
  delete_transient("tnp_extensions_json");
56
+ delete_transient('newsletter_license_data');
57
  }
58
 
59
  if ($controls->is_action('create')) {
79
  }
80
  }
81
 
82
+ $license_data = $module->get_license_data(true);
83
 
84
+ if (is_wp_error($license_data)) {
85
+ $controls->errors .= esc_html('[' . $license_data->get_error_code()) . '] - ' . esc_html($license_data->get_error_message());
86
+ } else {
87
+ if ($license_data !== false) {
88
+ if ($license_data->expire == 0) {
89
+ $controls->messages = 'Your FREE license is valid';
90
+ } elseif ($license_data->expire >= time()) {
91
+ $controls->messages = 'Your license is valid and expires on ' . esc_html(date('Y-m-d', $license_data->expire));
 
 
 
 
 
 
 
 
 
 
 
 
92
  } else {
93
+ $controls->errors = 'Your license is expired on ' . esc_html(date('Y-m-d', $license_data->expire));
 
 
 
 
 
 
 
 
 
 
 
 
 
 
94
  }
 
95
  }
 
96
  }
97
 
98
  $return_path = $module->options['return_path'];
main/smtp.php CHANGED
@@ -103,7 +103,7 @@ if (empty($controls->data['enabled']) && !empty($controls->data['host'])) {
103
  <th>Authentication</th>
104
  <td>
105
  user: <?php $controls->text('user', 30); ?>
106
- password: <?php $controls->text('pass', 30); ?>
107
  <p class="description">
108
  If authentication is not required, leave "user" field blank.
109
  </p>
103
  <th>Authentication</th>
104
  <td>
105
  user: <?php $controls->text('user', 30); ?>
106
+ password: <?php $controls->password('pass', 30); ?>
107
  <p class="description">
108
  If authentication is not required, leave "user" field blank.
109
  </p>
main/status.php CHANGED
@@ -8,10 +8,12 @@ $controls = new NewsletterControls();
8
 
9
 
10
  $wp_cron_calls = get_option('newsletter_diagnostic_cron_calls', array());
 
 
 
 
11
  if (count($wp_cron_calls) > 20) {
12
- $total = 0;
13
- $wp_cron_calls_max = 0;
14
- $wp_cron_calls_min = 0;
15
  for ($i = 1; $i < count($wp_cron_calls); $i++) {
16
  $diff = $wp_cron_calls[$i] - $wp_cron_calls[$i - 1];
17
  $total += $diff;
@@ -1036,9 +1038,9 @@ $speed = Newsletter::$instance->options['scheduler_max'];
1036
 
1037
  <?php
1038
  wp_mkdir_p(NEWSLETTER_LOG_DIR);
1039
- $res = is_dir(NEWSLETTER_LOG_DIR);
1040
  if ($res) {
1041
- file_put_contents(NEWSLETTER_LOG_DIR . '/test.txt', "");
1042
  $res = is_file(NEWSLETTER_LOG_DIR . '/test.txt');
1043
  if ($res) {
1044
  @unlink(NEWSLETTER_LOG_DIR . '/test.txt');
8
 
9
 
10
  $wp_cron_calls = get_option('newsletter_diagnostic_cron_calls', array());
11
+ $total = 0;
12
+ $wp_cron_calls_max = 0;
13
+ $wp_cron_calls_min = 0;
14
+ $wp_cron_calls_avg = 0;
15
  if (count($wp_cron_calls) > 20) {
16
+
 
 
17
  for ($i = 1; $i < count($wp_cron_calls); $i++) {
18
  $diff = $wp_cron_calls[$i] - $wp_cron_calls[$i - 1];
19
  $total += $diff;
1038
 
1039
  <?php
1040
  wp_mkdir_p(NEWSLETTER_LOG_DIR);
1041
+ $res = is_dir(NEWSLETTER_LOG_DIR) && is_writable(NEWSLETTER_LOG_DIR);
1042
  if ($res) {
1043
+ @file_put_contents(NEWSLETTER_LOG_DIR . '/test.txt', "");
1044
  $res = is_file(NEWSLETTER_LOG_DIR . '/test.txt');
1045
  if ($res) {
1046
  @unlink(NEWSLETTER_LOG_DIR . '/test.txt');
plugin.php CHANGED
@@ -4,7 +4,7 @@
4
  Plugin Name: Newsletter
5
  Plugin URI: https://www.thenewsletterplugin.com/plugins/newsletter
6
  Description: Newsletter is a cool plugin to create your own subscriber list, to send newsletters, to build your business. <strong>Before update give a look to <a href="https://www.thenewsletterplugin.com/category/release">this page</a> to know what's changed.</strong>
7
- Version: 6.3.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.
@@ -28,7 +28,7 @@
28
 
29
  */
30
 
31
- define('NEWSLETTER_VERSION', '6.3.9');
32
 
33
  global $newsletter, $wpdb;
34
 
@@ -186,11 +186,28 @@ class Newsletter extends NewsletterModule {
186
 
187
  add_shortcode('newsletter_replace', array($this, 'shortcode_newsletter_replace'));
188
 
189
- if (!method_exists('NewsletterExtensions', 'hook_site_transient_update_plugins')) {
190
- add_filter('site_transient_update_plugins', array($this, 'hook_site_transient_update_plugins'));
191
- }
192
 
193
  if (is_admin()) {
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
194
  add_action('in_admin_header', array($this, 'hook_in_admin_header'), 1000);
195
 
196
  if ($this->is_admin_page()) {
@@ -642,7 +659,6 @@ class Newsletter extends NewsletterModule {
642
  $wpdb->query("update " . NEWSLETTER_EMAILS_TABLE . " set status='sent', total=sent where id=" . $email->id . " limit 1");
643
  return true;
644
  }
645
-
646
  } else {
647
  $this->logger->info(__METHOD__ . '> Subscribers supplied');
648
  }
@@ -670,7 +686,7 @@ class Newsletter extends NewsletterModule {
670
  $user = apply_filters('newsletter_send_user', $user);
671
  $message = $this->build_message($email, $user);
672
  $this->save_sent_message($message);
673
-
674
  if (!$test) {
675
  $wpdb->query("update " . NEWSLETTER_EMAILS_TABLE . " set sent=sent+1, last_id=" . $user->id . " where id=" . $email->id . " limit 1");
676
  }
@@ -709,7 +725,7 @@ class Newsletter extends NewsletterModule {
709
  $message = $this->build_message($email, $user);
710
  $this->save_sent_message($message);
711
  $messages[] = $message;
712
-
713
  if (!$test) {
714
  $wpdb->query("update " . NEWSLETTER_EMAILS_TABLE . " set sent=sent+1, last_id=" . $user->id . " where id=" . $email->id . " limit 1");
715
  }
@@ -724,7 +740,7 @@ class Newsletter extends NewsletterModule {
724
  $this->save_sent_message($message);
725
  }
726
  }
727
-
728
  if (is_wp_error($r)) {
729
  $this->logger->error($r);
730
  return $r;
@@ -747,7 +763,7 @@ class Newsletter extends NewsletterModule {
747
  if ($supplied_users && $this->limits_exceeded()) {
748
  $result = false;
749
  }
750
-
751
  $this->logger->info(__METHOD__ . '> End run for email ' . $email->id);
752
 
753
  return $result;
@@ -1064,11 +1080,11 @@ class Newsletter extends NewsletterModule {
1064
  $plugin->plugin = $extension->plugin;
1065
  $plugin->new_version = $extension->version;
1066
  $plugin->url = $extension->url;
1067
- if (class_exists('NewsletterExtensions') && $extension->downloadable) {
1068
  // NO filters here!
1069
  $plugin->package = NewsletterExtensions::$instance->get_package($extension->id, $license_key);
1070
  } else {
1071
-
1072
  }
1073
  // [banners] => Array
1074
  // (
@@ -1132,9 +1148,6 @@ class Newsletter extends NewsletterModule {
1132
 
1133
  if (empty($extensions_json)) {
1134
  $url = "http://www.thenewsletterplugin.com/wp-content/extensions.json?ver=" . NEWSLETTER_VERSION;
1135
- if (!empty($this->options['contract_key'])) {
1136
- $url = "http://www.thenewsletterplugin.com/wp-content/plugins/file-commerce-pro/extensions.php?k=" . $this->options['contract_key'] . '&ver=' . NEWSLETTER_VERSION;
1137
- }
1138
  $extensions_response = wp_remote_get($url);
1139
  $extensions_json = wp_remote_retrieve_body($extensions_response);
1140
  if (!empty($extensions_json)) {
@@ -1216,6 +1229,74 @@ class Newsletter extends NewsletterModule {
1216
  return false;
1217
  }
1218
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1219
  public static function check_license($license_key) {
1220
  $response = wp_remote_get('http://www.thenewsletterplugin.com/wp-content/plugins/file-commerce-pro/check.php?k=' . urlencode($license_key), array('sslverify' => false));
1221
  if (is_wp_error($response)) {
4
  Plugin Name: Newsletter
5
  Plugin URI: https://www.thenewsletterplugin.com/plugins/newsletter
6
  Description: Newsletter is a cool plugin to create your own subscriber list, to send newsletters, to build your business. <strong>Before update give a look to <a href="https://www.thenewsletterplugin.com/category/release">this page</a> to know what's changed.</strong>
7
+ Version: 6.4.1
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.
28
 
29
  */
30
 
31
+ define('NEWSLETTER_VERSION', '6.4.1');
32
 
33
  global $newsletter, $wpdb;
34
 
186
 
187
  add_shortcode('newsletter_replace', array($this, 'shortcode_newsletter_replace'));
188
 
189
+ add_filter('site_transient_update_plugins', array($this, 'hook_site_transient_update_plugins'));
 
 
190
 
191
  if (is_admin()) {
192
+ if (!class_exists('NewsletterExtensions')) {
193
+
194
+ add_filter('plugin_row_meta', function ($plugin_meta, $plugin_file) {
195
+
196
+ static $slugs = array();
197
+ if (empty($slugs)) {
198
+ $addons = $this->getTnpExtensions();
199
+ foreach ($addons as $addon) {
200
+ $slugs[] = $addon->wp_slug;
201
+ }
202
+ }
203
+ if (array_search($plugin_file, $slugs) !== false) {
204
+
205
+ $plugin_meta[] = '<a href="admin.php?page=newsletter_main_extensions" style="font-weight: bold">Newsletter Addons Manager required</a>';
206
+ }
207
+ return $plugin_meta;
208
+ }, 10, 2);
209
+ }
210
+
211
  add_action('in_admin_header', array($this, 'hook_in_admin_header'), 1000);
212
 
213
  if ($this->is_admin_page()) {
659
  $wpdb->query("update " . NEWSLETTER_EMAILS_TABLE . " set status='sent', total=sent where id=" . $email->id . " limit 1");
660
  return true;
661
  }
 
662
  } else {
663
  $this->logger->info(__METHOD__ . '> Subscribers supplied');
664
  }
686
  $user = apply_filters('newsletter_send_user', $user);
687
  $message = $this->build_message($email, $user);
688
  $this->save_sent_message($message);
689
+
690
  if (!$test) {
691
  $wpdb->query("update " . NEWSLETTER_EMAILS_TABLE . " set sent=sent+1, last_id=" . $user->id . " where id=" . $email->id . " limit 1");
692
  }
725
  $message = $this->build_message($email, $user);
726
  $this->save_sent_message($message);
727
  $messages[] = $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
  }
740
  $this->save_sent_message($message);
741
  }
742
  }
743
+
744
  if (is_wp_error($r)) {
745
  $this->logger->error($r);
746
  return $r;
763
  if ($supplied_users && $this->limits_exceeded()) {
764
  $result = false;
765
  }
766
+
767
  $this->logger->info(__METHOD__ . '> End run for email ' . $email->id);
768
 
769
  return $result;
1080
  $plugin->plugin = $extension->plugin;
1081
  $plugin->new_version = $extension->version;
1082
  $plugin->url = $extension->url;
1083
+ if (class_exists('NewsletterExtensions')) {
1084
  // NO filters here!
1085
  $plugin->package = NewsletterExtensions::$instance->get_package($extension->id, $license_key);
1086
  } else {
1087
+ $plugin->package = '';
1088
  }
1089
  // [banners] => Array
1090
  // (
1148
 
1149
  if (empty($extensions_json)) {
1150
  $url = "http://www.thenewsletterplugin.com/wp-content/extensions.json?ver=" . NEWSLETTER_VERSION;
 
 
 
1151
  $extensions_response = wp_remote_get($url);
1152
  $extensions_json = wp_remote_retrieve_body($extensions_response);
1153
  if (!empty($extensions_json)) {
1229
  return false;
1230
  }
1231
 
1232
+ function get_license_data($refresh = false) {
1233
+
1234
+ if (!$refresh) {
1235
+ $license_data = get_transient('newsletter_license_data');
1236
+ if (!empty($license_data) && is_object($license_data)) {
1237
+ return $license_data;
1238
+ }
1239
+ }
1240
+
1241
+ $this->logger->debug('Refreshing the license data');
1242
+
1243
+ delete_transient('newsletter_license_data');
1244
+
1245
+ $license_key = $this->get_license_key();
1246
+ if (empty($license_key)) {
1247
+ $this->logger->debug('License was empty');
1248
+ return false;
1249
+ }
1250
+ $license_data_url = 'https://www.thenewsletterplugin.com/wp-content/plugins/file-commerce-pro/get-license-data.php';
1251
+
1252
+ $response = wp_remote_post($license_data_url, array(
1253
+ 'body' => array('k' => $license_key)
1254
+ ));
1255
+
1256
+ // Fall back to http...
1257
+ if (is_wp_error($response)) {
1258
+ $this->logger->error('Falling back to http');
1259
+ $this->logger->error($response);
1260
+ $response = wp_remote_post($license_data_url, array(
1261
+ 'body' => array('k' => $license_key)
1262
+ ));
1263
+ if (is_wp_error($response)) {
1264
+ $this->logger->error($response);
1265
+ return $response;
1266
+ }
1267
+ }
1268
+
1269
+ $download_message = 'You can download all addons from www.thenewsletterplugin.com if your license is valid.';
1270
+
1271
+ if (wp_remote_retrieve_response_code($response) != '200') {
1272
+ $this->logger->error('license data error: ' . wp_remote_retrieve_response_code($response));
1273
+ return new WP_Error(wp_remote_retrieve_response_code($response), 'License validation service error. <br>' . $download_message);
1274
+ }
1275
+
1276
+ $json = wp_remote_retrieve_body($response);
1277
+ $data = json_decode($json);
1278
+
1279
+ if (!is_object($data)) {
1280
+ $this->logger->error($json);
1281
+ return new WP_Error(1, 'License validation service error. <br>' . $download_message);
1282
+ }
1283
+
1284
+ if (isset($data->message)) {
1285
+ return new WP_Error(1, $data->message . ' (check the license on Newsletter main settings)');
1286
+ }
1287
+
1288
+ $timeout = 24 * 7 * 3600;
1289
+ if ($data->expire < time() + $timeout) $timeout = $data->expire;
1290
+ set_transient('newsletter_license_data', $data, $timeout);
1291
+
1292
+ return $data;
1293
+ }
1294
+
1295
+ /**
1296
+ * @deprecated
1297
+ * @param type $license_key
1298
+ * @return \WP_Error
1299
+ */
1300
  public static function check_license($license_key) {
1301
  $response = wp_remote_get('http://www.thenewsletterplugin.com/wp-content/plugins/file-commerce-pro/check.php?k=' . urlencode($license_key), array('sslverify' => false));
1302
  if (is_wp_error($response)) {
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.2.4
5
- Stable tag: 6.3.9
6
  Requires PHP: 5.6
7
  Contributors: satollo,webagile,michael-travan
8
 
@@ -109,6 +109,21 @@ Thank you, The Newsletter Team
109
 
110
  == Changelog ==
111
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
112
  = 6.3.9 =
113
 
114
  * Improved antibot and/or spam subscription checks (please review your security configuration)
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.3.2
5
+ Stable tag: 6.4.1
6
  Requires PHP: 5.6
7
  Contributors: satollo,webagile,michael-travan
8
 
109
 
110
  == Changelog ==
111
 
112
+ = 6.4.1 =
113
+
114
+ * Added statistics shortcut for sent newsletters
115
+ * Fixed unsubscription from email tracking
116
+ * Password field in smtp configuration
117
+ * Small fixes to header block
118
+ * Fixed the subject on online newsletter view
119
+ * Fixed the subject ideas popup X button
120
+
121
+ = 6.4.0 =
122
+
123
+ * Fixed extra profile fields management in REST and PHP API
124
+ * Removed the "read more" added by themes on posts excerpt
125
+ * Core improvements
126
+
127
  = 6.3.9 =
128
 
129
  * Improved antibot and/or spam subscription checks (please review your security configuration)
tnp-header.php CHANGED
@@ -138,37 +138,38 @@ $warning |= empty($status_options['mail']);
138
  </a>
139
  </li>
140
  <?php } ?>
 
 
141
 
142
- <?php if (empty(Newsletter::instance()->options['contract_key']) && !defined('NEWSLETTER_LICENSE_KEY')) { ?>
143
 
144
  <li class="tnp-professional-extensions-button"><a href="https://www.thenewsletterplugin.com/premium?utm_source=plugin&utm_medium=link&utm_campaign=header" target="_blank">
145
  <i class="fa fa-trophy"></i> <?php _e('Get Professional Addons', 'newsletter') ?></a>
146
  </li>
 
 
 
 
147
 
148
- <?php } elseif (Newsletter::instance()->options['licence_expires'] == -1) { ?>
149
 
150
  <li class="tnp-professional-extensions-button"><a href="https://www.thenewsletterplugin.com/premium?utm_source=plugin&utm_medium=link&utm_campaign=header" target="_blank">
151
  <i class="fa fa-trophy"></i> <?php _e('Get Professional Addons', 'newsletter') ?></a>
152
  </li>
153
 
154
- <?php } elseif (empty(Newsletter::instance()->options['licence_expires'])) { ?>
155
 
156
  <li class="tnp-professional-extensions-button-red">
157
- <a href="?page=newsletter_main_main"><i class="fa fa-hand-paper" style="color: white"></i> <?php _e('Licence not valid', 'newsletter') ?></a>
158
  </li>
159
 
160
- <?php } elseif (Newsletter::instance()->options['licence_expires'] >= time()) { ?>
161
 
162
  <?php $p = class_exists('NewsletterExtensions')?'newsletter_extensions_index':'newsletter_main_extensions'; ?>
163
  <li class="tnp-professional-extensions-button">
164
- <a href="?page=<?php echo $p?>"><i class="fa fa-check-square"></i> <?php _e('Licence active', 'newsletter') ?></a>
165
- </li>
166
-
167
- <?php } elseif (Newsletter::instance()->options['licence_expires'] < time()) { ?>
168
-
169
- <li class="tnp-professional-extensions-button-red">
170
- <a href="?page=newsletter_main_main"><i class="fa fa-hand-paper" style="color: white"></i> <?php _e('Licence expired', 'newsletter') ?></a>
171
  </li>
 
172
 
173
  <?php } ?>
174
  </ul>
138
  </a>
139
  </li>
140
  <?php } ?>
141
+
142
+ <?php $license_data = Newsletter::instance()->get_license_data() ?>
143
 
144
+ <?php if (empty($license_data)) { ?>
145
 
146
  <li class="tnp-professional-extensions-button"><a href="https://www.thenewsletterplugin.com/premium?utm_source=plugin&utm_medium=link&utm_campaign=header" target="_blank">
147
  <i class="fa fa-trophy"></i> <?php _e('Get Professional Addons', 'newsletter') ?></a>
148
  </li>
149
+ <?php } elseif (is_wp_error($license_data)) { ?>
150
+ <li class="tnp-professional-extensions-button-red">
151
+ <a href="?page=newsletter_main_main"><i class="fa fa-hand-paper" style="color: white"></i> <?php _e('License not valid', 'newsletter') ?></a>
152
+ </li>
153
 
154
+ <?php } elseif ($license_data->expire == 0) { ?>
155
 
156
  <li class="tnp-professional-extensions-button"><a href="https://www.thenewsletterplugin.com/premium?utm_source=plugin&utm_medium=link&utm_campaign=header" target="_blank">
157
  <i class="fa fa-trophy"></i> <?php _e('Get Professional Addons', 'newsletter') ?></a>
158
  </li>
159
 
160
+ <?php } elseif ($license_data->expire < time()) { ?>
161
 
162
  <li class="tnp-professional-extensions-button-red">
163
+ <a href="?page=newsletter_main_main"><i class="fa fa-hand-paper" style="color: white"></i> <?php _e('License expired', 'newsletter') ?></a>
164
  </li>
165
 
166
+ <?php } elseif ($license_data->expire >= time()) { ?>
167
 
168
  <?php $p = class_exists('NewsletterExtensions')?'newsletter_extensions_index':'newsletter_main_extensions'; ?>
169
  <li class="tnp-professional-extensions-button">
170
+ <a href="?page=<?php echo $p?>"><i class="fa fa-check-square"></i> <?php _e('License active', 'newsletter') ?></a>
 
 
 
 
 
 
171
  </li>
172
+
173
 
174
  <?php } ?>
175
  </ul>
unsubscription/unsubscription.php CHANGED
@@ -96,7 +96,7 @@ class NewsletterUnsubscription extends NewsletterModule {
96
 
97
  $email = $this->get_email_from_request();
98
  if ($email) {
99
- $wpdb->update(NEWSLETTER_USERS_TABLE, array('unsub_email_id' => (int) $email_id, 'unsub_time' => time()), array('id' => $user->id));
100
  }
101
 
102
  $this->send_unsubscribed_email($user);
96
 
97
  $email = $this->get_email_from_request();
98
  if ($email) {
99
+ $wpdb->update(NEWSLETTER_USERS_TABLE, array('unsub_email_id' => (int) $email->id, 'unsub_time' => time()), array('id' => $user->id));
100
  }
101
 
102
  $this->send_unsubscribed_email($user);