PluginProbe
Mail Queue / 1.2
Mail Queue v1.2
1.6.1 1.6.0 1.5.1 trunk 1.0 1.1 1.2 1.3 1.3.1 1.4 1.4.1 1.4.2 1.4.3 1.4.4 1.4.5 1.4.6 1.5.0
mail-queue / mail-queue.php

mail-queue.php in Mail Queue 1.2, at mail-queue.php

280 lines 11.7 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 /**
4 * Plugin Name: Mail Queue
5 * Plugin URI: https://www.webdesign-muenchen.de/wordpress-plugin-mail-queue/
6 * Description: Take Control and improve Security of wp_mail(). Queue outgoing emails, log their sendings and get alerted, if your website wants to send more emails than usual.
7 * Version: 1.2
8 * Requires at least: 5.2
9 * Requires PHP: 7.2
10 * Author: WDM
11 * Author URI: https://www.webdesign-muenchen.de
12 * License: GPLv3 or later
13 * License URI: https://www.gnu.org/licenses/gpl-3.0.html
14 */
15
16 if (!defined('ABSPATH')) { exit; }
17
18
19 /* ***************************************************************
20 PLUGIN DEFAULT SETTINGS
21 **************************************************************** */
22 function wdm_wpma_get_settings() {
23 $defaults = array(
24 'enabled' => '0',
25 'alert_enabled' => '0',
26 'email' => get_option('admin_email'),
27 'email_amount' => '10',
28 'queue_amount' => '1',
29 'queue_interval' => '5',
30 'clear_queue' => '14',
31 'tableName' => 'mail_queue',
32 );
33 $args = get_option('wdm_wpma_settings');
34 $options = wp_parse_args($args,$defaults);
35 $options['queue_interval'] = intval($options['queue_interval']) * 60;
36 $options['clear_queue'] = intval($options['clear_queue']) * 24;
37 return $options;
38 }
39
40
41
42
43
44 /* ***************************************************************
45 Overwrite wp_mail() if Plugin enabled and no Cron is running
46 **************************************************************** */
47 $wdm_wpma_mailid = 0;
48 $wdm_wpma_options = wdm_wpma_get_settings(); // Get Settings
49
50 if ($wdm_wpma_options['enabled'] == '1' && !defined( 'DOING_CRON' )) {
51
52 if ( !function_exists( 'wp_mail' ) ) {
53 function wp_mail ( $to, $subject, $message, $headers = '', $attachments = [] ) {
54
55 global $wpdb, $wdm_wpma_options;
56
57 // Write email in Queue
58 $tableName = $wpdb->prefix.$wdm_wpma_options['tableName'];
59 $data = array(
60 'timestamp'=> current_time('mysql',false),
61 'recipient'=> maybe_serialize($to),
62 'subject'=> $subject,
63 'message'=> $message,
64 'status' => 'queue',
65 'attachments' => ''
66 );
67 if (isset($headers) && $headers) { $data['headers'] = maybe_serialize($headers); }
68
69 // store attachments in /attachments/ Folder, to address them later
70 if (isset($attachments) && $attachments && $attachments != '') {
71
72 $subfolder = time().'-'.rand(0,999999);
73 $foldercreated = wp_mkdir_p(plugin_dir_path(__FILE__).'attachments/'.$subfolder);
74 if (!$foldercreated) {
75 error_log('Could not create Subfolder for Email attachment');
76 $data['info'] = 'Error: Could not store attachments';
77 } else {
78 if (!is_array($attachments)) { $attachments = array($attachments); }
79 $newattachments = array();
80 global $wp_filesystem;
81 if ( ! is_a( $wp_filesystem, 'WP_Filesystem_Base') ){
82 include_once(ABSPATH . 'wp-admin/includes/file.php');
83 WP_Filesystem();
84 }
85 foreach($attachments as $item) {
86 $newfile = plugin_dir_path(__FILE__).'attachments/'.$subfolder.'/'.basename($item);
87 $wp_filesystem->copy($item,$newfile);
88 array_push($newattachments,$newfile);
89 }
90 $data['attachments'] = maybe_serialize($newattachments);
91 }
92 }
93 $wpdb->insert($tableName,$data);
94
95 // Fake Submit by returning 'True'
96 return true;
97
98 }
99 }
100
101 }
102
103
104
105 // show wp_mail() errors
106 function wdm_wpma_mail_failed( $wp_error ) {
107 global $wpdb,$wdm_wpma_options,$wdm_wpma_mailid;
108 if (isset($wdm_wpma_mailid) && $wdm_wpma_mailid != 0) {
109 $tableName = $wpdb->prefix.$wdm_wpma_options['tableName'];
110 $wpMailFailedError = isset( $wp_error->errors ) && isset( $wp_error->errors['wp_mail_failed'][0] ) ? implode( '; ', $wp_error->errors['wp_mail_failed'] ) : '<em>Unknown</em>';
111 $wpdb->update($tableName,array('timestamp'=>current_time('mysql',false),'status'=>'error', 'info'=>$wpMailFailedError),array('id'=>intval($wdm_wpma_mailid)),array('%s', '%s', '%s'),'%d');
112 }
113 return error_log(print_r($wp_error, true));
114 }
115 add_action('wp_mail_failed','wdm_wpma_mail_failed',10,1);
116
117
118
119
120
121
122
123
124 /* ***************************************************************
125 CRON
126 **************************************************************** */
127 function wdm_wpma_search_mail_from_queue() {
128
129 global $wpdb,$wdm_wpma_options,$wdm_wpma_mailid;
130 if ($wdm_wpma_options['enabled'] != '1') { return; }
131 $tableName = $wpdb->prefix.$wdm_wpma_options['tableName'];
132
133 // Mails in Queue?
134 $mailjobs = $wpdb->get_results("SELECT * FROM `$tableName` WHERE `status` = 'queue' ORDER BY `id`",'ARRAY_A');
135 $mailsInQueue = is_array($mailjobs) ? count($mailjobs) : 0;
136
137 // Alert Admin, if too many mails in the Queue.
138 if ($wdm_wpma_options['alert_enabled'] == '1' && $mailsInQueue > intval($wdm_wpma_options['email_amount'])) {
139
140 // Last alerts older than 6 hours?
141 $alerts = $wpdb->get_results("SELECT * FROM `$tableName` WHERE `status` = 'alert' AND `timestamp` > NOW() - INTERVAL 6 HOUR",'ARRAY_A');
142
143 // If no alerts, then send one
144 if (!$alerts) {
145 $alertMessage = 'Hi,';
146 $alertMessage .= "\n\n";
147 $alertMessage .= 'this is an important message from your WordPress website '.esc_url(get_option('siteurl')).'.';
148 $alertMessage .= "\n";
149 $alertMessage .= "\n".'The Mail Queue Plugin has detected that your website tries to send more emails than expected.';
150 $alertMessage .= "\n".'Please take a close look at the email queue, because it contains more messages than the specified limit.';
151 $alertMessage .= "\n";
152 $alertMessage .= "\n".'In case this is the usual amount of emails, you can adjust the threshold for alerts in the settings of your Mail Queue Plugin.';
153 $alertMessage .= "\n\n";
154 $alertMessage .= "-- ";
155 $alertMessage .= "\n";
156 $alertMessage .= admin_url();
157 $alertSubject = '🔴 WordPress Mail Queue Alert - '.esc_html(get_option('blogname'));
158 $data = array(
159 'timestamp'=> current_time('mysql',false),
160 'recipient'=> sanitize_email($wdm_wpma_options['email']),
161 'subject' => $alertSubject,
162 'message' => $alertMessage,
163 'status' => 'alert',
164 'info' => json_encode([
165 'in_queue' => strval( $mailsInQueue ),
166 'email_amount' => intval($wdm_wpma_options['email_amount']),
167 'queue_amount' => intval($wdm_wpma_options['queue_amount']),
168 'queue_interval' => intval($wdm_wpma_options['queue_interval']),
169 ]),
170 );
171 $wpdb->insert($tableName,$data);
172 wp_mail($wdm_wpma_options['email'],$alertSubject,$alertMessage);
173 }
174
175 }
176
177 // Send Mails in Queue
178 if ($mailsInQueue > 0) {
179 $results = array_slice($mailjobs,0,intval($wdm_wpma_options['queue_amount']));
180 if ($results && count($results) > 0) {
181 foreach($results as $item) {
182 if ($item['recipient'] && $item['recipient'] != '') { $to = maybe_unserialize($item['recipient']); } else { $to = $wdm_wpma_options['email']; $item['subject'] = 'ERROR // '.$item['subject']; }
183 if ($item['headers'] && $item['headers'] != '') { $headers = maybe_unserialize($item['headers']); } else { $headers = ''; }
184 if ($item['attachments'] && $item['attachments'] != '') { $attachments = maybe_unserialize($item['attachments']); } else { $attachments = ''; }
185 $wdm_wpma_mailid = $item['id'];
186 $sendstatus = wp_mail($to,$item['subject'],$item['message'],$headers,$attachments); // Finally sends the email for real
187 if ($sendstatus) {
188 $wpdb->update($tableName,array('timestamp'=>current_time('mysql',false),'status'=>'sent'),array('id'=>$item['id']),'%s','%d');
189 }
190 if (is_array($attachments)) {
191 global $wp_filesystem;
192 if ( ! is_a( $wp_filesystem, 'WP_Filesystem_Base') ){
193 include_once(ABSPATH . 'wp-admin/includes/file.php');
194 WP_Filesystem();
195 }
196 $attachmentfolder = pathinfo($attachments[0]);
197 $wp_filesystem->delete($attachmentfolder['dirname'],true,'d');
198 }
199 }
200 }
201 }
202
203 // Delete old logs
204 $wpdb->query("DELETE FROM `$tableName` WHERE `status` != 'queue' AND `timestamp` < NOW() - INTERVAL ".esc_sql($wdm_wpma_options['clear_queue'])." HOUR");
205
206 }
207 add_action('wp_mail_queue_hook','wdm_wpma_search_mail_from_queue');
208
209 // Custom Cron Interval
210 function wdm_wpma_cron_interval( $schedules ) {
211 global $wdm_wpma_options;
212 $schedules['wdm_wpma_interval'] = array(
213 'interval' => $wdm_wpma_options['queue_interval'],
214 'display' => esc_html__('WP Mail Queue'), );
215 return $schedules;
216 }
217 add_filter('cron_schedules','wdm_wpma_cron_interval');
218
219 // Set or Remove Cron
220 $next_wpma_cron_timestamp = wp_next_scheduled('wp_mail_queue_hook');
221 if ($next_wpma_cron_timestamp && $wdm_wpma_options['enabled'] != '1') {
222 wp_unschedule_event($next_wpma_cron_timestamp,'wp_mail_queue_hook');
223 } else if (!$next_wpma_cron_timestamp && $wdm_wpma_options['enabled'] == '1') {
224 wp_schedule_event(time(),'wdm_wpma_interval','wp_mail_queue_hook');
225 }
226
227
228
229 /* ***************************************************************
230 Install/Uninstall
231 **************************************************************** */
232
233
234 /* Delete plugin options and database table */
235 function wdm_wpma_uninstall () {
236 global $wpdb;
237
238 $optionName = 'wdm_wpma_settings';
239 delete_option( $optionName );
240
241 $tableName = $wpdb->prefix.'mail_queue';
242 $wpdb->query( "DROP TABLE IF EXISTS $tableName" );
243 }
244
245 /* Create MySQL Table on Activation: https://codex.wordpress.org/Creating_Tables_with_Plugins */
246 function wdm_wpma_installDatabaseTables() {
247 global $wpdb;
248
249 $tableName = $wpdb->prefix.'mail_queue';
250
251 $charset_collate = $wpdb->get_charset_collate();
252
253 $sql = "CREATE TABLE $tableName (
254 id mediumint(9) NOT NULL AUTO_INCREMENT,
255 timestamp TIMESTAMP NOT NULL,
256 status varchar(55) DEFAULT '' NOT NULL,
257 recipient varchar(255) DEFAULT '' NOT NULL,
258 subject varchar(255) DEFAULT '' NOT NULL,
259 message text NOT NULL,
260 headers text NOT NULL,
261 attachments text NOT NULL,
262 info varchar(255) DEFAULT '' NOT NULL,
263 PRIMARY KEY (id)
264 ) $charset_collate;";
265
266 require_once( ABSPATH . 'wp-admin/includes/upgrade.php' );
267 dbDelta( $sql );
268
269 register_uninstall_hook( __FILE__, 'wdm_wpma_uninstall' );
270 }
271 register_activation_hook( __FILE__, 'wdm_wpma_installDatabaseTables' );
272
273
274 /* ***************************************************************
275 Options Page
276 **************************************************************** */
277 if (is_admin()) {
278 require_once( plugin_dir_path( __FILE__ ) . 'mail-queue-options.php' );
279 }
280