Summary
The three channels — email, SMS, push — are routed by MAM_Notification_Dispatcher to per-channel sender classes. Each sender owns its channel-specific transport, queueing, and failure handling. Per-channel routing is gated by the notification-type registry’s default_on plus per-type opt-in option keys.
Email — MAM_Email_Sender
Transport: wp_mail() synchronously, or queue → cron.
Queueing decision: count > 10 AND mam_notification_use_cron option enabled → queue. Otherwise immediate.
Storage:
- Queue:
wp_mam_mail_queue - Attachments:
wp_mam_mail_attachments - History:
wp_mam_notification_history
Cron processor: mam_cron_mail::mail_cron() — batch of 50, retry up to 3 times.
Opt-out: Reads wp_mam_email_opted_out (per-user) before sending.
Templating: Uses the tsl_notification_subject_<slug> (email + SMS share subject) and tsl_notification_email_text_<slug> option keys with replacement-token substitution.
SMS — MAM_Sms_Sender
Transport: Global $sms->SendSMS() — typically Twilio, but the global is provider-agnostic. The sender appends a STOP-to-opt-out copy automatically.
Queueing decision: Same as email.
Storage:
- Queue:
wp_mam_sms_queue(unified PN + SMS queue,send_text=1flag) - Phone numbers:
usermetabilling_phone - History:
wp_mam_notification_history
Cron processor: Same mam_cron_mail::mail_cron() — batch of 20 PN/SMS sends per tick.
Opt-out: Read from wp_mam_email_opted_out-style table per phone number (in some configs); STOP-keyword opt-out is provider-side (Twilio handles it).
Templating: Uses tsl_notification_subject_<slug> for the message preview and tsl_notification_text_text_<slug> for the full body.
⚠️ $sms is a global. If absent (no SMS provider configured), the sender silently fails. The dispatcher should null-check; it currently doesn’t (tracked).
Push — MAM_Pn_Sender → MAM_PushDispatcher
Transport:
MAM_Pn_Sender::send($msg, $type, $use_cron)
│
▼
do_action('mam_notification_send_pn', $msg)
│
▼
mam_push_notification_manager::send_push_notification() ← legacy bridge
│
▼
MAM_PushDispatcher::dispatch( MAM_PushNotification )
│
┌────┴────┬───────────┐
▼ ▼ ▼
APNs APNs VoIP FCM v1
HTTP/2
Queueing decision: Same as email/SMS.
Storage:
- Queue:
wp_mam_sms_queue(send_pn=1flag) - Tokens:
usermetakeysmam_app_ios_pn_token,mam_app_android_pn_token,mam_ios_voip_token - History:
wp_mam_notification_history
Cron processor: Shared with SMS.
Retry: None on the PN flow. Failures land in MAM_PushResult->errors.
Templating: Uses tsl_notification_subject_<slug> for the title and tsl_notification_pn_text_<slug> for the body.
Per-channel send-message message shape
do_action( 'mam_notification_send_message', array(
'message_type' => 'mam-my-plugin-event_name',
'recipient_id' => 123, // WP user id
'email' => 'override@example.com', // optional — defaults to user's email
'phone' => '+15551234567', // optional — defaults to billing_phone usermeta
'replacements' => array(
'order_id' => '42',
'tracking_number' => 'ABC123',
),
'send_now' => true, // bypass cron
'data' => array( ... ), // arbitrary push payload data
) );
The dispatcher resolves message_type to a registry entry, then per-channel decides whether to send.
Channel-specific failure modes
| Channel | Common failures | Where to diagnose |
|---|---|---|
| SMTP refused, bounced, rate-limited | wp_mail_failed action; outbox viewer |
|
| SMS | Invalid phone, provider quota, opt-out | MAM_Sms_Result; provider dashboard |
| Push | BadDeviceToken, Unregistered, MismatchSenderId |
MAM_PushResult->errors; outbox viewer |
The outbox viewer (Mobile App Manager → Notifications → Outbox) shows recent dispatches across all three channels.
Gotchas
- Removed dead flags.
send_text,send_email,send_pnper-message flags were inert — removed in PR #34. Channel routing comes from the type registry. - System chat is a special case.
message_type = system_chatbypasses notification-list resolution and firesmam_notification_send_pndirectly. Used by the chat manager. - Email-channel writes to two tables (
wp_mam_mail_queue+wp_mam_notification_history). PN/SMS writes only towp_mam_sms_queue+wp_mam_notification_history. - No retry on push. A push that fails once stays failed; the next attempt requires a fresh
mam_notification_send_messagefire.
Related articles
- Notifications overview
- Notification types registry
- Notification queue and cron
- Notification history and opt-out
- Push notification credentials and tokens
- Hook: mam_notification_send_message
- Hook: mam_notification_send_pn
Metadata
| Field | Value |
|---|---|
| Article type | Plugin Overview |
| Plugin slug | mam-main |
| Applies to plugin version | 2.1.11+ |
| Category | Plugin Reference |
| Audience | PHP developer |
| Last verified | 2026-05-02 |
