使用 SMTP 客户端在 C# 中发送电子邮件、转发消息并执行邮件合并
发送电子邮件
使用 SmtpClient 类发送电子邮件
该 SmtpClient 类使应用程序能够通过简单邮件传输协议 (SMTP) 发送电子邮件。
其关键特性之一是能够 批量发送消息.
它也完全支持 同步 和 异步 编程模型。若要在操作完成前阻塞主线程发送电子邮件,开发者可以使用同步的 发送 方法。此外,为了在发送邮件时让主线程继续执行,开发者可以使用 SendAsync 方法。
此外, SmtpClient 支持发送消息的 传输中立封装格式 (TNEF).
同步发送电子邮件
可以使用…同步发送电子邮件 发送 方法的 SmtpClient 类。它通过 SMTP 服务器发送指定的电子邮件以进行投递。要同步发送电子邮件,请按以下步骤进行:
- 创建以下实例: MailMessage 类并设置其属性。
- 创建以下实例: SmtpClient 类并指定主机、端口、用户名和密码。
- 使用…发送消息 发送 方法的 SmtpClient 类并传递 MailMessage 实例。
以下 C# 代码片段展示了如何同步发送 Outlook 邮件。
// For complete examples and data files, please go to https://github.com/aspose-email/Aspose.Email-for-.NET
// Declare msg as MailMessage instance
MailMessage msg = new MailMessage();
// Create an instance of SmtpClient class
SmtpClient client = new SmtpClient();
// Specify your mailing host server, Username, Password, Port # and Security option
client.Host = "mail.server.com";
client.Username = "username";
client.Password = "password";
client.Port = 587;
client.SecurityOptions = SecurityOptions.SSLExplicit;
try
{
// Client.Send will send this message
client.Send(msg);
Console.WriteLine("Message sent");
}
catch (Exception ex)
{
Trace.WriteLine(ex.ToString());
}
异步发送电子邮件
有时,您可能希望异步发送邮件,以便程序在后台发送邮件时继续执行其他操作。从 .NET Framework 4.5 开始,您可以使用符合以下实现的异步方法 TAP 模型。下面的 C# 代码片段展示了如何使用基于任务的异步模式方法发送 Outlook 电子邮件。
-
SendAsync 发送指定的消息。
-
IAsyncSmtpClient - 允许应用程序使用 Simple Mail Transfer Protocol(SMTP)发送消息。
-
SmtpClient.CreateAsync - 创建 Aspose.Email.Clients.Smtp.SmtpClient 类的新实例
-
SmtpSend - Aspose.Email.Clients.Smtp.IAsyncSmtpClient.SendAsync(Aspose.Email.Clients.Smtp.Models.SmtpSend) 方法的参数集合。
-
SmtpForward - Aspose.Email.Clients.Smtp.IAsyncSmtpClient.ForwardAsync(Aspose.Email.Clients.Smtp.Models.SmtpForward) 参数。
// Authenticate the client to obtain necessary permissions
static readonly string tenantId = "YOU_TENANT_ID";
static readonly string clientId = "YOU_CLIENT_ID";
static readonly string redirectUri = "http://localhost";
static readonly string username = "username";
static readonly string[] scopes = { "https://outlook.office.com/SMTP.Send" };
// Use the SmtpAsync method for asynchronous operations
static async Task Main(string[] args)
{
await SmtpAsync();
Console.ReadLine();
}
static async Task SmtpAsync()
{
// Create token provider and get access token
var tokenProvider = new TokenProvider(clientId, tenantId, redirectUri, scopes);
var client = SmtpClient.CreateAsync("outlook.office365.com", username, tokenProvider, 587).GetAwaiter().GetResult();
// Create a message to send
var eml = new MailMessage("from@domain.com", "to@domain.com", "test subj async", "test body async");
// send message
var sendOptions = SmtpSend.Create();
sendOptions.AddMessage(eml);
await client.SendAsync(sendOptions);
Console.WriteLine("message was sent");
// forward message
var fwdOptions = SmtpForward.Create();
fwdOptions.SetMessage(eml);
fwdOptions.AddRecipient("rec@domain.com");
await client.ForwardAsync(fwdOptions);
Console.WriteLine("message was forwarded");
}
// Token provider implementation
public class TokenProvider : IAsyncTokenProvider
{
private readonly PublicClientApplicationOptions _pcaOptions;
private readonly string[] _scopes;
public TokenProvider(string clientId, string tenantId, string redirectUri, string[] scopes)
{
_pcaOptions = new PublicClientApplicationOptions
{
ClientId = clientId,
TenantId = tenantId,
RedirectUri = redirectUri
};
_scopes = scopes;
}
public async Task<OAuthToken> GetAccessTokenAsync(bool ignoreExistingToken = false, CancellationToken cancellationToken = default)
{
var pca = PublicClientApplicationBuilder
.CreateWithApplicationOptions(_pcaOptions).Build();
try
{
var result = await pca.AcquireTokenInteractive(_scopes)
.WithUseEmbeddedWebView(false)
.ExecuteAsync(cancellationToken);
return new OAuthToken(result.AccessToken);
}
catch (MsalException ex)
{
Console.WriteLine($"Error acquiring access token: {ex}");
}
catch (Exception ex)
{
Console.WriteLine($"Error: {ex}");
}
return null;
}
public void Dispose()
{
}
}
从磁盘发送消息
EML 文件包含头部、正文和附件。Aspose.Email 让开发者以多种方式处理 EML 文件。本节展示了如何从磁盘加载 EML 文件并通过 SMTP 发送为电子邮件。您可以将 .eml 文件从磁盘或流加载到 MailMessage 类并使用 SmtpClient 类。该 MailMessage 类是用于创建新电子邮件、从磁盘或流加载电子邮件文件以及保存消息的主要类。以下 C# 代码片段展示了如何从磁盘发送已存储的消息。
// For complete examples and data files, please go to https://github.com/aspose-email/Aspose.Email-for-.NET
// Load an EML file in MailMessage class
var message = MailMessage.Load(dataDir + "test.eml");
// Send this message using SmtpClient
var client = new SmtpClient("host", "username", "password");
try
{
client.Send(message);
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
发送纯文本电子邮件
该 正文 属性,是 MailMessage 类用于指定消息正文的纯文本内容。要发送纯文本电子邮件,请按以下步骤操作:
- 创建该类的实例 MailMessage 类。
- 在 MailMessage 实例。
- 指定 正文 内容,用于纯文本消息。
- 创建该类的实例 SmtpClient 类并发送邮件。
以下代码片段展示了如何发送纯文本电子邮件。
// For complete examples and data files, please go to https://github.com/aspose-email/Aspose.Email-for-.NET
//Create an instance of the MailMessage class
var message = new MailMessage();
// Set From field, To field and Plain text body
message.From = "sender@sender.com";
message.To.Add("receiver@receiver.com");
message.Body = "This is Plain Text Body";
// Create an instance of the SmtpClient class
var client = new SmtpClient();
// And Specify your mailing host server, Username, Password and Port
client.Host = "smtp.server.com";
client.Username = "Username";
client.Password = "Password";
client.Port = 25;
try
{
//Client.Send will send this message
client.Send(message);
Console.WriteLine("Message sent");
}
catch (Exception ex)
{
System.Diagnostics.Trace.WriteLine(ex.ToString());
}
发送带 HTML 正文的电子邮件
下面的编程示例展示了如何发送简易的 HTML 邮件。该 HtmlBody,是 MailMessage 类用于指定消息正文的 HTML 内容。要发送简易的 HTML 邮件,请按以下步骤操作:
- 创建该类的实例 MailMessage 类。
- 在 MailMessage 实例。
- 指定 HtmlBody 内容。
- 创建该类的实例 SmtpClient 类并使用 发送 方法。
本文中,电子邮件的 HTML 内容为简易示例:
This is the HTML body 大多数 HTML 邮件会更复杂。以下代码片段演示了如何发送带有 HTML 正文的电子邮件。// For complete examples and data files, please go to https://github.com/aspose-email/Aspose.Email-for-.NET
public static void Run()
{
// Declare msg as MailMessage instance
var msg = new MailMessage();
// Use MailMessage properties like specify sender, recipient, message and HtmlBody
msg.From = "newcustomeronnet@gmail.com";
msg.To = "asposetest123@gmail.com";
msg.Subject = "Test subject";
msg.HtmlBody = "<html><body>This is the HTML body</body></html>";
var client = GetSmtpClient();
try
{
// Client will send this message
client.Send(msg);
Console.WriteLine("Message sent");
}
catch (Exception ex)
{
Trace.WriteLine(ex.ToString());
}
Console.WriteLine(Environment.NewLine + "Email sent with HTML body.");
}
private static SmtpClient GetSmtpClient()
{
var client = new SmtpClient("smtp.gmail.com", 587, "your.email@gmail.com", "your.password");
client.SecurityOptions = SecurityOptions.Auto;
return client;
}
发送带备用文本的 HTML 电子邮件
使用 AlternateView 类中指定电子邮件消息的不同格式副本。例如,如果您以 HTML 发送消息,可能还希望为无法显示 HTML 内容的收件人提供纯文本版本。或者在发送简报时,您可能想为选择接收纯文本版本的收件人提供纯文本副本。要发送包含替代文本的电子邮件,请按以下步骤操作:
- 创建该类的实例 MailMessage 类。
- 在 MailMessage 实例。
- 创建该类的实例 AlternateView 类。
这会使用字符串中指定的内容为电子邮件消息创建替代视图。
- 添加该类的实例 AlternateView 类发送到 MailMessage 对象。
- 创建该类的实例 SmtpClient 类并使用 发送 方法。
以下代码片段展示了如何发送包含替代文本的电子邮件。
// For complete examples and data files, please go to https://github.com/aspose-email/Aspose.Email-for-.NET
// Declare message as MailMessage instance
var message = new MailMessage();
// Creates AlternateView to view an email message using the content specified in the //string
var alternate = AlternateView.CreateAlternateViewFromString("Alternate Text");
// Adding alternate text
message.AlternateViews.Add(alternate);
批量发送电子邮件
我们可以使用该方法发送一批电子邮件 SmtpClient 类的 发送 接受 MailMessageCollection:
- 创建以下实例: SmtpClient 类。
- 指定 SmtpClient 类属性。
- 创建该类的实例 MailMessage 类。
- 在实例中指定发件人、收件人、邮件主题和内容 MailMessage 类。
- 如果想给其他人发送邮件,请再次重复以上两步。
- 创建以下实例: MailMessageCollection 类。
- 添加一个实例 MailMessage 类在对象的 MailMessageCollection 类。
- 现在使用 SmtpClient 类 发送 方法通过传入 MailMessageCollection 其中的类。
以下代码片段展示了如何批量发送电子邮件。
// For complete examples and data files, please go to https://github.com/aspose-email/Aspose.Email-for-.NET
// Create SmtpClient as client and specify server, port, user name and password
var client = new SmtpClient("mail.server.com", 25, "Username", "Password");
// Create instances of MailMessage class and Specify To, From, Subject and Message
var message1 = new MailMessage("msg1@from.com", "msg1@to.com", "Subject1", "message1, how are you?");
var message2 = new MailMessage("msg1@from.com", "msg2@to.com", "Subject2", "message2, how are you?");
var message3 = new MailMessage("msg1@from.com", "msg3@to.com", "Subject3", "message3, how are you?");
// Create an instance of MailMessageCollection class
var manyMsg = new MailMessageCollection();
manyMsg.Add(message1);
manyMsg.Add(message2);
manyMsg.Add(message3);
try
{
// Send Messages using Send method
client.Send(manyMsg);
Console.WriteLine("Message sent");
}
catch (Exception ex)
{
Trace.WriteLine(ex.ToString());
}
跟踪批量邮件发送成功
批量发送消息时,您可以获取已成功发送的消息数量信息,甚至获取这些消息的列表。 SucceededSending 事件用于此目的。
代码示例:
using (var client = new SmtpClient(host, SecurityOptions.Auto))
{
int messageCount = 0;
client.SucceededSending += (sender, eventArgs) =>
{
Console.WriteLine("The message '{0}' was successfully sent.", eventArgs.Message.Subject);
messageCount++;
};
client.Send(messages);
Console.WriteLine("{0} messages were successfully sent.", messageCount);
}
使用多连接发送电子邮件
该 UseMultiConnection 属性可用于为繁重操作创建多个连接。您还可以通过使用该属性设置多连接模式下使用的连接数。 SmtpClient.ConnectionsQuantity。以下代码片段演示了使用多连接模式发送多条消息。
var smtpClient = new SmtpClient();
smtpClient.Host = "<HOST>";
smtpClient.Username = "<USERNAME>";
smtpClient.Password = "<PASSWORD>";
smtpClient.Port = 587;
smtpClient.SupportedEncryption = EncryptionProtocols.Tls;
smtpClient.SecurityOptions = SecurityOptions.SSLExplicit;
var messages = new List<MailMessage>();
for (int i = 0; i < 20; i++)
{
MailMessage message = new MailMessage(
"<EMAIL ADDRESS>",
"<EMAIL ADDRESS>",
"Test Message - " + Guid.NewGuid().ToString(),
"SMTP Send Messages with MultiConnection");
messages.Add(message);
}
smtpClient.ConnectionsQuantity = 5;
smtpClient.UseMultiConnection = MultiConnectionMode.Enable;
smtpClient.Send(messages);
以 TNEF 形式发送邮件
TNEF 邮件拥有特殊的格式,如果使用标准 API 发送可能会丢失。 SmtpClient 类 UseTnef 属性可以设置为以 TNEF 形式发送电子邮件。以下代码片段展示了如何以 TNEF 发送消息。
var emlFileName = RunExamples.GetDataDir_Email() + "Message.eml"; // A TNEF Email
// Load from eml
var eml1 = MailMessage.Load(emlFileName, new EmlLoadOptions());
eml1.From = "somename@gmail.com";
eml1.To.Clear();
eml1.To.Add(new MailAddress("first.last@test.com"));
eml1.Subject = "With PreserveTnef flag during loading";
eml1.Date = DateTime.Now;
var client = new SmtpClient("smtp.gmail.com", 587, "somename", "password");
client.SecurityOptions = SecurityOptions.Auto;
client.UseTnef = true; // Use this flag to send as TNEF
client.Send(eml1);
发送会议请求
Aspose.Email 让开发者能够在电子邮件中添加日历功能。
通过电子邮件发送请求
要通过电子邮件发送会议请求,请按以下步骤操作:
- 创建该类的实例 MailMessage 类。
- 使用…的实例指定发件人和收件人地址 MailMessage 类。
- 初始化…的实例 Appointment 类并传递其值。
- 在…中指定摘要和描述 Calendar 实例。
- 添加 Calendar 到 MailMessage 实例并传递给它 Appointment 实例。
|iCalendar 会议请求通过电子邮件发送| | :- | |
| 以下代码片段展示了如何通过电子邮件发送请求。
// Create an instance of the MailMessage class
var msg = new MailMessage();
// Set the sender, recipient, who will receive the meeting request. Basically, the recipient is the same as the meeting attendees
msg.From = "newcustomeronnet@gmail.com";
msg.To = "person1@domain.com, person2@domain.com, person3@domain.com, asposetest123@gmail.com";
// Create Appointment instance
var app = new Appointment("Room 112", new DateTime(2015, 7, 17, 13, 0, 0), new DateTime(2015, 7, 17, 14, 0, 0), msg.From, msg.To);
app.Summary = "Release Meetting";
app.Description = "Discuss for the next release";
// Add appointment to the message and Create an instance of SmtpClient class
msg.AddAlternateView(app.RequestApointment());
var client = GetSmtpClient();
try
{
// Client.Send will send this message
client.Send(msg);
Console.WriteLine("Message sent");
}
catch (Exception ex)
{
Trace.WriteLine(ex.ToString());
}
转发邮件
使用 SMTP 客户端转发邮件
转发电子邮件是常见做法。收到的邮件可以转发给特定收件人。 转发 此方法可用于将已接收或已保存的电子邮件转发给指定收件人。以下代码片段演示了如何使用 SMTP 客户端转发电子邮件。
//Create an instance of SmtpClient class
var client = new SmtpClient();
// Specify your mailing host server, Username, Password, Port and SecurityOptions
client.Host = "mail.server.com";
client.Username = "username";
client.Password = "password";
client.Port = 587;
client.SecurityOptions = SecurityOptions.SSLExplicit;
var message = MailMessage.Load(dataDir + "Message.eml");
client.Forward("Recipient1@domain.com", "Recipient2@domain.com", message);
在不使用 MailMessage 转发邮件
该 API 还支持在未先加载到 MailMessage。这在系统内存资源有限的情况下很有用。
using (var client = new SmtpClient(host, smtpPort, username, password, SecurityOptions.Auto))
{
using (var fs = File.OpenRead(@"test.eml"))
{
client.Forward(sender, recipients, fs);
}
}
在不使用 MailMessage 的情况下异步转发邮件
using (var client = new SmtpClient(host, smtpPort, username, password))
{
using (var fs = File.OpenRead(@"test.eml"))
{
await client.ForwardAsync(sender, recipients, fs);
}
}
邮件合并
如何合并电子邮件
邮件合并帮助您创建并发送一批相似的电子邮件。邮件的核心内容相同,但可以对内容进行个性化。通常使用收件人的联系信息(名、姓、公司等)来个性化邮件。
|邮件合并工作示意:| | :- | |
| Aspose.Email 让开发者能够设置包含多种数据源数据的邮件合并。
要使用 Aspose.Email 执行邮件合并,请执行以下步骤:
- 创建一个具有以下签名的函数
- 创建该类的实例 MailMessage 类。
- 指定发件人、收件人、主题和正文。
- 为电子邮件末尾创建签名。
- 创建该类的实例 TemplateEngine 类中获取签名并传递给 MailMessage 实例。
- 在 TemplateEngine 实例。
- 创建 DataTable 类的实例。
- 在 DataTable 类中添加列 Receipt、FirstName 和 LastName 作为数据源。
- 创建 DataRow 类的实例。
- 在 DataRow 对象中指定收件地址、名和姓。
- 创建该类的实例 MailMessageCollection 类
- 指定 TemplateEngine 以及 DataTable 实例在 MailMessageCollection 实例。
- 创建该类的实例 SmtpClient 类并指定服务器、端口、用户名和密码。
- 使用以下方式发送电子邮件: SmtpClient 类 发送 方法。
在下面的示例中,#FirstName# 表示 DataTable 列,其值由用户设置。以下代码片段演示了如何执行邮件合并。
// For complete examples and data files, please go to https://github.com/aspose-email/Aspose.Email-for-.NET
public static void Run()
{
// The path to the File directory.
string dataDir = RunExamples.GetDataDir_SMTP();
string dstEmail = dataDir + "EmbeddedImage.msg";
// Create a new MailMessage instance
MailMessage msg = new MailMessage();
// Add subject and from address
msg.Subject = "Hello, #FirstName#";
msg.From = "sender@sender.com";
// Add email address to send email also Add mesage field to HTML body
msg.To.Add("your.email@gmail.com");
msg.HtmlBody = "Your message here";
msg.HtmlBody += "Thank you for your interest in <STRONG>Aspose.Email</STRONG>.";
// Use GetSignment as the template routine, which will provide the same signature
msg.HtmlBody += "<br><br>Have fun with it.<br><br>#GetSignature()#";
// Create a new TemplateEngine with the MSG message, Register GetSignature routine. It will be used in MSG.
TemplateEngine engine = new TemplateEngine(msg);
engine.RegisterRoutine("GetSignature", GetSignature);
// Create an instance of DataTable and Fill a DataTable as data source
DataTable dt = new DataTable();
dt.Columns.Add("Receipt", typeof(string));
dt.Columns.Add("FirstName", typeof(string));
dt.Columns.Add("LastName", typeof(string));
DataRow dr = dt.NewRow();
dr["Receipt"] = "abc<asposetest123@gmail.com>";
dr["FirstName"] = "a";
dr["LastName"] = "bc";
dt.Rows.Add(dr);
dr = dt.NewRow();
dr["Receipt"] = "John<email.2@gmail.com>";
dr["FirstName"] = "John";
dr["LastName"] = "Doe";
dt.Rows.Add(dr);
dr = dt.NewRow();
dr["Receipt"] = "Third Recipient<email.3@gmail.com>";
dr["FirstName"] = "Third";
dr["LastName"] = "Recipient";
dt.Rows.Add(dr);
MailMessageCollection messages;
try
{
// Create messages from the message and datasource.
messages = engine.Instantiate(dt);
// Create an instance of SmtpClient and specify server, port, username and password
SmtpClient client = new SmtpClient("smtp.gmail.com", 587, "your.email@gmail.com", "your.password");
client.SecurityOptions = SecurityOptions.Auto;
// Send messages in bulk
client.Send(messages);
}
catch (MailException ex)
{
Debug.WriteLine(ex.ToString());
}
catch (SmtpException ex)
{
Debug.WriteLine(ex.ToString());
}
Console.WriteLine(Environment.NewLine + "Message sent after performing mail merge.");
}
// Template routine to provide signature
static object GetSignature(object[] args)
{
return "Aspose.Email Team<br>Aspose Ltd.<br>" + DateTime.Now.ToShortDateString();
}
如何执行行级邮件合并
用户可以合并单个数据行,也可以获取完整且已准备好的 MailMessage 对象。该 TemplateEngine.Merge 方法可用于执行逐行邮件合并。
// For complete examples and data files, please go to https://github.com/aspose-email/Aspose.Email-for-.NET
// Create message from the data in current row.
message = engine.Merge(currentRow);