C#使用System.Net庫實(shí)現(xiàn)自動(dòng)發(fā)送郵件功能
一、基本概念
在C#編程環(huán)境中,實(shí)現(xiàn)郵件發(fā)送功能是一項(xiàng)常見的需求,無論是Web應(yīng)用程序還是Windows窗體應(yīng)用程序,郵件服務(wù)都能幫助用戶進(jìn)行信息的傳遞和溝通。使用C#中的System.Net庫,來實(shí)現(xiàn)自動(dòng)發(fā)送郵件的功能。
二、郵箱授權(quán)
下面進(jìn)行郵箱的授權(quán),本篇文章使用QQ郵箱作為案列進(jìn)行示范。



發(fā)送完成按照指引將會獲得一串授權(quán)碼。將授權(quán)碼填入下面代碼的指定位置。
三、示例代碼
使用System.Net.Mail發(fā)送一封簡單的文本郵件:
using System;
using System.Net;
using System.Net.Mail;
class EmailSender
{
public static void Main()
{
try
{
// 配置SMTP服務(wù)器信息(以QQ郵箱為例)
string smtpServer = "smtp.qq.com"; //此處修改發(fā)送郵箱的服務(wù)器地址
int smtpPort = 587;
bool enableSsl = true;
string fromEmail = "your_email@qq.com";//使用的郵箱
string password = "your_password_or_auth_code"; // 此處填寫剛剛獲得的授權(quán)碼
// 創(chuàng)建郵件客戶端
using SmtpClient client = new SmtpClient(smtpServer)
{
Port = smtpPort,
Credentials = new NetworkCredential(fromEmail, password),
EnableSsl = enableSsl
};
// 創(chuàng)建郵件內(nèi)容
MailMessage message = new MailMessage
{
From = new MailAddress(fromEmail),
Subject = "測試郵件",
Body = "這是一封來自C#程序的測試郵件",
IsBodyHtml = false // 設(shè)置為true發(fā)送HTML郵件
};
// 添加收件人
message.To.Add("recipient@example.com"); //填入接受郵件的郵箱地址
// 發(fā)送郵件
client.Send(message);
Console.WriteLine("郵件發(fā)送成功!");
}
catch (Exception ex)
{
Console.WriteLine($"郵件發(fā)送失?。簕ex.Message}");
}
}
}常見郵箱服務(wù)器配置
| 郵箱服務(wù)商 | SMTP服務(wù)器地址 | 端口 | SSL要求 |
|---|---|---|---|
| QQ郵箱 | smtp.qq.com | 587 | 是 |
| 163郵箱 | smtp.163.com | 465 | 是 |
| Gmail | smtp.gmail.com | 587 | 是 |
| Outlook | smtp.office365.com | 587 | 是 |
四、制作一個(gè)報(bào)錯(cuò)提醒功能的函數(shù)
制作一個(gè)報(bào)錯(cuò)提醒功能的函數(shù),當(dāng)現(xiàn)成的程序出現(xiàn)了問題,自動(dòng)發(fā)送郵件提醒程序員進(jìn)行遠(yuǎn)程處理。打工的牛馬制作一個(gè)鞭子抽自己起來干活。實(shí)現(xiàn)效果如下

using System;
using System.Diagnostics;
using System.Net;
using System.Net.Mail;
using System.Security.Cryptography;
using System.Text;
class EmailSender
{
// ======== 配置信息 ========
static string smtpServer = "smtp.qq.com";
static int smtpPort = 587;
static bool enableSsl = true;
static string fromEmail = "填入發(fā)送的郵箱"; //發(fā)送郵箱
static string password = "郵箱授權(quán)碼"; // QQ郵箱需要授權(quán)碼
static string incomingEmail = "接受郵件的郵箱地址";//收件郵箱地址
private static readonly object fileLock = new object();
private const string LogDirectory = "EmailSendLogs";
/// <summary>
/// 報(bào)警信息發(fā)送至郵箱
/// </summary>
/// <param name="alertLevel">報(bào)警級別支持:
/// CRITICAL:嚴(yán)重問題(紅色)
/// HIGH:高級別問題(橙色)
/// MEDIUM:中等問題(黃色)
/// LOW:低級別通知(綠色)
/// </param>
/// <param name="alertContent">報(bào)警內(nèi)容</param>
/// <param name="errorDetails">錯(cuò)誤詳情</param>
/// <param name="attachmentPaths">附件</param>
public static void SendToEmail(string alertLevel, string alertContent, string errorDetails = null, string[] attachmentPaths = null)
{
try
{
//1和2是會在程序運(yùn)行的文件夾中生成一個(gè)日志文件,當(dāng)同一個(gè)報(bào)錯(cuò)今天已經(jīng)發(fā)送過了,將會 //不再發(fā)送,防止報(bào)錯(cuò)一直觸發(fā)然后一直給自己發(fā)送郵件,這樣子抽牛馬干活打在自己身上就太痛了
// ===== 1. 生成錯(cuò)誤唯一標(biāo)識 =====
string errorHash = GenerateErrorHash(alertContent, errorDetails);
// ===== 2. 檢查是否已發(fā)送過 =====
if (IsAlreadySentToday(errorHash))
{
Console.WriteLine("相同錯(cuò)誤今日已發(fā)送過,不再重復(fù)發(fā)送");
return;
}
// ======== 創(chuàng)建郵件客戶端 ========
using SmtpClient client = new SmtpClient(smtpServer)
{
Port = smtpPort,
Credentials = new NetworkCredential(fromEmail, password),
EnableSsl = enableSsl
};
// ======== 報(bào)警級別顏色映射 ========
var alertLevelInfo = new Dictionary<string, (string color, string emoji)>
{
{ "CRITICAL", ("#d32f2f", "??") }, // 紅色
{ "HIGH", ("#f57c00", "??") }, // 橙色
{ "MEDIUM", ("#ffa000", "?") }, // 黃色
{ "LOW", ("#4caf50", "??") } // 綠色
};
// 獲取當(dāng)前報(bào)警級別的顏色和表情符號
var (color, emoji) = alertLevelInfo.ContainsKey(alertLevel)
? alertLevelInfo[alertLevel]
: ("#666666", "??");
// ======== 構(gòu)建郵件內(nèi)容 ========
string htmlBody = $@"
<!DOCTYPE html>
<html>
<head>
<style>
.card {{
border: 1px solid #e0e0e0;
padding: 20px;
max-width: 800px;
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
}}
.header {{
border-bottom: 2px solid {color};
padding-bottom: 10px;
margin-bottom: 20px;
}}
.alert-level {{
color: {color};
font-weight: bold;
}}
pre {{
background: #f8f9fa;
padding: 15px;
border-radius: 4px;
overflow-x: auto;
}}
</style>
</head>
<body>
<div class='card'>
<div class='header'>
<h2>{emoji} 系統(tǒng)報(bào)警 - {alertLevel}</h2>
</div>
<table>
<tr><th>報(bào)警時(shí)間:</th><td>{DateTime.Now:yyyy-MM-dd HH:mm:ss}</td></tr>
<tr><th>報(bào)警級別:</th><td class='alert-level'>{alertLevel}</td></tr>
</table>
<h3>▌ 報(bào)警內(nèi)容</h3>
<p>{alertContent}</p>
{(errorDetails != null ? $@"
<h3>▌ 錯(cuò)誤詳情</h3>
<pre>{errorDetails}</pre>
" : "")}
<div style='margin-top: 25px; color: #666; font-size: 0.9em;'>
<hr>
<p>此郵件由系統(tǒng)自動(dòng)發(fā)送,請勿直接回復(fù)</p>
<p>負(fù)責(zé)人:牛馬程序員 (123456@niuma.com)</p>
</div>
</div>
</body>
</html>";
// ======== 創(chuàng)建郵件消息 ========
MailMessage message = new MailMessage
{
From = new MailAddress(fromEmail),
Subject = $"{emoji} 系統(tǒng)報(bào)警 - {alertLevel}",
Body = htmlBody,
IsBodyHtml = true
};
// 添加收件人
message.To.Add(incomingEmail);
// 添加附件
if (attachmentPaths != null)
{
foreach (var path in attachmentPaths)
{
if (File.Exists(path))
{
message.Attachments.Add(new Attachment(path));
}
}
}
// ======== 發(fā)送郵件 ========
client.Send(message);
// ===== 4. 記錄發(fā)送日志 =====
LogError(errorHash, alertLevel, alertContent, errorDetails);
Console.WriteLine("郵件發(fā)送成功!");
}
catch (Exception ex)
{
Console.WriteLine($"郵件發(fā)送失敗:{ex.Message}");
}
}
/// <summary>
/// 創(chuàng)建唯一加密標(biāo)識符號
/// </summary>
/// <param name="content"></param>
/// <param name="details"></param>
/// <returns></returns>
private static string GenerateErrorHash(string content, string details)
{
using MD5 md5 = MD5.Create();
string rawData = $"{content}|{details}";
byte[] hashBytes = md5.ComputeHash(Encoding.UTF8.GetBytes(rawData));
return BitConverter.ToString(hashBytes).Replace("-", "");
}
/// <summary>
/// 檢查是否已經(jīng)發(fā)送過
/// </summary>
/// <param name="errorHash"></param>
/// <returns></returns>
private static bool IsAlreadySentToday(string errorHash)
{
string todayLogFile = GetTodayLogFilePath();
lock (fileLock)
{
if (!File.Exists(todayLogFile)) return false;
foreach (string line in File.ReadAllLines(todayLogFile))
{
if (line.StartsWith(errorHash))
{
return true;
}
}
}
return false;
}
//記錄報(bào)警內(nèi)容
private static void LogError(string errorHash, string level,
string content, string details)
{
string logEntry = $"{errorHash}|{DateTime.Now:yyyy-MM-dd HH:mm:ss}|" +
$"{level}|{content}|{details}\n";
lock (fileLock)
{
EnsureLogDirectoryExists();
File.AppendAllText(GetTodayLogFilePath(), logEntry);
}
}
//獲取報(bào)警日志地址
private static string GetTodayLogFilePath()
{
return Path.Combine(LogDirectory,
$"SnedErrorLog_{DateTime.Now:yyyyMMdd}.txt");
}
//無文件創(chuàng)建文件夾
private static void EnsureLogDirectoryExists()
{
if (!Directory.Exists(LogDirectory))
{
Directory.CreateDirectory(LogDirectory);
}
}
public static void Main()
{
SendToEmail(
alertLevel: "HIGH",
alertContent: "數(shù)據(jù)庫益處請?zhí)幚?,可能?dǎo)致系統(tǒng)響應(yīng)緩慢。",
errorDetails: "TimeoutException: Could not connect to database.\n at DatabaseService.Connect() Line 123",
attachmentPaths: new[] { "error.log" });
SendToEmail(
alertLevel: "HIGH",
alertContent: "數(shù)據(jù)庫連接池使用率超過90%,可能導(dǎo)致系統(tǒng)響應(yīng)緩慢。",
errorDetails: "TimeoutException: Could not connect to database.\n at DatabaseService.Connect() Line 123",
attachmentPaths: new[] { "error.log" });
}
}到此這篇關(guān)于C#使用System.Net庫實(shí)現(xiàn)自動(dòng)發(fā)送郵件功能的文章就介紹到這了,更多相關(guān)C#自動(dòng)發(fā)送郵件內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
淺談C#2.0泛型中的變化:default關(guān)鍵字
下面就詳細(xì)的說明一下。之所以會用到default關(guān)鍵字,是因?yàn)樾枰诓恢李愋蛥?shù)為值類型還是引用類型的情況下,為對象實(shí)例賦初值2013-09-09
Unity實(shí)現(xiàn)大轉(zhuǎn)盤的簡單筆記
這篇文章主要為大家分享了Unity實(shí)現(xiàn)大轉(zhuǎn)盤的簡單筆記,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2019-02-02
運(yùn)用示例簡單講解C#取消令牌CancellationTokenSource
這篇文章運(yùn)用示例簡單講解C#取消令牌CancellationTokenSource,文中通過示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2021-08-08
C# WebApi+Webrtc局域網(wǎng)音視頻通話實(shí)例
這篇文章主要為大家詳細(xì)介紹了C# WebApi+Webrtc局域網(wǎng)音視頻通話實(shí)例,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2021-07-07
C#面向?qū)ο髮?shí)現(xiàn)圖書管理系統(tǒng)
這篇文章主要為大家詳細(xì)介紹了C#面向?qū)ο髮?shí)現(xiàn)圖書管理系統(tǒng),文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2022-02-02
C#中Dictionary與List的用法區(qū)別以及聯(lián)系詳解
List和Dictionary想必是我們平常用到最多的C#容器了,他們使用起來都很簡單,這篇文章主要給大家介紹了關(guān)于C#中Dictionary與List的用法區(qū)別以及聯(lián)系的相關(guān)資料,需要的朋友可以參考下2023-11-11

