C#中Mailjet邮件发送异常:返回200未送达,事务消息为空
问题排查与解决方案:.NET Core中Mailjet邮件发送失败
核心问题分析
你的情况大概率是平台配置未完全生效 + 代码版本/字段缺失的混合问题,以下分步骤排查并给出修正方案:
一、优先排查平台配置
- 域名验证状态
确认已添加的域名完成了DKIM、SPF、DMARC的全部验证(Mailjet域名管理页面会显示验证状态)。未验证的域名会导致邮件被静默拦截,无任何投递记录。 - 发件人地址验证
即使域名验证通过,单个发件人地址(如mymail@mydomain.com)也需要点击Mailjet发送的验证邮件完成确认,否则无法作为发件人使用。 - 账户模式检查
确认账户是否处于Sandbox模式:Sandbox模式下仅允许发送到预验证的收件人列表,且不会实际投递邮件。可在Mailjet账户设置中切换到生产模式。 - API密钥权限
使用的API密钥需具备邮件发送权限,子密钥可能被限制了功能,建议先用主密钥测试。
二、代码问题修正
1. 事务邮件代码问题(第二种方案)
原代码存在两个关键问题:
- 未打印完整错误信息,仅输出
response无法看到具体失败原因; - 缺少纯文本邮件部分(
WithTextPart),部分邮件网关会拒绝无纯文本的邮件。
修正后的代码:
var client = new MailjetClient(apiKey, secretKey) { // 指定API版本,避免版本兼容问题 Version = ApiVersion.V3_1 }; var email = new TransactionalEmailBuilder() .WithFrom(new SendContact("mymail@mydomain.com", "Mailjet Sender")) .WithSubject("Test Transactional Email") .WithHtmlPart("<h1>Hello from Mailjet</h1>") .WithTextPart("Hello from Mailjet") // 必须添加纯文本部分 .WithTo(new SendContact("your-verified-recipient@example.com")) // 确保收件人已验证(Sandbox模式下) .Build(); var response = await client.SendTransactionalEmailAsync(email); // 打印完整响应信息 if (response.IsSuccessStatusCode) { Console.WriteLine($"发送成功!消息ID: {response.Messages[0].To[0].MessageID}"); } else { Console.WriteLine($"错误状态码: {response.StatusCode}"); Console.WriteLine($"错误详情: {response.GetErrorInfo()}"); Console.WriteLine($"错误消息: {response.GetErrorMessage()}"); }
2. 推广邮件代码问题(第三种方案)
原代码的核心问题是使用了v3版本的Send.Resource,而Mailjet当前推荐使用v3.1版本的SendV31.Resource,导致请求被解析异常(返回200但无实际处理)。此外,营销邮件需添加退订链接(测试可临时使用占位链接)。
修正后的代码:
var client = new MailjetClient(apiKey, secretKey) { Version = ApiVersion.V3_1 }; var request = new MailjetRequest { Resource = SendV31.Resource, } .Property(SendV31.FromEmail, "mymail@mydomain.com") .Property(SendV31.FromName, "Mailjet Pilot") .Property(SendV31.Subject, "Your Email Flight Plan") .Property(SendV31.TextPart, "Dear passenger, welcome to Mailjet!") .Property(SendV31.HtmlPart, "<h3>Dear passenger, welcome to Mailjet!</h3>") .Property(SendV31.Recipients, new JArray { new JObject { { "Email", "your-verified-recipient@example.com" }, { "Name", "Passenger 1" } } }) // 营销邮件必须添加退订链接(正式环境需使用真实链接) .Property(SendV31.Unsubscribe, new JObject { { "Method", "link" }, { "Url", "https://yourdomain.com/unsubscribe" } }); var response = await client.PostAsync(request); if (response.IsSuccessStatusCode) { var data = response.GetData(); Console.WriteLine($"Total: {response.GetTotal()}, Count: {response.GetCount()}"); Console.WriteLine($"消息ID: {data[0]["Messages"][0]["To"][0]["MessageID"]}"); } else { Console.WriteLine($"状态码: {response.StatusCode}"); Console.WriteLine($"错误详情: {response.GetErrorInfo()}"); Console.WriteLine($"错误消息: {response.GetErrorMessage()}"); Console.WriteLine($"响应数据: {response.GetData()}"); }
三、获取更多排查信息
- 查看Mailjet API日志
在Mailjet后台的「账户 > API密钥 > API日志」中,可查看所有API请求的详细参数、响应状态和错误原因,这是排查问题最直接的方式。 - 使用Mailjet内置测试工具
在Mailjet后台的「邮件 > 发送测试邮件」中直接发送测试邮件,若工具发送失败,说明是平台配置问题;若成功,则是代码问题。 - 打印完整响应数据
不要仅打印response对象,需输出response.GetErrorInfo()、response.GetErrorMessage()和response.GetData()的完整内容,这些会包含Mailjet返回的具体错误代码和原因。
内容的提问来源于stack exchange,提问作者afriedman111
相关产品推荐
相关产品推荐

