Skip to content

Send errors to admins via email (if possible) #11841

@benbowler

Description

@benbowler

Feature Description

Update the scheduler system so that if an entire batch fails to send, including all fallbacks, the error is sent to relevant admins. Only errors which do not prevent email sending can be sent.


Do not alter or remove anything below. The following sections will be managed by moderators only.

Acceptance criteria

  • After a batch exhausts all three send attempts (worker + fallbacks) and every log in the batch has status email_failed with _send_attempts >= MAX_ATTEMPTS, an admin-facing error email is sent exactly once for that batch to Site Kit admins (users with Permissions::MANAGE_OPTIONS), provided the failure reason is sendable.
  • If any log in the batch was sent successfully (email_sent status), no admin error email is sent for that batch.
  • The admin email uses the existing error-email template with title and description set based on the error type in PUE Errors spreadsheet.
  • Error emails are recorded via a new META_ADMIN_NOTIFIED post meta flag on the batch's first log, preventing duplicate sends for the same batch failure.

Implementation Brief

Backend

  • Create file includes/Core/Email_Reporting/Batch_Error_Notifier.php

    • Constructor accepts Email_Log_Batch_Query, Email (sender), and Context (for site URL/domain).
    • maybe_notify( string $batch_id, string $frequency ) method:
      1. Query all post IDs in the batch via Email_Log_Batch_Query.
      2. Return early if any log has email_sent status, or any failed log has _send_attempts < MAX_ATTEMPTS using is_batch_all_failed.
      3. Return early if META_ADMIN_NOTIFIED is already set on the first log in the batch (prevents duplicate sends) using is_batch_admin_notified.
      4. Extract META_ERROR_DETAILS from the first failed log, decode JSON, and read category_id from error_data.[first_error_code].category_id.
      5. Return early (do nothing) if category_id === 'sending_error' - the mail system is broken, so admin email cannot be sent.
      6. Map category_id to a human-readable failure description via Content_Map::get_body() using category-keyed title copy built from copy below in the PUE Errors spreadsheet.
      7. Resolve admin recipients: get_users( array( 'capability' => PERMISSIONS::MANAGE_OPTIONS ) ); dedupe email addresses; return early if none.
      8. Extract META_REPORT_REFERENCE_DATES from the first log via Email_Log::get_date_range_from_log() and META_REPORT_FREQUENCY for the batch context.
      9. Build the template data array matching the error-email template contract: subject, preheader, site.domain, site.url, title, body (array of paragraphs), primary_call_to_action, footer.
      10. Create an Email_Template_Renderer( null ) (no sections map needed) and call render( 'error-email', $template_data ) for HTML and render_text( 'error-email', $template_data ) for plain text.
      11. Send via Email::send() to all resolved admin addresses with both HTML and plain text content.
      12. On success or failure, set META_ADMIN_NOTIFIED to 1 using mark_batch_admin_notified.
  • Update file includes/Core/Email_Reporting/Email_Log.php

    • Add constant META_ADMIN_NOTIFIED = '_admin_notified'.
    • Register the new post meta in register_post_meta() with type => 'string', single => true, using the existing meta_auth_callback.
  • Update file includes/Core/Email_Reporting/Email_Log_Batch_Query.php

    • Add is_batch_all_failed( string $batch_id ): bool - returns true only when every log in the batch has email_failed status and _send_attempts >= MAX_ATTEMPTS, and no log has email_sent status.
    • Add is_batch_admin_notified( string $batch_id ): bool - checks if META_ADMIN_NOTIFIED is set on the first log in the batch.
    • Add mark_batch_admin_notified( string $batch_id ): void - sets META_ADMIN_NOTIFIED on the first log in the batch.
  • Update file includes/Core/Email_Reporting/Fallback_Task.php

    • Accept Batch_Error_Notifier as a new constructor dependency.
    • In handle_fallback_action(), when $this->batch_query->is_complete( $batch_id ) returns true, call $this->batch_error_notifier->maybe_notify( $batch_id, $frequency ) before the early return.
  • Update file includes/Core/Email_Reporting/Worker_Task.php

    • Accept Batch_Error_Notifier as a new constructor dependency.
    • In handle_callback_action(), after process_pending_logs() completes, check $this->batch_query->is_complete( $batch_id ) and if true, call $this->batch_error_notifier->maybe_notify( $batch_id, $frequency ).
  • Update file includes/Core/Email_Reporting/Email_Reporting.php

    • Instantiate Batch_Error_Notifier with $this->email_log_batch_query, $email_sender, and $this->context.
    • Pass the notifier instance into both Worker_Task and Fallback_Task constructors.
  • Update file includes/Core/Email_Reporting/Content_Map.php

Test Coverage

  • Create tests/phpunit/integration/Core/Email_Reporting/Batch_Error_NotifierTest.php:
    • Test: sends admin email when all logs failed after MAX_ATTEMPTS with a sendable category_id (permissions_error, report_error, or absent).
    • Test: does not send when category_id === 'sending_error' (non-sendable).
    • Test: does not send when any log in the batch has email_sent status (mixed batch).
    • Test: does not send when META_ADMIN_NOTIFIED is already set (duplicate prevention).
    • Test: sets META_ADMIN_NOTIFIED after sending.
    • Test: correctly resolves admin recipients with MANAGE_OPTIONS capability.
    • Test: does nothing if no eligible admin recipients exist.
    • Assert email sentwith correct recipients, subject, and body content matching the error category.
  • Update tests/phpunit/integration/Core/Email_Reporting/Fallback_TaskTest.php:
    • Test: when is_complete() returns true, maybe_notify() on the notifier is called.
    • Test: when batch is not complete, notifier is not called.
  • Update tests/phpunit/integration/Core/Email_Reporting/Worker_TaskTest.php:
    • Test: after processing, if batch becomes complete, maybe_notify() is called.
    • Test: if batch still has pending logs, notifier is not called.

QA Brief

  • Install the new tester plugin (@benbowler will share in Slack)
    • Test each error type in the PUE Errors spreadsheet and confirm the emails are received correctly by all authenticated admins and the copy and links match the spreadsheet.

Changelog entry

  • Send emails to site admins when entire batches of emails fail to send.

Metadata

Metadata

Assignees

No one assigned

    Labels

    P0High priorityTeam SIssues for Squad 1Type: EnhancementImprovement of an existing feature

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions