Amazon SES — Claude CLI Access & Tracking Configuration
Context
Section titled “Context”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:
- Deliverability noise — generic AWS tracking domains in body links look like bulk/marketing infrastructure to inbox filters and reputation systems.
- Link readability — recipients hovering over a link see
awstrack.me, not a Baseworks-branded URL. - 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.
- Provision a least-privilege IAM principal that the Claude Code CLI on Patrick’s Mac can use to manage SES indefinitely.
- Use that access to disable SES open and click tracking on the active configuration set(s) so SES stops wrapping links.
- 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).
- Send a test campaign (or trigger a transactional message) and confirm delivered links resolve through the FluentCRM custom domain only — no
awstrack.me. - Document the credential location and the tracking decision so future sessions don’t re-enable it.
Non-goals
Section titled “Non-goals”- 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.
Approach
Section titled “Approach”Phase 1 — Provision Claude-scoped AWS credentials
Section titled “Phase 1 — Provision Claude-scoped AWS credentials”- Sign in to the AWS console as the root/admin user that owns the SES account (Patrick).
- Create an IAM user:
claude-cli-ses(programmatic access, no console login). - 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.
-
Generate an access key pair for that user.
-
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-1output = jsonConfirm 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). -
Smoke test:
aws --profile baseworks-ses sesv2 list-configuration-setsaws --profile baseworks-ses sesv2 get-account -
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”-
List the configuration sets attached to the FluentCRM sending identity:
aws --profile baseworks-ses sesv2 list-configuration-sets -
For each, dump the tracking options:
aws --profile baseworks-ses sesv2 get-configuration-set --configuration-set-name <name>Look for
TrackingOptions.CustomRedirectDomainand any event destination of typeOpen/Click. -
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”-
Remove the
OpenandClickevent 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-destinationwithMatchingEventTypesreduced toBOUNCE,COMPLAINT,DELIVERY,REJECT,RENDERING_FAILURE— keep the deliverability events, drop the open/click pixel-and-redirect events.) -
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 "" -
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”- WP admin → FluentCRM → Settings → Email Settings → confirm “Track Email Opens” and “Track Click” remain ON.
- 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”- Send a test campaign to a small internal list (Patrick’s address + one alias).
- Inspect the delivered email source:
- Links should be wrapped as
https://<fcrm-tracking-domain>/...only. - No
awstrack.meor SES tracking domain in any link. - Open-tracking pixel (if FCRM injects one) points to the FCRM domain.
- Links should be wrapped as
- Click a link, confirm it redirects through FCRM and lands on the intended URL with no double-redirect.
- Confirm in FluentCRM’s per-campaign analytics that opens/clicks are still being recorded — i.e. the FCRM tracking layer survived.
Phase 6 — Document & memorialize
Section titled “Phase 6 — Document & memorialize”- Add a
reference-memory entry pointing to the changelog secrets file for the SES credentials and the tracking decision. - Update
00-inbox/claude-code-shared-context.mdwith a short “Email infrastructure → SES” section: where the IAM user lives, which profile name to use, the tracking decision, and the date. - Move this plan to
03-resources/plans/executed-plans/once Phase 5 verifies clean.
Critical Files / Surfaces
Section titled “Critical Files / Surfaces”~/.aws/credentialsand~/.aws/configon 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).
Risks & Mitigations
Section titled “Risks & Mitigations”- 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+CLICKevent 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-destinationcall is reversible — re-add OPEN/CLICK destinations to roll back.
Verification
Section titled “Verification”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 noCustomRedirectDomain.- 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).