DPD Escalation Email - CC Recipients
Summary
When DPD claims reach the 3rd reminder (escalation), the email now CCs three DPD contacts in addition to the original TO recipient. The approval UI shows CC recipients before you approve, with a fallback for the 3 existing pending escalation workflows.
Flow
sequenceDiagram
participant W as DPD Workflow
participant UI as Approval UI
participant A as SendReminderEmail Activity
participant G as Microsoft Graph
W->>W: reminderNumber >= 3?
W->>W: Load CC from DPDWorkflowConstants
W->>UI: Request approval (includes CC preview)
UI->>UI: Display From, To, CC, Subject, Body
UI-->>W: Approved
W->>A: SendReminderEmailAsync(to, reminder#, ccRecipients)
A->>A: CC present? Skip reply path, use new email
A->>G: SendEmail(to, cc, subject, body)What Changed
1. Contract: SendReminderEmailRequest
Added List<string>? CcRecipients — nullable for backwards compatibility. Existing serialized requests from Temporal history deserialize with null, so replay is safe.
2. Constants: DPDWorkflowConstants
New ESCALATION_CC_RECIPIENTS array:
| Contact | |
|---|---|
stevie-leanne.oconnor@dpd.uk |
Stevie-Leanne O'Connor |
hannah.willetts@cs.dpd.co.uk |
Hannah Willetts |
suki.balli@cs.dpd.co.uk |
Suki Balli |
3. Activity: SendReminderEmailActivity
Two changes to the send logic:
- Reply path gating: Changed from
if (ReplyToEmailId != null)toif (ReplyToEmailId != null && no CC). Graph'sReplyToEmailByIddoesn't support CC, so when CC is present we fall back to the new-email path. The "ESCALATION - RE:" subject prefix provides visual threading. - CC construction: Builds
List<Recipient>fromrequest.CcRecipientsand passes toSendEmail()(was hardcodednull).
4. Base Class: ClaimWorkflowBase.SendReminderEmailAsync
Added optional ccRecipients parameter, sets it on the request. Non-breaking — existing callers (Asendia etc.) pass nothing and get null.
5. DPD Workflow: DPDClaimWorkflow
Two integration points:
- Intervention data (line ~232): Stores CC recipients in approval data so the UI can display them
- Send call (line ~277): When
reminderNumber >= 3, passes CC recipients toSendReminderEmailAsync
6. Approval UI: PendingApprovalsPanel.razor
- Displays CC row in email preview when CC recipients are present
- Fallback for existing workflows: If CC data is missing from intervention but it's a DPD reminder >= 3, infers CC from
DPDWorkflowConstants.ESCALATION_CC_RECIPIENTS
Impact on 3 Running Workflows
graph TD
subgraph "Already Baked In Temporal"
I[Intervention Data<br/>NO CC field]
end
subgraph "UI Fallback"
C{DPD courier?}
R{Reminder >= 3?}
F[Infer CC from constants]
end
subgraph "Activity Execution"
N[New worker code]
S[SendEmail with CC]
end
I --> C
C -->|Yes| R
R -->|Yes| F
F --> |Display CC| UI[Approval UI shows CC]
UI -->|Approve| N
N --> S
style I fill:#fff3e0
style F fill:#e8f5e9
style S fill:#e1f5fe