Marketing suppression — process and file changes#
Last verified against code: 2026-05-27.
This guide explains how the AutoResponder handles marketing suppression today: what changed for the marketing team, and how inactive people become SFMC-ready CSV files emailed on catalog N04 for marketing to import.
Only the marketing CSV + N04 email path is in use. The pipeline includes scaffold code to call SFMC REST during _handle_inactive, but live SFMC suppression is not hooked up yet (credentials/mapping not in production). Marketing should treat the attached *_NoLongerThere_*.csv file(s) as the authoritative suppression list for each run.
Audience: Marketing operations importing suppressions into SFMC; engineers tracing N04 / SFMC behavior. Column-level specs: DATA_DICTIONARY — Marketing suppression deliverable.
On this page#
- What changed (2026-05)
- How suppression works today
- End-to-end flow
- Marketing CSV specification
- Internal inactive-people file
- N04 notification
- Excluded scenarios
- Future business-unit files
- Code map
What changed (2026-05)#
| Before | After |
|---|---|
N04 attached output_document_inactive_people.csv — wide internal ops file (Cupola IDs, Hodor ProsNums, Multipub blobs, etc.) | N04 attaches only {BusinessUnit}_NoLongerThere_{YYYY-MM-DD}.csv (glob *_NoLongerThere_*.csv) |
| Marketing parsed 19 columns to find emails | Three columns: Email Address, Status (Unsubscribed), Date Added |
| One combined attachment | One CSV per business-unit label (today always Marketing_NoLongerThere_{date}.csv) |
| — | Internal output_document_inactive_people.csv still written every run — not emailed on N04 |
How suppression works today#
For each INACTIVE determination (left company, retired, deceased, no longer at org), marketing suppression is delivered as follows:
| Step | When | What happens | Who acts |
|---|---|---|---|
| 1 — Collect | Per email in ActionEngine._handle_inactive | OutputDocumentCollector.add_inactive_person(...) records the email and inbox (AccountName) | Automatic |
| 2 — Write CSV | End of batch run | write_marketing_suppression_deliverables writes {BusinessUnit}_NoLongerThere_{YYYY-MM-DD}.csv under the run folder | Automatic |
| 3 — Email N04 | Immediately after output files are written | notify_marketing_suppression attaches all *_NoLongerThere_*.csv files | Marketing team imports into SFMC (or equivalent workflow) |
- Changed-email and undeliverable rows are not on the marketing suppression CSV.
- Internal
output_document_inactive_people.csvmay still show SFMC Suppression Added = No for every row until live SFMC REST is enabled — that column reflects the future automated upsert, not whether N04 was sent. - See connections/sfmc.html for the planned (not yet production) REST hook.
End-to-end flow#
- Ingest — Auto-responses from the central repository;
AccountName→email.inbox_source(e.g.energy@thompson.com). - Classify & determine — LLM + rules; only INACTIVE flows below feed suppression outputs.
- Per-email (
_handle_inactive):- Cupola / Hodor inactive updates (per active-only and CUPOLA gates).
- Multipub validation may queue N02 when subscriptions exist.
- Collector:
add_inactive_person(...)→InactivePersonRecord(feeds the marketing CSV at run end).
- End of run (
main.py):OutputDocumentGenerator.write_all()→output_document_inactive_people.csv/.json.write_marketing_suppression_deliverables(...)→Marketing_NoLongerThere_{date}.csv(today).notify_marketing_suppression(N04) attaches*_NoLongerThere_*.csv.
- Marketing team — Mailbox
NOTIFICATION_EMAIL_ERIN(defaultmarketing-team-cbi@columbiabooks.com); Max + Vish Cc unless SMTP override.
Marketing deliverable file specification#
Filename#
{BusinessUnit}_NoLongerThere_{YYYY-MM-DD}.csv
- BusinessUnit —
resolve_business_unit_label(account_name); currently alwaysMarketing. - YYYY-MM-DD — from run folder
run_YYYY-MM-DD_HH-MM-SS, else today. - Non-alphanumeric characters in the label become underscores.
Columns#
| Column | Value |
|---|---|
| Email Address | Inactive person email |
| Status | Unsubscribed (fixed) |
| Date Added | YYYY-MM-DD (matches filename date) |
Encoding and deduplication#
- UTF-8 BOM; all fields quoted; Unix
\nline endings. - Emails deduped case-insensitively within each business-unit file.
- Path:
processing_reports/run_{timestamp}/Marketing_NoLongerThere_{date}.csv
Internal file (not emailed on N04)#
output_document_inactive_people.csv is the ops system of record: AccountName, names, Cupola/Hodor/Multipub IDs, subscription summaries, and a SFMC Suppression Added column reserved for a future live REST upsert (typically No today). Used by batch reports, replay, and the action-items tracker — not attached on N04. See DATA_DICTIONARY §10.
N04 notification#
Notifier.notify_marketing_suppression — full catalog entry.
| Field | Value |
|---|---|
| To | NOTIFICATION_EMAIL_ERIN |
| Trigger | At least one *_NoLongerThere_*.csv in run dir |
| Attachments | Marketing CSV(s) only |
| Resend | auto-responder-send-output-emails <run_dir> |
Excluded from marketing suppression CSV#
| Scenario | Typical output |
|---|---|
| Changed Email | output_document_email_update_requests.csv |
| Undeliverable / bounce | output_document_undeliverables.csv; N02 if Multipub evidence |
| Out of office | Human review only |
| Active / title update | No inactive-person list |
Future: per-business-unit files#
Requested naming: Energy_NoLongerThere_{date}.csv, etc. The writer already groups by label; only the AccountName → label map is stubbed to Marketing. A future settings map will produce multiple N04 attachments when several labels appear in one run.
Code map#
| Role | Module |
|---|---|
| Marketing CSV writer | utils/marketing_suppression_deliverable.py |
| Write on run end | utils/output_document_generator.py |
| Collect inactive rows | utils/output_document_collector.py / processors/action_engine.py (add_inactive_person) |
| N04 email | services/notifications/notifier.py |
| Orchestration | main.py |