Skip to content

Amazon SES — Claude CLI Access & Tracking Configuration

Created 2026-04-23
Status planned
Tags planinfrastructureemailsesfluentcrmdeliverability

FluentCRM on crm.baseworks.com sends email through Amazon SES. SES configuration sets currently have open and click tracking enabled, which rewrites every outbound link to a generic AWS tracking URL (*.awstrack.me). That wrapping has three downsides:

  1. Deliverability noise — generic AWS tracking domains in body links look like bulk/marketing infrastructure to inbox filters and reputation systems.
  2. Link readability — recipients hovering over a link see awstrack.me, not a Baseworks-branded URL.
  3. Double-wrapping — FluentCRM also wraps links with its own click tracking (using its already-configured custom tracking domain). The two layers compound and produce ugly, fragile redirects.

A previous manual attempt (Patrick + Claude in the SES web console) couldn’t locate the correct tracking toggle. The console UI buries it inside configuration set event destinations, and it’s easy to confuse with engagement metrics. CLI access removes the ambiguity — aws sesv2 get-configuration-set --configuration-set-name X shows the current tracking options as plain JSON, and put-configuration-set-tracking-options is a single deterministic call.

The deliverability objective: keep one tracking layer (FluentCRM, on its branded custom domain) and turn the SES layer off, so links in delivered email read as track.baseworks.com/... (or whatever the FluentCRM tracking domain is), not as awstrack.me/....

CLI access is also a long-term investment — future SES work (DKIM rotation, suppression list management, configuration set tuning, reputation monitoring, sending-statistics queries) becomes scriptable and auditable instead of click-paths through a console.


  1. Provision a least-privilege IAM principal that the Claude Code CLI on Patrick’s Mac can use to manage SES indefinitely.
  2. Use that access to disable SES open and click tracking on the active configuration set(s) so SES stops wrapping links.
  3. Verify FluentCRM’s own click tracking remains enabled and is using its custom tracking domain (i.e. the surviving tracking layer is the branded one).
  4. Send a test campaign (or trigger a transactional message) and confirm delivered links resolve through the FluentCRM custom domain only — no awstrack.me.
  5. Document the credential location and the tracking decision so future sessions don’t re-enable it.

  • Migrating away from SES.
  • Reconfiguring DKIM/SPF/DMARC (already in place on crm.baseworks.com).
  • Adding a new custom tracking subdomain at the SES layer — explicitly the rejected alternative; FluentCRM’s existing custom domain is the chosen tracking surface.
  • Changing FluentCRM’s tracking on/off state. It stays on. We only verify it.

Phase 1 — Provision Claude-scoped AWS credentials

Section titled “Phase 1 — Provision Claude-scoped AWS credentials”
  1. Sign in to the AWS console as the root/admin user that owns the SES account (Patrick).
  2. Create an IAM user: claude-cli-ses (programmatic access, no console login).
  3. Attach a least-privilege inline policy scoped to SES v2 + supporting read APIs. Starting policy (refine if SDK calls error during execution):
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "SESConfigAndSend",
"Effect": "Allow",
"Action": [
"ses:*",
"sesv2:*",
"ses:GetSendQuota",
"ses:GetSendStatistics"
],
"Resource": "*"
},
{
"Sid": "CloudWatchReadForReputation",
"Effect": "Allow",
"Action": [
"cloudwatch:GetMetricData",
"cloudwatch:GetMetricStatistics",
"cloudwatch:ListMetrics"
],
"Resource": "*"
}
]
}

Rationale: ses:* + sesv2:* covers tracking options, configuration sets, identities, suppression list, dedicated IP management, and event destinations — the surfaces we’ll touch over time. CloudWatch read is needed for reputation/bounce-rate queries. No IAM, no S3, no logging-destination write — narrowly scoped.

  1. Generate an access key pair for that user.

  2. Install on Patrick’s Mac under a named profile so it doesn’t collide with any other AWS work:

    ~/.aws/credentials
    [baseworks-ses]
    aws_access_key_id = AKIA...
    aws_secret_access_key = ...
    ~/.aws/config
    [profile baseworks-ses]
    region = us-east-1
    output = json

    Confirm the SES region first — crm.baseworks.com’s SMTP endpoint hostname tells us which region to use (e.g. email-smtp.us-east-1.amazonaws.com → us-east-1).

  3. Smoke test:

    aws --profile baseworks-ses sesv2 list-configuration-sets
    aws --profile baseworks-ses sesv2 get-account
  4. Store credentials in the changelog repo’s secrets reference (per the “all server SSH credentials live in the changelog repo” rule — extend it to AWS keys). Add a one-line memory pointer; do not duplicate the secret in the vault.

Phase 2 — Inventory current SES tracking state

Section titled “Phase 2 — Inventory current SES tracking state”
  1. List the configuration sets attached to the FluentCRM sending identity:

    aws --profile baseworks-ses sesv2 list-configuration-sets
  2. For each, dump the tracking options:

    aws --profile baseworks-ses sesv2 get-configuration-set --configuration-set-name <name>

    Look for TrackingOptions.CustomRedirectDomain and any event destination of type Open / Click.

  3. Identify which configuration set FluentCRM is actually using. This is settable in FluentCRM → Settings → Email Settings → Amazon SES connection. Confirm in the WP admin (or via the FluentCRM PHP API) before changing anything, so we don’t disable tracking on the wrong set.

Phase 3 — Disable SES open/click tracking

Section titled “Phase 3 — Disable SES open/click tracking”
  1. Remove the Open and Click event destinations on the live configuration set:

    aws --profile baseworks-ses sesv2 list-configuration-set-event-destinations --configuration-set-name <name>
    aws --profile baseworks-ses sesv2 delete-configuration-set-event-destination \
    --configuration-set-name <name> --event-destination-name <dest>

    (Or update-configuration-set-event-destination with MatchingEventTypes reduced to BOUNCE, COMPLAINT, DELIVERY, REJECT, RENDERING_FAILURE — keep the deliverability events, drop the open/click pixel-and-redirect events.)

  2. Clear the SES custom tracking domain if one is set (we don’t want SES to keep rewriting links to a branded SES domain when the intent is no SES rewriting at all):

    aws --profile baseworks-ses sesv2 put-configuration-set-tracking-options \
    --configuration-set-name <name> --custom-redirect-domain ""
  3. Re-fetch the configuration set and confirm no Open/Click event destinations remain.

Phase 4 — Verify FluentCRM tracking layer

Section titled “Phase 4 — Verify FluentCRM tracking layer”
  1. WP admin → FluentCRM → Settings → Email Settings → confirm “Track Email Opens” and “Track Click” remain ON.
  2. Confirm the custom tracking domain is set (it already is, per Patrick’s note) and resolves with a valid TLS cert. From Patrick’s Mac:
    curl -I https://<fcrm-tracking-domain>/

Phase 5 — End-to-end deliverability test

Section titled “Phase 5 — End-to-end deliverability test”
  1. Send a test campaign to a small internal list (Patrick’s address + one alias).
  2. Inspect the delivered email source:
    • Links should be wrapped as https://<fcrm-tracking-domain>/... only.
    • No awstrack.me or SES tracking domain in any link.
    • Open-tracking pixel (if FCRM injects one) points to the FCRM domain.
  3. Click a link, confirm it redirects through FCRM and lands on the intended URL with no double-redirect.
  4. Confirm in FluentCRM’s per-campaign analytics that opens/clicks are still being recorded — i.e. the FCRM tracking layer survived.
  1. Add a reference- memory entry pointing to the changelog secrets file for the SES credentials and the tracking decision.
  2. Update 00-inbox/claude-code-shared-context.md with a short “Email infrastructure → SES” section: where the IAM user lives, which profile name to use, the tracking decision, and the date.
  3. Move this plan to 03-resources/plans/executed-plans/ once Phase 5 verifies clean.

  • ~/.aws/credentials and ~/.aws/config on Patrick’s Mac (profile: baseworks-ses) — created in Phase 1.
  • ~/Documents/baseworks-changelog/CLAUDE-INSTRUCTIONS.md — extend the existing “credentials reference” section to include this AWS profile.
  • 00-inbox/claude-code-shared-context.md — add an Email Infrastructure section.
  • FluentCRM Settings UI on crm.baseworks.com (read-only check, no edits expected).

  • Wrong configuration set edited. Mitigation: Phase 2 explicitly identifies the live set before any change in Phase 3.
  • Disabling tracking event destinations also drops bounce/complaint capture. Mitigation: only remove OPEN + CLICK event types; keep BOUNCE/COMPLAINT/DELIVERY/REJECT/RENDERING_FAILURE — these feed reputation monitoring.
  • IAM key leakage. Mitigation: key lives only in ~/.aws/credentials (not committed) and the encrypted secrets reference in the changelog repo. Rotate annually as a habit; SES API key has no console blast radius (no IAM/billing access in the policy).
  • FluentCRM tracking domain quietly broken. Mitigation: Phase 4 verifies the cert before Phase 5 sends real traffic.
  • Deliverability regression. Mitigation: send the Phase 5 test to internal addresses only; if anything looks off (Spam folder placement, broken links), the update-configuration-set-event-destination call is reversible — re-add OPEN/CLICK destinations to roll back.

End-to-end success means all of the following are true after Phase 5:

  • aws --profile baseworks-ses sesv2 get-configuration-set --configuration-set-name <live> shows no Open/Click event destinations and no CustomRedirectDomain.
  • A delivered test email’s HTML source contains zero occurrences of awstrack.me (or any SES-owned tracking host).
  • FluentCRM analytics show the test email’s open and at least one click registered.
  • A click on a body link redirects through <fcrm-tracking-domain> exactly once and lands on the intended URL.
  • Bounce/complaint events still flow to whatever destination they currently target (CloudWatch / SNS / FluentCRM webhook — confirm whichever is wired).