AWS Amplify Gen2 结合SES发邮件遇权限问题及优化咨询
Nuxt3 + Amplify Gen2 实现SES邮件发送问题解答
问题背景
我正在开发基于Nuxt 3的应用,使用AWS Amplify Hosting(Gen 2),希望通过Lambda函数调用AWS SES发送邮件。已编写如下Lambda函数:
import type { Schema } from "../../data/resource"; import { SESClient, SendEmailCommand } from "@aws-sdk/client-ses"; const sesClient = new SESClient({ region: "af-south-1" }); export const handler: Schema["sendEmail"]["functionHandler"] = async (event) => { const recipient = "testemail@gmail.com"; const subject = "Subject"; const body = "Body"; const command = new SendEmailCommand({ Source: "testemail@gmail.com", Destination: { ToAddresses: [recipient], }, Message: { Body: { Text: { Data: body }, }, Subject: { Data: subject }, }, }); try { const result = await sesClient.send(command); console.log(`Email sent to ${recipient}: ${result.MessageId}`); } catch (error) { console.error(`Error sending email to ${recipient}: ${error}`); throw new Error(`Failed to send email to ${recipient}`, { cause: error }); } return `Hello, ${event.name}!`; };
前端触发Lambda的代码:
import { generateClient } from "aws-amplify/api"; import type { Schema } from "~/amplify/data/resource"; const client = generateClient<Schema>(); const response = await client.queries.sendEmail({ name: "Amplify", });
触发时出现错误:"Not Authorized to access sendEmail on type Query",后端资源配置如下:
import { type ClientSchema, a, defineData } from '@aws-amplify/backend'; import { sendEmail } from '../functions/send-email/resource'; const schema = a.schema({ sendEmail: a .query() .arguments({ name: a.string(), }) .returns(a.string()) .authorization((allow) => [allow.guest() ,allow.authenticated()]) .handler(a.handler.function(sendEmail)), Todo: a .model({ content: a.string(), }) .authorization((allow) => [allow.publicApiKey(), allow.guest() ,allow.authenticated()]), }); export type Schema = ClientSchema<typeof schema>; export const data = defineData({ schema, authorizationModes: { defaultAuthorizationMode: 'apiKey', apiKeyAuthorizationMode: { expiresInDays: 30 } } });
已在SES af-south-1区域验证了邮箱,现寻求以下指导:
- 当前通过Lambda调用SES发邮件是否为最优方式,还是自定义类更合适?
- 如何从前端安全触发邮件发送?
- Lambda函数成功发送邮件需要哪些权限?
问题解答
1. Lambda调用SES是否为最优方式?
直接用Lambda调用SES是非常合适的方案,也是AWS生态里的常规做法:
- Lambda是无服务器执行环境,无需维护服务器,按需付费,完美适配邮件发送这类触发式任务
- 自定义类本质上还是要依托Lambda或其他计算环境运行,单独写自定义类没有额外优势,反而会增加复杂度
- Amplify Gen2的函数集成天然支持Lambda,和你的现有技术栈契合度最高
2. 解决前端触发的授权问题并安全触发邮件
你遇到的授权错误,核心原因是API默认授权模式为apiKey,但sendEmail查询仅配置了guest和authenticated授权规则,未包含apiKey。
修复授权配置
修改后端schema中的sendEmail授权规则,添加allow.publicApiKey():
sendEmail: a .query() .arguments({ name: a.string(), }) .returns(a.string()) .authorization((allow) => [allow.guest(), allow.authenticated(), allow.publicApiKey()]) // 新增apiKey授权 .handler(a.handler.function(sendEmail)),
安全触发的额外建议
- 限制邮件参数:不要让前端直接传入收件人、主题等敏感内容,避免被滥用发送垃圾邮件。可以在Lambda中固定收件人,或只允许前端传入特定模板参数(比如用户反馈内容),由Lambda组装邮件内容
- 添加参数校验:在Lambda中校验前端传入参数的合法性,比如内容长度、格式,过滤无效请求
- 人机验证:如果是公开可访问的功能,添加reCAPTCHA验证,防止恶意批量调用
3. Lambda需要的SES权限
必须给Lambda对应的IAM角色添加SES发送邮件的权限,操作步骤如下:
- 打开AWS控制台的IAM服务,找到Amplify为
sendEmailLambda创建的角色(通常命名格式为amplify-<项目名>-<环境名>-sendEmail-role-xxxx) - 为该角色添加内联策略,基础权限配置如下:
{ "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Action": [ "ses:SendEmail", "ses:SendRawEmail" ], "Resource": "*" } ] }
如果需要更严格的权限控制,可以限定到你已验证的发件人邮箱:
{ "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Action": [ "ses:SendEmail", "ses:SendRawEmail" ], "Resource": "arn:aws:ses:af-south-1:<你的AWS账号ID>:identity/testemail@gmail.com" } ] }
- 注意:如果SES处于沙箱模式,只能发送到已验证的邮箱,需要先验证收件人邮箱,或申请移出沙箱
内容的提问来源于stack exchange,提问作者dev.learn
相关产品推荐
相关产品推荐

