AutoResponder: notification recipients and timing#
Simplified reference for who receives email notifications and when — aligned with the live Notifier surface in notifier.py.
For the long-form catalog — exact To / Cc, subject templates, attachments, and body text from code — see NOTIFICATIONS_CATALOG.html. Deferred work (leadership summary, etc.) is listed in catalog §6 and IMPLEMENTATION_PLAN.html.
- Global Cc: Max and Vish are copied on every outbound notification (interim default until the dedicated
cbi-automationmailbox is provisioned), unless a row below explicitly says otherwise. - Attachments: CSV only by default — drop JSON attachments from notification emails.
- Plain language: every action-required email (except the full audit log to Venu) must state clearly what the recipient should do — no internal jargon.
- Client Services routing for subscription/Multipub items: Client Services on Multipub-related emails is Angel + Yogesh as To, Matt on Cc. Tarun is no longer Cc'd on routine Multipub Client Services emails — he only receives the dedicated "undetermined sender" review queue.
- Subscription evidence requirement: every Multipub Client Services email must include subscriber numbers and surface active subscriptions / subscriptions in the last 12 months / purchases in the last 12 months — both inline in the body and as a CSV attachment.
- Tarun review loop: when the auto-responder cannot determine the true sender email, a separate output goes to Tarun so he can review email bodies against Multipub. Tarun replies through the upload endpoint with a Yes (which fires a Client Services email — same shape as 1.1) or a No (which only logs that the case has been reviewed). Cases where the sender is determinable but absent from Multipub do not go to Tarun.
- Marketing team (N04): only the suppression list is sent to Marketing team — people the auto responder marked deceased / retired / inactive at their org / no longer there) — CSV only, no other SFMC files.
- Sai Teja consolidation: manual-review work for Cupola is consolidated to a single Sai action-items email (replacement contacts, inactive-no-Cupola-match research, inactive-at-new-org follow-up, and Human Review rows that need manual action). Subject line for replacements is "New replacements for inactive contacts".
- Venu audit log: Venu still receives the full Cupola audit log every run — CSV only, no JSON. We expect a confirmation reply from Venu when the report has been completed.
- Leadership run summary (2.2): scaffolded only — not sent until all action-item confirmation replies (from Sai Teja and Venu) have been received for that run. Metrics include orgs added, records added, corrections made; no per-record CSVs.
- Run audit (2.1): trim the body, surface clearer metrics (run dates, total emails processed, complete vs. pending counts).
Implementation lives in:
src/auto_responder/services/notifications/notifier.py,
src/auto_responder/processors/action_engine.py,
src/auto_responder/main.py,
src/auto_responder/config.py.
Configured roles#
| Role | Setting | Notes |
|---|---|---|
| Client Services — Angel | NOTIFICATION_EMAIL_ANGEL | Primary To (with Yogesh) on Multipub Client Services notifications and on the Tarun-upload Yes-path notification. |
| Client Services — Yogesh | NOTIFICATION_EMAIL_YOGESH | Primary To (with Angel) on Multipub Client Services notifications and on the Tarun-upload Yes-path notification. |
| Client Services — Matt | NOTIFICATION_EMAIL_MATT | Cc on Multipub Client Services notifications and on the Tarun-upload Yes-path notification. |
| Client Services (Max) | NOTIFICATION_EMAIL_MAX | Cc on every notification (global Cc — interim default). Distinct role from Angel/Yogesh/Matt; Max is the supervisor copy, not the action owner for Multipub follow-ups. |
| Vish (supervisor) | NOTIFICATION_EMAIL_VISH | Cc on every notification (global Cc — interim default). |
| Marketing team (N04) | NOTIFICATION_EMAIL_ERIN | To recipient of the marketing suppression list CSV (deceased / retired / inactive-at-org / no longer there). No other SFMC files are routed to Marketing team. |
| Leadership (optional) | NOTIFICATION_EMAIL_LEADERSHIP | To on the leadership run summary (orgs added / records added / corrections made). Not sent until every action-item recipient (Sai Teja, Venu) has confirmed completion for the run. |
| Sai Teja (IP4 / manual review) | NOTIFICATION_EMAIL_SAI | To on the consolidated Sai action-items email (replacement contacts, inactive-no-Cupola-match, inactive-at-new-org, Human Review rows). Sole recipient of the run audit / full ledger email. |
| Venu (CUPOLA audit / Hodor) | NOTIFICATION_EMAIL_VENU | To on the full Cupola audit log (CSV only). Receives the Hodor Prospect Import digest by default. We expect a reply confirming the audit has been processed. |
| Hodor Prospect Import digest | NOTIFICATION_EMAIL_VENU | Defaults to NOTIFICATION_EMAIL_VENU if unset. Receives queued Prospect Import rows formatted as a SAC import file. |
| Tarun (undetermined sender review) | NOTIFICATION_EMAIL_TARUN | Receives only the dedicated "undetermined sender / Multipub review" queue — cases where the auto-responder could not determine the true sender email so Tarun can review the email body and match against Multipub. Tarun replies through the upload endpoint. |
| Tarun upload endpoint | TARUN_UPLOAD_DIR | Directory where POST /multipub/upload persists Tarun's reviewed files; defaults to ./tarun_uploads. The endpoint accepts a Yes (fires the Client Services notification — same shape as 1.1) or a No (logs the review, no email). |
Global Cc (interim)#
Until the dedicated cbi-automation mailbox is provisioned, Max and Vish are Cc'd on every outbound notification. This is the meeting-level default for the 2026-05-17 alignment and applies in addition to any per-notification Cc list. Once the dedicated mailbox is live, the global Cc can be relaxed to per-row defaults.
Global override#
When SMTP_NOTIFICATION_RECIPIENTS is set (comma-separated list), all outbound notification emails go to that list instead of the role addresses above (EmailService.send_email). When the override is active, Cc on a notification is suppressed — including the global Max+Vish Cc. Notifier._send_notification_email appends a Delivery note footer to every message body listing override To, intended To (catalog owners), and intended Cc (merged per-notification + global Max+Vish). If SMTP_ALWAYS_CC is set while override is active, the footer lists those addresses with an explicit “not added to delivery” qualifier.
Simulation / dev mock-all#
When WRITE_OPERATIONS_ENABLED=false (simulation — live reads, no writes) or MOCK_ALL_SERVICES_FOR_DEV=true (dev/CI mock-all), the notifier runs with dry_run=True: every send is logged to the run log + action_log.log, nothing is sent.
Notification model#
- Per-contact events queue during
ActionEngine.execute(). - Batch categories send one email at
flush_batch_notifications()(N01–N03). - Run deliverables send from
main.pyafter output files are written (N04–N08; N11 scaffold log-only). - Tarun upload Yes/No is independent of the batch run (N09–N10).
Batch notifications (end of run)#
| ID | Recipient | Method | Trigger | Attachment |
|---|---|---|---|---|
| N01 | Venu | notify_hodor_prospect_import | Queued Prospect Import rows | hodor_prospect_import_verification.csv |
| N02 | Angel + Yogesh (Matt Cc) | notify_multipub_subscriber_followup_batch | Left-org/inactive or undeliverable bounce (matched contact), sender known, Multipub shows active or recent subscription/purchase — undeliverables still skip CUPOLA/Hodor/SF writes (bounce-pending rule) | multipub_subscriber_followup.csv |
| N03 | Tarun | notify_tarun_undetermined_sender_review | Sender email could not be determined | tarun_undetermined_senders.csv |
Once per batch run (post-processing)#
These fire from main.py after every email has been processed and the run directory is fully written. Each short-circuits cleanly when its recipient env var is unset or the deliverable produced zero rows. Every row inherits the global Max + Vish Cc.
| Recipient | Notifier method | Attachments (CSV only) | When it fires |
|---|---|---|---|
| Sai Teja (IP4) | notify_run_audit_for_ip4 | processing_report.log (includes IMPACT SUMMARY), processing_report_master.csv, processing_report_ip4.csv, category_summary_report.csv, batch_report.html | After report files are written. Body sections: run identity, email pull window (UTC), impact summary with definitions, processed-this-run vs repository-backlog estimate, category/status/IP4 tallies, backlog snapshot; plus an Attachments: guide (filename and purpose) appended by _send_notification_email. impact_report.txt is written on disk but not emailed. Subject [AutoResponder] Run reports — {run_dir_name} (no [ACTION REQUIRED] prefix). JSON attachments are dropped per the 2026-05-17 alignment. |
| Leadership (scaffold only — not sent yet) | notify_run_summary_for_leadership (scaffolded — not sent) | None (impact metrics inline only — no CSVs) | Called from main.py after run audit; builds metrics-only body and logs deferral at INFO until Sai + Venu confirmations exist. Mirror of N08 with leadership-friendly metrics (orgs added, records added, corrections made — no per-record detail). Held until every action-item recipient (Sai Teja, Venu) replies confirming completion for the run — either by reply email to the service mailbox or via API. |
| Venu (To); Sai Teja (Cc); Max Cc as well (Human Review metadata) | notify_venu_cupola_audit_files | cupola_audit_log.csv (and cupola_audit_log_rollback_plan.csv when present); output_document_human_review.csv when present | Every run, including 0-entry runs. CSV only — no JSON. Body asks for a confirmation reply when the report has been processed. Human Review metadata is attached here; actionable HR rows also go to Sai action items. |
| Marketing team (N04 suppression) | notify_marketing_suppression | *_NoLongerThere_*.csv only (e.g. Marketing_NoLongerThere_2026-05-27.csv) — SFMC import layout: Email Address, Status (Unsubscribed), Date Added. Derived from inactive-people rows at end of run. | Every run with at least one marketing suppression deliverable on disk. Body names attached SFMC file(s) and asks marketing to suppress those addresses. output_document_inactive_people.csv remains internal ops only. Email-update-requests and undeliverables are not sent to marketing. |
| Sai Teja (IP4) | notify_sai_action_items | output_document_alternate_contacts.csv, output_document_inactive_no_cupola_match.csv, output_document_inactive_new_org.csv, output_document_human_review_action_items.csv | Every run with at least one row. Body lists each record with explicit instructions (search Cupola, create the record if missing, associate to org). One Sai email per run replaces the old four. |
| Angel + Yogesh (To); Matt (Cc) | services/tarun_upload_api._notify_client_services (Yes path) | Tarun's reviewed Multipub file (CSV/Excel as uploaded), plus subscriber details inline + as CSV. | Triggered on POST /multipub/upload when Tarun submits Yes (he located the subscriber). Same shape and ask as the Multipub subscriber-evidence email (N02). The No path writes only to the upload audit log and sends no email. |
Resending from an output folder#
Use auto-responder-send-output-emails <processing_reports/run_*> to resend the
emails that can be reconstructed from an existing output folder. Add --dry-run
to preview the notification groups without sending, or --skip-queued to send
only the once-per-run deliverable bundles.
Quick mental model#
- Client Services (Angel + Yogesh, Matt Cc): customer follow-up when Multipub still shows subscription activity, including after Tarun confirms a match (N09).
- Tarun: only undetermined-sender cases; replies via upload Yes/No.
- Sai: run audit every time; one action-items email when manual Cupola work is needed.
- Venu: full Cupola audit log every run; Hodor import digest when queued (N01).
- Marketing team: SFMC suppression import file(s) only (N04) —
*_NoLongerThere_*.csvviamarketing-team-cbi@columbiabooks.com/NOTIFICATION_EMAIL_ERIN. - Max + Vish: Cc on everything (interim).
Resend from an output folder#
auto-responder-send-output-emails <processing_reports/run_*> — --dry-run to preview, --skip-queued for run-end notifications (N04–N08) only. Hodor replay loads hodor_prospect_import_verification.csv.
Audit + rollback#
Venu receives cupola_audit_log.csv every run. When auto-apply ran, cupola_audit_log_rollback_plan.csv may also attach. See DATA_DICTIONARY §22.
Open follow-ups#
- Hosting: target deployment on bumblebee / AWS (access TBD).
- Service mailbox:
CBISAutomation@columbiabooks.com(display name CBIS Automation). Outbound notifications use SMTP AUTH with a Microsoft 365 App Password onsmtp.office365.com:587(STARTTLS). Complete Authenticator MFA registration before relying on automated SMTP/IMAP access. - Leadership email (2.5): implement
notify_run_summary_for_leadershipand confirmation channel for Sai/Venu.