|
|
|
|
using MailKit;
|
|
|
|
|
using MailKit.Net.Smtp;
|
|
|
|
|
using MailKit.Security;
|
|
|
|
|
using MailKit.Search;
|
|
|
|
|
using System;
|
|
|
|
|
using System.Collections.Generic;
|
|
|
|
|
using System.Data;
|
|
|
|
|
using System.IO;
|
|
|
|
|
using System.Linq;
|
|
|
|
|
using System.Web;
|
|
|
|
|
using System.Threading.Tasks;
|
|
|
|
|
using CommonTool.MailKit;
|
|
|
|
|
using MailKit.Net.Imap;
|
|
|
|
|
using MimeKit;
|
|
|
|
|
using System.Configuration;
|
|
|
|
|
|
|
|
|
|
namespace CommonTool.MailKit
|
|
|
|
|
{
|
|
|
|
|
public static class MailHelper
|
|
|
|
|
{
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// 发送邮件
|
|
|
|
|
/// </summary>
|
|
|
|
|
/// <param name="mailBodyEntity">邮件基础信息</param>
|
|
|
|
|
/// <param name="sendServerConfiguration">发件人基础信息</param>
|
|
|
|
|
public static SendResultEntity SendMail(MailBodyEntity mailBodyEntity,
|
|
|
|
|
SendServerConfigurationEntity sendServerConfiguration)
|
|
|
|
|
{
|
|
|
|
|
if (mailBodyEntity == null)
|
|
|
|
|
{
|
|
|
|
|
throw new ArgumentNullException();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (sendServerConfiguration == null)
|
|
|
|
|
{
|
|
|
|
|
throw new ArgumentNullException();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
var sendResultEntity = new SendResultEntity();
|
|
|
|
|
|
|
|
|
|
using (var client = new SmtpClient(new ProtocolLogger(MailMessage.CreateMailLog())))
|
|
|
|
|
{
|
|
|
|
|
client.ServerCertificateValidationCallback = (s, c, h, e) => true;
|
|
|
|
|
|
|
|
|
|
Connection(mailBodyEntity, sendServerConfiguration, client, sendResultEntity);
|
|
|
|
|
|
|
|
|
|
if (sendResultEntity.ResultStatus == false)
|
|
|
|
|
{
|
|
|
|
|
return sendResultEntity;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
SmtpClientBaseMessage(client);
|
|
|
|
|
|
|
|
|
|
// Note: since we don't have an OAuth2 token, disable
|
|
|
|
|
// the XOAUTH2 authentication mechanism.
|
|
|
|
|
client.AuthenticationMechanisms.Remove("XOAUTH2");
|
|
|
|
|
|
|
|
|
|
Authenticate(mailBodyEntity, sendServerConfiguration, client, sendResultEntity);
|
|
|
|
|
|
|
|
|
|
if (sendResultEntity.ResultStatus == false)
|
|
|
|
|
{
|
|
|
|
|
return sendResultEntity;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Send(mailBodyEntity, sendServerConfiguration, client, sendResultEntity);
|
|
|
|
|
|
|
|
|
|
if (sendResultEntity.ResultStatus == false)
|
|
|
|
|
{
|
|
|
|
|
return sendResultEntity;
|
|
|
|
|
}
|
|
|
|
|
client.Disconnect(true);
|
|
|
|
|
}
|
|
|
|
|
return sendResultEntity;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// 连接服务器
|
|
|
|
|
/// </summary>
|
|
|
|
|
/// <param name="mailBodyEntity">邮件内容</param>
|
|
|
|
|
/// <param name="sendServerConfiguration">发送配置</param>
|
|
|
|
|
/// <param name="client">客户端对象</param>
|
|
|
|
|
/// <param name="sendResultEntity">发送结果</param>
|
|
|
|
|
public static void Connection(MailBodyEntity mailBodyEntity, SendServerConfigurationEntity sendServerConfiguration,
|
|
|
|
|
SmtpClient client, SendResultEntity sendResultEntity)
|
|
|
|
|
{
|
|
|
|
|
try
|
|
|
|
|
{
|
|
|
|
|
client.Connect(sendServerConfiguration.SmtpHost, sendServerConfiguration.SmtpPort);
|
|
|
|
|
}
|
|
|
|
|
catch (SmtpCommandException ex)
|
|
|
|
|
{
|
|
|
|
|
sendResultEntity.ResultInformation = $"尝试连接时出错:{0}" + ex.Message;
|
|
|
|
|
sendResultEntity.ResultStatus = false;
|
|
|
|
|
}
|
|
|
|
|
catch (SmtpProtocolException ex)
|
|
|
|
|
{
|
|
|
|
|
sendResultEntity.ResultInformation = $"尝试连接时的协议错误:{0}" + ex.Message;
|
|
|
|
|
sendResultEntity.ResultStatus = false;
|
|
|
|
|
}
|
|
|
|
|
catch (Exception ex)
|
|
|
|
|
{
|
|
|
|
|
sendResultEntity.ResultInformation = $"服务器连接错误:{0}" + ex.Message;
|
|
|
|
|
sendResultEntity.ResultStatus = false;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// 账户认证
|
|
|
|
|
/// </summary>
|
|
|
|
|
/// <param name="mailBodyEntity">邮件内容</param>
|
|
|
|
|
/// <param name="sendServerConfiguration">发送配置</param>
|
|
|
|
|
/// <param name="client">客户端对象</param>
|
|
|
|
|
/// <param name="sendResultEntity">发送结果</param>
|
|
|
|
|
public static void Authenticate(MailBodyEntity mailBodyEntity, SendServerConfigurationEntity sendServerConfiguration,
|
|
|
|
|
SmtpClient client, SendResultEntity sendResultEntity)
|
|
|
|
|
{
|
|
|
|
|
try
|
|
|
|
|
{
|
|
|
|
|
client.Authenticate(sendServerConfiguration.SenderAccount, sendServerConfiguration.SenderPassword);
|
|
|
|
|
}
|
|
|
|
|
catch (AuthenticationException ex)
|
|
|
|
|
{
|
|
|
|
|
sendResultEntity.ResultInformation = $"无效的用户名或密码:{0}" + ex.Message;
|
|
|
|
|
sendResultEntity.ResultStatus = false;
|
|
|
|
|
}
|
|
|
|
|
catch (SmtpCommandException ex)
|
|
|
|
|
{
|
|
|
|
|
sendResultEntity.ResultInformation = $"尝试验证错误:{0}" + ex.Message;
|
|
|
|
|
sendResultEntity.ResultStatus = false;
|
|
|
|
|
}
|
|
|
|
|
catch (SmtpProtocolException ex)
|
|
|
|
|
{
|
|
|
|
|
sendResultEntity.ResultInformation = $"尝试验证时的协议错误:{0}" + ex.Message;
|
|
|
|
|
sendResultEntity.ResultStatus = false;
|
|
|
|
|
}
|
|
|
|
|
catch (Exception ex)
|
|
|
|
|
{
|
|
|
|
|
sendResultEntity.ResultInformation = $"账户认证错误:{0}" + ex.Message;
|
|
|
|
|
sendResultEntity.ResultStatus = false;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// 发送邮件
|
|
|
|
|
/// </summary>
|
|
|
|
|
/// <param name="mailBodyEntity">邮件内容</param>
|
|
|
|
|
/// <param name="sendServerConfiguration">发送配置</param>
|
|
|
|
|
/// <param name="client">客户端对象</param>
|
|
|
|
|
/// <param name="sendResultEntity">发送结果</param>
|
|
|
|
|
public static void Send(MailBodyEntity mailBodyEntity, SendServerConfigurationEntity sendServerConfiguration,
|
|
|
|
|
SmtpClient client, SendResultEntity sendResultEntity)
|
|
|
|
|
{
|
|
|
|
|
try
|
|
|
|
|
{
|
|
|
|
|
client.Send(MailMessage.AssemblyMailMessage(mailBodyEntity));
|
|
|
|
|
}
|
|
|
|
|
catch (SmtpCommandException ex)
|
|
|
|
|
{
|
|
|
|
|
switch (ex.ErrorCode)
|
|
|
|
|
{
|
|
|
|
|
case SmtpErrorCode.RecipientNotAccepted:
|
|
|
|
|
sendResultEntity.ResultInformation = $"收件人未被接受:{ex.Message}";
|
|
|
|
|
break;
|
|
|
|
|
case SmtpErrorCode.SenderNotAccepted:
|
|
|
|
|
sendResultEntity.ResultInformation = $"发件人未被接受:{ex.Message}";
|
|
|
|
|
break;
|
|
|
|
|
case SmtpErrorCode.MessageNotAccepted:
|
|
|
|
|
sendResultEntity.ResultInformation = $"消息未被接受:{ex.Message}";
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
sendResultEntity.ResultStatus = false;
|
|
|
|
|
}
|
|
|
|
|
catch (SmtpProtocolException ex)
|
|
|
|
|
{
|
|
|
|
|
sendResultEntity.ResultInformation = $"发送消息时的协议错误:{ex.Message}";
|
|
|
|
|
sendResultEntity.ResultStatus = false;
|
|
|
|
|
}
|
|
|
|
|
catch (Exception ex)
|
|
|
|
|
{
|
|
|
|
|
sendResultEntity.ResultInformation = $"邮件接收失败:{ex.Message}";
|
|
|
|
|
sendResultEntity.ResultStatus = false;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// 获取SMTP基础信息
|
|
|
|
|
/// </summary>
|
|
|
|
|
/// <param name="client">客户端对象</param>
|
|
|
|
|
/// <returns></returns>
|
|
|
|
|
public static MailServerInformation SmtpClientBaseMessage(SmtpClient client)
|
|
|
|
|
{
|
|
|
|
|
var mailServerInformation = new MailServerInformation
|
|
|
|
|
{
|
|
|
|
|
Authentication = client.Capabilities.HasFlag(SmtpCapabilities.Authentication),
|
|
|
|
|
BinaryMime = client.Capabilities.HasFlag(SmtpCapabilities.BinaryMime),
|
|
|
|
|
Dsn = client.Capabilities.HasFlag(SmtpCapabilities.Dsn),
|
|
|
|
|
EightBitMime = client.Capabilities.HasFlag(SmtpCapabilities.EightBitMime),
|
|
|
|
|
Size = client.MaxSize
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
return mailServerInformation;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/*接收邮件*/
|
|
|
|
|
public static class ReceiveEmailHelper
|
|
|
|
|
{
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// 设置发件人信息
|
|
|
|
|
/// </summary>
|
|
|
|
|
/// <returns></returns>
|
|
|
|
|
public static SendServerConfigurationEntity SetSendMessage()
|
|
|
|
|
{
|
|
|
|
|
var sendServerConfiguration = new SendServerConfigurationEntity
|
|
|
|
|
{
|
|
|
|
|
SmtpHost = ConfigurationManager.AppSettings["SmtpServer"],
|
|
|
|
|
SmtpPort = int.Parse(ConfigurationManager.AppSettings["SmtpPort"]),
|
|
|
|
|
IsSsl = Convert.ToBoolean(ConfigurationManager.AppSettings["IsSsl"]),
|
|
|
|
|
MailEncoding = ConfigurationManager.AppSettings["MailEncoding"],
|
|
|
|
|
SenderAccount = ConfigurationManager.AppSettings["SenderAccount"],
|
|
|
|
|
SenderPassword = ConfigurationManager.AppSettings["SenderPassword"]
|
|
|
|
|
};
|
|
|
|
|
return sendServerConfiguration;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// 接收邮件
|
|
|
|
|
/// </summary>
|
|
|
|
|
public static void ReceiveEmail()
|
|
|
|
|
{
|
|
|
|
|
var sendServerConfiguration = SetSendMessage();
|
|
|
|
|
|
|
|
|
|
if (sendServerConfiguration == null)
|
|
|
|
|
{
|
|
|
|
|
throw new ArgumentNullException();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
using (var client = new ImapClient(new ProtocolLogger(MailMessage.CreateMailLog())))
|
|
|
|
|
{
|
|
|
|
|
client.Connect(sendServerConfiguration.SmtpHost, sendServerConfiguration.SmtpPort,
|
|
|
|
|
SecureSocketOptions.SslOnConnect);
|
|
|
|
|
client.Authenticate(sendServerConfiguration.SenderAccount, sendServerConfiguration.SenderPassword);
|
|
|
|
|
client.Inbox.Open(FolderAccess.ReadOnly);
|
|
|
|
|
var uids = client.Inbox.Search(SearchQuery.All);
|
|
|
|
|
foreach (var uid in uids)
|
|
|
|
|
{
|
|
|
|
|
var message = client.Inbox.GetMessage(uid);
|
|
|
|
|
message.WriteTo($"{uid}.eml");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
client.Disconnect(true);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// 下载邮件内容
|
|
|
|
|
/// </summary>
|
|
|
|
|
public static void DownloadBodyParts()
|
|
|
|
|
{
|
|
|
|
|
var sendServerConfiguration = SetSendMessage();
|
|
|
|
|
|
|
|
|
|
using (var client = new ImapClient())
|
|
|
|
|
{
|
|
|
|
|
client.Connect(sendServerConfiguration.SmtpHost, sendServerConfiguration.SmtpPort,
|
|
|
|
|
SecureSocketOptions.SslOnConnect);
|
|
|
|
|
client.Authenticate(sendServerConfiguration.SenderAccount, sendServerConfiguration.SenderPassword);
|
|
|
|
|
client.Inbox.Open(FolderAccess.ReadOnly);
|
|
|
|
|
|
|
|
|
|
// 搜索Subject标题包含“MimeKit”或“MailKit”的邮件
|
|
|
|
|
var query = SearchQuery.SubjectContains("MimeKit").Or(SearchQuery.SubjectContains("MailKit"));
|
|
|
|
|
var uids = client.Inbox.Search(query);
|
|
|
|
|
|
|
|
|
|
// 获取搜索结果的摘要信息(我们需要UID和BODYSTRUCTURE每条消息,以便我们可以提取文本正文和附件)
|
|
|
|
|
var items = client.Inbox.Fetch(uids, MessageSummaryItems.UniqueId | MessageSummaryItems.BodyStructure);
|
|
|
|
|
|
|
|
|
|
foreach (var item in items)
|
|
|
|
|
{
|
|
|
|
|
// 确定一个目录来保存内容
|
|
|
|
|
var directory = Path.Combine(AppDomain.CurrentDomain.BaseDirectory + "/MailBody", item.UniqueId.ToString());
|
|
|
|
|
|
|
|
|
|
Directory.CreateDirectory(directory);
|
|
|
|
|
|
|
|
|
|
// IMessageSummary.TextBody是一个便利的属性,可以为我们找到“文本/纯文本”的正文部分
|
|
|
|
|
var bodyPart = item.TextBody;
|
|
|
|
|
|
|
|
|
|
// 下载'text / plain'正文部分
|
|
|
|
|
var body = (TextPart)client.Inbox.GetBodyPart(item.UniqueId, bodyPart);
|
|
|
|
|
|
|
|
|
|
// TextPart.Text是一个便利的属性,它解码内容并将结果转换为我们的字符串
|
|
|
|
|
var text = body.Text;
|
|
|
|
|
|
|
|
|
|
File.WriteAllText(Path.Combine(directory, "body.txt"), text);
|
|
|
|
|
|
|
|
|
|
// 现在遍历所有附件并将其保存到磁盘
|
|
|
|
|
foreach (var attachment in item.Attachments)
|
|
|
|
|
{
|
|
|
|
|
// 像我们对内容所做的那样下载附件
|
|
|
|
|
var entity = client.Inbox.GetBodyPart(item.UniqueId, attachment);
|
|
|
|
|
|
|
|
|
|
// 附件可以是message / rfc822部件或常规MIME部件
|
|
|
|
|
var messagePart = entity as MessagePart;
|
|
|
|
|
if (messagePart != null)
|
|
|
|
|
{
|
|
|
|
|
var rfc822 = messagePart;
|
|
|
|
|
|
|
|
|
|
var path = Path.Combine(directory, attachment.PartSpecifier + ".eml");
|
|
|
|
|
|
|
|
|
|
rfc822.Message.WriteTo(path);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
var part = (MimePart)entity;
|
|
|
|
|
|
|
|
|
|
// 注意:这可能是空的,但大多数会指定一个文件名
|
|
|
|
|
var fileName = part.FileName;
|
|
|
|
|
|
|
|
|
|
var path = Path.Combine(directory, fileName);
|
|
|
|
|
|
|
|
|
|
// decode and save the content to a file
|
|
|
|
|
using (var stream = File.Create(path))
|
|
|
|
|
part.Content.DecodeTo(stream);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
client.Disconnect(true);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
}
|