Skip to main content

AWS SES domain & deliverability setup

This guide is for DevOps / platform operators who configure Amazon SES before agents can connect email via the Any email (forwarding) path in Fiko.

Architecture overview

Inbound: MX on inbound.example.com → SES receipt rule → S3/SNS → Fiko messaging-service

Per-channel address: [email protected] (generated in Fiko UI)

Outbound From: [email protected]

Reply-To: tokenized address on reply domain for threading

Figure 1 — Two verified domains: inbound (receive) and reply (send). Publish MX, SPF, DKIM, and DMARC on each.

SES email receiving is only available in specific regions (e.g. us-east-1, eu-west-1). Pick one region and keep MX, receipt rules, and API calls in the same region.

Before you start

AWS account with SES access

Permission to create identities, receipt rules, and IAM users.

Two subdomains you control

e.g. inbound.example.com (receive) and reply.example.com (send).

DNS admin access

To publish MX, TXT, CNAME records for both subdomains.

fiko-messaging-service .env access

For EMAIL_SES_* credentials and domain vars.

Step-by-step setup

Setup time: 45–90 minutes (includes DNS propagation)

Part A — Choose region and request production access

  1. 1Open AWS Console → switch to your target region (e.g. US East (N. Virginia) us-east-1).
  2. 2Go to Amazon SESAccount dashboard.
  3. 3If status shows Sandbox, click Request production access.
    • Mail type: Transactional
    • Use case: Customer support email for SaaS platform
    • Approval typically within 24–48 hours

    Expected result

    In sandbox you can only send to verified addresses. Agents cannot go live until production access is granted.

Part B — Verify inbound domain (receive mail)

  1. 4SES → Verified identitiesCreate identity → type Domain.
  2. 5Enter inbound subdomain: e.g. inbound.example.com → Create.
  3. 6Copy DNS records SES shows (DKIM CNAMEs + verification TXT) → publish in your DNS provider.
  4. 7Add MX record for inbound subdomain:
    Host: inbound.example.com
    Type: MX
    Priority: 10
    Value: inbound-smtp.us-east-1.amazonaws.com

    Expected result

    SES identity status becomes Verified (may take up to 72 hours for DNS).

Part C — Receipt rule set (route inbound mail to Fiko)

SES receives mail via MX → the receipt rule decides where to store the raw MIME and how to notify Fiko. Fiko reads the email from S3 (or from SNS inline payload if the message is small).

  1. 8SES → Email receivingRule setsCreate rule set.
    • Rule set name: fiko-inbound
    • Click Create
  2. 9Select the new rule set → Set as active rule set.

    Expected result

    Only one active rule set per region. Deactivate the old rule set first if needed.
  3. 10Inside the rule set → Create rule. Fill each field below:

Receipt rule — every field to fill

SES Console fieldValueNotes
Rule namecatch-all-inboundAny descriptive name
StatusEnabledRule must be Enabled to receive mail
TLSOptional (or Required if policy mandates)Non-TLS mail still accepted if Optional
Spam and virus scanningEnabledFiko reads spamVerdict / virusVerdict from SNS payload
Recipients*@inbound.example.comReplace inbound.example.com with EMAIL_INBOUND_DOMAIN. Wildcard matches all per-channel addresses
[email protected]You can add specific addresses — but *@ is enough because Fiko auto-generates per channel

Actions — order and configuration (critical)

#Action typeDetailed configuration
1Deliver to S3 bucketBucket: fiko-ses-inbound-prod (create first, same region e.g. us-east-1). Object key prefix: emails/ (optional). IAM role for this action: create role with trust policy ses.amazonaws.com + s3:PutObject on bucket — SES Console can auto-create this role when you pick the bucket
2Publish to Amazon SNS topicAttach SNS to the S3 action (recommended) OR add a standalone SNS action. Topic: fiko-ses-inbound-notify. Encoding: UTF-8
  1. 11Create S3 bucket (if not exists): S3 → Create bucket → name fiko-ses-inbound-prod → same region as SES.
    • Block public access: ON (private bucket)
    • Versioning: optional
    • Lifecycle: optional — delete objects after 90 days to save cost
  2. 12Create SNS topic: SNS → TopicsCreate topic → name fiko-ses-inbound-notify → Standard.
  3. 13Subscribe topic to Fiko webhook:
    • Topic → Create subscription
    • Protocol: HTTPS
    • Endpoint: https://msg.fikosrv.com/v2/email/ses/inbound
    • Enable raw message delivery: OFF (Fiko verifies SNS signature on JSON envelope)

    Expected result

    SNS sends SubscriptionConfirmation — Fiko auto-confirms via SubscribeURL. Check messaging-service log: SES SNS subscription confirmed.
  4. 14(Optional) Bounce/complaint events — separate topic subscribed to:
    https://msg.fikosrv.com/v2/email/ses/events
    Configure in SES → Configuration sets or identity notifications.
  5. 15Save receipt rule → send test email to [email protected] → verify:
    • S3 bucket has a new .eml object
    • SNS topic shows successful delivery to Fiko endpoint
    • CloudWatch / messaging-service log shows no Invalid SNS signature errors
Figure 3 — Receipt rule: match *@inbound.example.com, then S3 store + SNS notify Fiko messaging-service.

Part D — Verify reply domain (send mail)

  1. 16SES → Verified identities → Create identity → Domain → reply.example.com.
  2. 17Enable Easy DKIM → publish the 3 CNAME records SES provides.
  3. 18Configure Custom MAIL FROM domain:
    • MAIL FROM: e.g. bounce.reply.example.com
    • Publish MX + SPF records SES provides for MAIL FROM subdomain
  4. 19Add SPF on reply domain:
    Host: reply.example.com
    Type: TXT
    Value: v=spf1 include:amazonses.com ~all
  5. 20Add DMARC (start monitoring):
    Host: _dmarc.reply.example.com
    Type: TXT
    Value: v=DMARC1; p=none; rua=mailto:[email protected]
Figure 2 — DNS records for reply domain: align SPF, DKIM, and DMARC before sending to customers (reduces spam).

Part E — IAM user for Fiko

  1. 21IAM → UsersCreate user → name fiko-email-ses → do not enable console access.
  2. 22Attach inline policy (replace bucket name if different):
    {
      "Version": "2012-10-17",
      "Statement": [
        {
          "Sid": "SesSend",
          "Effect": "Allow",
          "Action": ["ses:SendRawEmail", "ses:SendEmail"],
          "Resource": "*"
        },
        {
          "Sid": "SesInboundS3Read",
          "Effect": "Allow",
          "Action": ["s3:GetObject"],
          "Resource": "arn:aws:s3:::fiko-ses-inbound-prod/*"
        }
      ]
    }

    Expected result

    Use a dedicated fiko-email-ses user — do not reuse PRIVATE_AWS_* (company file-upload S3 keys).
  3. 23Security credentials → Create access key → Use case: Application running outside AWS → copy Access key ID + Secret.

Part F — Environment variables

  1. 24On fiko-messaging-service:
    EMAIL_SES_ACCESS_KEY_ID=AKIA...
    EMAIL_SES_SECRET_ACCESS_KEY=...
    AWS_SES_REGION=us-east-1
    EMAIL_INBOUND_DOMAIN=inbound.example.com
    EMAIL_REPLY_DOMAIN=reply.example.com
  2. 25On fiko-core-service (validates inbound address when agent creates forwarding channel):
    EMAIL_INBOUND_DOMAIN=inbound.example.com
  3. 26Redeploy / restart messaging-service and core-service after updating env.

Part G — Verify end-to-end

  1. 27In Fiko → AppsEmailAdd newAny email (forwarding).
  2. 28Enter support address → Fiko generates inbound address like support-{token}@inbound.example.com.
  3. 29Configure forwarding on the mail server → Test configuration → Connect.
  4. 30Complete test configuration → create channel → send test email.

    Expected result

    Chat appears in Fiko; reply sends from @reply.example.com with spf=pass, dkim=pass in Gmail "Show original".

DNS records — complete reference

Replace example.com with your real domain. Production uses e.g. inbound.fiko.ai / reply.fiko.ai.

Host / NameTypeValuePurpose
inbound.example.comMX10 inbound-smtp.us-east-1.amazonaws.comInbound — receive mail
inbound.example.comTXT(SES domain verification token)Inbound — verify identity
*._domainkey.inbound.example.comCNAME(3 DKIM CNAME from SES — if DKIM enabled on inbound)Inbound — optional
reply.example.comTXTv=spf1 include:amazonses.com ~allReply — SPF
reply.example.comTXT(SES domain verification)Reply — verify identity
*._domainkey.reply.example.comCNAME(3 Easy DKIM CNAME from SES)Reply — DKIM required
bounce.reply.example.comMX(MAIL FROM MX from SES Custom MAIL FROM)Reply — bounce alignment
bounce.reply.example.comTXTv=spf1 include:amazonses.com ~allReply — MAIL FROM SPF
_dmarc.reply.example.comTXTv=DMARC1; p=none; rua=mailto:[email protected]Reply — DMARC monitor

Fiko webhook endpoints (SES)

EndpointMethodCallerPurpose
https://msg.fikosrv.com/v2/email/ses/inboundPOST (HTTPS)Amazon SNSNew mail → Fiko parses → creates chat
https://msg.fikosrv.com/v2/email/ses/eventsPOST (HTTPS)Amazon SNSBounce / complaint notifications (optional)

SNS subscription confirmation: Fiko auto-calls SubscribeURL when it receives Type=SubscriptionConfirmation. No manual confirm needed if messaging-service is running and the endpoint is publicly reachable.

Per-channel inbound addresses

When an agent creates a forwarding channel, Fiko auto-generates the address — no separate receipt rule per address if the rule uses *@inbound.example.com.

# Example format (random token per channel):
[email protected]

# Env must match the suffix:
EMAIL_INBOUND_DOMAIN=inbound.example.com

SES sandbox vs production access

CheckSandbox (default)Production (required for real customers)
Send to unverified addressesBlockedAllowed
Receive inbound mailWorks if DNS + receipt rule configuredSame
Daily send quota200 emails/dayStarts at 50,000/day (request increase)
How to exit sandboxSES Console → Account dashboard → Request production access

Request production access with: use case (customer support email), expected volume, bounce/complaint handling, and confirmation that SPF/DKIM/DMARC are configured on the reply domain.

Environment variables reference

VariableServiceExample
EMAIL_SES_ACCESS_KEY_IDmessaging onlyAKIA...
EMAIL_SES_SECRET_ACCESS_KEYmessaging only...
AWS_SES_REGIONmessaging onlyus-east-1
EMAIL_INBOUND_DOMAINmessaging + coreinbound.example.com
EMAIL_REPLY_DOMAINmessaging onlyreply.example.com

Deliverability checklist

  • SPF on reply domain includes amazonses.com
  • DKIM Easy DKIM shows Verified in SES
  • Custom MAIL FROM configured and verified
  • DMARC published (start p=none, tighten later)
  • SES production access granted (not sandbox)
  • Warm up sending volume gradually
  • Test with mail-tester.com — target score 8+/10

In Gmail "Show original", look for spf=pass, dkim=pass, dmarc=pass.

Use dedicated EMAIL_SES_* IAM credentials — never commit to git or reuse company S3 keys.

AWS SES Domain & Deliverability Setup — Email Integration