关于 amazon-ses
amazon-ses 是面向开发者的 Amazon SES 邮件发送配置技能,涵盖身份验证、沙盒入门和生产权限申请。它先检查现有状态,只处理缺失配置,并要求在申请生产权限前取得明确同意。
主要功能
- 01指导 SES v2 入门与域名配置
- 02检查现有状态并跳过已完成步骤
- 03涵盖 DKIM 与 MAIL FROM 配置
- 04申请生产权限前要求明确同意
适用场景
- 01配置 SES 域名身份
- 02发送首封通过身份验证的邮件
- 03诊断地址未验证错误
MCP 相关
推荐使用 AWS MCP 服务进行沙盒执行和 CloudTrail 审计;也可通过标准 AWS CLI 命令操作。
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ aws/ agent-toolkit-for-aws --skill amazon-ses安装后在 Claude Code 中输入/amazon-ses确认已加载。
附带文件references/onboarding.mdreferences/setting-up-ses-domain-identity.md
详细介绍
Amazon SES
概述
推荐:使用具备 SES 权限的 AWS MCP Server,以便在沙箱中执行操作并记录 CloudTrail 审计日志。 不使用 MCP 时:所有操作都使用标准 AWS CLI 语法(
aws sesv2 ...)。
帮助不具备电子邮件身份验证专业知识的开发者,从一个空的 AWS 账户开始,让真实邮件通过身份验证并送达其收件箱;如果 AWS 批准请求,还可继续开启生产环境邮件发送。
在执行任何操作前,先读取账户和身份状态;仅完成域名设置中实际缺失的部分。只有在域名设置完成且用户明确同意后,才申请生产环境访问权限。测试发送为可选操作:仅当用户提出请求时才执行,并发送给当前账户状态允许的收件人。
路由
| 如果用户想要…… | 阅读 |
|---|---|
开始使用 SES、设置邮件发送、发送第一封或测试邮件、退出沙箱,或诊断 MessageRejected: Email address is not verified | SES 入门:从零到首次成功送达邮件 |
| 设置用于发送邮件的域名、配置电子邮件身份验证,或排查 DKIM 问题 | 设置 SES 域名身份 |
防护规则 — 此技能自身文件的位置(MCP 与本地安装)
此技能有两种加载方式,它们从不同位置解析自身捆绑的文件。读取参考文件前,请先确定此技能的加载方式:
- **通过 AWS MCP
retrieve_skill工具加载:**此技能不在本地文件系统中。必须通过retrieve_skill并使用file参数获取每个参考文件(例如file="references/onboarding.md")。不要在本地使用file_read读取这些路径——它们在磁盘上不存在。 - 本地安装(例如
~/.kiro/skills/amazon-ses/、.kiro/skills/amazon-ses/或~/.claude/skills/amazon-ses/):使用上述相对路径,从本地技能目录读取文件。
此区别仅适用于技能自身打包的文件。用户数据和会话产物始终应从用户的工作目录读取并写入——绝不要通过 retrieve_skill 获取或写入客户数据。
关键规则
- 必须使用 SES v2 API:
aws sesv2 ...,绝不可使用 v1 的aws ses ...命令。v1 命令不会报错提示选错了 API,因此这个错误不会被发现;而此流程所需的操作——申请生产访问权限,以及在一次身份读取中获取 DKIM 和 MAIL FROM 属性——仅存在于 v2 中。基于已发布 CLI 示例训练的模型往往会默认使用 v1 语法。 - 绝不可主动提供 API 版本机制、内部限制数值或其他底层细节。只解释用户需要决定、同意、付费或采取行动的内容。只有在用户询问、问题取决于这些信息,或参考文件明确要求披露时,才说明其余内容。
- 必须一次性在同一组问题中询问所有缺失输入,不得逐个询问;并且绝不可询问请求不需要的输入。问题范围应与用户的请求相符:如果请求已指定域名和 MAIL FROM 子域名,则域名设置所需信息已齐全,应读取状态并执行,而不是因缺少发送时或生产访问权限相关输入而停滞。如果当前范围内没有缺失信息,就不要提问。
- 绝不可在 AWS CLI 配置文件或 Region 仍可解析时询问用户要使用哪个 AWS CLI 配置文件或 Region。只有用户指定配置文件时,才使用
--profile。**按以下顺序解析 Region,并采用第一个能得到值的来源:**用户指定的 Region;AWS_REGION;AWS_DEFAULT_REGION;aws configure get region,如果用户指定了配置文件,则添加--profile '{PROFILE}',因为配置文件可能带有自己的 Region。最后一条命令只读取 CLI 配置文件,不会读取环境变量,因此要先单独检查两个环境变量。执行任何更改前,先说明解析出的 Region,因为 SES 状态按 Region 区分,并报告aws sts get-caller-identity返回的账户和主体。只有以下两种情况需要询问:按上述顺序仍无法得到 Region,因为每次aws sesv2调用都必须指定 Region;以及aws sts get-caller-identity因凭证过期或无效而失败,此时应询问凭证刷新后要使用哪个账户(配置文件)和 Region,因为已配置的默认值不再可信。将这两种情况都合并到同一组问题中,不要额外多花一轮询问。 - 必须将请求载荷(更改批次和消息内容)作为内联 JSON 字符串传递给 CLI,绝不可使用
file://路径,因为file://是 AWS CLI 专用语法,通过 AWS MCP 服务执行 CLI 时无法解析。 - 必须在每个步骤前读取当前状态,并跳过已满足的步骤。特别是:身份已存在时,绝不可调用
create-email-identity(它会返回AlreadyExistsException);身份的DkimAttributes.Status为SUCCESS时,绝不可重新运行put-email-identity-dkim-signing-attributes,因为重新初始化可能会更改其令牌。应根据状态而非已发布的 CNAME 是否可解析来决定是否调用——对于状态为FAILED的身份,记录通常确实可以解析,只是未被认可;这正是FAILED的含义,因此记录可以解析并不是不执行恢复操作的理由。状态门控恢复路径及其之前的 BYODKIM 检查由setting-up-ses-domain-identity.md负责。 - **设置域名时,创建域名身份。**只有用户明确选择验证该单独地址时,才创建电子邮件地址身份。
不变规则
这些规则在本技能的所有场景中均适用。参考文件必须遵循这些规则,也可以在此基础上补充特定工作流的细节——例如说明某一步骤如何检查某项规则,或根据该步骤的状态缩小适用范围。任何内容都不得与此处规定相矛盾或放宽这些规则。
- 域名设置完成表示以下三项在同一条
aws sesv2 get-email-identity响应中全部成立:VerifiedForSendingStatus为true,并且DkimAttributes.Status为SUCCESS,并且MailFromAttributes.MailFromDomainStatus为SUCCESS。三项中满足两项不算完成。当MailFromDomainStatus为PENDING、FAILED或TEMPORARY_FAILURE时,AWS 文档说明 SES 会使用自定义 MAIL FROM 回退设置:使用USE_DEFAULT_VALUE时,它会通过amazonses.com的子域发送,因此 SPF 验证会通过,但信封发件人与From域不对齐,DMARC 无法通过 SPF 路径;使用REJECT_MESSAGE时,SES 会返回MailFromDomainNotVerified,且不会尝试投递。这就是本技能其余部分所说的“域名设置完成”门槛。 - 沙盒收件人规则。 当
ProductionAccessEnabled为false时,AWS 文档说明,你只能向已验证的电子邮件地址和域名发送,或向 Amazon SES 邮箱模拟器发送。也就是说,按本技能始终采用的顺序:(1) 将其自身验证为电子邮件身份的地址,(2) Amazon SES 邮箱模拟器,或 (3) 账户中任何已验证域名下的任意地址——不只是刚设置的域名。此限制针对的是收件人,而非发件人:已完全验证的发送域名不会解除此限制,而且绝不能尝试绕过它。生产访问仅由ProductionAccessEnabled决定——只要它为false,无论Details.ReviewDetails.Status显示什么,都适用这三个选项。向用户解释此限制时,你必须先按相同编号列出当前可用的全部三种收件人选项,再提出申请生产访问作为解决办法;你绝不能将此限制描述为“每个收件人都必须单独验证”:已验证的域名涵盖该域名下的所有地址。 - 无论账户处于何种状态,发件人也必须经过验证。 AWS 文档说明,账户进入生产状态后,“你仍必须验证所有用作 ‘From’、‘Source’、‘Sender’ 或 ‘Return-Path’ 地址的身份。”因此,
MessageRejected: Email address is not verified有两个原因:沙盒中不允许的收件人,以及任何状态下未经验证的发送身份。选择解决办法前,先查看错误中提到的地址,并确认 From 地址所在的域名或地址已在此 Region 中验证。 - 已验证发件人是 SES 服务的最低要求;本技能的流程要求更高。 即使 DKIM 尚未达到
SUCCESS,SES 本身仍会接受来自已验证可发送身份的邮件。本技能刻意不止步于此:其目标是首次发送一封已投递且经过身份验证的邮件,因此在宣称域名设置或身份验证完成之前,以及发送之前,都要求DkimAttributes.Status: SUCCESS。此更严格的标准只在onboarding.md域名验证步骤中作为发送前提说明一次,所有发送路径都会遵循它。两者并不冲突——前者是服务强制执行的要求,后者是此流程对用户的承诺。 - 验证每个替换值,然后根据其上下文进行引用。 直接插入 Shell 命令的值必须使用单引号;放在内联 JSON 中的值必须进行 JSON 编码(按 JSON 规则使用双引号),并且只对整个 JSON 字符串使用 Shell 单引号——绝不要对 JSON 中的单个值使用 Shell 引号。此规则适用于本技能替换的每个用户提供的值——
DOMAIN、MAIL FROM 子域、FROM_ADDRESS、TEST_RECIPIENT、CHOSEN_RECIPIENT、MAIL_TYPE、WEBSITE_URL、REGION、PROFILE——而不仅仅是 DNS 名称。拒绝任何包含单引号、双引号、反引号、$、;、反斜杠或空白字符的值,并要求用户重新提供;绝不要尝试转义被拒绝的值来使其符合要求。各值的格式:DOMAIN和 MAIL FROM 子域——仅限 DNS 标签,可包含字母、数字、连字符和点;From 地址以及所有收件人值,包括TEST_RECIPIENT和CHOSEN_RECIPIENT——必须是包含一个@的单个地址,并拒绝逗号分隔的列表(多个收件人应放入ToAddresses数组);MAIL_TYPE——必须恰为TRANSACTIONAL或MARKETING;WEBSITE_URL——长度为 1–1000 个字符的http/httpsURL,不必位于已验证域名下,因为 AWS 接受与邮件相关的任何企业网站,所以问题集只能将https://{DOMAIN}作为建议的默认值;REGION——AWS Region 代码;PROFILE——CLI 配置文件名称。由本技能提供的选项绑定到CHOSEN_RECIPIENT的值——即邮箱模拟器地址——也必须按相同方式验证。使用序列化器对任何用户提供的主题或正文文本进行 JSON 编码,而不要将其直接粘贴到引号之间。
IAM 权限
仅授予正在运行的工作流实际调用的操作,不多授予任何权限——绝不要使用 ses:*
或 *FullAccess。每个参考文件都有一个 Required IAM actions 部分,准确列出该文件调用的操作;请使用该列表,而非通配符。
将针对身份的操作限定到每次调用实际操作的身份:
- 域名操作使用
arn:aws:ses:{region}:{account-id}:identity/{domain}。 - 电子邮件地址身份使用
arn:aws:ses:{region}:{account-id}:identity/{address}——这既包括用于沙盒收件人验证的身份,也包括发件人使用单独验证的电子邮件地址、而非该域名下的地址时所用的 From 身份。仅限定到域名的策略会拒绝这些调用。读取操作也采用相同的限定方式:ses:GetEmailIdentity语句必须包含实际读取的每个身份的 ARN,其中包括收件人地址身份,以及沙盒收件人选项 3 中用户指定的另一个已验证域名的确切身份 ARN。仅限定到发送域名的策略会拒绝该读取,导致权限问题看起来像是缺少收件人。**发送操作由涵盖其 From 地址的身份授权,**因此应将ses:SendEmail限定到对应身份;onboarding.md的Required IAM actions列出了这三种情况。 - 将 Route 53 区域操作(
route53:GetHostedZone、route53:ListResourceRecordSets、route53:ChangeResourceRecordSets)限定到arn:aws:route53:::hostedzone/{hosted_zone_id},使用纯区域 ID——list-hosted-zones-by-name返回/hostedzone/Z123ABC,因此在构建 ARN 前请去掉此前缀,否则结果会重复添加此前缀,无法匹配任何资源。只要 Agent 检查 Route 53 是否托管该域名,就需要读取区域的操作;只有在用户批准写入时,才需要route53:ChangeResourceRecordSets。
只有真正的账户级操作和列表操作(sts:GetCallerIdentity、ses:GetAccount、
ses:ListEmailIdentities、route53:ListHostedZonesByName、route53:TestDNSAnswer)不支持资源级限定,必须对 * 授予权限。请审慎授予 ses:PutAccountDetails,因为它会更改账户范围的发送策略。
安全注意事项
- 临时凭证。 使用带 STS 的 IAM 角色——绝不要使用长期访问密钥。
- 同意门槛。 启动生产权限审核和发送真实消息都会以任何 API 都无法撤销的方式让用户作出承诺,而 Route 53 更改可能影响线上流量。每个门槛——生产权限同意门槛、发送确认和 DNS 写入权限——均由执行相应操作的参考文件负责;绝不要因为本文件对此作了概述,就越过任何门槛。
- 默认情况下,传输 TLS 采用尽力而为策略。 AWS 文档说明,SES 始终尝试与接收邮件服务器建立安全连接;如果无法建立连接,则会以未加密方式发送邮件。文档还说明,要强制使用 TLS,必须将配置集的
TlsPolicy设为REQUIRE——配置集工作流不在此技能的范围内。 - 在将用户提供的每个值放入 Shell 命令或内嵌 JSON 之前,都要进行验证并加引号。规则和字符集见上文的 Invariants。
- 绝不要在日志中写入邮件正文或收件人列表。
- 绝不要在示例中硬编码凭证、端点或机密信息。 将任何应用凭证存储在 AWS Secrets Manager 或 Parameter Store 中。
- 启用 CloudTrail 以审计 SES API 调用,并针对反复出现的
AccessDeniedException和异常发送量发出警报。使用 AWS KMS 密钥(SSE-KMS)加密跟踪日志文件,并限制对跟踪所用 S3 存储桶和 CloudWatch Logs 日志组的访问;同时使用 KMS 密钥加密该日志组(在create-log-group上使用--kms-key-id)——SES CloudTrail 条目包含电子邮件地址、域名和账户详细信息。