Debugging Email Delivery Failures: Gmail SMTP Relay vs. SES API Pathways

During a recent development session, we encountered email delivery failures across multiple pathways in our Queen of San Diego infrastructure. What appeared to be a single SES configuration issue turned out to be two distinct failure modes operating simultaneously: a stale Gmail "Send mail as" SMTP relay and a separate recipient-side rejection. Here's how we diagnosed and approached remediation.

The Problem: Two Failure Modes

Screenshots from user reports showed bounce messages arriving at jadasailing@gmail.com with the error "misconfigured or out of date" credentials. Initial assumption: SES was misconfigured. Reality: we had two separate issues.

  • Failure 1: Gmail's "Send mail as" alias for admin@queenofsandiego.com had stale SMTP relay credentials pointing to Amazon SES
  • Failure 2: A separate email sent via SES API was rejected by Exchange Online at the recipient domain (steigerwald-dougherty.com)

Only by isolating the email pathways could we address each independently.

Technical Investigation: Email Pathway Mapping

We started by mapping the email infrastructure:

User sends from: jadasailing@gmail.com
  └─ Using Gmail alias: admin@queenofsandiego.com
       └─ Relayed through SMTP server: email-smtp.us-east-1.amazonaws.com:587
            └─ Auth mechanism: IAM-derived SES SMTP credentials
                 └─ Bounce returned to: jadasailing@gmail.com (Gmail's sending account)

The key insight: Gmail bounced the email before it left Gmail's infrastructure. The bounce didn't come from SES or the recipient—it came from Gmail's SMTP relay validation layer.

Credential Rotation and SES SMTP Authentication

Our next step was to verify SES SMTP credentials. AWS SES doesn't use standard IAM access keys for SMTP authentication; instead, it requires a derived credential set using a specific v4 signature algorithm.

We tested credential derivation using the current IAM user's access key:

# Pseudo-command (actual credentials never logged):
# 1. Retrieve current IAM user's access key ID and secret
# 2. Apply AWS SES SMTP v4 derivation algorithm to generate SMTP password
# 3. Test authentication against email-smtp.us-east-1.amazonaws.com:587
#    Username: [IAM-derived SMTP username format]
#    Password: [v4-derived SMTP password]

The credentials we derived did authenticate successfully against the SES SMTP endpoint. This confirmed that our SES infrastructure was healthy and that the problem lay with whatever credentials were previously configured in Gmail's alias settings.

SES Domain and Email Authentication Infrastructure

While debugging the SMTP relay issue, we verified the underlying email authentication setup for completeness:

  • SES verified identities: Checked all identities in us-east-1 and us-west-2 regions for verification status and bounce/complaint suppression lists
  • SPF record for queenofsandiego.com: Present in Route53, includes SES sending IP ranges
  • DKIM configuration: All three CNAME records present in DNS, pointing to SES-managed DKIM tokens
  • DMARC policy: Configured with aggregate reporting endpoint
  • Custom MAIL FROM domain: Set to mail.queenofsandiego.com with verified MX and SPF records

All email authentication infrastructure was correctly configured. The issue was purely credential-related at the Gmail application layer.

SES Suppression List Analysis

We also audited the SES suppression lists across regions to understand historical bounce patterns:

# Commands executed (no credentials shown):
# - List all suppressed addresses in us-east-1 and us-west-2
# - Filter by suppression reason (bounce vs. complaint)
# - Check for addresses added on specific dates (e.g., April 18)
# - Verify evastarr24@example.com suppression status and reason

The suppression lists showed expected patterns from previous campaigns, but no blocking issues that would prevent future sends—assuming credentials are correct.

The Gmail "Send mail as" Alias: How It Works

Gmail's "Send mail as" feature allows users to send from alias addresses by configuring an external SMTP relay. The flow:

  1. User composes email in Gmail interface, selects admin@queenofsandiego.com as sender
  2. Gmail connects to configured SMTP server (email-smtp.us-east-1.amazonaws.com:587) using stored credentials
  3. Gmail performs SMTP AUTH with username and password
  4. If auth fails, Gmail bounces the email back to the sending account (jadasailing@gmail.com)
  5. If auth succeeds, Gmail relays the message through the external SMTP server

The "misconfigured or out of date" error indicates step 3 failed—the stored credentials no longer work.

Root Cause: Credential Lifecycle

SES SMTP credentials, while derived from current IAM credentials, can become stale when:

  • The underlying IAM access key is rotated or regenerated
  • The person who originally configured the alias leaves or has their credentials revoked
  • A credential generation script was used with a specific IAM user that no longer has permissions

In this case, whoever set up the Gmail alias likely used an older IAM user or access key that has since been rotated out of service.

Remediation Path

To fix the Gmail alias, the following steps are required (no CLI needed—all through Gmail UI):

  1. Log into jadasailing@gmail.com
  2. Navigate to Settings → Accounts and Import → "Send mail as"
  3. Click "edit info" on the admin@queenofsandiego.com alias entry
  4. Update SMTP credentials:
    • Server: email-smtp.us-east-1.amazonaws.com
    • Port: 587
    • Username: [Current IAM-derived SES SMTP username]
    • Password: [Current v4-derived SES SMTP password]
  5. Gmail will validate the credentials by attempting a test send
  6. Once validated, the alias will be functional again

To obtain fresh credentials: AWS Management Console → SES → SMTP Settings → "Create SMTP Credentials" (generates a new username/password pair specific to that IAM user).

The Second Failure: Exchange Online Rejection

The separate email that was successfully relayed through SES was rejected at steigerwald-dougherty.com (an Exchange Online domain). This is a recipient-side filtering decision, not an SES issue. Typical causes include:

  • DMARC policy rejection (recipient enforces DMARC p=reject)
  • Recipient domain's blocklist