C# MVC应用使用AWS SES发邮件遇IAM凭证及签名错误求助
AWS SES在C# MVC应用中发送邮件的凭证配置与签名错误排查
问题描述
我在C# MVC应用中使用AWS SES官方模板代码发送邮件,EmailSender.cs代码如下:
using System; using System.Collections.Generic; using System.Threading.Tasks; using Amazon; using Amazon.Runtime; using Amazon.SimpleEmail; using Amazon.SimpleEmail.Model; using Microsoft.AspNetCore.Identity.UI.Services; using Microsoft.Extensions.Options; namespace amaranth.Helpers { public class EmailSender : IEmailSender { private ApiEndpoints _endpoints; public EmailSender(IOptions<ApiEndpoints> _options) { _endpoints = _options.Value; } public async Task SendEmailAsync(string email, string subject, string htmlMessage) { using (var client = new AmazonSimpleEmailServiceClient(RegionEndpoint.USEast1)) { var sendRequest = new SendEmailRequest { Source = "<A DOMAIN THAT I DO OWN>", Destination = new Destination { ToAddresses = new List<string> { email } }, Message = new Message { Subject = new Content(subject), Body = new Body { Html = new Content { Charset = "UTF-8", Data = htmlMessage } } } }; try { Console.WriteLine("Sending email using Amazon SES..."); var response = await client.SendEmailAsync(sendRequest); Console.WriteLine("The email was sent successfully."); } catch (Exception ex) { Console.WriteLine("The email was not sent."); Console.WriteLine("Error message: " + ex.Message); } } } } }
已确认:
- 收件人邮箱、主题、HTML内容格式正确
Source对应的域名已验证,且AWS SES已脱离沙箱- 已创建用于邮件操作的IAM用户
初始错误
运行应用时无法发送邮件,报错:Error message: Unable to get IAM security credentials from EC2 Instance Metadata Service.
更新后错误
添加BasicAWSCredentials传入IAM用户的Access Key ID和Secret Access Key后,新报错:Error message: The request signature we calculated does not match the signature you provided. Check your AWS Secret Access Key and signing method. Consult the service documentation for details.
排查步骤与解决方案
1. 验证IAM用户凭证与权限
- 核对凭证准确性:确认Access Key ID和Secret Access Key无空格、大小写错误(Secret Key严格区分大小写),可临时在代码中打印值(注意不要泄露到日志)验证配置读取是否正确。
- 检查IAM权限:确保IAM用户拥有SES发送邮件的权限,可附加
AmazonSESFullAccess策略(生产环境建议使用最小权限策略,仅允许ses:SendEmail、ses:SendRawEmail操作)。
2. 选择正确的凭证配置方式(推荐优先级)
AWS SDK会自动按以下顺序读取凭证,推荐优先使用非硬编码方式:
- 本地凭证文件:在用户目录下创建
.aws/credentials文件(Windows路径:C:\Users\<用户名>\.aws\credentials;Linux/macOS路径:~/.aws/credentials),格式如下:
[default] aws_access_key_id = YOUR_ACCESS_KEY aws_secret_access_key = YOUR_SECRET_KEY
此时代码无需显式传入凭证,SDK会自动读取:
using (var client = new AmazonSimpleEmailServiceClient(RegionEndpoint.USEast1))
- 系统环境变量:设置
AWS_ACCESS_KEY_ID和AWS_SECRET_ACCESS_KEY环境变量,SDK会自动识别。 - 代码显式传入(仅测试用):若必须在代码中传递,确保配置值未被转义或篡改,比如检查
_endpoints.EmailUsername和_endpoints.EmailPassword是否正确绑定配置文件值。
3. 签名错误的额外排查点
- 区域匹配:代码中使用的
RegionEndpoint.USEast1必须与SES服务所在区域一致(例如SES在美西2区则改为RegionEndpoint.USWest2)。 - 时间同步:服务器系统时间与AWS时间偏差超过5分钟会导致签名验证失败,检查并同步服务器时间。
- 内容编码:若主题或HTML内容包含特殊字符,确认UTF-8编码生效(代码中已设置
Charset = "UTF-8",可尝试简化内容测试)。
4. 代码优化建议
将AWS配置移至appsettings.json避免硬编码:
"AWSSettings": { "AccessKey": "YOUR_ACCESS_KEY", "SecretKey": "YOUR_SECRET_KEY", "Region": "us-east-1" }
创建配置类:
public class AWSSettings { public string AccessKey { get; set; } public string SecretKey { get; set; } public string Region { get; set; } }
在Program.cs中注册配置:
builder.Services.Configure<AWSSettings>(builder.Configuration.GetSection("AWSSettings"));
修改EmailSender注入并使用配置:
private readonly AWSSettings _awsSettings; public EmailSender(IOptions<AWSSettings> awsSettings) { _awsSettings = awsSettings.Value; } public async Task SendEmailAsync(string email, string subject, string htmlMessage) { var region = RegionEndpoint.GetBySystemName(_awsSettings.Region); using (var client = new AmazonSimpleEmailServiceClient( new BasicAWSCredentials(_awsSettings.AccessKey, _awsSettings.SecretKey), region)) { // 原有sendRequest逻辑不变 } }
内容的提问来源于stack exchange,提问作者ChristianOConnor
相关产品推荐
相关产品推荐

