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

ASP.NET 發送郵件完整指南:SmtpClient、MailMessage、附件、SSL、異步發送

     編輯:ASP.NET 基礎

前言

.NET Framework 2.0+ 內建 `System.Net.Mail` 命名空間,提供 `SmtpClient`、`MailMessage`、`Attachment` 等類別,無需註冊 COM 元件、支援 SSL/TLS、非同步發送、標準 MIME 編碼。本文整理郵件發送核心類別、封裝通用發送元件、附件處理、SSL 設定、異步模式與常見問題排查。

核心類別速查

類別用途
MailMessage郵件實體:From/To/CC/Bcc/Subject/Body/Attachments/Priority/Encoding
SmtpClientSMTP 傳輸客戶端:Host/Port/Credentials/EnableSsl/Timeout/Send/SendAsync
Attachment附件:檔案路徑/串流、ContentType/ContentDisposition/NameEncoding
MailAddress郵件地址:Address/DisplayName/Encoding
AlternateView替代檢視:純文字/HTML 多部分郵件

1. 基本發送 (同步)


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

public void SendBasic()
{
    using (var msg = new MailMessage())
    {
        msg.From = new MailAddress("sender@domain.com", "發件人");
        msg.To.Add(new MailAddress("receiver@domain.com", "收件人"));
        msg.Subject = "測試主旨";
        msg.Body = "

HTML 內容

"; msg.IsBodyHtml = true; msg.BodyEncoding = Encoding.UTF8; msg.SubjectEncoding = Encoding.UTF8; msg.Priority = MailPriority.Normal; using (var client = new SmtpClient("smtp.domain.com", 587)) { client.Credentials = new NetworkCredential("user", "pwd"); client.EnableSsl = true; // STARTTLS (587) 或 Implicit SSL (465) client.Timeout = 30000; client.Send(msg); } } }

2. 封裝通用發送元件


public class MailService
{
    private readonly string _host;
    private readonly int _port;
    private readonly string _user;
    private readonly string _pass;
    private readonly bool _ssl;
    private readonly string _fromAddr;
    private readonly string _fromName;

    public MailService(string host, int port, string user, string pass, bool ssl, string fromAddr, string fromName)
    {
        _host = host; _port = port; _user = user; _pass = pass; _ssl = ssl; _fromAddr = fromAddr; _fromName = fromName;
    }

    public bool Send(string to, string subject, string htmlBody, 
        IEnumerable cc = null, IEnumerable bcc = null, 
        IEnumerable attachments = null, string replyTo = null)
    {
        try
        {
            using (var msg = new MailMessage())
            {
                msg.From = new MailAddress(_fromAddr, _fromName, Encoding.UTF8);
                msg.To.Add(new MailAddress(to));
                if (cc != null) foreach (var c in cc) msg.CC.Add(new MailAddress(c));
                if (bcc != null) foreach (var b in bcc) msg.Bcc.Add(new MailAddress(b));
                if (!string.IsNullOrEmpty(replyTo)) msg.ReplyToList.Add(new MailAddress(replyTo));

                msg.Subject = subject;
                msg.SubjectEncoding = Encoding.UTF8;
                msg.Body = htmlBody;
                msg.BodyEncoding = Encoding.UTF8;
                msg.IsBodyHtml = true;
                msg.Priority = MailPriority.Normal;

                if (attachments != null) foreach (var a in attachments) msg.Attachments.Add(a);

                using (var client = new SmtpClient(_host, _port))
                {
                    client.Credentials = new NetworkCredential(_user, _pass);
                    client.EnableSsl = _ssl;
                    client.Send(msg);
                }
            }
            return true;
        }
        catch (Exception ex)
        {
            // 記錄 Log
            return false;
        }
    }

    // 附件建立輔助
    public static Attachment CreateAttachment(string filePath, string mimeType = null)
    {
        var att = new Attachment(filePath);
        if (!string.IsNullOrEmpty(mimeType)) att.ContentType = new ContentType(mimeType);
        // 中文檔名 RFC 2231 編碼 (System.Net.Mail 4.5+ 自動處理)
        return att;
    }
}

3. 附件中文檔名正確編碼 (.NET 4.5+)


// .NET 4.5+ 自動使用 RFC 2231 (filename*=UTF-8'')
var att = new Attachment(@"C:\報表.xlsx");
// 手動指定 (舊版或特殊需求)
att.ContentDisposition.FileName = "報表.xlsx"; // 自動編碼
att.ContentDisposition.FileNameStar = "UTF-8''" + Uri.EscapeDataString("報表.xlsx"); // 明確指定

4. 異步發送 (不阻塞 UI/執行緒)


public async Task SendAsync(string to, string subject, string htmlBody, 
    IEnumerable attachments = null)
{
    using (var msg = new MailMessage())
    {
        msg.From = new MailAddress(_fromAddr, _fromName, Encoding.UTF8);
        msg.To.Add(new MailAddress(to));
        msg.Subject = subject;
        msg.SubjectEncoding = Encoding.UTF8;
        msg.Body = htmlBody;
        msg.BodyEncoding = Encoding.UTF8;
        msg.IsBodyHtml = true;

        if (attachments != null) foreach (var a in attachments) msg.Attachments.Add(a);

        using (var client = new SmtpClient(_host, _port))
        {
            client.Credentials = new NetworkCredential(_user, _pass);
            client.EnableSsl = _ssl;
            // 事件式非同步 (舊版) 或 Task 包裝
            await client.SendMailAsync(msg); // .NET 4.5+
        }
    }
    return true;
}

5. 常見 SMTP 設定對照表

提供者SMTP HostPortSSL 模式
Gmailsmtp.gmail.com587STARTTLS (EnableSsl=true)
Outlook/Office365smtp.office365.com587STARTTLS
163/126smtp.163.com465 / 587Implicit SSL (465) / STARTTLS (587)
QQ 企業郵箱smtp.exmail.qq.com465Implicit SSL
本機 IIS SMTPlocalhost25無 (內網常用)

6. 常見錯誤與排查

錯誤原因解決
5.7.1 Unable to relaySMTP 未授權中繼設定 SMTP 允許該 IP 中繼、或使用認證帳號
The SMTP server requires a secure connection未啟用 SSL`EnableSsl=true`、確認 Port (465/587)
Authentication failed帳號/密碼錯誤、未開啟 SMTP 服務、需應用程式專用密碼檢查郵件商設定 (Gmail 需開啟「低安全性應用」或使用 App Password)
Timeout防火牆阻擋、Port 錯誤、網路不通`telnet smtp.host port` 測試連通性、調整 `client.Timeout`
附件檔名亂碼舊版 .NET 編碼不標準升級 .NET 4.5+、或手動設定 `ContentDisposition.FileNameStar`

7. 本機 IIS SMTP 虛擬伺服器快速設定

  1. 「伺服器管理員」→ 新增功能 → SMTP Server。
  2. IIS 6.0 管理器 → SMTP 虛擬伺服器 → 屬性 → 「存取」→ 「中繼限制」→ 新增本機 IP (127.0.0.1 / 伺服器 IP)。
  3. 「傳遞」→ 「輸出安全性」→ 匿名存取 (內網) 或基本認證。
  4. 防火牆開放 TCP 25/587/465。

總結

`System.Net.Mail` 是 ASP.NET 發送郵件的標準方式:無 COM 依賴、支援 SSL/TLS、異步、標準 MIME 編碼。封裝 `MailService` 統一管理認證、編碼、附件建立,即可滿足絕大多數業務場景。避免使用已停止維護的 JMail/CDO 元件,降低部署與相容性風險。

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