Settings', 'Log', 'Queue', 'FAQs', ); return array_merge($actions,$links ); } add_filter('plugin_action_links_mail-queue/mail-queue.php','wdm_wpma_actionlinks'); // Options Page function wdm_wpma_settings_page_menuitem() { add_menu_page('Mail Queue','Mail Queue','manage_options','wdm_wpma_mail_queue','wdm_wpma_settings_page','data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTc4IiBoZWlnaHQ9IjE3OCIgdmlld0JveD0iMCAwIDE3OCAxNzgiIGZpbGw9Im5vbmUiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+CjxwYXRoIGZpbGwtcnVsZT0iZXZlbm9kZCIgY2xpcC1ydWxlPSJldmVub2RkIiBkPSJNNzguNzI0MSA1LjI1MzA5Qzc2LjkwNzQgNC43MDgxIDc0Ljk0MDEgNS4wNTQxMyA3My40MTg0IDYuMTg2MjlDNzEuODk2OCA3LjMxODQ1IDcxIDkuMTAzNDEgNzEgMTEuMDAwMVYxNjdDNzEgMTY4Ljg5NyA3MS44OTY4IDE3MC42ODIgNzMuNDE4NCAxNzEuODE0Qzc0Ljk0MDEgMTcyLjk0NiA3Ni45MDc0IDE3My4yOTIgNzguNzI0MSAxNzIuNzQ3TDE1OC43MjQgMTQ4Ljc0N0MxNjEuMjYyIDE0Ny45ODYgMTYzIDE0NS42NSAxNjMgMTQzVjM1QzE2MyAzMi4zNTA0IDE2MS4yNjIgMzAuMDE0NSAxNTguNzI0IDI5LjI1MzFMNzguNzI0MSA1LjI1MzA5Wk04NS43ODg3IDIyLjM4NDZDODcuNzg1NCAyMS40Mzk0IDkwLjE3MDMgMjIuMjkxOSA5MS4xMTU0IDI0LjI4ODdMMTIyLjg1MiA5MS4zMzc4TDE0My4zMzQgNDQuNDAwMkMxNDQuMjE3IDQyLjM3NTUgMTQ2LjU3NSA0MS40NTAzIDE0OC42IDQyLjMzMzhDMTUwLjYyNSA0My4yMTc0IDE1MS41NSA0NS41NzUgMTUwLjY2NiA0Ny41OTk4TDEyNi42NjYgMTAyLjZDMTI2LjAzOSAxMDQuMDM3IDEyNC42MjkgMTA0Ljk3NiAxMjMuMDYxIDEwNUMxMjEuNDkzIDEwNS4wMjQgMTIwLjA1NiAxMDQuMTI5IDExOS4zODUgMTAyLjcxMUw4My44ODQ2IDI3LjcxMTNDODIuOTM5NCAyNS43MTQ2IDgzLjc5MTkgMjMuMzI5NyA4NS43ODg3IDIyLjM4NDZaIiBmaWxsPSIjYTdhYWFkIi8+CjxwYXRoIGQ9Ik00OSAxM0M1Mi4zMTM3IDEzIDU1IDE1LjY4NjMgNTUgMTlWMTU5QzU1IDE2Mi4zMTQgNTIuMzEzNyAxNjUgNDkgMTY1QzQ1LjY4NjMgMTY1IDQzIDE2Mi4zMTQgNDMgMTU5VjE5QzQzIDE1LjY4NjMgNDUuNjg2MyAxMyA0OSAxM1oiIGZpbGw9IiNhN2FhYWQiLz4KPHBhdGggZD0iTTIxIDIxQzI0LjMxMzcgMjEgMjcgMjMuNjg2MyAyNyAyN1YxNTFDMjcgMTU0LjMxNCAyNC4zMTM3IDE1NyAyMSAxNTdDMTcuNjg2MyAxNTcgMTUgMTU0LjMxNCAxNSAxNTFWMjdDMTUgMjMuNjg2MyAxNy42ODYzIDIxIDIxIDIxWiIgZmlsbD0iI2E3YWFhZCIvPgo8L3N2Zz4='); add_submenu_page('wdm_wpma_mail_queue','Settings','Settings','manage_options','wdm_wpma_mail_queue','wdm_wpma_settings_page'); add_submenu_page('wdm_wpma_mail_queue','Log','Log','manage_options','wdm_wpma_mail_queue-tab-log','wdm_wpma_settings_page'); add_submenu_page('wdm_wpma_mail_queue','Queue','Queue','manage_options','wdm_wpma_mail_queue-tab-queue','wdm_wpma_settings_page'); add_submenu_page('wdm_wpma_mail_queue','FAQ','FAQ','manage_options','wdm_wpma_mail_queue-tab-faq','wdm_wpma_settings_page'); if (defined('DISABLE_WP_CRON') && DISABLE_WP_CRON) { add_submenu_page('wdm_wpma_mail_queue','Cron Information','Cron Information','manage_options','wdm_wpma_mail_queue-tab-croninfo','wdm_wpma_settings_page'); } } add_action('admin_menu','wdm_wpma_settings_page_menuitem'); function wdm_wpma_settings_page_assets () { $screen = get_current_screen(); if ( preg_match( '#wdm_wpma_mail_queue#', $screen->base ) ) { wp_enqueue_style( 'wdm_wpma_style', plugins_url( 'assets/css/admin.css', __FILE__ ) ); wp_enqueue_script( 'wdm_wpma_script', plugins_url( 'assets/js/wdm-wpma-admin.js', __FILE__ ), [ 'jquery' ], false, true ); } } add_action( 'admin_enqueue_scripts', 'wdm_wpma_settings_page_assets' ); // Options Page Settings function wdm_wpma_settings_page() { // Only Admins if ( ! current_user_can( 'manage_options' ) ) { return; } // Settings global $wdm_wpma_options; // Get the active tab from the $_GET param $default_tab = null; $tab = isset($_GET['tab']) ? sanitize_key($_GET['tab']) : $default_tab; echo '
'; // Options Header echo '

'; $tab = sanitize_key($_GET['page']); if ($tab != 'wdm_wpma_mail_queue-tab-croninfo' ) { if (defined('DISABLE_WP_CRON') && DISABLE_WP_CRON) { echo '
'; $url = esc_url(get_option('siteurl').'/wp-cron.php'); echo '

Please note:
Your normal WP Cron is disabled. Please make sure you\'re running the Cron manually by calling '.$url.' every couple of minutes.

'; echo '

More information

'; echo '
'; } } wdm_wpma_settings_page_navi($tab); // Tabs // Options Page Content if ($tab == 'wdm_wpma_mail_queue') { echo '
'; settings_fields('wdm_wpma_settings'); do_settings_sections('wdm_wpma_settings_page'); submit_button(); echo '
'; } else if ($tab == 'wdm_wpma_mail_queue-tab-log') { echo '
'; $logtable = new wdm_wpma_Log_Table(); $logtable->prepare_items(); $logtable->display(); echo '
'; } else if ($tab == 'wdm_wpma_mail_queue-tab-queue') { if (isset($_GET['addtestmail'])) { global $wpdb; $tableName = $wpdb->prefix.$wdm_wpma_options['tableName']; $data = array( 'timestamp'=>current_time('mysql',false), 'recipient'=>$wdm_wpma_options['email'], 'subject'=>'Testmail #'.time(), 'message'=>'This is just a test email send by the Mail Queue plugin.', 'status' => 'queue' ); $wpdb->insert($tableName,$data); } $next_cron_timestamp = wp_next_scheduled('wp_mail_queue_hook'); if ($next_cron_timestamp) { if ($next_cron_timestamp > time()) { echo '

Next Sending will be triggered in '.esc_html(human_time_diff($next_cron_timestamp)).' at '.esc_html(wp_date('H:i',$next_cron_timestamp)).'.

'; } } else { echo '

The Queue is not enabled at the moment. Enable it in the Settings.

'; } echo '
'; $queuetable = new wdm_wpma_Log_Table(); $queuetable->prepare_items(); $queuetable->display(); echo '
'; } else if ($tab == 'wdm_wpma_mail_queue-tab-faq') { echo '
'; echo '

How does this Plugin work?

'; echo '

If enabled this plugin intercepts the wp_mail() function. Instead of sending the mails directly, it stores them in the database and sends them step by step with a delay during the WP Cron.

'; echo '

Current state: '; if ($wdm_wpma_options['enabled'] == '1') { echo 'The plugin is enabled All Mails sent through wp_mail() are delayed by the Queue.'; } else { echo 'The plugin is disabled. The plugin has no impact at the moment, no Mails inside the Queue are going to be sent.'; } echo '

'; echo '
'; echo '
'; echo '

Does this plugin change the way HOW emails are sent?

'; echo '

No, don\'t worry. This plugin only affects WHEN emails are sent, not how. It delays the sending (by the Queue), nonetheless all emails are sent through the standard wp_mail() function.

'; echo '

If you use SMTP for sending, or an external service like Mailgun, everything will still work as expected.

'; echo '
'; echo '
'; echo '

Does this plugin work, if I have a Caching Plugin installed? E.g. W3 Total Cache or similar?

'; echo '

If you\'re using a Caching plugin like W3 Total Cache, WP Rocket or any other caching solution which generates static html-files and serves them to visitors, you\'ll have to make sure you\'re calling the wp-cron file manually every couple of minutes.

'; echo '

Otherwise your normal WP Cron wouldn\'t be called as often as it should be and scheduled messages would be sent with big delays.

'; echo '
'; echo '
'; echo '

What about Proxy-Caching, e.g. NGINX?

'; echo '

Same situation here. Please make sure you\'re calling the WordPress Cron by an external service or your webhoster every couple of minutes.

'; echo '
'; echo '
'; echo '

My form builder supports attachments. What about them?

'; echo '

You are covered. All attachments are stored temporarily in the queue until they are sent along with their corresponding emails.

'; echo '
'; echo '
'; echo '

What are Queue alerts?

'; echo '

This is a simple and effective way to improve the security of your WordPress installation.

Imagine: In case your website is sending spam through wp_mail(), the email Queue would fill up very quickly preventing your website from sending so many spam emails at once. This gives you time and avoids a lot of trouble.

Queue Alerts warn you, if the Queue is longer than usal. You decide at which point you want to be alerted. So you get the chance to have a look if there might be something wrong on the website.

'; echo '

Current state: '; if ($wdm_wpma_options['alert_enabled'] == '1') { echo 'Alerts are enabled If more than '.esc_html($wdm_wpma_options['email_amount']).' emails are waiting in the Queue, WordPress will sent an alert email to '.esc_html($wdm_wpma_options['email']).'.'; } else { echo 'Alerting is disabled. No alerts will be sent.'; } echo '

'; echo '

Please note: This plugin will only send one alert every six hours.

'; echo '
'; echo '
'; echo '

Want to put a test email into the Queue?

'; echo '

Sure! Put a Test Email for '.esc_html($wdm_wpma_options['email']).' into the Queue

'; echo '
'; } else if ($tab == 'wdm_wpma_mail_queue-tab-croninfo') { echo '
'; echo '

Information: Your common WP Cron is disabled

'; echo '

It look\'s like you deactived the WP Cron by define( \' DISABLE_WP_CRON \' , true ).

'; $url = esc_url(get_option('siteurl').'/wp-cron.php'); echo '

In general, this is no problem at all. We just want to remind you to make sure you\'re running the Cron manually by calling '.$url.' every couple of minutes.

'; echo '
'; if (function_exists('_get_cron_array')) { $next_tasks = _get_cron_array(); if ($next_tasks) { $tasks_in_past = false; $tasks_of_mailqueue_in_past = false; foreach($next_tasks as $key => $val) { if (time() > intval($key) + intval($wdm_wpma_options['queue_interval'])) { if (array_keys($val)[0] == 'wp_mail_queue_hook') { $tasks_of_mailqueue_in_past = intval($key); } $tasks_in_past = true; } } if ($tasks_in_past) { echo '
'; echo '

Attention: It seams that your WP Cron is not running. There are some jobs waiting to be completed.

'; if ($tasks_of_mailqueue_in_past) { echo '

The Queue wasn\'t been able to be executed since '.esc_html(human_time_diff($tasks_of_mailqueue_in_past,time())).'.

'; } echo '
'; } } } } echo '
'; } if(!class_exists('WP_List_Table')){ require_once( ABSPATH . 'wp-admin/includes/screen.php' ); require_once( ABSPATH . 'wp-admin/includes/class-wp-list-table.php' ); } class wdm_wpma_Log_Table extends WP_List_Table { function get_log() { global $wpdb, $wdm_wpma_options; $tableName = $wpdb->prefix.$wdm_wpma_options['tableName']; return $wpdb->get_results("SELECT * FROM `$tableName` WHERE `status` != 'queue' ORDER BY `timestamp` DESC",'ARRAY_A'); } function get_queue() { global $wpdb, $wdm_wpma_options; $tableName = $wpdb->prefix.$wdm_wpma_options['tableName']; return $wpdb->get_results("SELECT * FROM `$tableName` WHERE `status` = 'queue' ORDER BY `timestamp`",'ARRAY_A'); } function get_columns() { $columns = array( 'id' => '', 'timestamp' => 'Time', 'status' => 'Status', 'recipient' => 'Recipient', 'subject' => 'Subject', 'message' => 'Message', 'headers' => 'Headers', 'attachments' => 'Attachments', ); return $columns; } public function prepare_items() { $type = sanitize_key($_GET['page']); $columns = $this->get_columns(); $hidden = array(); $sortable = array(); $this->_column_headers = array($columns, $hidden, $sortable); $this->process_bulk_action(); if ($type == 'wdm_wpma_mail_queue-tab-log') { $data = $this->get_log(); } else if ($type == 'wdm_wpma_mail_queue-tab-queue') { $data = $this->get_queue(); } if ($data && is_array($data)) { $perPage = 50; $currentPage = $this->get_pagenum(); $totalItems = count($data); $this->set_pagination_args( array( 'total_items' => $totalItems, 'per_page' => $perPage ) ); $data = array_slice($data,(($currentPage-1)*$perPage),$perPage); } $this->items = $data; } public function column_default( $item, $column_name ) { switch( $column_name ) { case 'timestamp': case 'subject': case 'info': return esc_html( maybe_unserialize($item[$column_name]) ); break; case 'recipient': case 'headers': $return = maybe_unserialize($item[$column_name]); if (is_array($return)) { return esc_html( implode(',',$return) ); } else { return esc_html( $return ); } break; case 'attachments': $return = maybe_unserialize($item[$column_name]); //var_dump($return); if (is_array($return)) { $betterreturn = array(); foreach($return as $item) { array_push($betterreturn,basename($item)); } return esc_html( implode('
',$betterreturn) ); } else { return esc_html( basename($return) ); } break; case 'status': $info = isset( $item[ 'info' ] ) && $item[ 'info' ] ? $item[ 'info' ] : ''; if ( $item[$column_name] === 'alert' ) { $alertData = json_decode($info,/*associative*/true); if ( $alertData ) { $info = 'Emails in queue: '.esc_html($alertData['in_queue']); $info .= '
Queue settings: Send max '.esc_html($alertData['queue_amount']).' email(s) every '.esc_html($alertData['queue_interval']/60).' minute(s).'; $info .= '
Alert settings: Send alert if more than '.esc_html($alertData['email_amount']).' email(s) in the queue.'; } else { $info = ''; } } $htmlInfo = $info ? ''.$info.'' : ''; $cssStatus = $htmlInfo ? ' wdm-wpma-status-has-info' : ''; return ''.$item[$column_name].$htmlInfo.''; break; case 'message': $message = $item[$column_name]; if ( $message ) { $messageLen = strlen($message); $message = htmlentities($message); $message = preg_replace('#^(.*<body>)(\r?\n)?#ims', '
HEADER$1
', $message ); $message = preg_replace('#(</body>.*)$#ims', '
FOOTER$1
', $message); $message = preg_replace('#(.*)#ims', '$1', $message); $message = preg_replace('#\r?\n#', '
', $message); $return = '
'; $return .= 'View message ('.esc_html($messageLen).' bytes)'; $return .= '
'.wp_kses_post($message).'
'; $return .= '
'; } else { $return = 'Empty'; } return $return; break; case 'id': return ''; break; default: return print_r( $item, true ) ; //Show the whole array for troubleshooting purposes } } public function get_bulk_actions() { if (isset($_GET['page']) && $_GET['page'] == 'wdm_wpma_mail_queue-tab-queue') { $actions = array( 'delete' => __( 'Delete') ); } else { $actions = array( 'delete' => __( 'Delete'), 'resend' => __( 'Resend'), ); } return $actions; } public function process_bulk_action() { // security check! if ( isset( $_POST['_wpnonce'] ) && ! empty( $_POST['_wpnonce'] ) ) { $nonce = filter_input( INPUT_POST, '_wpnonce', FILTER_SANITIZE_STRING ); $action = 'bulk-' . $this->_args['plural']; if ( ! wp_verify_nonce( $nonce, $action ) ) wp_die( 'Nope! Security check failed!' ); } // get IDs $request_ids = isset( $_REQUEST['id'] ) ? wp_parse_id_list( wp_unslash( $_REQUEST['id'] ) ) : array(); if ( empty( $request_ids ) ) { return; } global $wpdb, $wdm_wpma_options; $tableName = $wpdb->prefix.$wdm_wpma_options['tableName']; switch ( $this->current_action() ) { case 'delete': foreach($request_ids as $id) { $wpdb->delete($tableName,array('id'=>intval($id)),'%d'); } break; case 'resend': foreach($request_ids as $id) { $count_resend = 0; $count_error = 0; $maildata = $wpdb->get_row("SELECT * FROM `$tableName` WHERE `id` = '$id'"); if (!$maildata->attachments || $maildata->attachments == '') { $count_resend++; $data = array( 'timestamp'=> current_time('mysql',false), 'recipient'=> $maildata->recipient, 'subject'=> $maildata->subject, 'message'=> $maildata->message, 'status' => 'queue', 'attachments' => '', 'headers' => $maildata->headers, ); $wpdb->insert($tableName,$data); } else { $count_error++; $notice = '
'; $notice .= '

Sorry, your email to '.$maildata->recipient.' can\'t be sent again.

'; $notice .= '

The email used to have attachments, which are not available anymore. Only emails without attachments can be resend.

'; $notice .= '
'; echo $notice; } } if ($count_error == 0 && $count_resend > 0) { wp_redirect('admin.php?page=wdm_wpma_mail_queue-tab-queue'); exit; } else if ($count_error > 0 && $count_resend > 0) { $notice = '
'; $notice .= '

The other emails have been put again into the Queue.

'; $notice .= '
'; echo $notice; } break; } return; } } function wdm_wpma_settings_page_navi($tab) { echo ''; } function wdm_wpma_settings_init() { global $wdm_wpma_options; register_setting('wdm_wpma_settings','wdm_wpma_settings'); add_settings_section('wdm_wpma_settings_section','',null,'wdm_wpma_settings_page'); add_settings_field('wdm_wpma_status','Queue + Log enabled','wdm_wpma_render_option_status','wdm_wpma_settings_page','wdm_wpma_settings_section'); add_settings_field('wdm_wpma_queue','Queue','wdm_wpma_render_option_queue','wdm_wpma_settings_page','wdm_wpma_settings_section'); add_settings_field('wdm_wpma_log','Log','wdm_wpma_render_option_log','wdm_wpma_settings_page','wdm_wpma_settings_section'); add_settings_field('wdm_wpma_alert_status','Alert enabled','wdm_wpma_render_option_alert_status','wdm_wpma_settings_page','wdm_wpma_settings_section'); add_settings_field('wdm_wpma_sensitivity','Alert Sensitivity','wdm_wpma_render_option_sensitivity','wdm_wpma_settings_page','wdm_wpma_settings_section'); } add_action('admin_init','wdm_wpma_settings_init'); function wdm_wpma_render_option_status() { global $wdm_wpma_options; if ($wdm_wpma_options['enabled'] == '1') { echo ''; } else { echo '     ← Check this to enable the Queue. Otherwise this plugin won\'t have any effect on your website.'; } } function wdm_wpma_render_option_alert_status() { global $wdm_wpma_options; if ($wdm_wpma_options['alert_enabled'] == '1') { echo ''; } else { echo ''; } } function wdm_wpma_render_option_queue() { global $wdm_wpma_options; echo 'Send max. email(s) every minute(s) by WP Cron. '; } function wdm_wpma_render_option_log() { global $wdm_wpma_options; echo 'Delete Log entries older than days.'; } function wdm_wpma_render_option_sensitivity() { global $wdm_wpma_options; echo 'Send alert to if more than email(s) in the Queue.'; } /* *************************************************************** Alert WordPress User if last email in log could not be sent **************************************************************** */ function wdm_wpma_checkLogForErrors() { global $wpdb,$wdm_wpma_options; if ($wdm_wpma_options['enabled'] != '1') { return; } $tableName = $wpdb->prefix.$wdm_wpma_options['tableName']; $last_mail = $wpdb->get_row("SELECT * FROM `$tableName` WHERE `status` != 'queue' ORDER BY `id` DESC",'ARRAY_A'); if (!$last_mail) { return; } if ($last_mail['status'] == 'error') { if (current_user_can('manage_options')) { $notice = '
'; $notice .= '

Attention: Your website has problems sending e-mails

'; $notice .= '

This is an important message from your Mail Queue plugin. Please take a look at your Mail Log. The last email(s) couldn\'t be sent properly.

'; $notice .= '

Last error message was: '.$last_mail['info'].'

'; $notice .= '
'; echo $notice; } else if (current_user_can('edit_posts')) { $notice = '
'; $notice .= '

Attention: Your website has problems sending e-mails

'; $notice .= '

Please contact your Administrator. It seems that WordPress is not able to send emails.

'; $notice .= '

Last error message: '.$last_mail['info'].'

'; $notice .= '
'; echo $notice; } } } add_action('admin_notices', 'wdm_wpma_checkLogForErrors');