如何在VPC私有子网中通过AWS SES发送邮件(ECS Fargate场景)
问题解决:ECS Fargate私有子网中通过IAM角色使用SES发送邮件
问题根源分析
邮件请求超时的核心原因是VPC端点配置不匹配:
- 你创建的是
email-smtp类型的VPC端点,对应SMTP协议(端口587/465),但AWS SDK for SES使用的是HTTPS REST API,需要的是ses类型的VPC端点。 - 同时,VPC端点的安全组未放行ECS任务的HTTPS流量,导致无法建立API连接。
修复步骤
1. 修正SES VPC端点配置
将VPC端点的服务名替换为SES REST API对应的服务名:
resource "aws_vpc_endpoint" "ses" { vpc_id = aws_vpc.this.id // 替换为SES REST API的服务名,而非SMTP端点 service_name = "com.amazonaws.${var.aws_region}.ses" vpc_endpoint_type = "Interface" subnet_ids = aws_subnet.private[*].id security_group_ids = [aws_security_group.vpc_endpoints.id] private_dns_enabled = true tags = merge({ Name = "${local.common_name}-ses-endpoint" }, local.common_tags) }
2. 配置VPC端点安全组的入站规则
确保VPC端点的安全组允许ECS任务安全组发起的HTTPS(443端口)请求:
resource "aws_security_group" "vpc_endpoints" { name = "${local.common_name}-vpc-endpoints-sg" description = "Security group for VPC endpoints" vpc_id = aws_vpc.this.id ingress { description = "Allow HTTPS from ECS tasks" from_port = 443 to_port = 443 protocol = "tcp" security_groups = [aws_security_group.ecs_tasks.id] } egress { from_port = 0 to_port = 0 protocol = "-1" cidr_blocks = ["0.0.0.0/0"] } tags = local.common_tags }
3. 简化Node.js代码中的SES客户端配置
ECS Fargate会自动为任务注入IAM角色的临时凭证,无需手动配置,简化发送逻辑:
import { createTransport } from 'nodemailer'; import { SES } from '@aws-sdk/client-ses'; // 仅指定区域,SDK自动获取任务角色凭证 const sesClient = new SES({ region: process.env.AWS_REGION }); this.transporter = createTransport({ SES: { ses: sesClient } }); async sendMail(options: { to: string | string[]; subject: string; text?: string; html?: string; }) { try { await this.transporter.sendMail({ from: this.from, ...options, }); this.logger.log(`Email sent successfully to ${options.to}`); } catch (error) { this.logger.error(`Failed to send email to ${options.to}:`, error); throw error; } }
4. 额外验证项
- 确认ECS任务已关联包含SES权限的IAM角色
- 检查私有子网路由表,无需配置NAT网关(通过VPC端点直接访问SES)
- 确认SES已验证发件人邮箱/域名,避免因未验证导致的发送失败
内容的提问来源于stack exchange,提问作者Lazar
相关产品推荐
相关产品推荐

