Repository navigation
Let requesters reply to messages by e-mail #1861
Copy link
Copy link
Open
Labels
enhancementNew feature or requestNew feature or request
Description
Requesters get an e-mail for every new message from the studio (email_user_new_comment in backend/video_requests/emails.py), but to answer they have to log in. Replying to that e-mail should add their answer to the request's message thread. Only for requesters; the crew keeps using the admin.
We have no mail server, but the domain's mail goes through Cloudflare Email Routing, which can hand incoming mail to a Worker's email() handler (docs). Cloudflare already sees this mail, so no new third party gets personal data.
Flow
- E-mails to the requester set
Reply-Toto a per-request address, e.g.valasz-<request id>-<mac>@…, instead ofDEFAULT_REPLY_EMAIL. - An Email Routing rule sends these addresses to the Worker: either the catch-all (the Worker forwards everything else to where the catch-all goes today) or a separate subdomain, so the existing rules stay untouched.
- The Worker only matches the address pattern and POSTs the raw MIME to a backend endpoint with a shared secret. On a 4xx answer it calls
message.setReject(reason), so the sender gets a bounce with our text. - The backend checks the MAC, loads the request, checks that the sender is the requester, parses the MIME with the standard
emailmodule, cuts the quoted history and createsComment(internal=False, author=requester). Then it notifies the crew the same wayCommentCreateUpdateSerializerdoes.
Parsing stays in the backend so the logic lives in one place and pytest covers it.
Address token
- The token must be unguessable, not look random.
<id>-<HMAC(secret, id) truncated to ~20 hex chars>needs no extra column and is an O(1) lookup; request IDs are already public in URLs. A salted hash without the ID would force the backend to hash every request or store the token. - Lowercase hex or base32 only: some mail systems lowercase addresses, so base64 and Django
signing(case-sensitive,:separator) would break.
Gotchas
- Spoofed
From. Email Routing rejects mail that fails both SPF and DKIM and enforces the sender's DMARC policy (postmaster), but common providers like gmail.com publishp=none, so a forged headerFromcan still get through. The token is the real secret; the sender check is a second factor. Worst case is a fake message in one thread that the crew sees. Check with a real mail whether the Worker gets anAuthentication-Resultsheader. - Compare the header
From, not the envelope sender: forwarding and university relays often rewrite the envelope to a bounce address. - Quoted history is the hardest part. Replies contain the whole previous e-mail, so cut at Gmail and Outlook separators in Hungarian and English (
… ezt írta:,On … wrote:,Feladó:/From:blocks,>lines).email-reply-parseronly knows English. The alternative is a "write above this line" marker in our e-mails: reliable, but ugly. Collect real samples for tests. - Auto-replies: drop mail with
Auto-Submittedother thanno,Precedence: bulkorauto_reply, or an empty envelope sender, or out-of-office replies become messages. - HTML-only mail needs an HTML-to-text fallback. Attachments: ignore, or bounce with a pointer to the site.
- Retries: the docs do not say whether an exception in the Worker is a temporary failure or a bounce. If the sender's server retries, the comment can be created twice; deduplicate on
Message-IDif needed. - Reply-all: the request confirmation CCs
DEFAULT_REPLY_EMAIL. If it also gets the token address, a reply-all reaches both. - New deployable: a Worker project, a
wrangler deploystep and the shared secret on both sides.
Open decisions
- Can unregistered requesters (
is_active=False, who cannot log in) reply by e-mail? It would be their only way to answer, so probably yes. - Which e-mails get the token address: only new messages, or also the request confirmation and the video published e-mail?
- Banned requesters: bounce or drop silently?
- The address prefix (
valasz-,uzenet-, …) shows in the requester's To field.
Nice to have, low priority.
Metadata
Metadata
Assignees
Labels
enhancementNew feature or requestNew feature or request
Activity