C#邮件发送实战:SMTP协议与.NET类库详解

1. C#邮件发送实战指南:从基础到高阶应用

在.NET生态中,邮件功能集成是企业级开发的标配需求。不同于简单的API调用,完整的邮件发送方案需要考虑协议选择、身份认证、附件处理、异常重试等工程化细节。本文将基于SMTP协议,拆解C#邮件发送的完整技术栈,包含我多年实践中总结的7个关键优化点。

2. 核心组件与协议选型

2.1 SMTP协议工作原理解析

SMTP(Simple Mail Transfer Protocol)采用TCP端口25或加密端口465/587通信。其交互过程可分为三个阶段:

  1. 握手阶段:EHLO命令建立连接
  2. 传输阶段:MAIL FROM/RCPT TO指定收发方
  3. 内容阶段:DATA命令传输邮件头和正文

现代邮件服务商如QQ邮箱、163邮箱都要求启用SSL加密。以下是协议交互的典型过程:

220 smtp.qq.com ESMTP
EHLO client
250-smtp.qq.com
250-AUTH LOGIN PLAIN
250-STARTTLS
...

2.2 .NET邮件类库架构

System.Net.Mail命名空间提供核心组件:

  • MailMessage:构建邮件实体(收件人、主题、正文)
  • SmtpClient:协议实现层(服务器配置、发送操作)
  • Attachment:附件处理类

高阶场景会用到:

  • AlternateView:多版本内容(HTML/纯文本)
  • LinkedResource:内嵌资源(如图片)

3. 基础发送实现

3.1 最小化代码示例

using (var client = new SmtpClient("smtp.qq.com", 587))
{
    client.Credentials = new NetworkCredential("your@qq.com", "授权码");
    client.EnableSsl = true;
    
    var mail = new MailMessage();
    mail.From = new MailAddress("your@qq.com");
    mail.To.Add("recipient@domain.com");
    mail.Subject = "测试邮件";
    mail.Body = "这是纯文本内容";
    
    client.Send(mail);
}

注意:主流邮箱需使用授权码而非密码,在邮箱设置中生成

3.2 关键参数说明

参数 示例值 必要性 说明
Host smtp.qq.com 必填 服务商SMTP地址
Port 587 必填 加密端口号
UseDefaultCredentials false 推荐 禁用Windows认证
DeliveryMethod SmtpDeliveryMethod.Network 默认 网络发送模式
Timeout 10000 可选 超时毫秒数

4. 进阶功能实现

4.1 带附件的邮件发送

处理附件需注意:

  1. 文件名编码转换
  2. 内容类型(ContentType)设置
  3. 大文件分块上传
var attachment = new Attachment("report.pdf");
attachment.ContentDisposition.CreationDate = File.GetCreationTime(filePath);
attachment.ContentDisposition.ModificationDate = File.GetLastWriteTime(filePath);
mail.Attachments.Add(attachment);

4.2 HTML格式邮件

支持HTML时需提供纯文本备用版本:

mail.IsBodyHtml = true;
mail.Body = "<h1>HTML内容</h1><img src='cid:logo'>";

// 添加内嵌图片
var res = new LinkedResource("logo.png");
res.ContentId = "logo";
var htmlView = AlternateView.CreateAlternateViewFromString(
    mail.Body, null, "text/html");
htmlView.LinkedResources.Add(res);
mail.AlternateViews.Add(htmlView);

5. 生产环境优化策略

5.1 连接池管理

高频发送场景应复用SmtpClient实例:

// 静态客户端实例
private static readonly SmtpClient _client = new SmtpClient();

// 使用前重置状态
_client.ServicePoint.CloseConnectionGroup(_client.ServicePoint.ConnectionName);

5.2 异步发送实现

推荐使用SendMailAsync避免阻塞:

try 
{
    await client.SendMailAsync(mail);
}
catch (SmtpException ex) 
{
    if(ex.StatusCode == SmtpStatusCode.MailboxBusy)
    {
        // 实现重试逻辑
    }
}

5.3 邮件队列持久化

我常用的本地存储方案:

// 序列化邮件到磁盘
var xml = new XmlSerializer(typeof(MailMessage));
using (var writer = new StreamWriter("mail.queue"))
{
    xml.Serialize(writer, mail);
}

// 定时任务处理队列
var timer = new Timer(_ => {
    foreach(var file in Directory.GetFiles("*.queue"))
    {
        RetrySend(DeserializeMail(file));
    }
}, null, 0, 60000);

6. 常见问题排查指南

6.1 认证失败处理

典型错误场景:

  1. 错误代码534:需开启SSL
  2. 错误代码535:检查授权码而非密码
  3. 错误代码553:发件人地址与认证账号不一致

6.2 超时问题优化

网络不稳定时的应对措施:

  1. 设置Timeout=30000(30秒)
  2. 实现指数退避重试:
int retry = 0;
while(retry < 3)
{
    try {
        client.Send(mail);
        break;
    }
    catch {
        Thread.Sleep(1000 * (int)Math.Pow(2, retry));
        retry++;
    }
}

6.3 垃圾邮件规避策略

  1. 添加DKIM签名:
var headers = new NameValueCollection();
headers.Add("DKIM-Signature", BuildDkimHeader());
mail.Headers.Add(headers);
  1. 控制发送频率(建议<50封/分钟)
  2. 避免使用敏感关键词(如"免费"、"促销")

7. 扩展应用场景

7.1 邮件模板引擎

结合Razor模板生成动态内容:

string template = @"
Dear @Model.Name,
Your order @Model.OrderNo has been shipped!
";
var engine = new RazorLightEngineBuilder()
    .UseMemoryCachingProvider()
    .Build();
mail.Body = await engine.CompileRenderStringAsync("templateKey", 
    template, new { Name = "John", OrderNo = "12345" });

7.2 与企业微信集成

通过邮件网关实现跨平台通知:

// 转换为企业微信接受格式
mail.To.Add("12345@qywechat.com");
mail.Headers.Add("X-WeChat-Format", "{\"msgtype\":\"text\"}");

7.3 监控告警系统

邮件发送量监控实现:

// 使用PerformanceCounter
var counter = new PerformanceCounter(
    "SMTP", 
    "Messages Sent/sec", 
    Process.GetCurrentProcess().ProcessName);
    
if(counter.NextValue() > 100)
{
    TriggerAlert("邮件发送速率过高!");
}

8. 安全防护要点

8.1 凭据存储方案

避免硬编码的推荐做法:

  1. 使用Azure Key Vault:
var credential = new DefaultAzureCredential();
var secret = new SecretClient(
    new Uri("https://your-vault.vault.azure.net/"), 
    credential);
string password = secret.GetSecret("smtp-password").Value.Value;
  1. 开发环境用user-secrets:
dotnet user-secrets set "SMTP:Password" "your_password"

8.2 内容安全过滤

防范注入攻击:

// 清理HTML标签
mail.Body = Regex.Replace(input, "<.*?>", string.Empty);

// 验证发件人域名
if(!mail.From.Host.EndsWith("your-company.com"))
{
    throw new SecurityException("非法发件人地址");
}

8.3 传输加密强化

强制TLS 1.2+:

ServicePointManager.SecurityProtocol = 
    SecurityProtocolType.Tls12 | SecurityProtocolType.Tls13;
client.EnableSsl = true;

9. 性能调优实战

9.1 批量发送优化

使用Parallel处理批量任务:

var options = new ParallelOptions { MaxDegreeOfParallelism = 4 };
Parallel.ForEach(recipients, options, email => {
    var msg = CloneMail(mail);
    msg.To.Clear();
    msg.To.Add(email);
    client.Send(msg);
});

9.2 连接预热策略

首次连接预建立:

// 应用启动时执行
var warmupClient = new SmtpClient();
warmupClient.Send(new MailMessage(
    "noreply@domain.com", 
    "noreply@domain.com", 
    "Warmup", ""));

9.3 内存管理技巧

大附件处理方案:

// 使用文件流避免内存驻留
using (var stream = new FileStream(
    "largefile.zip", 
    FileMode.Open, 
    FileAccess.Read, 
    FileShare.Read, 
    4096, 
    FileOptions.DeleteOnClose | FileOptions.SequentialScan))
{
    mail.Attachments.Add(new Attachment(stream, "largefile.zip"));
}

10. 调试与日志记录

10.1 协议日志捕获

启用SMTP协议日志:

client.EnableSsl = true;
client.DeliveryFormat = SmtpDeliveryFormat.International;
client.DeliveryMethod = SmtpDeliveryMethod.Network;
client.TargetName = "SMTPSVC/" + client.Host;
client.Log = new SmtpLogger(); // 自定义实现TextWriter

10.2 结构化日志集成

结合Serilog记录:

Log.Information("发送邮件到 {To} 主题 {Subject}", 
    string.Join(",", mail.To.Select(x => x.Address)),
    mail.Subject);
    
try {
    await client.SendMailAsync(mail);
    Log.Information("邮件发送成功");
}
catch (Exception ex) {
    Log.Error(ex, "邮件发送失败");
}

10.3 邮件追踪实现

添加Message-ID追踪:

mail.Headers.Add("Message-ID", 
    $"<{Guid.NewGuid()}@{client.Host}>");

11. 跨平台适配方案

11.1 Linux环境配置

在Docker中的特殊处理:

RUN apt-get update && \
    apt-get install -y --no-install-recommends \
    libc6-dev libgdiplus

11.2 云函数部署

Azure Functions实现示例:

[FunctionName("SendEmail")]
public static async Task Run(
    [QueueTrigger("email-queue")] EmailRequest request,
    ILogger log)
{
    using var client = new SmtpClient();
    // 发送逻辑
}

11.3 移动端适配

Xamarin特殊权限需求:

<application>
    <uses-permission android:name="android.permission.INTERNET" />
</application>

12. 测试策略设计

12.1 单元测试方案

使用SmtpClient的测试模式:

var client = new SmtpClient();
client.DeliveryMethod = SmtpDeliveryMethod.SpecifiedPickupDirectory;
client.PickupDirectoryLocation = @"C:\TestMails";

// 发送后检查目录下文件
var files = Directory.GetFiles(client.PickupDirectoryLocation);
Assert.That(files, Has.Length.EqualTo(1));

12.2 集成测试框架

MailHog测试容器配置:

services:
  mailhog:
    image: mailhog/mailhog
    ports:
      - "1025:1025"
      - "8025:8025"

12.3 负载测试要点

使用BenchmarkDotNet测试:

[Benchmark]
public void SendTestEmail()
{
    var mail = CreateTestMail();
    _client.Send(mail);
}

13. 现代化替代方案

13.1 MailKit库迁移

从SmtpClient切换到MailKit:

using var client = new MailKit.Net.Smtp.SmtpClient();
await client.ConnectAsync("smtp.qq.com", 587, SecureSocketOptions.StartTls);
await client.AuthenticateAsync("user", "pwd");
await client.SendAsync(mimeMessage);

13.2 第三方API集成

SendGrid API调用示例:

var apiKey = Environment.GetEnvironmentVariable("SENDGRID_API_KEY");
var client = new SendGridClient(apiKey);
var msg = new SendGridMessage();
msg.SetFrom("test@domain.com");
msg.AddTo("recipient@domain.com");
msg.SetSubject("测试邮件");
msg.AddContent(MimeType.Text, "正文内容");
var response = await client.SendEmailAsync(msg);

13.3 无服务器架构

AWS Lambda实现:

public async Task FunctionHandler(SQSEvent evnt)
{
    foreach(var record in evnt.Records)
    {
        var mail = JsonConvert.DeserializeObject<MailMessage>(record.Body);
        using var client = new SmtpClient();
        await client.SendMailAsync(mail);
    }
}

14. 法律合规要点

14.1 GDPR合规处理

邮件内容加密存储:

var encryptedBody = ProtectedData.Protect(
    Encoding.UTF8.GetBytes(mail.Body),
    null,
    DataProtectionScope.CurrentUser);
File.WriteAllBytes("encrypted.eml", encryptedBody);

14.2 退订功能实现

添加List-Unsubscribe头:

mail.Headers.Add("List-Unsubscribe", 
    "<https://domain.com/unsubscribe?id=123>");

14.3 内容审核流程

敏感词过滤示例:

var bannedWords = new[] { "赌场", "发票" };
if(bannedWords.Any(w => mail.Body.Contains(w)))
{
    throw new ContentPolicyException("邮件包含违禁词汇");
}

15. 故障转移设计

15.1 备用服务器配置

多SMTP服务器切换:

var servers = new[]
{
    new SmtpConfig("smtp1.domain.com"),
    new SmtpConfig("smtp2.domain.com")
};

foreach(var server in servers)
{
    try {
        using var client = CreateClient(server);
        client.Send(mail);
        break;
    }
    catch { /* 记录日志 */ }
}

15.2 断点续传实现

大附件分块传输:

const int chunkSize = 1024 * 1024; // 1MB
var buffer = new byte[chunkSize];
using var fs = File.OpenRead("largefile.iso");

while (fs.Position < fs.Length)
{
    int bytesRead = fs.Read(buffer, 0, buffer.Length);
    var chunk = new Attachment(new MemoryStream(buffer, 0, bytesRead), 
        $"largefile.part{(fs.Position / chunkSize) + 1}");
    mail.Attachments.Add(chunk);
    client.Send(mail);
    mail.Attachments.Remove(chunk);
}

15.3 监控告警集成

健康检查实现:

var healthCheck = new SmtpHealthCheck();
var result = await healthCheck.CheckHealthAsync(context);
if(result.Status == HealthStatus.Unhealthy)
{
    await NotifyAdmin("SMTP服务异常!");
}

16. 国际化支持

16.1 多语言邮件处理

编码设置关键点:

mail.SubjectEncoding = Encoding.GetEncoding("ISO-8859-1");
mail.BodyEncoding = Encoding.UTF8;
mail.HeadersEncoding = Encoding.UTF8;

16.2 时区转换方案

本地化发送时间:

mail.Headers.Add("Date", 
    DateTimeOffset.Now.ToOffset(recipientTimeZone.BaseUtcOffset).ToString("r"));

16.3 右向左语言支持

阿拉伯语内容处理:

mail.Body = "<html dir='rtl'><body>مرحبا</body></html>";
mail.Headers.Add("Content-Language", "ar");

17. 邮件服务器自建方案

17.1 Papercut SMTP调试

开发环境快速搭建:

docker run -d -p 25:25 -p 3000:3000 rnwood/smtp4dev

17.2 hMailServer配置

Windows服务器安装要点:

  1. 创建域名并配置MX记录
  2. 设置SPF记录:v=spf1 a mx ~all
  3. 启用TLS证书绑定

17.3 Postfix集成

Linux环境邮件网关:

client.DeliveryMethod = SmtpDeliveryMethod.Network;
client.Host = "localhost";
client.Port = 25;

18. 邮件数据分析

18.1 打开率追踪

嵌入追踪像素:

var trackingImg = $"<img src='https://api.domain.com/track?mid={messageId}' width='1' height='1'>";
mail.Body += trackingImg;

18.2 点击热图实现

链接重定向处理:

string originalUrl = "https://product.com";
string trackedUrl = $"https://track.domain.com/redirect?url={WebUtility.UrlEncode(originalUrl)}&mid={messageId}";
mail.Body = mail.Body.Replace(originalUrl, trackedUrl);

18.3 发送报告生成

使用EPPlus导出Excel:

using var pkg = new ExcelPackage();
var sheet = pkg.Workbook.Worksheets.Add("发送报告");
sheet.Cells["A1"].LoadFromDataTable(reportData, true);
File.WriteAllBytes("report.xlsx", pkg.GetAsByteArray());

19. 特殊场景处理

19.1 延迟发送实现

使用Hangfire定时任务:

BackgroundJob.Schedule(
    () => SendEmail(mail),
    sendTime - DateTime.Now);

19.2 邮件撤回功能

Exchange服务器方案:

var outlook = new Application();
var mapiNamespace = outlook.GetNamespace("MAPI");
mapiNamespace.SendAndReceive(false);
var item = mapiNamespace.GetItemFromID(entryId) as MailItem;
item.Delete();

19.3 自动回复识别

检测Auto-Submitted头:

if(mail.Headers.AllKeys.Contains("Auto-Submitted"))
{
    Log.Warning("收到自动回复邮件");
}

20. 架构设计进阶

20.1 微服务拆分

邮件服务独立部署:

// 定义gRPC服务
service MailService {
    rpc Send (MailRequest) returns (MailResponse);
}

20.2 事件驱动架构

通过消息队列解耦:

bus.Subscribe<EmailRequestedEvent>(async msg => {
    using var client = new SmtpClient();
    await client.SendMailAsync(ConvertToMailMessage(msg));
});

20.3 服务网格集成

Istio流量管理配置:

apiVersion: networking.istio.io/v1alpha3
kind: DestinationRule
metadata:
  name: smtp
spec:
  host: smtp.prod.svc.cluster.local
  trafficPolicy:
    connectionPool:
      tcp: 
        maxConnections: 100

21. 性能监控体系

21.1 Prometheus指标

暴露SMTP指标:

var gauge = Metrics.CreateGauge("smtp_active_connections", "当前活跃连接数");
gauge.Set(client.ServicePoint.CurrentConnections);

21.2 Grafana看板

关键监控指标:

  1. 发送成功率
  2. 平均延迟
  3. 并发连接数
  4. 重试次数

21.3 告警规则配置

Alertmanager规则示例:

groups:
- name: smtp-alerts
  rules:
  - alert: HighFailureRate
    expr: rate(smtp_failures_total[5m]) > 0.1
    for: 10m

22. CI/CD集成

22.1 构建流水线配置

邮件通知阶段示例:

- stage: Notify
  jobs:
  - job: send_email
    steps:
    - task: DotNetCoreCLI@2
      inputs:
        command: run
        arguments: 'SendBuildNotification --buildId $(Build.BuildId)'

22.2 安全扫描集成

敏感信息检测:

gitleaks detect --source . --report-format json --config .gitleaks.toml

22.3 部署验证

端到端测试方案:

[Test]
public async Task TestEmailDelivery()
{
    var testMail = CreateTestMail();
    var tracker = new DeliveryTracker();
    testMail.Headers.Add("X-Test-ID", tracker.Id);
    
    await _smtpService.SendAsync(testMail);
    Assert.True(await tracker.WaitAsync(TimeSpan.FromMinutes(1)));
}

23. 成本优化策略

23.1 发送配额管理

限流器实现:

var limiter = new TokenBucketRateLimiter(
    tokensPerPeriod: 100,
    replenishmentPeriod: TimeSpan.FromMinutes(1));
    
if(await limiter.AttemptAcquireAsync())
{
    client.Send(mail);
}

23.2 附件压缩处理

使用SharpZipLib压缩:

using var output = new MemoryStream();
using var zip = new ZipOutputStream(output);
zip.PutNextEntry(new ZipEntry("report.pdf"));
fileStream.CopyTo(zip);
mail.Attachments.Add(new Attachment(
    new MemoryStream(output.ToArray()), 
    "reports.zip"));

23.3 云服务选型

各厂商成本对比:

服务商 每千封价格 免费额度
SendGrid $0.90 100封/天
Mailgun $0.80 10,000封/月
AWS SES $0.10 62,000封/月

24. 灾难恢复方案

24.1 邮件归档设计

使用MinIO存储:

var minio = new MinioClient()
    .WithEndpoint("minio.domain.com")
    .WithCredentials("key", "secret")
    .Build();
    
await minio.PutObjectAsync("email-archive", 
    $"{DateTime.UtcNow:yyyyMMddHHmmss}.eml", 
    mailStream, mailStream.Length);

24.2 数据备份策略

Azure Blob版本控制:

var blobClient = new BlobClient(connectionString, "backup", "emails.bak");
await blobClient.UploadAsync(backupStream, 
    new BlobUploadOptions { 
        AccessTier = AccessTier.Cool 
    });

24.3 恢复演练流程

自动化测试脚本:

Invoke-RestMethod -Uri "https://api.domain.com/disaster-recovery/test" -Method Post

25. 开发者工具链

25.1 代码片段管理

VS Code用户片段:

{
    "C# Email": {
        "prefix": "email",
        "body": [
            "using var client = new SmtpClient(\"${1:smtp.domain.com}\", ${2:587});",
            "client.Credentials = new NetworkCredential(\"${3:user}\", \"${4:pass}\");",
            "client.EnableSsl = true;",
            "var mail = new MailMessage(\"${5:from@domain.com}\", \"${6:to@domain.com}\");",
            "mail.Subject = \"${7:Subject}\";",
            "mail.Body = \"${8:Body}\";",
            "client.Send(mail);"
        ]
    }
}

25.2 单元测试模板

xUnit测试示例:

public class EmailTests : IDisposable
{
    private readonly SmtpClient _client;
    
    public EmailTests()
    {
        _client = new SmtpClient { DeliveryMethod = SmtpDeliveryMethod.SpecifiedPickupDirectory };
    }
    
    [Fact]
    public void ShouldContainValidHeaders()
    {
        var mail = new MailMessage("test@domain.com", "test@domain.com");
        _client.Send(mail);
        
        var file = Directory.GetFiles(_client.PickupDirectoryLocation).First();
        var content = File.ReadAllText(file);
        Assert.Contains("Message-ID:", content);
    }
    
    public void Dispose() => _client.Dispose();
}

25.3 性能分析技巧

使用JetBrains dotTrace:

// 在需要分析的代码段前后添加
Profile.Start();
// 邮件发送代码
Profile.Stop();

26. 安全审计要点

26.1 渗透测试项目

必备检查项:

  1. 开放中继测试
  2. 命令注入检测
  3. 敏感信息泄露扫描
  4. TLS配置检查(使用testssl.sh)

26.2 日志审计实现

关键日志字段:

var auditLog = new {
    Timestamp = DateTime.UtcNow,
    Sender = mail.From.Address,
    Recipients = mail.To.Select(x => x.Address),
    Subject = mail.Subject,
    AttachmentCount = mail.Attachments.Count,
    ClientIP = HttpContext.Connection.RemoteIpAddress
};

26.3 合规检查清单

企业级部署必须:

  1. 实现双因素认证
  2. 开启完整协议日志
  3. 配置邮件内容存档
  4. 定期轮换加密证书

27. 文档与知识管理

27.1 Swagger集成

API文档示例:

[SwaggerOperation(
    Summary = "发送邮件",
    Description = "通过SMTP协议发送电子邮件")]
[HttpPost("send")]
public async Task<IActionResult> SendEmail([FromBody] EmailDto request)

27.2 Markdown文档

技术方案模板:

## 邮件发送方案

### 配置参数
| 参数 | 类型 | 说明 |
|------|------|------|
| Host | string | SMTP服务器地址 |

### 示例代码
```csharp
// 示例代码

常见问题

Q: 认证失败怎么办? A: 检查...


### 27.3 架构决策记录
ADR示例:
```text
# 1. SMTP客户端选型

## 状态
已采纳

## 决策
选用System.Net.Mail而非MailKit,因为...

## 后果
需自行处理某些高级功能...

28. 团队协作规范

28.1 代码审查要点

必查项目:

  1. 凭据是否硬编码
  2. 异常处理是否完整
  3. 是否有未关闭的资源
  4. 附件大小是否有限制

28.2 Git工作流

功能分支命名:

git checkout -b feature/email-attach-opt

28.3 环境隔离策略

配置分离方案:

{
  "SMTP": {
    "Development": {
      "Host": "localhost"
    },
    "Production": {
      "Host": "smtp.domain.com"
    }
  }
}

29. 新技术趋势适配

29.1 QUIC协议支持

试验性实现:

var quicConnection = await QuicConnection.ConnectAsync(
    new QuicClientConnectionOptions {
        RemoteEndPoint = new DnsEndPoint("smtp.domain.com", 587),
        ClientAuthenticationOptions = new SslClientAuthenticationOptions {
            TargetHost = "smtp.domain.com"
        }
    });

29.2 AI内容生成

智能邮件草稿:

var prompt = $"写一封关于{subject}的正式邮件";
var completion = await openai.Completions.Create(
    new CompletionCreateRequest { 
        Prompt = prompt,
        MaxTokens = 500 
    });
mail.Body = completion.Choices[0].Text;

29.3 区块链存证

邮件哈希上链:

var hash = SHA256.HashData(Encoding.UTF8.GetBytes(mail.ToString()));
var txHash = await ethers.Provider.SendTransaction(
    new TransactionRequest {
        To = "0xYourContractAddress",
        Data = "0x" + BitConverter.ToString(hash).Replace("-", "")
    });

30. 维护与演进建议

长期维护需要考虑:

  1. 协议版本升级路线(如SMTP over HTTP/3)
  2. 依赖库的安全更新策略
  3. 监控指标的持续优化
  4. 与新兴消息渠道的集成(如企业微信、飞书)

对于高并发场景,建议逐步迁移到专业邮件发送服务(如SendGrid、Mailgun),它们提供:

  • 自动IP预热
  • 智能路由选择
  • 深度数据分析
  • 合规性保障

在.NET 7+环境中,可尝试新的System.Net.Mail改进特性:

// 新的超时控制方式
client.SendTimeout = TimeSpan.FromSeconds(30);
client.ReceiveTimeout = TimeSpan.FromSeconds(30);

最后分享一个调试技巧:使用Telnet直接测试SMTP服务器响应,快速验证网络和认证问题:

telnet smtp.qq.com 587
EHLO test
AUTH LOGIN
<base64编码的用户名>
<base64编码的密码>
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值