首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> C語言 >> 關於C語言

ASP.NET C# 發送電子郵件完整指南:SmtpClient、HTML 郵件、驗證與附件實戰

     編輯:關於C語言

核心類別:System.Net.Mail.SmtpClient(取代舊版 System.Web.Mail)

.NET 2.0+ **棄用 `System.Web.Mail`**,統一使用 `System.Net.Mail` 命名空間,功能更完整、支援 SSL/TLS、附件、非同步發送。

基本發送流程

using System.Net;
using System.Net.Mail;

public void SendEmail(string to, string subject, string htmlBody, string from = "noreply@example.com")
{
    using (var message = new MailMessage())
    {
        message.From = new MailAddress(from, "系統通知");
        message.To.Add(to);
        message.Subject = subject;
        message.Body = htmlBody;
        message.IsBodyHtml = true; // 關鍵:啟用 HTML 內容
        message.BodyEncoding = System.Text.Encoding.UTF8;
        message.SubjectEncoding = System.Text.Encoding.UTF8;

        using (var client = new SmtpClient("smtp.example.com", 587)) // 或 25, 465
        {
            client.Credentials = new NetworkCredential("username", "password");
            client.EnableSsl = true; // 必須:現代 SMTP 多要求 STARTTLS (587) 或隱性 SSL (465)
            client.DeliveryMethod = SmtpDeliveryMethod.Network;
            client.Timeout = 30000; // 30 秒逾時

            client.Send(message); // 同步發送
            // 或 client.SendMailAsync(message); // 非同步
        }
    }
}

關鍵設定詳解

屬性/方法說明常見值
`SmtpClient.Host` / `Port`SMTP 伺服器位址與埠號`smtp.gmail.com` 587 / `smtp.office365.com` 587 / `smtp.163.com` 25/465/587
`EnableSsl`啟用 SSL/TLS 加密傳輸`true` (587 通常 STARTTLS) / `false` (25 明文,不建議)
`Credentials`登入帳密`new NetworkCredential("user@domain.com", "authCode")`
`DeliveryMethod`發送方式`Network` (直接連 SMTP) / `SpecifiedPickupDirectory` (存檔至 IIS Pickup 目錄) / `PickupDirectoryFromIis`
`Timeout`發送逾時毫秒數`30000` (預設 100 秒較長,建議縮短)
`MailMessage.IsBodyHtml`內容是否為 HTML`true` 允許標籤渲染,`false` 純文字
`MailMessage.Priority`郵件優先權`High` / `Normal` / `Low`
`MailMessage.Attachments`附件集合`message.Attachments.Add(new Attachment("path.pdf"))`
`AlternateViews`多格式內容(純文字 + HTML)`message.AlternateViews.Add(AlternateView.CreateAlternateViewFromString(plainText, null, "text/plain"));`

進階實戰:HTML 郵件 + 內嵌圖片 + 附件 + 非同步 + 錯誤處理

public async Task SendRichEmailAsync(EmailRequest request)
{
    using (var message = new MailMessage())
    {
        message.From = new MailAddress(request.FromEmail, request.FromName);
        request.ToEmails.ForEach(t => message.To.Add(t));
        request.CcEmails.ForEach(c => message.CC.Add(c));
        request.BccEmails.ForEach(b => message.Bcc.Add(b));
        message.Subject = request.Subject;
        message.Priority = request.IsUrgent ? MailPriority.High : MailPriority.Normal;

        // 1. 純文字備用內容(反垃圾郵件加分)
        string plainText = StripHtml(request.HtmlBody);
        var plainView = AlternateView.CreateAlternateViewFromString(plainText, null, "text/plain");

        // 2. HTML 內容 + 內嵌圖片 (LinkedResource)
        var htmlView = AlternateView.CreateAlternateViewFromString(request.HtmlBody, null, "text/html");
        foreach (var inline in request.InlineImages) // { ContentId, FilePath }
        {
            var img = new LinkedResource(inline.FilePath, MediaTypeNames.Image.Jpeg);
            img.ContentId = inline.ContentId; // HTML 中 
            img.TransferEncoding = System.Net.Mime.TransferEncoding.Base64;
            htmlView.LinkedResources.Add(img);
        }

        message.AlternateViews.Add(plainView);
        message.AlternateViews.Add(htmlView);

        // 3. 一般附件
        foreach (var att in request.Attachments)
        {
            message.Attachments.Add(new Attachment(att.FilePath, att.MediaType));
        }

        using (var client = new SmtpClient(request.SmtpHost, request.SmtpPort))
        {
            client.Credentials = new NetworkCredential(request.UserName, request.Password);
            client.EnableSsl = request.EnableSsl;
            client.Timeout = 30000;

            try
            {
                await client.SendMailAsync(message);
                return SendResult.Success();
            }
            catch (SmtpException ex)
            {
                return SendResult.Fail($"SMTP 錯誤: {ex.StatusCode} - {ex.Message}");
            }
            catch (Exception ex)
            {
                return SendResult.Fail($"發送失敗: {ex.Message}");
            }
        }
    }
}

// 簡易 HTML 標籤移除
private string StripHtml(string html) => System.Text.RegularExpressions.Regex.Replace(html, "<[^>]+>", "").Trim();

常見提供商 SMTP 設定速查

提供商SMTP HostPortSSL/TLS備註
Gmailsmtp.gmail.com587STARTTLS (EnableSsl=true)需開啟「低安全性應用程式存取」或使用應用程式密碼
Outlook / Office 365smtp.office365.com587STARTTLS企業帳號可能需管理員允許 SMTP Auth
163 / 126smtp.163.com465 / 587SSL (465) / STARTTLS (587)需在網頁版設定開啟 SMTP/IMAP/POP3,取得授權碼
QQ 郵箱smtp.qq.com465 / 587SSL / STARTTLS需開啟服務獲取授權碼
SendGrid / Mailgun / Amazon SESAPI 為主,亦支援 SMTP587/2525STARTTLS建議用官方 SDK (API) 而非 SMTP,功能更豐富

避坑指南與最佳實踐

  • ✅ **永遠使用 `using` 釋放 `SmtpClient`、`MailMessage`、`Attachment`、`LinkedResource`** — 實作 `IDisposable`,未釋放會導致檔案鎖定、連線池洩漏。
  • ✅ **非同步 `SendMailAsync`** — ASP.NET Core / Web API 必須用非同步避免阻塞執行緒池。
  • ✅ **HTML 郵件務必提供純文字 `AlternateView`** — 提高送達率,避免被判定垃圾郵件。
  • ✅ **內嵌圖片用 `LinkedResource` + `cid:`** — 而非外部連結(會被郵件客戶端封鎖/需用戶同意下載)。
  • ✅ **大量發送用佇列/背景服務** — 直接在請求中發送會導致回應緩慢、SMTP 連線限流。採用 `BackgroundService` + `Channel` / Hangfire / MassTransit 異步處理。
  • ✅ **錯誤重試策略** — `Polly` 定義指數退避重試(針對暫時性 `SmtpException` 如 `ServiceNotAvailable`、`TransactionFailed`)。
  • ❌ **不要在 `web.config` 硬編碼密碼** — 用 `appsettings.json` + `Secret Manager` / Azure Key Vault / 環境變數。
  • ❌ **避免 `System.Web.Mail`** — 已棄用 15 年,無 SSL 支援、無附件、無非同步。

ASP.NET Core 依賴注入整合範例

// 介面
public interface IEmailService
{
    Task SendAsync(EmailRequest request);
}

// 實作
public class SmtpEmailService : IEmailService
{
    private readonly SmtpOptions _opt;
    public SmtpEmailService(IOptions opt) => _opt = opt.Value;
    // 實作 SendAsync 使用 _opt 設定...
}

// 註冊
services.Configure(config.GetSection("Smtp"));
services.AddTransient();

// 控制器使用
public class NotifyController : ControllerBase
{
    private readonly IEmailService _email;
    public NotifyController(IEmailService email) => _email = email;
    [HttpPost] public async Task Send(EmailRequest req) => Ok(await _email.SendAsync(req));
}

總結

掌握 `System.Net.Mail.SmtpClient` 核心參數、**HTML/純文字多格式、內嵌圖片、附件、非同步、資源釋放、錯誤重試、DI 整合**,即可構建健壯、可維護的郵件發送模組。現代專案建議**優先考慮交易型郵件 API (SendGrid, Mailgun, SES, Postmark)**,獲得更高送達率、詳細追蹤、模板管理與退訂合規,僅在內部通知、低頻場景使用自建 SMTP。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved