# Messaging Campaign compose/send, SMTP2GO email + SMS, PCM Integrations postcards, and delivery webhooks. ## SMTP2GO webhook setup Campaign report page polls provider events every 10s. Create **two** webhooks in SMTP2GO → **Settings → Webhooks** (email and SMS stay separate). ### Auth (`SMTP2GO_WEBHOOK_SECRET`) 1. Set `SMTP2GO_WEBHOOK_SECRET` in `.env` / prod env (long random string). 2. In SMTP2GO, set **Authorization header** to **Bearer** and paste that same secret (do not leave it as “None”). 3. Fallback: `?token=` on the webhook URL also works. ### Email webhook | Field | Value | |-------|--------| | URL | `https://mkdrealtor.com/portal/messaging/webhooks/email/` | | Authorization header | **Bearer** + `SMTP2GO_WEBHOOK_SECRET` | | Output type | JSON | | Email events | processed, bounced, rejected, spam, delivered, unsub/resub, opened, clicked | | Email headers | `X-Monica-Message-Id` | | SMS events | leave unchecked | `X-Monica-Message-Id` is set on every campaign email send and is required so webhook events match the correct recipient row. Beta / other hosts: swap the hostname, keep the path. ### SMS webhook (separate) | Field | Value | |-------|--------| | URL | `https://mkdrealtor.com/portal/messaging/webhooks/sms/` | | Authorization header | **Bearer** + same `SMTP2GO_WEBHOOK_SECRET` | | Output type | JSON | | Email events | leave unchecked | | SMS events | Submitted, Sending, Delivered, Failed, Rejected, Opt-out | This endpoint also accepts inbound reply POSTs (`text=STOP`, `from=…`) and opts the contact out of SMS. ## PCM Integrations (postcards) Default postcard provider. Designer embeds PCM’s editor; orders use DirectMail API v3. ### Env | Var | Purpose | |-----|---------| | `PCM_API_KEY` | Bearer token for `https://v3.pcmintegrations.com` | | `PCM_WEBHOOK_SECRET` | Auth for inbound status webhooks | | `PCM_RETURN_ADDRESS` | JSON return address on orders | | `POSTCARD_PROVIDER` | `pcm` (default) | ### Designer Portal → **Postcard design**: create/list designs via API, edit in iframe (`POST /design/custom`, `GET /design/{id}/edit?mode=embed`). Save as a `MessageTemplate` (stores `design_id`) then pick it when composing a postcard campaign. ### Postcard webhook Create a webhook subscription in the PCM dashboard (Working with Webhooks): | Field | Value | |-------|--------| | URL | `https://mkdrealtor.com/portal/messaging/webhooks/postcard/` | | Authorization | **Bearer** + `PCM_WEBHOOK_SECRET` | | Events | Order / recipient status (Pending, Processing, Processed, Delivered, Undeliverable, Canceled) | | Environments | Sandbox and/or Production as needed | Fallback: `?token=` on the URL. Correlation: we send `extRefNbr=` on each recipient; webhooks should echo that (or `orderID`, matched to `Message.provider_message_id`). ### Campaign completion email When a campaign reaches **completed** (email, SMS, or postcard), one summary email goes to `campaign.created_by.email`, else `CONTACT_EMAIL`. Guarded by `Campaign.notify_sent_at` so it only sends once. ### Local development SMTP2GO / PCM cannot reach `localhost`. Use a tunnel (Cloudflare Tunnel / ngrok) to `:8000`, or test webhooks against beta/prod. For real SMTP delivery locally (not console logs): ```bash # in .env EMAIL_BACKEND=django.core.mail.backends.smtp.EmailBackend EMAIL_HOST_USER=… EMAIL_HOST_PASSWORD=… SMTP2GO_WEBHOOK_SECRET=… SMTP2GO_SMS_API_KEY=… # SMS sends only PCM_API_KEY=… PCM_WEBHOOK_SECRET=… PCM_RETURN_ADDRESS={…} ``` ### Endpoints (app) | Path | Purpose | |------|---------| | `POST /portal/messaging/webhooks/email/` | Email delivery / open / click / bounce / … | | `POST /portal/messaging/webhooks/sms/` | SMS delivery events + inbound STOP | | `POST /portal/messaging/webhooks/postcard/` | PCM order / mail tracking events | | `GET /portal/messaging/campaigns//status.json` | Live stats for the campaign report UI | | `GET /portal/messaging/postcard/` | PCM designer iframe | Code: `webhooks.py`, `providers/postcard/pcm.py`, `views.py`.