You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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区域验证了邮箱,现寻求以下指导:

  1. 当前通过Lambda调用SES发邮件是否为最优方式,还是自定义类更合适?
  2. 如何从前端安全触发邮件发送?
  3. 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发送邮件的权限,操作步骤如下:

  1. 打开AWS控制台的IAM服务,找到Amplify为sendEmailLambda创建的角色(通常命名格式为amplify-<项目名>-<环境名>-sendEmail-role-xxxx)
  2. 为该角色添加内联策略,基础权限配置如下:
{
  "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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.16 04:47:23