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

使用C# SendGrid库发送邮件在测试环境报错求助

使用C# SendGrid库发送邮件时测试环境出现连接被强制关闭错误

开发环境下用C# SendGrid库发送邮件完全正常,但部署到测试环境后,调用SendEmailAsync方法时抛出以下异常:

{"Message":"Erro: System.AggregateException: One or more errors occurred. ---> System.Net.Http.HttpRequestException: An error occurred while sending the request. ---> System.Net.WebException: The underlying connection was closed: An unexpected error occurred on a send. ---> System.IO.IOException: Unable to read data from the transport connection: An existing connection was forcibly closed by the remote host. ---> System.Net.Sockets.SocketException: An existing connection was forcibly closed by the remote host\r\n at System.Net.Sockets.Socket.EndReceive(IAsyncResult asyncResult)\r\n at System.Net.Sockets.NetworkStream.EndRead(IAsyncResult asyncResult)\r\n --- End of inner exception stack trace ---\r\n at System.Net.TlsStream.EndWrite(IAsyncResult asyncResult)\r\n at System.Net.PooledStream.EndWrite(IAsyncResult asyncResult)\r\n at System.Net.ConnectStream.WriteHeadersCallback(IAsyncResult ar)\r\n --- End of inner exception stack trace ---\r\n at System.Net.HttpWebRequest.EndGetRequestStream(IAsyncResult asyncResult, TransportContext& context)\r\n at System.Net.Http.HttpClientHandler.GetRequestStreamCallback(IAsyncResult ar)\r\n --- End of inner exception stack trace ---\r\n at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)\r\n at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)\r\n at SendGrid.Helpers.Reliability.RetryDelegatingHandler.d__3.MoveNext()\r\n--- End of stack trace from previous location where exception was thrown ---\r\n at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)\r\n at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)\r\n at SendGrid.BaseClient.d__20.MoveNext()\r\n--- End of stack trace from previous location where exception was thrown ---\r\n at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)\r\n at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)\r\n at SendGrid.BaseClient.d__21.MoveNext()\r\n--- End of stack trace from previous location where exception was thrown ---\r\n at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)\r\n at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)\r\n at SendGrid.BaseClient.d__22.MoveNext()\r\n --- End of inner exception stack trace ---\n

最初怀疑是权限问题,但同一服务器上另一个仅用于发送邮件的站点能正常运行,说明问题出在当前项目本身,无法定位具体原因。

报错发生在代码行:
_client.SendEmailAsync(emailMessage).Result

相关代码:

public EmailResponse Send(EmailContract contract)
{
    var emailMessage = new SendGridMessage()
    {
        From = new EmailAddress(contract.FromEmailAddress, contract.Alias),
        Subject = contract.Subject,
        HtmlContent = contract.Body,
        PlainTextContent = contract.Body
    };

    emailMessage.AddTo(new EmailAddress(contract.ToEmailAddress));
    if (!string.IsNullOrWhiteSpace(contract.BccEmailAddress))
    {
        emailMessage.AddBcc(new EmailAddress(contract.BccEmailAddress));
    }

   if (!string.IsNullOrWhiteSpace(contract.CcEmailAddress))
   {
        emailMessage.AddCc(new EmailAddress(contract.CcEmailAddress));
    }
    return ProcessResponse(_client.SendEmailAsync(emailMessage).Result);
}

可能的原因及解决方法

1. 同步阻塞调用引发的问题

代码中使用.Result同步等待异步方法完成,这种方式在ASP.NET等上下文环境中可能导致死锁,也会干扰HttpClient连接池的正常管理,进而引发连接异常。

解决方法:将方法改为异步实现,全程使用await替代.Result:

public async Task<EmailResponse> SendAsync(EmailContract contract)
{
    var emailMessage = new SendGridMessage()
    {
        From = new EmailAddress(contract.FromEmailAddress, contract.Alias),
        Subject = contract.Subject,
        HtmlContent = contract.Body,
        PlainTextContent = contract.Body
    };

    emailMessage.AddTo(new EmailAddress(contract.ToEmailAddress));
    if (!string.IsNullOrWhiteSpace(contract.BccEmailAddress))
    {
        emailMessage.AddBcc(new EmailAddress(contract.BccEmailAddress));
    }

   if (!string.IsNullOrWhiteSpace(contract.CcEmailAddress))
   {
        emailMessage.AddCc(new EmailAddress(contract.CcEmailAddress));
    }
    var response = await _client.SendEmailAsync(emailMessage);
    return ProcessResponse(response);
}

调用该方法的上层代码也需同步改为异步调用,保持异步流程一致性。

2. TLS版本不兼容

测试环境服务器可能默认使用TLS 1.0/1.1等旧版本协议,而SendGrid要求使用TLS 1.2或更高版本,导致握手失败被远程主机关闭连接。

解决方法:在项目启动阶段强制设置TLS版本:

// 可添加在Program.cs或Startup.cs的初始化代码中
System.Net.ServicePointManager.SecurityProtocol = 
    System.Net.SecurityProtocolType.Tls12 | System.Net.SecurityProtocolType.Tls13;

3. SendGrid客户端实例管理不当

如果_client是每次请求都创建新实例,会导致连接资源耗尽;或者实例生命周期过长引发连接池异常。另一个测试站点可能正确复用了单例实例。

解决方法:将SendGrid客户端注册为单例模式(以依赖注入为例):

// 在Program.cs中添加注册代码
builder.Services.AddSingleton<ISendGridClient>(sp => 
    new SendGridClient(builder.Configuration["SendGrid:ApiKey"]));

4. 项目网络配置差异

当前项目可能配置了代理,或者测试环境的防火墙、出站规则对该项目有特殊限制,而另一个站点未受影响。

解决方法:检查项目配置文件(如appsettings.json)的代理设置,确保测试环境允许项目访问SendGrid的API地址https://api.sendgrid.com。

内容的提问来源于stack exchange,提问作者Alex Becker

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.14 22:47:08