Outbound Email Log
"Did that email actually go out?" used to be unanswerable. Since theme v4.9.0, every email the portal hands to the mailer is recorded in an outbound email log — so you (or the AI assistant) can answer it from the actual send record instead of guessing.
What Gets Logged
Every wp_mail attempt on the site, whatever feature triggered it — transfer notifications, ticket replies, invoices, magic links, campaigns, even other plugins' mail. Each row records:
- Recipient(s) and subject
- Notification type — e.g.
transfer_ready,upload_request,ticket_update, when the sending feature declares it - Related record — the transfer, ticket, or invoice the email belongs to
- Transport — what actually carried the mail: the managed ClientCove proxy, your SendGrid or Postmark SMTP, or PHP
mail(). The transport is corrected to reality at send time, so a proxy fallback never masquerades as a proxy send. - Status —
sent, orfailedwith the mailer's exact error message - Timestamp (UTC) and the logged-in user who initiated it
Email bodies are never stored — the log is metadata only, so it stays small (roughly 550 bytes per email) and doesn't duplicate sensitive content.
Asking the AI
The query_email_log tool is registered in the unified tool catalog, so full-access staff can ask the portal AI things like:
- "Did the transfer notification to jane@example.com go out yesterday?"
- "Show me failed emails from the last week"
- "What emails did we send about invoice 4021?"
The tool filters by recipient, subject text, status (sent / failed), notification type, and date, and returns each attempt's transport and error message. It's also exposed through the MCP bridge for Claude and other MCP clients once the bridge's tool catalog includes it.
REST API
GET /clientcove/v1/email-log — staff only. Query parameters:
to— recipient email (substring match)search— subject text (substring match)status—sentorfailedtype— notification type keysince— only rows at/after this date (YYYY-MM-DD)related_type+related_id— scope to one record (e.g.transfer+ the transfer id)page/per_page— pagination (max 100 per page)
Retention and Purging
- Rows older than 180 days are pruned automatically by a daily cron job.
- Child themes can change the window:
add_filter('clientcove_email_log_retention_days', fn() => 30); - Administrators can purge on demand:
POST /clientcove/v1/email-log/purgewithbefore=2026-06-01(delete older rows) orall=true(empty the log).
Who Can See It
The log exposes recipient addresses across the whole site, so read access is limited to full-access staff roles (administrators, editors, and the tech roles) — both the REST endpoint and the AI tool use the same shared gate. Purging requires administrator capabilities. Clients and representatives never see the log.
Reading the Status Column Honestly
sent means the email was handed to the transport without error — it is not a delivery receipt. Two caveats worth knowing:
- When the transport column says
phpmail, the server's own PHPmail()accepted the message, which on many hosts means very little. Connect a real provider (Settings → Notifications) for delivery you can trust. - Inbox placement (spam filtering, suppression lists) happens after handoff and isn't visible to the portal. For SendGrid, check the provider's suppression dashboard when a
sentemail never arrives.
failed rows are always trustworthy: they carry the mailer's actual error message, which is usually enough to diagnose bad credentials, a rejected sender identity, or an unreachable SMTP host.