Email Principles
PayCal treats transactional email as part of account safety and account continuity, not as marketing infrastructure.
- Flow-specific templates are used for verification, recovery, account-change, and contact support paths.
- Email composition is centralized to avoid divergent message logic across controllers.
- Delivery failures return explicit outcomes so calling flows can fail safely and inform users clearly.
What We Send
| Flow | Purpose | Template Family |
|---|---|---|
| Email verification | Confirm ownership during account lifecycle events | email-verification-* |
| Recovery email verification | Prove destination ownership before sensitive recovery actions | email-recovery-email-code-* |
| Recovery Key Delivery | Provide account recovery material | email-recovery-key-* |
| Account recovery transaction | Issue account-recovery verification code | email-account-recovery-code-* |
| Email change (old/new inbox) | Dual inbox confirmation for account email mutation | email-change-code-* and email-change-confirmation-* |
| Contact support relay | Forward support requests to support inbox with normalized content | contact-email-* |
Delivery Pipeline
PayCal uses a two-layer email stack:
PayCal\Domain\EmailGarum: workflow-level orchestration and template selection.PayCal\Domain\EmailTransport: SMTP protocol transport (connect, STARTTLS, AUTH, send, close).
Template rendering is performed via PayCal\Domain\Render::template(), with both HTML and text bodies built for each flow.
Verification links are environment-localized using request host resolution so links remain aligned to the current deployment context.
Support Email Telemetry and Auditability
Contact-support submissions include best-effort telemetry so delivery health can be monitored without blocking user submissions.
- Aggregate counters are recorded under
telemetry:contact:*keys. - JSONL event records are appended to rotated logs via
PayCal\Domain\ContactSupportTelemetry. - Log writing is non-blocking to preserve support-form UX if telemetry storage is degraded.
Verification and Reliability Checks
html/tests/Unit/EmailTemplateRenderTest.phpverifies all supported templates render with expected placeholder substitution.html/tests/Integration/LiveEmailTemplateSweepTest.phpprovides opt-in live SMTP end-to-end template coverage.html/tests/Integration/EmailSendTest.phpprovides opt-in single-message verification for SMTP, DKIM, DMARC, and Message-ID health.
# Opt-in live template sweep cd html PAYCAL_RUN_LIVE_EMAIL_SWEEP=1 PAYCAL_LIVE_EMAIL_RECIPIENT=you@example.com \ ./vendor/bin/phpunit --configuration phpunit.xml tests/Integration/LiveEmailTemplateSweepTest.php # Opt-in single email stack verification cd html PAYCAL_RUN_LIVE_EMAIL=1 PAYCAL_LIVE_EMAIL_RECIPIENT=you@example.com \ ./vendor/bin/phpunit --configuration phpunit.xml tests/Integration/EmailSendTest.php
Scope Boundary
This page documents transactional and support email behavior for PayCal product operations. It does not document marketing automation because PayCal does not use a marketing email funnel in this codebase.
Last updated: March 21, 2026.