- Overview
- Architecture
- Consumer Email Sequences
- Reminder Scheduling Logic
- Team Member & Settlement Office Sequences
- Email Configuration System
- RON Email Sequences
- State Transitions & Triggers
The Snapdocs Closing Product email system is a sophisticated, multi-channel notification platform that orchestrates communication between consumers, lenders, settlement offices, and notaries throughout the closing lifecycle.
Key Characteristics:
- Event-driven architecture - Emails triggered by state changes and milestones
- Multi-channel - Email + SMS notifications with consent management
- Highly configurable - 150+ company-specific email settings
- Role-based - Different sequences for consumers, team members, settlement offices
- Time-aware - Business hours respect, timezone handling, appointment-based scheduling
- Asynchronous processing - Background workers for reliable delivery
graph TB
subgraph "Trigger Layer"
A[State Changes] --> B[Closing Events Watcher]
C[API Actions] --> B
D[Background Jobs] --> B
end
subgraph "Orchestration Layer"
B --> E[Notifier Services]
E --> F[Consumer Notifier]
E --> G[Team Member Notifier]
E --> H[Settlement Office Notifier]
end
subgraph "Business Logic Layer"
F --> I[Mailer Services]
G --> I
H --> I
I --> J[Email Settings Check]
I --> K[Feature Policy Check]
I --> L[SMS Consent Check]
end
subgraph "Delivery Layer"
J --> M[Mailers]
M --> N[Consumer Mailer]
M --> O[Company Team Mailer]
M --> P[Settlement Office Mailer]
N --> Q[Email Templates]
O --> Q
P --> Q
end
subgraph "Scheduling Layer"
R[Reminder Scheduler] --> S[Recurring Reminders]
R --> T[Hours-Before Reminders]
S --> D
T --> D
end
style B fill:#e1f5ff
style E fill:#fff4e1
style I fill:#ffe1f5
style M fill:#e1ffe1
Mailers:
/app/mailers/closing_mailer.rb- Base mailer/app/mailers/closings/consumer_mailer.rb- Consumer emails/app/mailers/closings/company_team_member_mailer.rb- Team emails/app/mailers/closings/settlement_office_mailer.rb- Settlement emails
Services:
/app/services/mailers/closings/consumer_mailer_service.rb- Consumer orchestration/app/services/closings/notifiers/consumers.rb- Consumer notification logic/app/services/closings/reminder_emails_scheduler.rb- Reminder scheduling/app/services/closings/send_first_email_to_consumer.rb- First email trigger logic
Interactors:
/app/interactors/esignings/schedule_reminders_hours_before_appointment.rb- Pre-appointment reminders/app/interactors/esignings/schedule_recurring_consumer_reminders.rb- Recurring reminder logic
Workers:
/app/workers/closings/notify_consumer_milestone_worker.rb- Async consumer notifications/app/workers/closings/esignings/send_esigning_complete_emails.rb- Completion notifications
Configuration:
/app/models/company_email_settings.rb- 150+ email settings
sequenceDiagram
participant S as System
participant C as Consumer
participant SMS as SMS Channel
participant E as Email Channel
Note over S,E: Documents Uploaded & Ready
S->>E: Introductory Email
S->>SMS: SMS Opt-in Notification
E->>C: "Welcome to your digital closing"
Note over S,E: Documents Ready for Preview
S->>E: Preview Email
E->>C: "Review your closing documents"
Note over S,E: eSigning Package Ready
S->>E: Ready for eSigning
S->>SMS: eSigning Ready SMS
E->>C: "Review and eSign your documents"
Note over S,E: Recurring Reminders (Every N hours)
loop Custom Interval (1-9 hours)
S->>E: Automated Reminder
E->>C: "Reminder: please eSign now"
S->>SMS: Reminder SMS
end
Note over S,E: 2-3 Hours Before Appointment
S->>E: Hours-Before Reminder
E->>C: "Final reminder to eSign"
Note over S,E: Notary Assigned
S->>E: Notary Assignment
E->>C: "Signing agent confirmed"
Note over S,E: After Signing Complete
S->>E: Signed Docs Available
E->>C: "Your signed documents are ready"
graph TD
Start[Documents Uploaded] --> CheckStatus{Document Status?}
CheckStatus -->|split/annotating| Intro[Send Introductory Email]
CheckStatus -->|annotated| CheckESigning{eSigning Status?}
CheckESigning -->|out_for_signature| ReadySign[Send Ready for eSigning]
CheckESigning -->|not ready| Preview[Send Preview Email]
Intro --> WaitAnnotated[Wait for Annotation Complete]
WaitAnnotated --> CheckESigning
ReadySign --> ScheduleReminders[Schedule Recurring Reminders]
ScheduleReminders --> CheckAppt{Has Appointment?}
CheckAppt -->|Yes| ScheduleHoursBefore[Schedule Hours-Before Reminder]
CheckAppt -->|No| ContinueRecurring[Continue Recurring Only]
ScheduleHoursBefore --> ApptTime{Time of Day?}
ApptTime -->|Before 10am| Schedule2Hr[Schedule 2hrs before]
ApptTime -->|10am or later| Schedule3Hr[Schedule 3hrs before]
ApptTime -->|No time set| Schedule8am[Schedule 8am on appt date]
Preview --> WaitESigning[Wait for eSigning Ready]
WaitESigning --> ReadySign
style Start fill:#e1f5ff
style Intro fill:#fff4e1
style Preview fill:#ffe1f5
style ReadySign fill:#e1ffe1
graph LR
subgraph "Onboarding Sequence"
A1[Introductory Email] --> A2[Preview Email]
A2 --> A3[Ready for eSigning]
end
subgraph "Reminder Sequence"
B1[Recurring Reminders] --> B2[Hours-Before Reminder]
B2 --> B3[Manual Reminders]
end
subgraph "Update Sequences"
C1[Documents Updated] --> C2[New eSign Package]
C2 --> C3[Documents Replaced]
end
subgraph "Appointment Sequences"
D1[Notary Assigned] --> D2[Appointment Changed]
D2 --> D3[Appointment Canceled]
end
subgraph "Status Change Sequences"
E1[Opted Out of eSigning] --> E2[Opted Into eSigning]
E2 --> E3[Signing Method Changed]
end
subgraph "Post-Signing Sequences"
F1[Signed Docs Available] --> F2[Signed Docs Updated]
end
subgraph "eNote Sequence"
G1[eNote Ready to Sign] --> G2[eNote Reminder]
end
A3 --> B1
C1 -.Update Path.-> A3
D1 -.Appointment Info.-> B2
E1 -.Status Change.-> A3
B2 --> F1
A3 --> G1
style A1 fill:#e1f5ff
style A3 fill:#e1ffe1
style B1 fill:#fff4e1
style F1 fill:#ffe1f5
flowchart TD
Start[eSigning Ready] --> GetInterval[Get Custom Hour Interval<br/>1-9 hours from settings]
GetInterval --> CalcNext[Calculate Next Reminder Time<br/>Current Time + Interval]
CalcNext --> CheckTime{Within Business Hours?<br/>8am - 5pm local time}
CheckTime -->|Before 8am| Reschedule8am[Reschedule to 8am same day]
CheckTime -->|After 5pm| RescheduleNext8am[Reschedule to 8am next day]
CheckTime -->|8am - 5pm| ScheduleReminder[Schedule Reminder]
Reschedule8am --> ScheduleReminder
RescheduleNext8am --> ScheduleReminder
ScheduleReminder --> WaitForTime[Wait for Scheduled Time]
WaitForTime --> CheckSigned{Consumer Signed?}
CheckSigned -->|No| SendReminder[Send Email + SMS Reminder]
CheckSigned -->|Yes| Stop[Stop Reminders]
SendReminder --> CheckAppt{Appointment Within<br/>Custom Interval?}
CheckAppt -->|Yes| StopRecurring[Stop Recurring<br/>Hours-Before takes over]
CheckAppt -->|No| CalcNext
style Start fill:#e1f5ff
style SendReminder fill:#e1ffe1
style Stop fill:#ffcccc
style StopRecurring fill:#ffffcc
flowchart TD
Start[Appointment Scheduled] --> CheckSameDay{Same Day as<br/>Current Time?}
CheckSameDay -->|Yes| NoReminder[No Hours-Before Reminder<br/>Too Close]
CheckSameDay -->|No| CheckTime{Appointment Time<br/>Available?}
CheckTime -->|No Time Set| Schedule8am[Schedule for 8am<br/>on Appointment Date]
CheckTime -->|Has Time| CheckHour{Time of Day?}
CheckHour -->|Before 10am| Calc2Hr[Schedule 2 Hours Before]
CheckHour -->|10am or Later| Calc3Hr[Schedule 3 Hours Before]
Calc2Hr --> Validate
Calc3Hr --> Validate
Schedule8am --> Validate
Validate[Validate Scheduled Time] --> CheckPast{In the Past?}
CheckPast -->|Yes| NoReminder2[Skip Reminder]
CheckPast -->|No| CheckSigned{Consumer Signed?}
CheckSigned -->|Yes| NoReminder3[Skip Reminder]
CheckSigned -->|No| SendReminder[Send Final Reminder<br/>Email + SMS]
NoReminder --> End[End]
NoReminder2 --> End
NoReminder3 --> End
SendReminder --> End
style Start fill:#e1f5ff
style SendReminder fill:#e1ffe1
style NoReminder fill:#ffcccc
style NoReminder2 fill:#ffcccc
style NoReminder3 fill:#ffcccc
graph TB
subgraph "Recurring Reminder Schedule"
R1[Interval: 1-9 hours] --> R2[Next = Now + Interval]
R2 --> R3{Next < 8am?}
R3 -->|Yes| R4[Next = 8am today]
R3 -->|No| R5{Next > 5pm?}
R5 -->|Yes| R6[Next = 8am tomorrow]
R5 -->|No| R7[Use calculated time]
R4 --> R8[Schedule Job]
R6 --> R8
R7 --> R8
end
subgraph "Hours-Before Reminder Schedule"
H1{Has Appt Time?} -->|No| H2[8am on Appt Date]
H1 -->|Yes| H3{Time < 10am?}
H3 -->|Yes| H4[Appt Time - 2 hours]
H3 -->|No| H5[Appt Time - 3 hours]
H2 --> H6[Schedule Job]
H4 --> H6
H5 --> H6
end
subgraph "Job Execution"
J1[Job Runs] --> J2{Signed?}
J2 -->|No| J3[Send Email + SMS]
J2 -->|Yes| J4[Cancel]
J3 --> J5[Log Event]
J4 --> J5
end
R8 -.Triggers.-> J1
H6 -.Triggers.-> J1
style R1 fill:#e1f5ff
style H1 fill:#fff4e1
style J3 fill:#e1ffe1
graph LR
subgraph "Closing Lifecycle Events"
E1[Closing Created]
E2[Documents Ready]
E3[Consumer Signed]
E4[Appointment Set]
E5[Scanbacks Uploaded]
E6[Closing Complete]
end
subgraph "Recipient Roles"
R1[Loan Officer]
R2[Broker]
R3[Loan Coordinator]
R4[Closer]
R5[Funder]
R6[Other Lender Users]
end
subgraph "Email Settings Check"
C[Company Email Settings]
end
E1 --> C
E2 --> C
E3 --> C
E4 --> C
E5 --> C
E6 --> C
C -->|Role Enabled| R1
C -->|Role Enabled| R2
C -->|Role Enabled| R3
C -->|Role Enabled| R4
C -->|Role Enabled| R5
C -->|Role Enabled| R6
style C fill:#fff4e1
style R1 fill:#e1ffe1
style R2 fill:#e1ffe1
style R3 fill:#e1ffe1
style R4 fill:#e1ffe1
style R5 fill:#e1ffe1
style R6 fill:#e1ffe1
graph TD
subgraph "Pre-Signing"
A1[Documents Ready for Download]
A2[Appointment Reminders]
A3[Day-of-Signing Reminders]
end
subgraph "During Signing"
B1[Signing Started]
B2[Signing Progress Updates]
end
subgraph "Post-Signing"
C1[Scanbacks Uploaded]
C2[Signing Complete]
C3[QC Review Ready]
end
A1 --> A2
A2 --> A3
A3 --> B1
B1 --> B2
B2 --> C1
C1 --> C2
C2 --> C3
style A1 fill:#e1f5ff
style B1 fill:#fff4e1
style C2 fill:#e1ffe1
graph TB
subgraph "CompanyEmailSettings Model"
A[150+ Boolean Settings]
B[Custom Integer Settings]
C[Recipient Role Arrays]
end
subgraph "Consumer Email Settings"
D1[closing_consumer_introductory]
D2[closing_docs_ready_to_preview]
D3[closing_ready_to_esign]
D4[closing_reminder_to_esign]
D5[closing_redraw_documents_added]
D6[closing_appointment_date_set]
D7[closing_mobile_notary_assigned]
D8[closing_ready_for_signed_doc_download]
D9[+ 40 more settings]
end
subgraph "Team Member Settings"
E1[closing_created_lender]
E2[closing_docs_ready_lender]
E3[closing_esigning_complete_lender]
E4[+ 30 more settings]
end
subgraph "Settlement Settings"
F1[closing_created_settlement]
F2[closing_scanbacks_uploaded_settlement]
F3[+ 20 more settings]
end
subgraph "Scheduling Settings"
G1[esign_reminder_custom_hour_interval]
G2[completion_time_out]
end
A --> D1
A --> E1
A --> F1
B --> G1
C --> D1
C --> E1
C --> F1
style A fill:#e1f5ff
style D1 fill:#fff4e1
style E1 fill:#ffe1f5
style F1 fill:#e1ffe1
flowchart LR
Start[Email Trigger Event] --> GetSettings[Get Company Email Settings]
GetSettings --> CheckEnabled{Setting Enabled?}
CheckEnabled -->|No| Block1[Block Email]
CheckEnabled -->|Yes| CheckRole{Recipient Role<br/>in Settings?}
CheckRole -->|No| Block2[Block Email]
CheckRole -->|Yes| CheckPolicy{Feature Policy<br/>Allows?}
CheckPolicy -->|No| Block3[Block Email]
CheckPolicy -->|Yes| CheckConsent{Consumer?}
CheckConsent -->|No| Send[Send Email]
CheckConsent -->|Yes| CheckPhone{Has Phone?}
CheckPhone -->|No| Block4[Block Email]
CheckPhone -->|Yes| CheckSMS{SMS Consent?}
CheckSMS -->|Yes| SendBoth[Send Email + SMS]
CheckSMS -->|No| Send
style Start fill:#e1f5ff
style Send fill:#e1ffe1
style SendBoth fill:#e1ffe1
style Block1 fill:#ffcccc
style Block2 fill:#ffcccc
style Block3 fill:#ffcccc
style Block4 fill:#ffcccc
sequenceDiagram
participant S as System
participant C as Consumer
participant N as Notary
participant P as RON Platform
Note over S,P: RON Notary Assignment
S->>C: RON Notary Assigned Email
Note right of C: "Confirm your webcam<br/>closing appointment"
S->>N: Notary Assignment Notification
Note over S,P: Before Appointment
S->>C: Appointment About to Begin
Note right of C: "Your online signing begins<br/>in X minutes"
Note over S,P: Documents Ready in RON Platform
S->>C: Signing Link Available
Note right of C: "You have documents to review"
C->>P: Access RON Platform
P->>C: Display Documents
Note over S,P: During RON Session
C->>P: Sign Documents
N->>P: Notarize
Note over S,P: After RON Complete
P->>S: Signing Complete Notification
S->>C: eSigned Docs Available
Note right of C: "Your copy of eSigned<br/>documents is ready"
S->>N: Completion Notification
graph TB
subgraph "Standard Closing"
A1[Introductory] --> A2[Preview]
A2 --> A3[Ready for eSigning]
A3 --> A4[Recurring Reminders]
A4 --> A5[Notary Assigned - Mobile]
A5 --> A6[Signed Docs Available]
end
subgraph "RON Closing"
B1[Introductory] --> B2[RON Signing Link Available]
B2 --> B3[RON Notary Assigned]
B3 --> B4[Appointment About to Begin]
B4 --> B5[RON eSigned Docs Available]
end
style A3 fill:#e1f5ff
style B2 fill:#fff4e1
style B4 fill:#ffe1f5
stateDiagram-v2
[*] --> Uploaded: Documents Uploaded
Uploaded --> Split: Auto-split
Split --> AutoAnnotating: Start Annotation
AutoAnnotating --> AutoAnnotated: Complete
AutoAnnotated --> ManualAnnotating: Manual Review
ManualAnnotating --> ManualAnnotated: Complete
ManualAnnotated --> QualityControlling: QC Start
QualityControlling --> QualityControlled: QC Complete
QualityControlled --> Annotated: Final State
Annotated --> PreviewSent: Send Preview Email
note right of Split
Trigger: Introductory Email
end note
note right of Annotated
Trigger: Preview Email OR
Ready for eSigning Email
(depends on eSigning status)
end note
PreviewSent --> ESigningReady: eSigning Package Ready
note right of ESigningReady
Trigger: Ready for eSigning Email
Schedule: Recurring Reminders
Schedule: Hours-Before Reminder
end note
ESigningReady --> ESigningInProgress: Consumer Starts
ESigningInProgress --> ESigningComplete: All Signed
note right of ESigningComplete
Trigger: Completion Emails
to Team, Settlement, Consumer
end note
ESigningComplete --> SignedDocsAvailable: Processing Complete
note right of SignedDocsAvailable
Trigger: Signed Docs Available Email
end note
stateDiagram-v2
[*] --> NotReady: Initial State
NotReady --> ReadyToSend: Package Prepared
ReadyToSend --> OutForSignature: Sent to Consumer
note right of OutForSignature
Trigger: Ready for eSigning Email
Start: Reminder Sequences
end note
OutForSignature --> PartiallySigned: Some Signers Complete
OutForSignature --> Complete: All Signers Complete
PartiallySigned --> Complete: Remaining Signers Complete
note right of Complete
Trigger: Completion Emails
Stop: All Reminders
end note
OutForSignature --> Redraw: Documents Changed
PartiallySigned --> Redraw: Documents Changed
note right of Redraw
Trigger: New eSign Package Email OR
Documents Updated Email OR
Documents Replaced Email
end note
Redraw --> OutForSignature: New Package Sent
graph TD
Start[Trigger: Send First Email] --> GetDocStatus[Get Document Status]
GetDocStatus --> CheckStatus{Document Status}
CheckStatus -->|split<br/>auto_annotating<br/>auto_annotated<br/>manual_annotating<br/>manual_annotated<br/>quality_controlling<br/>quality_controlled| SendIntro[Send Introductory Email]
CheckStatus -->|annotated| CheckESign{eSigning Status}
CheckESign -->|out_for_signature| CheckSigned{User Signed?}
CheckSigned -->|No| SendReady[Send Ready for eSigning]
CheckSigned -->|Yes| SendPreview[Send Preview Email]
CheckESign -->|not ready| SendPreview
SendIntro --> End[End]
SendReady --> ScheduleReminders[Schedule Reminder Sequences]
SendPreview --> End
ScheduleReminders --> End
style Start fill:#e1f5ff
style SendIntro fill:#fff4e1
style SendReady fill:#e1ffe1
style SendPreview fill:#ffe1f5
flowchart TD
Start[Appointment Change Event] --> DetectChange{What Changed?}
DetectChange -->|Date/Time| RescheduleReminders[Reschedule All Reminders]
DetectChange -->|Location| SendUpdate[Send Appointment Updated Email]
DetectChange -->|Notary| SendNotaryChange[Send Notary Assignment Email]
DetectChange -->|Canceled| CancelReminders[Cancel All Reminders]
RescheduleReminders --> RecalcRecurring[Recalculate Recurring Reminders]
RecalcRecurring --> RecalcHoursBefore[Recalculate Hours-Before Reminder]
RecalcHoursBefore --> SendUpdate
CancelReminders --> SendCanceled[Send Appointment Canceled Email]
SendUpdate --> NotifyTeam[Notify Team Members & Settlement]
SendNotaryChange --> NotifyTeam
SendCanceled --> NotifyTeam
style Start fill:#e1f5ff
style RescheduleReminders fill:#fff4e1
style SendUpdate fill:#e1ffe1
stateDiagram-v2
[*] --> OriginalDocs: Initial Documents Sent
OriginalDocs --> DetectChange: Document Change Event
DetectChange --> EvaluateChange: Determine Change Type
state EvaluateChange <<choice>>
EvaluateChange --> MinorUpdate: New docs added (preview only)
EvaluateChange --> NewESignPackage: Additional eSigning docs
EvaluateChange --> FullRedraw: Complete replacement
note right of MinorUpdate
Trigger: Documents Updated Email
No eSigning impact
end note
note right of NewESignPackage
Trigger: New eSign Package Email
Trigger: Reset Reminder Schedules
end note
note right of FullRedraw
Trigger: Documents Replaced Email
Trigger: Reset ALL Sequences
end note
MinorUpdate --> [*]
NewESignPackage --> ResetReminders
FullRedraw --> ResetReminders
ResetReminders --> RecurringScheduled: Schedule Recurring
RecurringScheduled --> HoursBeforeScheduled: Schedule Hours-Before
HoursBeforeScheduled --> [*]
graph TB
subgraph "Base Templates"
A[application.html.haml]
B[closing_mailer_layout.html.haml]
end
subgraph "Shared Partials"
C[_closing_details.html.haml]
D[_closing_details_concise.html.haml]
E[_closing_appointment_and_signer.html.haml]
F[_notary_info_table.html.haml]
G[_closing_user_contact_info.html.haml]
end
subgraph "Checklist Partials"
H1[_closing_checklist_full_eclosing.html.haml]
H2[_closing_checklist_full_eclosing_with_enote.html.haml]
H3[_closing_checklist_hybrid.html.haml]
H4[_closing_checklist_hybrid_with_enote.html.haml]
H5[_closing_checklist_wet.html.haml]
H6[_closing_consumer_ron_checklist.html.haml]
end
subgraph "Email-Specific Templates"
I1[notify_consumer_introductory.html.haml]
I2[notify_consumer_ready_for_review.html.haml]
I3[notify_consumer_ready_for_signing.html.haml]
I4[send_esigning_reminder.html.haml]
I5[notify_consumer_mobile_notary_assigned.html.haml]
I6[notify_consumer_ready_for_signed_doc_download.html.haml]
end
A --> B
B --> I1
B --> I2
B --> I3
B --> I4
B --> I5
B --> I6
I1 --> C
I2 --> C
I3 --> D
I3 --> H3
I4 --> E
I5 --> F
I6 --> G
style A fill:#e1f5ff
style C fill:#fff4e1
style I3 fill:#e1ffe1
| Email Type | Subject | Trigger | SMS? | Settings Key |
|---|---|---|---|---|
| Introductory | "Welcome to your Snapdocs digital closing" | Documents uploaded | Yes | closing_consumer_introductory |
| Ready for Review | "Review your closing documents" | Documents ready for preview | No | closing_docs_ready_to_preview |
| Ready for eSigning | "Review and eSign your closing documents" | eSigning package ready | Yes | closing_ready_to_esign |
| eSign Reminder (Auto) | "Reminder: please eSign your documents now" | Scheduled (recurring) | Yes | closing_reminder_to_esign |
| eSign Reminder (Manual) | "Reminder: please eSign your documents now" | User-triggered | Yes | closing_reminder_to_esign |
| Hours-Before Reminder | "Reminder: please eSign your documents now" | 2-3 hrs before appt | Yes | closing_reminder_to_esign |
| eNote Ready | "Please sign your eNote" | eNote package ready | No | closing_ready_to_sign_enote |
| eNote Reminder | "Reminder: Please sign your note" | eNote unsigned | No | closing_reminder_to_sign_enote |
| Documents Updated | "Your closing documents are updated" | Documents added (preview) | No | closing_redraw_documents_added |
| New eSign Package | "We added additional documents for you to eSign" | Additional eSigning docs | No | closing_redraw_documents_added |
| Documents Replaced | "We've replaced your closing documents" | Complete doc replacement | No | closing_redraw_documents_added |
| Mobile Notary Assigned | "A signing agent is confirmed for your closing" | Notary assigned | No | closing_mobile_notary_assigned |
| Appointment Changed | "Signing details updated" | Appointment modified | No | closing_appointment_date_set |
| Appointment Canceled | "Your signing appointment has been canceled" | Appointment canceled | No | closing_appointment_canceled |
| RON Notary Assigned | "Confirm your webcam closing appointment" | RON notary assigned | No | closing_ron_notary_assigned |
| RON About to Begin | "{Name}, your online signing begins in X minutes" | Pre-RON appointment | No | closing_ron_appointment_about_to_begin |
| RON Signing Link | "{Name}, you have documents to review" | RON link available | No | closing_ron_signing_link_available |
| RON eSigned Docs | "Your copy of eSigned documents is ready" | RON signing complete | No | closing_ron_signed_docs_available |
| Signed Docs Available | "Your signed closing documents are available" | Signing complete | No | closing_ready_for_signed_doc_download |
| Signed Docs Updated | "A new version of your signed closing documents is available" | Signed docs changed | No | closing_signed_docs_changed_post_download |
| Opted Out of eSigning | "You've opted out of eSigning" | eSigning opt-out | No | closing_consumer_opted_out_of_esigning |
| Opted Into eSigning | "Reminder to eSign your documents" | eSigning opt-in | No | closing_consumer_opted_into_esigning |
| Signing Method Changed | "Update to your closing" | Signing method change | No | closing_signing_changed |
- Closing created
- Documents ready to download
- Consumer documents updated
- Appointment changes
- eSign completion
- Scanbacks uploaded
- Closing completion
- CQC status changes
- Comments added
- Documents ready for download
- Appointment reminders
- Day-of-signing reminders
- Scanback notifications
- Signing completion
- QC review ready
- Comments added
flowchart TD
Start[Email Trigger] --> CheckPhone{Consumer Has Phone?}
CheckPhone -->|No - Phoneless| Block1[SUPPRESS ALL CONSUMER EMAILS]
CheckPhone -->|Yes| CheckNBO{Is NBO?}
CheckNBO -->|Yes| CheckPolicy{NBO Preview Policy?}
CheckPolicy -->|Disabled| Block2[SUPPRESS PREVIEW EMAILS]
CheckPolicy -->|Enabled| CheckPOS
CheckNBO -->|No| CheckPOS{POS Ownership?}
CheckPOS -->|POS Owns Comms| Block3[SUPPRESS - External System]
CheckPOS -->|Snapdocs Owns| CheckBlockPreview{Block Consumer Preview?}
CheckBlockPreview -->|Yes| Block4[SUPPRESS PREVIEW EMAILS]
CheckBlockPreview -->|No| CheckRON{RON Closing?}
CheckRON -->|Yes + No NBO Preview| Block5[SUPPRESS STANDARD EMAILS<br/>Use RON Sequence]
CheckRON -->|No| CheckSettings{Email Setting Enabled?}
CheckSettings -->|No| Block6[SUPPRESS - Setting Disabled]
CheckSettings -->|Yes| Allow[SEND EMAIL]
style Block1 fill:#ffcccc
style Block2 fill:#ffcccc
style Block3 fill:#ffcccc
style Block4 fill:#ffcccc
style Block5 fill:#fff4cc
style Block6 fill:#ffcccc
style Allow fill:#e1ffe1
graph LR
subgraph "Consumer Events"
A1[DOCS_SENT_TO_CONSUMER_FOR_PREVIEW]
A2[DOCS_SENT_TO_CONSUMER_FOR_SIGNING]
A3[ENOTE_SENT_TO_CONSUMER_FOR_SIGNING]
A4[CONSUMER_INTRODUCTORY_EMAIL_SENT]
A5[AUTOMATED_EMAIL_ESIGNING_REMINDER_SENT]
A6[ESIGN_REMINDER]
end
subgraph "System Events"
B1[EMAIL_SENT]
B2[SMS_SENT]
B3[EMAIL_FAILED]
B4[SMS_FAILED]
end
subgraph "Audit Trail"
C[ClosingsEventsWatcher]
end
A1 --> C
A2 --> C
A3 --> C
A4 --> C
A5 --> C
A6 --> C
B1 --> C
B2 --> C
B3 --> C
B4 --> C
style C fill:#e1f5ff
sequenceDiagram
participant S as System
participant C as Consent Service
participant T as Twilio
participant U as Consumer
S->>C: Check SMS Consent
C->>S: Consent Status
alt Has Consent
S->>S: Check Business Hours<br/>7am-midnight local
alt Within Business Hours
S->>T: Send SMS
T->>U: Deliver SMS
else Outside Business Hours
S->>S: Schedule for 7am
Note right of S: Wait until 7am
S->>T: Send SMS
T->>U: Deliver SMS
end
else No Consent
S->>S: Skip SMS
Note right of S: Send Email Only
end
- Introductory SMS (with opt-in prompt)
- Documents ready for preview
- Documents ready for eSigning
- eSign reminders (recurring + hours-before)
- Document updates/redraws
- eNote signing reminders
graph TB
subgraph "Synchronous Layer"
A[User Action / State Change]
end
subgraph "Queue Layer"
B[Background Job Queue]
end
subgraph "Worker Layer"
C1[NotifyConsumerMilestoneWorker]
C2[SendESigningCompleteEmailsWorker]
C3[Reminder Scheduler Jobs]
end
subgraph "Execution Layer"
D[Mailer Services]
E[Email Delivery]
F[SMS Delivery]
end
A --> B
B --> C1
B --> C2
B --> C3
C1 --> D
C2 --> D
C3 --> D
D --> E
D --> F
style A fill:#e1f5ff
style B fill:#fff4e1
style D fill:#ffe1f5
style E fill:#e1ffe1
style F fill:#e1ffe1
Company Setting: esign_reminder_custom_hour_interval = 4
Scenario: eSigning ready at 2:00 PM, appointment at 2:00 PM next day
Reminder Schedule:
- 6:00 PM today (2pm + 4hrs)
- 10:00 PM today → RESCHEDULED to 8:00 AM tomorrow (after 5pm)
- 11:00 AM tomorrow (canceled - appointment at 2pm means hours-before reminder takes over at 11am)
Hours-Before Reminder:
- 11:00 AM tomorrow (2pm - 3hrs, since appointment is after 10am)
Scenario: eSigning ready at 10:00 AM, appointment at 3:00 PM same day
Reminder Schedule:
- Recurring reminders start: 2:00 PM (10am + 4hrs) → CANCELED (too close to appt)
- Hours-before reminder: SKIPPED (same day appointment)
Result: No automated reminders, rely on manual reminders if needed
The Snapdocs Closing Product email system is a sophisticated, event-driven notification platform that:
- Orchestrates 20+ consumer email sequences across the closing lifecycle
- Manages intelligent reminder scheduling with business hours respect and timezone awareness
- Supports multi-channel delivery (Email + SMS) with consent management
- Provides role-based notifications for team members and settlement offices
- Offers 150+ configuration options for company-specific customization
- Handles complex state transitions for documents, eSigning, and appointments
- Ensures reliable delivery through asynchronous processing and retry logic
- Maintains audit trails for compliance and debugging
The architecture prioritizes configurability, reliability, and user experience while handling the complexity of real estate closings across multiple signing methods (hybrid, RON, wet) and stakeholder types.