.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"));` |
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 Host | Port | SSL/TLS | 備註 |
|---|---|---|---|---|
| Gmail | smtp.gmail.com | 587 | STARTTLS (EnableSsl=true) | 需開啟「低安全性應用程式存取」或使用應用程式密碼 |
| Outlook / Office 365 | smtp.office365.com | 587 | STARTTLS | 企業帳號可能需管理員允許 SMTP Auth |
| 163 / 126 | smtp.163.com | 465 / 587 | SSL (465) / STARTTLS (587) | 需在網頁版設定開啟 SMTP/IMAP/POP3,取得授權碼 |
| QQ 郵箱 | smtp.qq.com | 465 / 587 | SSL / STARTTLS | 需開啟服務獲取授權碼 |
| SendGrid / Mailgun / Amazon SES | API 為主,亦支援 SMTP | 587/2525 | STARTTLS | 建議用官方 SDK (API) 而非 SMTP,功能更豐富 |
// 介面
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。