PCM DirectMail v3 needs POST /auth/login (apiKey+apiSecret) before design/order calls; accept each subscription's copy-only signature secret via PCM_WEBHOOK_SECRETS.
4.8 KiB
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)
- Set
SMTP2GO_WEBHOOK_SECRETin.env/ prod env (long random string). - In SMTP2GO, set Authorization header to Bearer and paste that same secret (do not leave it as “None”).
- Fallback:
?token=<SMTP2GO_WEBHOOK_SECRET>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 |
API key from PCM portal (My Account → API Keys) |
PCM_API_SECRET |
Matching API secret; used with key on POST /auth/login |
PCM_CHILD_REF_NBR |
Optional child-app ref for multi-account |
PCM_WEBHOOK_SECRETS |
Comma-separated signature secrets (one per PCM subscription) |
PCM_WEBHOOK_SECRET |
Optional single-secret alias (merged into the list above) |
PCM_RETURN_ADDRESS |
JSON return address on orders |
POSTCARD_PROVIDER |
pcm (default) |
Auth flow: POST /auth/login with {apiKey, apiSecret} → short-lived
token used as Authorization: Bearer … on design/order calls
(PCM Logging In).
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
PCM allows one event per subscription, and each subscription gets its own signature secret (copy-only in the UI). Create one subscription per status you care about; point them all at the same URL and paste every secret into env.
| Field | Value |
|---|---|
| URL | https://mkdrealtor.com/portal/messaging/webhooks/postcard/ |
| Events | One subscription each: Pending, Processing, Processed, Delivered, Undeliverable, Canceled (skip QrCodeScan unless needed) |
| Environments | Sandbox and/or Production as needed |
| Secrets | Copy each subscription signature → PCM_WEBHOOK_SECRETS=sec1,sec2,… |
We accept Bearer, ?token=, or common signature headers (raw secret or
HMAC-SHA256 of body) matching any listed secret.
Correlation: we send extRefNbr=<Message.uuid> 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):
# 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_API_SECRET=…
PCM_WEBHOOK_SECRETS=sec1,sec2,…
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/<id>/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.