Goal: Direct Email Sending for Email Orders
Enable users to send an Email Order directly from the system — from the
Order Queue’s Email Order composer (the EmailPanel) — through the now-shipped
ShopAccess/Email module, instead of copying the message to the clipboard and
sending it from their own mail client. This is the Email-Orders half of the
Enable Direct email sending for Orders
effort.
Linear Tickets
Section titled “Linear Tickets”- PDEV-969 — Enable Direct email sending for Email Orders: Add a direct email-send path to the Email Order composer, delivering the order email through the backend send pipeline. (this project)
- PDEV-968 — Enable Direct email sending for Orders: Umbrella effort. Sending depends on tenant email configurations being provisioned (PDEV-971).
Repositories
Section titled “Repositories”| Repository | Role | Planned Changes |
|---|---|---|
arda-frontend-app | Production frontend | Add a Send action to the EmailPanel; replace the stub POST /api/email/send-order BFF route with one that calls the backend job endpoint; supplier-recipient handling and not-provisioned UX. |
ux-prototype | Design system | Send-action UI components if the panel needs them (only if needed). |
documentation | Project docs | This project directory: the UI design build-up (email-order-ui.md), the integration design.md, and its decision-log.md. |
Success Criteria
Section titled “Success Criteria”- From the Email Order panel, a user can send the order email directly to the supplier without leaving the system (no copy + paste).
- The send is performed server-side via
POST /v1/shop-access/email/job(real delivery), not the current logging-only stub route. - The composed message (greeting, items table, signature) is delivered as the
email body (
htmlBody/textBody) per the backend contract. - The recipient is the supplier’s email address; the UI handles a missing or unknown supplier email gracefully.
- Sending is gated on the tenant having a sendable
EmailConfiguration; when none exists, the UI explains why and points to provisioning (depends on PDEV-971) rather than failing opaquely. - Delivery acceptance and error states (suppression, not-sendable) are surfaced to the user.
Context
Section titled “Context”In arda-frontend-app, the Order Queue (/order-queue) opens the EmailPanel
slide-over when ordering items whose supplier order method is EMAIL. Today it
composes a formatted order email but only offers Copy to clipboard; the
BFF route POST /api/email/send-order is a stub that logs generated HTML and
never reaches any backend. The backend send capability now exists and is
deployed to production. See the UI design build-up in
email-order-ui.mdx and the
Email module API reference.
Backend Contract (as-built)
Section titled “Backend Contract (as-built)”The integration is designed against the deployed Email module contract — see
design.md for the full treatment:
- Send —
POST /v1/shop-access/email/jobtakes anEmailJobInput(configurationEId,recipients {to, cc, bcc},subject,htmlBody/textBody,replyToEmail,attachments) with requiredX-Tenant-IdandIdempotency-Keyheaders, and is idempotent on that key. There is nofromfield — the sender is fixed by the configuration. - Capability detection —
POST /v1/shop-access/email/configuration/querylists the tenant’s configurations. Direct send is enabled when one is in Operational state and itsidentity.sendingDomainSlugcontains theprocurementmarker (a single, easily-updated front-end constant). Resolved at sign-in / tenant switch and cached in the SPA. - Field mapping — the composer’s recipients map to
to/cc; the UI From maps to Reply-To (replyToEmail); an editable Subject (defaultOrder for {supplier} — {MMM d, yyyy}) supplies the required subject; the rendered body is composed as inline-styled HTML plus a plain-text alternate.
In Scope
Section titled “In Scope”- A Send-by-email action on the Email Order composer, gated by the cached direct-send toggle. Send is a split button offering HTML (default) or plain text, mirroring the two versions the dual-format Copy provides.
- A BFF config-status route that resolves and caches the per-tenant toggle, and
a real BFF send path that builds the
EmailJobInput(recipients, subject, HTML/text body, Reply-To,Idempotency-Key) and calls the backendjobendpoint. - Client-side validation (≥1 To, well-formed addresses, escaped content) with blocking error feedback, and success/error toasts.
- UX for the not-provisioned / not-sendable (restricted, copy-only) case.
Out of Scope
Section titled “Out of Scope”- PO-Line order emails — tracked in PDEV-970.
- Provisioning tenant email configurations — tracked in PDEV-971.
- Per-send From override / multi-From (deferred to PDEV-903 at the backend).
Constraints
Section titled “Constraints”- The From address is fixed by the configuration’s signature — no per-send override.
- Cross-Universe rule: tenant/user references stay soft (no cross-service foreign keys or shared transactions).
- Reuse the existing
EmailPanelmessage composition (greeting, items table, signature) rather than rebuilding the email body. - Send requests require an
Idempotency-Key(minted per Send, stable across retries) and anX-Tenant-Id(injected by the BFF from the session). - Direct send is offered only when the tenant has an Operational procurement
EmailConfiguration; the marker slug lives in a single, easily-updated front-end constant. - User-entered content is HTML-escaped at compose time; the email body is never the raw rendered DOM.
- The shared BFF send route allow-list-sanitizes the HTML body and rejects the request if anything is stripped — an HTML/script-injection defense shared by all clients (e.g. the upcoming PO direct send). Backend-side hardening is tracked by PDEV-976.
Security & Abuse — Decisions Needed
Section titled “Security & Abuse — Decisions Needed”Direct send lets an authenticated user send email from the tenant’s verified
domain with editable recipients and body. The front-end / BFF injection
defenses are specified in design.md (§Security) and the backend
hardening in PDEV-976. The
following are product / security decisions still open:
- Recipient scope — constrain To/Cc to the supplier’s known contact address(es) (allow-list), or allow free-form entry with an audit trail? Free-form sending from a verified domain is a spam / phishing / data-exfiltration vector.
- Authorization to send — which role(s) may send directly? It is a higher-privilege action than copy-to-clipboard and may warrant a separate permission gate.
- Reply-To policy — allow an arbitrary Reply-To (the editable From → Reply-To, DQ-004), or constrain it (e.g. to the sending user or the tenant domain) to limit reply-redirection phishing?
- Rate / volume limits — per-tenant send caps to protect deliverability, domain reputation, and cost (also a backend item in PDEV-976).
These likely need product + security review before implementation locks.
Copyright: © Arda Systems 2025-2026, All rights reserved