Trust & Email Sending Practices

Last updated: 2026-05-16 · Maintained for AWS SES reviewers, security auditors, and compliance teams.

This page consolidates the operational facts about how MiGo Piggy sends email. It is intended as a single-page reference for AWS Support reviewers evaluating our SES production access request, as well as for any third party assessing our sender hygiene.

1. Product status

2. What email is used for

Email is used only for transactional, user-initiated messages tied to a specific account action. There is no marketing email, no newsletter, no announcement broadcast, no campaign feature, no CSV upload, and no arbitrary-text sending interface anywhere in the product.

TemplateTriggerRecipient
email_otpUser taps "Send code" in iOS app or webThe exact address the user just typed

The codebase contains one and only one entry point to SES SendEmail (apps/accounts/services/email.py). It enforces a compile-time template allowlist (ALLOWED_TEMPLATES = {'email_otp'}). Any future template additions (merchant claim approval, account security notice) will go through the same allowlist; no caller can pass a free-form subject or body.

3. Non-use commitments

4. Recipient source & consent

Each recipient address comes from a single user action: the user opens the iOS app or our website, types their own email into a labelled input field, and taps "Send verification code." This is the only path that produces a recipient address. The user is shown, before tapping, an explicit notice:

"Enter your email to receive a one-time verification code. We will only use this email for login, account security, and service-related notifications. We do not send marketing emails."

There are no pre-checked boxes, no opt-out / unsubscribe required (the message is a single-purpose security code under RFC 8058, which exempts transactional security messages), and no cookies or trackers gate this flow.

5. Anti-abuse controls (live in production today)

The OTP send endpoint is hardened at multiple layers before reaching SES. All limits are enforced atomically in Redis and tested under concurrency.

LayerLimitSource
Per-email cooldown1 request per 60 seconds (atomic SETNX)OTP_RATE_LIMIT_TTL=60
Per-email 24h cap10 sends per address per dayOTP_PER_ACCOUNT_DAILY_LIMIT=10
Per-IP cap3 OTP send requests per minute (DRF AnonRateThrottle)DEFAULT_THROTTLE_RATES['otp_send']
Global daily cap (email channel)50,000 sends per 24h, account-wide circuit breakerOTP_GLOBAL_DAILY_LIMITS['email']
Disposable email blocklist50+ throwaway domains (mailinator, guerrillamail, 10minutemail, tempmail, yopmail, ...) — rejected before any SES callapps/accounts/services/email_validation.py
Typo domain correctionCommon typos (gmial.com, qq.con, hotmial.com, icould.com, ...) intercepted with a "did you mean ___?" response — no SES call wastedSame module
Pre-send suppression checkLocal EmailSuppression table queried before every SendEmail; known-bad addresses silently skip the API callEmailSuppression model
OTP verify attempts5 wrong codes invalidates the OTP; failed verifies do not extend the OTP's TTL (no infinite-window attack)OTP_MAX_ATTEMPTS=5
User enumerationotp_send returns the same response whether the address exists in our user table or notapps/accounts/views.py

6. Email service provider

During MVP launch we send through Resend (region us-east-1) — a transactional-only email service that runs on AWS SES infrastructure under the hood. Post-launch we will migrate primary sending to our own AWS SES production access (currently in sandbox).

Both providers feed the same local EmailSuppression table; bounce/complaint hygiene is provider-agnostic.

7. Bounce & complaint feedback loop

End-to-end pipeline, verified in production:

Resend send (or SES SendEmail when switched back)
  → provider webhook (Svix HMAC-SHA256 for Resend; SNS+cert for SES)
  → https://api.migopiggy.com/api/v1/auth/resend-events/ (or /ses-events/)
  → signature verification + replay window check (±5 min Resend, ±1 hour SES)
  → PostgreSQL EmailSuppression table (permanent, indexed on lowercase email)
  → All future sends for that address silently skipped before reaching the provider

8. Domain authentication

9. Sample OTP email

Below is the verbatim production template (bilingual EN + Simplified Chinese, text/plain + text/html multipart). No tracking, no remote images, no marketing copy.

Subject: MiGo Piggy verification code / 验证码

You received this email because someone requested a MiGo Piggy login
verification code using this email address.

Your verification code is: 482913

This code expires in 5 minutes.

If you did not request this code, you can safely ignore this email. Your
account remains secure and no action is required. If you receive these
messages repeatedly without requesting them, please contact us at
support@migopiggy.com so we can investigate.

-- MiGo Piggy Team
   noreply@migopiggy.com
   https://migopiggy.com
   Support: support@migopiggy.com

10. Contact & RFC 2142 mailboxes

All standard administrative mailboxes are deliverable and monitored (via Cloudflare Email Routing):

11. AWS resources

12. Reporting abuse

If you receive an unsolicited MiGo Piggy email, suspect impersonation, or want to report a sender reputation issue, please email abuse@migopiggy.com or postmaster@migopiggy.com. Include full message headers if possible. We respond within 5 Australian business days; urgent reports prefixed [URGENT] are prioritised.