C#使用 MailKit 收發郵件

二次元攻城狮發表於2024-10-15

目錄
  • 獲取QQ郵箱授權碼
  • 安裝 MailKit
  • 配置郵件伺服器資訊
  • 實現郵件收發方法
  • 測試郵件收發
  • 參考文章

獲取QQ郵箱授權碼

開啟QQ郵箱,進入 設定->賬號 頁面:
image

POP3/IMAP/SMTP 中開啟 SMTP服務,然後點選 授權碼複製授權碼:
image

QQ郵箱伺服器的引數如下,詳細內容參考SMTP/IMAP服務

  • 接收郵件伺服器: imap.qq.com,使用SSL,埠號993
  • 傳送郵件伺服器: smtp.qq.com,使用SSL,埠號465或587

網易郵箱伺服器的引數如下,詳細內容參考網易郵箱伺服器引數如何設定?
image

安裝 MailKit

在專案中安裝 MailKit 庫,可以透過NuGet包管理器安裝它或者使用以下命令:

dotnet add package MailKit

MailKit 是在 MimeKit 之上構建的跨平臺郵件客戶端庫,目標是成為 .NET 的最佳電子郵件框架。

配置郵件伺服器資訊

配置郵件伺服器資訊,包括主機、埠、使用者名稱、密碼等,封裝成 EmailData 類:

/// <summary>
/// 郵件資料
/// </summary>
class EmailData
{
    /// <summary>
    /// 發件人
    /// </summary>
    public string From { get; set; }
    /// <summary>
    /// 授權碼
    /// </summary>
    public string Password { get; set; }
    /// <summary>
    /// 收件人
    /// </summary>
    public string To { get; set; }
    /// <summary>
    /// 主題
    /// </summary>
    public string Subject { get; set; }
    /// <summary>
    /// 純文字內容
    /// </summary>
    public string TextBody { get; set; }
    /// <summary>
    /// HTML內容
    /// </summary>
    public string HtmlBody { get; set; }

    /// <summary>
    /// 傳送郵件伺服器
    /// </summary>
    public HostInfo SMTP { get; set; }
    /// <summary>
    /// 接受郵件伺服器
    /// </summary>
    public HostInfo IMAP { get; set; }
}
/// <summary>
/// 伺服器資訊
/// </summary>
class HostInfo
{
    /// <summary>
    /// 伺服器地址
    /// </summary>
    public string Host { get; set; }
    /// <summary>
    /// 伺服器埠
    /// </summary>
    public int Port { get; set; }
}

實現郵件收發方法

郵件收發方法如下,這裡只接收最新的10封郵件便於實現互動邏輯:

static async Task SendEmail(EmailData data)
{
    try
    {
        // 建立一個新的 MIME 訊息物件
        var message = new MimeMessage();

        // 設定發件人
        message.From.Add(MailboxAddress.Parse(data.From));

        // 設定收件人
        message.To.Add(MailboxAddress.Parse(data.To));

        // 設定主題
        message.Subject = data.Subject;

        // 設定正文
        message.Body = new BodyBuilder
        {
            TextBody = data.TextBody,
            HtmlBody = data.HtmlBody
        }.ToMessageBody();

        // 使用 SMTP 客戶端傳送郵件
        using (var client = new SmtpClient())
        {
            await client.ConnectAsync(data.SMTP.Host, data.SMTP.Port, SecureSocketOptions.StartTls);

            // 注:使用者名稱和密碼應妥善保管,不要硬編碼到原始碼中
            await client.AuthenticateAsync(data.From, data.Password);

            // 傳送郵件
            await client.SendAsync(message);

            // 斷開與伺服器的連線
            await client.DisconnectAsync(true);
        }

        Console.WriteLine("郵件已成功傳送!");
    }
    catch (Exception ex)
    {
        Console.WriteLine($"郵件傳送失敗:{ex.Message}");
    }
}

static async Task GetEmail(EmailData data)
{
    try
    {
        // 連線到 IMAP 伺服器
        using (var client = new ImapClient())
        {
            await client.ConnectAsync(data.IMAP.Host, data.IMAP.Port, true); // 通常使用 TLS 加密

            // 認證使用者
            await client.AuthenticateAsync(data.From, data.Password);

            // 選擇收件箱
            var inbox = client.Inbox;
            await inbox.OpenAsync(FolderAccess.ReadOnly);

            // 獲取郵件數量
            int totalMessages = inbox.Count;
            // 確保開始位置不會小於1
            int start = Math.Max(totalMessages - 5, 1); 
            int end = totalMessages;


            // 獲取最新的10封郵件的資訊
            var messages = inbox.Fetch(start, end, MessageSummaryItems.Envelope | MessageSummaryItems.UniqueId);

            // 遍歷郵件資訊並列印出來
            foreach (var summary in messages)
            {
                var uid = summary.UniqueId;
                var message = await inbox.GetMessageAsync(uid);
                Console.WriteLine($"Subject: {message.Subject}");
                Console.WriteLine($"From: {message.From}");
                Console.WriteLine($"To: {message.To}");
                Console.WriteLine($"Date: {message.Date}");
				Console.WriteLine($"HtmlBody: {message.HtmlBody}");
 				Console.WriteLine($"TextBody: {message.TextBody}");
            }
            // 斷開連線
            await client.DisconnectAsync(true);
        }
    }
    catch (Exception ex)
    {
        Console.WriteLine($"接收郵件失敗:{ex.Message}");
    }
}

注意接受郵件時 message.Body 部分內容需要特殊的解析規則,比如附件部分、歷史郵件部分。

測試郵件收發

使用時關鍵資訊替換成自己的:

static async Task Main(string[] args)
{
    var data = new EmailData
    {
        From = "qqqqqq@qq.com",
        Password = "**********",
        To = "qqqqqq@qq.com",
        Subject = "來自 .NET Core 的測試郵件",
        TextBody = "這是純文字訊息內容。",
        HtmlBody = "<h1>這是HTML訊息</h1><p>這封郵件是透過MailKit從 .NET Core 傳送的。</p>",
        SMTP = new HostInfo()
        {
            Host = "smtp.qq.com",
            Port = 587
        },
        IMAP = new HostInfo()
        {
            Host = "imap.qq.com",
            Port = 993
        }

    };

    await SendEmail(data);
    await GetEmail(data);
}

參考文章

  • 使用MailKit在.NET Core中收發郵件的完整示例
  • QQ郵箱獲取和使用授權碼

相關文章