v2.2.7
This commit is contained in:
parent
64b13fe7aa
commit
fd33d35baf
5 changed files with 100 additions and 82 deletions
|
|
@ -1,3 +1,10 @@
|
||||||
|
= 2.2.7 =
|
||||||
|
|
||||||
|
* IMPROVED: Worker now runs as a continuous loop, draining the queue completely before exiting
|
||||||
|
* IMPROVED: Statistics are synced after each batch (not only at the end)
|
||||||
|
* IMPROVED: Worker output includes worker ID on each line for clearer parallel logs
|
||||||
|
* FIXED: Uneven work distribution between parallel workers
|
||||||
|
|
||||||
= 2.2.6 =
|
= 2.2.6 =
|
||||||
|
|
||||||
* CRITICAL FIX: Worker now suppresses plugin header warnings in MultiSite environments
|
* CRITICAL FIX: Worker now suppresses plugin header warnings in MultiSite environments
|
||||||
|
|
|
||||||
11
readme.txt
11
readme.txt
|
|
@ -4,7 +4,7 @@ Tags: newsletter, smtp, email, bulk, queue, worker, amazonses, statistics
|
||||||
Requires at least: 4.7
|
Requires at least: 4.7
|
||||||
Tested up to: 6.9
|
Tested up to: 6.9
|
||||||
Requires PHP: 7.2
|
Requires PHP: 7.2
|
||||||
Stable tag: 2.2.6
|
Stable tag: 2.2.7
|
||||||
License: GPLv2 or later
|
License: GPLv2 or later
|
||||||
License URI: https://www.gnu.org/licenses/gpl-2.0.html
|
License URI: https://www.gnu.org/licenses/gpl-2.0.html
|
||||||
|
|
||||||
|
|
@ -141,6 +141,12 @@ Yes. The plugin integrates with ROBOTSTXT SMTP rate limiting system to ensure yo
|
||||||
|
|
||||||
== Changelog ==
|
== Changelog ==
|
||||||
|
|
||||||
|
= 2.2.7 =
|
||||||
|
* IMPROVED: Worker now runs as a continuous loop, draining the queue completely before exiting
|
||||||
|
* IMPROVED: Statistics are synced after each batch
|
||||||
|
* IMPROVED: Worker output includes worker ID on each line for clearer parallel logs
|
||||||
|
* FIXED: Uneven work distribution between parallel workers
|
||||||
|
|
||||||
= 2.2.6 =
|
= 2.2.6 =
|
||||||
* CRITICAL FIX: Worker now suppresses plugin header warnings in MultiSite environments
|
* CRITICAL FIX: Worker now suppresses plugin header warnings in MultiSite environments
|
||||||
* CRITICAL FIX: Fixed Newsletter base class dependencies not loading in DOING_CRON context
|
* CRITICAL FIX: Fixed Newsletter base class dependencies not loading in DOING_CRON context
|
||||||
|
|
@ -208,6 +214,9 @@ Yes. The plugin integrates with ROBOTSTXT SMTP rate limiting system to ensure yo
|
||||||
|
|
||||||
== Upgrade Notice ==
|
== Upgrade Notice ==
|
||||||
|
|
||||||
|
= 2.2.7 =
|
||||||
|
Workers now drain the full queue per invocation. Recommended upgrade for better parallel distribution.
|
||||||
|
|
||||||
= 2.2.6 =
|
= 2.2.6 =
|
||||||
CRITICAL: Fixed multiple worker issues in MultiSite environments including header warnings, class loading, and subdirectory site detection. Essential for reliable worker operation.
|
CRITICAL: Fixed multiple worker issues in MultiSite environments including header warnings, class loading, and subdirectory site detection. Essential for reliable worker operation.
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,7 @@
|
||||||
* Plugin Name: Newsletter - SMTP (by ROBOTSTXT)
|
* Plugin Name: Newsletter - SMTP (by ROBOTSTXT)
|
||||||
* Plugin URI: https://git.robotstxt.es/ROBOTSTXT/robotstxt-smtp-newsletter
|
* Plugin URI: https://git.robotstxt.es/ROBOTSTXT/robotstxt-smtp-newsletter
|
||||||
* Description: Integrates ROBOTSTXT SMTP configuration with Newsletter plugin for efficient bulk email delivery with database-backed queue and external workers.
|
* Description: Integrates ROBOTSTXT SMTP configuration with Newsletter plugin for efficient bulk email delivery with database-backed queue and external workers.
|
||||||
* Version: 2.2.6
|
* Version: 2.2.7
|
||||||
* Requires at least: 4.7
|
* Requires at least: 4.7
|
||||||
* Requires PHP: 7.2
|
* Requires PHP: 7.2
|
||||||
* Security: robotstxt@robotstxt.es
|
* Security: robotstxt@robotstxt.es
|
||||||
|
|
@ -25,7 +25,7 @@ if ( ! defined( 'ABSPATH' ) ) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Plugin constants.
|
// Plugin constants.
|
||||||
define( 'ROBOTSTXT_SMTP_NEWSLETTER_VERSION', '2.2.6' );
|
define( 'ROBOTSTXT_SMTP_NEWSLETTER_VERSION', '2.2.7' );
|
||||||
define( 'ROBOTSTXT_SMTP_NEWSLETTER_FILE', __FILE__ );
|
define( 'ROBOTSTXT_SMTP_NEWSLETTER_FILE', __FILE__ );
|
||||||
define( 'ROBOTSTXT_SMTP_NEWSLETTER_PATH', plugin_dir_path( __FILE__ ) );
|
define( 'ROBOTSTXT_SMTP_NEWSLETTER_PATH', plugin_dir_path( __FILE__ ) );
|
||||||
define( 'ROBOTSTXT_SMTP_NEWSLETTER_URL', plugin_dir_url( __FILE__ ) );
|
define( 'ROBOTSTXT_SMTP_NEWSLETTER_URL', plugin_dir_url( __FILE__ ) );
|
||||||
|
|
|
||||||
14
update.json
14
update.json
File diff suppressed because one or more lines are too long
150
worker.php
150
worker.php
|
|
@ -130,92 +130,94 @@ if ( $plugin_manually_loaded ) {
|
||||||
$queue = \Robotstxt_SMTP_Newsletter\Queue::get_instance();
|
$queue = \Robotstxt_SMTP_Newsletter\Queue::get_instance();
|
||||||
$stats = \Robotstxt_SMTP_Newsletter\Statistics::get_instance();
|
$stats = \Robotstxt_SMTP_Newsletter\Statistics::get_instance();
|
||||||
|
|
||||||
// Process batch.
|
$total_success = 0;
|
||||||
$items = $queue->get_and_lock_batch( $batch_size, $worker_id );
|
$total_failure = 0;
|
||||||
|
|
||||||
if ( empty( $items ) ) {
|
// Continuous loop: keep processing batches until the queue is empty.
|
||||||
echo "No items to process\n";
|
while ( true ) {
|
||||||
exit( 0 );
|
$items = $queue->get_and_lock_batch( $batch_size, $worker_id );
|
||||||
}
|
|
||||||
|
|
||||||
echo sprintf( "Worker %s: Processing %d emails...\n", $worker_id, count( $items ) );
|
if ( empty( $items ) ) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
$success_count = 0;
|
foreach ( $items as $item ) {
|
||||||
$failure_count = 0;
|
try {
|
||||||
|
// Build headers array.
|
||||||
|
$headers = array();
|
||||||
|
|
||||||
foreach ( $items as $item ) {
|
// Add From header if specified.
|
||||||
try {
|
if ( ! empty( $item->from_email ) ) {
|
||||||
// Build headers array.
|
$from = ! empty( $item->from_name )
|
||||||
$headers = array();
|
? sprintf( '%s <%s>', $item->from_name, $item->from_email )
|
||||||
|
: $item->from_email;
|
||||||
|
$headers[] = 'From: ' . $from;
|
||||||
|
}
|
||||||
|
|
||||||
// Add From header if specified.
|
// Add Reply-To header if specified.
|
||||||
if ( ! empty( $item->from_email ) ) {
|
if ( ! empty( $item->reply_to ) ) {
|
||||||
$from = ! empty( $item->from_name )
|
$headers[] = 'Reply-To: ' . $item->reply_to;
|
||||||
? sprintf( '%s <%s>', $item->from_name, $item->from_email )
|
}
|
||||||
: $item->from_email;
|
|
||||||
$headers[] = 'From: ' . $from;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Add Reply-To header if specified.
|
// Add Content-Type header (prefer HTML if available).
|
||||||
if ( ! empty( $item->reply_to ) ) {
|
if ( ! empty( $item->body_html ) ) {
|
||||||
$headers[] = 'Reply-To: ' . $item->reply_to;
|
$headers[] = 'Content-Type: text/html; charset=UTF-8';
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add Content-Type header (prefer HTML if available).
|
// Decode and add custom headers from JSON.
|
||||||
if ( ! empty( $item->body_html ) ) {
|
if ( ! empty( $item->headers_json ) ) {
|
||||||
$headers[] = 'Content-Type: text/html; charset=UTF-8';
|
$custom = json_decode( $item->headers_json, true );
|
||||||
}
|
if ( is_array( $custom ) ) {
|
||||||
|
foreach ( $custom as $key => $value ) {
|
||||||
// Decode and add custom headers from JSON.
|
$headers[] = sprintf( '%s: %s', $key, $value );
|
||||||
if ( ! empty( $item->headers_json ) ) {
|
}
|
||||||
$custom = json_decode( $item->headers_json, true );
|
|
||||||
if ( is_array( $custom ) ) {
|
|
||||||
foreach ( $custom as $key => $value ) {
|
|
||||||
$headers[] = sprintf( '%s: %s', $key, $value );
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Select body (prefer HTML over text).
|
||||||
|
$body = ! empty( $item->body_html ) ? $item->body_html : $item->body_text;
|
||||||
|
|
||||||
|
if ( empty( $body ) ) {
|
||||||
|
throw new \Exception( 'Email body is empty' );
|
||||||
|
}
|
||||||
|
|
||||||
|
// Send via wp_mail (uses core SMTP configuration).
|
||||||
|
$result = wp_mail(
|
||||||
|
$item->to_email,
|
||||||
|
$item->subject,
|
||||||
|
$body,
|
||||||
|
$headers
|
||||||
|
);
|
||||||
|
|
||||||
|
if ( $result ) {
|
||||||
|
$queue->mark_sent( $item->id );
|
||||||
|
$total_success++;
|
||||||
|
echo sprintf( " ✓ [%s] Sent: %s\n", $worker_id, $item->to_email );
|
||||||
|
} else {
|
||||||
|
$queue->mark_failed( $item->id, 'wp_mail returned false' );
|
||||||
|
$total_failure++;
|
||||||
|
echo sprintf( " ✗ [%s] Failed: %s (wp_mail returned false)\n", $worker_id, $item->to_email );
|
||||||
|
}
|
||||||
|
} catch ( \Exception $e ) {
|
||||||
|
$queue->mark_failed( $item->id, $e->getMessage() );
|
||||||
|
$total_failure++;
|
||||||
|
echo sprintf( " ✗ [%s] Error: %s - %s\n", $worker_id, $item->to_email, $e->getMessage() );
|
||||||
}
|
}
|
||||||
|
|
||||||
// Select body (prefer HTML over text).
|
|
||||||
$body = ! empty( $item->body_html ) ? $item->body_html : $item->body_text;
|
|
||||||
|
|
||||||
if ( empty( $body ) ) {
|
|
||||||
throw new \Exception( 'Email body is empty' );
|
|
||||||
}
|
|
||||||
|
|
||||||
// Send via wp_mail (uses core SMTP configuration).
|
|
||||||
$result = wp_mail(
|
|
||||||
$item->to_email,
|
|
||||||
$item->subject,
|
|
||||||
$body,
|
|
||||||
$headers
|
|
||||||
);
|
|
||||||
|
|
||||||
if ( $result ) {
|
|
||||||
$queue->mark_sent( $item->id );
|
|
||||||
$success_count++;
|
|
||||||
echo sprintf( " ✓ Sent: %s\n", $item->to_email );
|
|
||||||
} else {
|
|
||||||
$queue->mark_failed( $item->id, 'wp_mail returned false' );
|
|
||||||
$failure_count++;
|
|
||||||
echo sprintf( " ✗ Failed: %s (wp_mail returned false)\n", $item->to_email );
|
|
||||||
}
|
|
||||||
|
|
||||||
} catch ( \Exception $e ) {
|
|
||||||
$queue->mark_failed( $item->id, $e->getMessage() );
|
|
||||||
$failure_count++;
|
|
||||||
echo sprintf( " ✗ Error: %s - %s\n", $item->to_email, $e->getMessage() );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Sync statistics after each batch.
|
||||||
|
$stats->sync_from_queue();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Sync statistics after batch processing.
|
if ( 0 === $total_success && 0 === $total_failure ) {
|
||||||
$stats->sync_from_queue();
|
echo sprintf( "Worker %s: No items to process\n", $worker_id );
|
||||||
|
} else {
|
||||||
echo sprintf(
|
echo sprintf(
|
||||||
"Worker %s: Done. Success: %d, Failed: %d\n",
|
"Worker %s: Done. Success: %d, Failed: %d\n",
|
||||||
$worker_id,
|
$worker_id,
|
||||||
$success_count,
|
$total_success,
|
||||||
$failure_count
|
$total_failure
|
||||||
);
|
);
|
||||||
|
}
|
||||||
|
|
||||||
exit( 0 );
|
exit( 0 );
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue