序言:
网上找了很多关于.Net如何访问电子邮箱的方法,但是大多数都达不到想要的需求,只有一些 收发邮件。因此 花了很大功夫去看 LumiSoft.Net.dll 的源码,总算做出自己想要的结果了,果然学习诗人进步。
介绍:
LumiSoft.Net.dll 是 C# 下的 免费开源 的关于网络 编程 的 一个类库,功能强大,包含FTP、FTP.Client、ICMP、IMAP、POP3、SMTP,如下图:
需求:
1、实现访问电子邮箱;
2、获取具体的某个文件夹下的邮箱,得到邮件的标题;
3、解析邮件的附件,并数据导入到数据库;
4、返回具体的邮件报错信息,发给相关人;
5、将导入数据库成功的邮件移入到另一个文件夹,失败的邮件 移入到另一个文件夹
实现步骤:
一、定义需要用到的信息变量
private string server = 服务器地址;
private int port = 端口号;
private bool useSsl = true;//是否跳过SSL验证
private string username = 邮件帐户;
private string password = 邮箱密码;
二、访问电子邮箱
IMAP_Client client = new IMAP_Client();
useSsl = false;
client.Connect(server, port, useSsl);
//登录获取授权操作
client.Login(username, password);
三、获取各个邮箱的概要信息
//获取各个邮箱目录的概要信息
client.GetFolders(null).ToList().ForEach(f =>
{
fileNameStrs = fileNameStrs + ";" + f.FolderName;
var list = client.FolderStatus(f.FolderName).ToList();
foreach (var item in list)
{
emailInfo = emailInfo + ";" + "总数:" + item.MessagesCount + ",未读:" + item.MessagesCount + ",最近" + item.UnseenCount;
}
});
//选择邮箱下的文件夹,这里面有自己需要的邮件
client.SelectFolder(邮箱下的文件夹);
//取出收件箱
var folder = client.SelectedFolder;
//邮件总数
var MessagesCount = folder.MessagesCount;
//未读邮件总数
var RecentMessagesCount = folder.RecentMessagesCount;
四、解析某个文件夹下的邮件信息,并导入数据库,移动相关邮件
//代表该文件夹下有邮件存在
if (MessagesCount > 0)
{
//首先确定取第x到第n封邮件,"1:*"表示第1封到最后一封
var seqSet = IMAP_t_SeqSet.Parse("1:*");
var items = new IMAP_t_Fetch_i[]
{
new IMAP_t_Fetch_i_Envelope(), //邮件的标题、正文等信息
new IMAP_t_Fetch_i_Uid(), //返回邮件的UID号,UID号是唯一标识邮件的一个号码
new IMAP_t_Fetch_i_Flags(), //此邮件的标志,应该是已读未读标志
new IMAP_t_Fetch_i_InternalDate(),//貌似是收到的日期
new IMAP_t_Fetch_i_Rfc822() //Rfc822是标准的邮件数据流,可以通过Lumisoft.Net.Mail.Mail_Message对象解析出邮件的所有信息
};
//Fetch 第一个参数false时seqSet有效
client.Fetch(false, seqSet, items, (s, e) =>
{
var isSuccees = true;
//处理邮件的匿名函数内容
var email = e.Value as IMAP_r_u_Fetch;
if (email != null && email.Rfc822 != null)
{
email.Rfc822.Stream.Position = 0;
var mime_message = Mail_Message.ParseFromStream(email.Rfc822.Stream);
email.Rfc822.Stream.Close();
//每封Email会有一个唯一的Id,检查这个Id是否存在就可以知道以前有没有接收过这封邮件
var UID = email.UID.UID;
//可能出现乱码问题,通过函数进行转换 //DecodeString(mime_header.Subject);
var emailTitle = mime_message.Subject;//邮件标题
var emailFrom = mime_message.From;//邮件发送人
var emailTo = mime_message.To;//邮件抄送人
//循环每个附件,并判断附件的后缀名是否满足要求
var file = mime_message.GetAttachments(true, true);
foreach (var entity in file)
{
if (entity.ContentDescription.IndexOf(".xlsx") <= 0 || entity.ContentDescription.IndexOf(".xls") <= 0)
{
errorMessage += "标题为'" + emailTitle + "'的邮件,附件格式错误,请检查邮件附件必须为(.xlsx/.xls)文件后缀格式";
isSuccees = false;
}
else
{
try
{
#region 解析附件,得到 单据信息
string fileName = "";
//判断是普通附件还是嵌入的内容附件
//if (entity.ContentDisposition != null && entity.ContentDisposition.DispositionType == MIME_DispositionTypes.Attachment)
//邮件的附件名称
fileName = entity.ContentDisposition.Param_FileName;
//代表文件下载到本地
//string localInbox = string.Format("{0}\\soEmail", Directory.GetCurrentDirectory());
If the folder is not existed, create it.
//if (!Directory.Exists(localInbox))
//{
// Directory.CreateDirectory(localInbox);
//}
//string fullPath = string.Format("{0}\\{1}", localInbox, fileName);
//直接解析邮件里面的附件信息
var byteObj = entity.Body as MIME_b_SinglepartBase;
var stream = byteObj.GetDataStream();
IWorkbook workbook = null;
// 2007版本
if (fileName.IndexOf(".xlsx") > 0)
{
workbook = new XSSFWorkbook(stream);
}
// 2003版本
else if (fileName.IndexOf(".xls") > 0)
{
workbook = new HSSFWorkbook(stream);
}
var count = workbook.NumberOfSheets;
ISheet sheet = null;
for (int i = 0; i < count; i++)
{
//获取sheet表
sheet = workbook.GetSheetAt(i);
//这块根据自己的需求来写,
#region 计算1-50行中 第一列包含第一个字符串 "aaa" 的行索引 index ;
int index = 0;
for (int ro = 0; ro < 50; ro++)
{
IRow rows = sheet.GetRow(ro);
if (rows.Cells != null && rows.Cells.Count > 0 && rows.GetCell(0) != null)
{
var cellValue = GetValueByType(rows.GetCell(0));
if (cellValue.ToLower().Contains("aaa"))
{
index = ro;
break;
}
}
}
#endregion
if (index == 0)//excel附件找不到 "aaa" 的列名信息
{
errorMessage += "标题为'" + emailTitle + "'的邮件,在附件信息中找不到aaa的列名信息";
isSuccees = false;
break;
}
#region 获取 需要保存数据库的数据
var cellIndex = index + 1;//对应Excel中 开始获取aaa数据的行索引
var code = "";//code
var name = "";//名称
for (int ro = cellIndex; ro < 1000; ro++)
{
IRow rows = sheet.GetRow(ro);
//判断是否为合并单元格
if (rows.GetCell(0).IsMergedCell)
{
//读取合并单元格的值
var cell = MergedCell(rows.GetCell(0));
code = GetValueByType(cell);
}
else
{
code = GetValueByType(rows.GetCell(0));
}
//判断是否为合并单元格
if (rows.GetCell(1).IsMergedCell)
{
//读取合并单元格的值
var cell = MergedCell(rows.GetCell(1));
name = GetValueByType(cell);
}
else
{
name = GetValueByType(rows.GetCell(1));
}
//如果 code和name都为空,则直接跳出循环
if (string.IsNullOrEmpty(code) && string.IsNullOrEmpty(name))
{
//第一行
if (ro == cellIndex)
{
errorMessage += "标题为'" + emailTitle + "'的邮件,在附件信息中第" + cellIndex + "行的数据信息全部为必填,不能为空,请检查邮件附件信息;";
isSuccees = false;
}
break;
}
//Excel中第cellIndex行,第1-2列的字段不能为空值
if (!string.IsNullOrEmpty(code) && !string.IsNullOrEmpty(name))
{
//将解析后的数据插入是list中
Model model = new Model();
model.code = code;
model.name = name;
list.Add(model);
}
if (list != null && list.Count > 0)
{
result.Succeeded = true;
result.Data = list.Count + "条数据插入成功," + errorMessage;
//执行插入数据库
}
}
#endregion
}
sheet = null;
workbook = null;
stream.Close();
stream.Dispose();
#endregion
}
catch (Exception ex)
{
errorMessage += "标题为'" + emailTitle + "'," + ex.Message + ex.InnerException;
isSuccees = false;
break;
}
}
}
if (isSuccees)
{
trueUid.Add(UID);//表示 每封邮件成功解析
}
else
{
flaseUid.Add(UID);//表示 邮件存在错误信息
}
}
});
foreach (var item in trueUid)
{
//将成功的邮件移动到 另一个文件夹
var value = "" + item + ":" + item + "";
var setIndex = IMAP_t_SeqSet.Parse(value);
client.MoveMessages(true, setIndex, "TestEmailComplete", true);
}
foreach (var item in flaseUid)
{
//将失败的邮件移动到 另一个文件夹
var value = "" + item + ":" + item + "";
var setIndex = IMAP_t_SeqSet.Parse(value);
client.MoveMessages(true, setIndex, "TestEmailError", true);
}
client.Dispose();
}
else
{
errorMessage = "操作成功";
}
五、邮件移动方法
IMAP_t_SeqSet.Parse(value)方法:
根据uid获取到第几封邮件,每一封邮件都有唯一的uid;格式 "1:3",代表1
foreach (var item in trueUid)
{
//将成功的邮件移动到 另一个文件夹
var value = "" + item + ":" + item + "";
var setIndex = IMAP_t_SeqSet.Parse(value);
client.MoveMessages(true, setIndex, "TestEmailComplete", true);
}
foreach (var item in flaseUid)
{
//将失败的邮件移动到 另一个文件夹
var value = "" + item + ":" + item + "";
var setIndex = IMAP_t_SeqSet.Parse(value);
client.MoveMessages(true, setIndex, "TestEmailError", true);
}