MailGap Reply User Flow

Status: Draft Last Updated: 2026-02-06 Owner: Product / Engineering


Purpose

This document defines the user flow for replying to an inbound email within the MailGap Proxy Email Service.

It describes:

  • How users initiate a reply
  • When replies are allowed or blocked
  • Page-by-page UI layout
  • System checks and enforcement points

This document defines how users experience replies. All rules are enforced server-side per the MailGap specification and contracts.


Scope

In Scope

  • Replying to an inbound MailGap message
  • Credit checks and consumption
  • Abuse and suppression enforcement
  • Blocked reply states

Out of Scope

  • Composing new outbound emails
  • Forwarding emails
  • Attachments in replies
  • HTML email composition

Preconditions

The flow assumes:

  • User is authenticated
  • User owns the MailGap alias
  • Inbound message exists
  • Alias status is active
  • User has not exceeded daily limits

Authorization MUST comply with:

  • docs/contracts/authz-and-roles.new.md
  • docs/contracts/rls-standard.new.md

Entry Points

Users enter this flow from:

  • MailGap Inbox → Message Detail View

    • CTA: “Reply”
  • Notification deep link (push, email, or in-app alert)

    • Route: /mailgap/messages/[message_id]
    • Lands directly on Message Detail View
    • Requires authentication
    • Requires ownership validation

Deep Link Authentication Behavior

If the user taps a notification while logged out:

  1. Redirect to login
  2. After successful login, redirect back to /mailgap/messages/[message_id]
  3. Validate message ownership via RLS
  4. If ownership fails, show 404 or generic error

This behavior MUST be implemented consistently for all notification types.


High-Level Flow Overview (ASCII)

[ Notification or Inbox ] | v [ Message Detail View ] | v [ Reply Composer ] | +--> [ Reply Blocked ] | v [ Send Attempt ] | +--> [ Error State ] | v [ Reply Sent Success ]


Page-by-Page Flow


Page 1: Message Detail View

Route: /mailgap/messages/[message_id]

Purpose

Allow the user to read an inbound message and initiate a reply.


UI Layout (ASCII)

+--------------------------------------------------+ | Header | | - MailGap | | - Credits: 72 / 100 | +--------------------------------------------------+ | | | From: support@example.com | | To: alias@cairlmail.com | | Subject: Your request |

Message body (plain text)
------------------------------------------------
[ Reply ] [ Delete ]
+--------------------------------------------------+

UI Elements

  • Message metadata (from, subject)
  • Message body (plain text)
  • Reply CTA
  • Credit indicator

User Actions

Action Result
Click Reply Proceed to Reply Composer
Click Delete Message removed

System Behavior

On load:

  • Authenticate user
  • Validate message ownership via RLS
  • Check alias status
  • Determine reply eligibility

If ownership validation fails:

  • Do not reveal message existence
  • Return 404 or generic error

Transition Conditions

Condition Next Page
Reply allowed Reply Composer
Reply blocked Reply Blocked State


Page 2: Reply Composer

Route: /mailgap/messages/[message_id]/reply

Purpose

Allow the user to compose a plain-text reply.


UI Layout (ASCII)

+--------------------------------------------------+ | Reply to: support@example.com | | From: alias@cairlmail.com | +--------------------------------------------------+ | | | +----------------------------------------------+ | | | Type your reply (plain text only) | | | | | | | | | | | +----------------------------------------------+ | | | | Credits required: 10 | | Credits remaining: 72 | | | | [ Send Reply ] [ Cancel ] | | | +--------------------------------------------------+


User Actions

Action Result
Click Send Reply Attempt send
Click Cancel Return to Message Detail

System Behavior (on Send)

Server performs, in order:

  1. Ownership check (RLS)
  2. Alias status check
  3. Allowlist validation
  4. Suppression check
  5. Credit availability check
  6. Abuse guardrail checks
  7. Send via email provider
  8. Persist outbound message
  9. Deduct credits atomically

Failures short-circuit immediately.


Transition Conditions

Condition Next Page
Send success Reply Sent Success
Any failure Error or Blocked State


Blocked and Error States


Blocked State: Reply Not Allowed

Displayed when:

  • Sender is not allowlisted
  • Recipient is suppressed
  • Alias is paused or disabled
  • Safety guardrails block sending

UI Layout (ASCII)

+--------------------------------------------------+ | ❌ Reply Not Available | | | | This sender cannot be replied to at this time. | | | | Reason (generic, non-exploitable): | | “Replies are restricted to protect deliverability”| | | | [ Request Access ] (if applicable) | | [ Back to Inbox ] | +--------------------------------------------------+

Behavior:

  • No send attempt occurs
  • Credits are not consumed
  • Event is logged

Error State: Send Failed

Displayed when:

  • Temporary provider failure
  • Network or system error

UI Layout (ASCII)

+--------------------------------------------------+ | ⚠️ Unable to Send Reply | | | | Something went wrong. Please try again later. | | | | [ Retry ] [ Cancel ] | +--------------------------------------------------+

Behavior:

  • Credits not consumed
  • Retry allowed
  • Error logged for observability

Success State


Reply Sent Confirmation

Purpose

Confirm the reply was successfully sent.


UI Layout (ASCII)

+--------------------------------------------------+ | ✅ Reply Sent | | | | Your message has been sent successfully. | | | | [ Back to Message ] | | [ Go to Inbox ] | +--------------------------------------------------+


Error Handling Summary

Error Type User Message Recovery
Allowlist Reply not available Request access
Suppression Cannot reply None
Rate limit Try again later Wait
Credits Not enough credits Upgrade
System Temporary issue Retry

Observability Notes

This flow MUST emit:

  • Reply attempt events
  • Blocked reply events (with reason code)
  • Successful send events
  • Provider failure events
  • Deep-link login redirects

Observability MUST comply with:

  • docs/architecture/observability-plan.new.md

Non-Negotiable Rules

  • Replies are reply-only
  • UI gating is advisory only
  • Server enforces all checks
  • Credits deducted atomically
  • Blocked states do not leak abuse logic

Acceptance Criteria

  • Deep links land on Message Detail View
  • Logged-out users are redirected back after login
  • Ownership validation enforced on load
  • Reply behavior matches spec
  • Credits and abuse controls enforced
  • All events observable

References

  • docs/specs/mailgap/mailgap-proxy-email-service.spec.new.md
  • docs/contracts/authz-and-roles.new.md
  • docs/contracts/rls-standard.new.md
  • docs/contracts/rate-limits-and-abuse.new.md
  • docs/architecture/observability-plan.new.md

End of Document