.Net 访问电子邮箱-LumiSoft.Net,好用

news2025/1/16 19:59:12

序言:

网上找了很多关于.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);
	}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1331510.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Qt 开源项目

Qt 开源项目 Omniverse View链接技术介绍 QuickQanava链接技术介绍QField链接技术介绍 AtomicDEX链接技术介绍 Status-desktop链接技术介绍 Librum链接技术介绍 A Simple Cross-Platform ReaderQPrompt链接技术介绍 GCompris链接技术介绍 Scrite链接技术介绍 QSkinny链接技术介…

如何在PC上运行大模型

如何在PC上运行大模型 在PC上使用CPU运行大模型不如使用GPU高效&#xff0c;但仍然是可以实现的大模型推理。 大模型训练要求的资源更高&#xff0c;这里直接使用面向开源的Facebook’s LLaMA model(llama-2-7b-chat.Q2_K.gguf)。 连接CPU与LLaMA model的是llama.cpp。 为方便…

认识Linux背景

1.发展史 Linux从哪里来&#xff1f;它是怎么发展的&#xff1f;在这里简要介绍Linux的发展史 要说Linux&#xff0c;还得从UNIX说起 UNIX发展的历史 1968年&#xff0c;一些来自通用电器公司、贝尔实验室和麻省理工学院的研究人员开发了一个名叫Multics的特殊操作系统。Mu…

LLaMA开源大模型源码分析!

Datawhale干货 作者&#xff1a;宋志学&#xff0c;Datawhale成员 花了一晚上照着transformers仓库的LLaMA源码&#xff0c;把张量并行和梯度保存的代码删掉&#xff0c;只留下模型基础结构&#xff0c;梳理了一遍LLaMA的模型结构。 今年四月份的时候&#xff0c;我第一次接触…

第一次记录QPSK,BSPK,MPSK,QAM—MATLAB实现

最近有偶然的机会学习了一次QPSK防止以后忘记又得找资料&#xff0c;这里就详细的记录一下 基于 QPSK 的通信系统如图 1 所示&#xff0c;QPSK 调制是目前最常用的一种卫星数字和数 字集群信号调制方式&#xff0c;它具有较高的频谱利用率、较强的抗干扰性、在电路上实现也较为…

基于STM32单片机模拟智能电梯步进电机控制升降毕业设计3

STM32单片机模拟智能电梯步进电机控制数码管显示3 演示视频&#xff08;复制到浏览器打开&#xff09;&#xff1a; 基于STM32单片机的智能电梯控制系统模拟智能电梯步进电机控制系统设计数码管显示楼层设计/DIY开发板套件3 产品功能描述&#xff1a; 本系统由STM32F103C8T6单…

技术交底二维码的应用

二维码技术交底可以逐级落实、责任到人、有据可查、是目前最方便、实用的交底方式&#xff0c;下面我们讲解技术交底二维码的应用。 1、生成对应的技术交底二维码&#xff0c;将施工方案、技术资料、安全教育资料等内容上传到二维码里。打印出来现场粘贴&#xff0c;便于作业班…

(一)深入理解Mysql底层数据结构和算法

什么是索引 索引是帮助MySQL高效获取数据的排好序的数据结构 数据结构有哪些 数据结构模拟网站&#xff1a;Data Structure Visualization 二叉树 不适合做自增ID的数据结构。如下示意图&#xff0c;假设采用二叉树作为表自增主键ID的数据存储结果如下&#xff1a;当查询i…

行列式:方程组未知数的计算:克拉默法则

行列式&#xff1a;方程组未知数的计算 ![ ](https://img-blog.csdnimg.cn/direct/4a9c2800da3746ea95c1a3c93057d796.png)

VS Code实现“Ctr+save”保存代码自动格式化

一、下载Prettier - Code formatter插件 点击安装即可 二、配置 【1】打开文件——首选项——设置 或者左下角齿轮打开设置 【2】搜索设置框输入editor default formatter&#xff08;意思是默认格式化设置&#xff09;&#xff0c;接着下拉选中刚下好的插件名称Prettier - C…

【Vulnhub 靶场】【Corrosion: 1】【简单】【20210731】

1、环境介绍 靶场介绍&#xff1a;https://www.vulnhub.com/entry/corrosion-1,730/ 靶场下载&#xff1a;https://download.vulnhub.com/corrosion/Corrosion.ova 靶场难度&#xff1a;简单 发布日期&#xff1a;2021年07月31日 文件大小&#xff1a;7.8 GB 靶场作者&#xf…

Windows安装cnpm报错 The operation was rejected by your operating system.

Windows在安装cnpm时出现如下错误 npm ERR! The operation was rejected by your operating system. npm ERR! Its possible that the file was already in use (by a text editor or antivirus), npm ERR! or that you lack permissions to access it. npm ERR! npm ERR! If y…

[vue]Echart使用手册

[vue]Echart使用手册 使用环境Echart的使用Echart所有组件和图表类型Echart 使用方法 使用环境 之前是在JQuery阶段使用Echart&#xff0c;直接引入Echart的js文件即可&#xff0c;现在是在vue中使用,不仅仅时echarts包&#xff0c;还需要安装vue-echarts&#xff1a; "…

智能优化算法应用:基于鹈鹕算法3D无线传感器网络(WSN)覆盖优化 - 附代码

智能优化算法应用&#xff1a;基于鹈鹕算法3D无线传感器网络(WSN)覆盖优化 - 附代码 文章目录 智能优化算法应用&#xff1a;基于鹈鹕算法3D无线传感器网络(WSN)覆盖优化 - 附代码1.无线传感网络节点模型2.覆盖数学模型及分析3.鹈鹕算法4.实验参数设定5.算法结果6.参考文献7.MA…

C语言——小细节和小知识6

一、转义字符相关 \ 反斜杠&#xff0c;转义字符中的转义序列符 \? 将?转义&#xff0c;防止他被识别成三字母词(很早的东西)中的问号 //三字母词 //??(是[ //??)是] printf("%s","??(??)"); //打印结果是[] 二、fopen函数fc…

Linux 基础指令三

一、cat命令 默认是顺序查看&#xff0c;可同时查看多个文件&#xff0c;只能看普通文件&#xff0c;不能看文件以外 使用格式: cat [选项] 文件名 常用选项 -n显示行号-b跳过空白行编号-s将所有的连续的多个空行替换为一个空行&#xff08;压缩成一个空行&#xff0…

适配器模式学习

适配器模式&#xff08;Adapter&#xff09;将一个类的接口转换成客户希望的另外一个接口。Adapter 模式使得原本由于接口不兼容而不能一起工作的那些类可以一起工作。 适配器模式分为类适配器模式和对象适配器模式两种&#xff0c;前者类之间的耦合度比后者高&#xff0c;且要…

在Linux安装卸载文件

目录 一、Linux系统应用程序 1.典型的应用程序的目录结构 2、常见的软件包封装类型 二、RPM软件包管理 1、RPM是什么&#xff1f; 2、rpm一般命名格式 3、RPM安装包从何而来&#xff1f;如何挂载&#xff1f; 4、挂载的注意事项: 5、目的&#xff1a;提供安装包 6、查…

初学链表(分析建立学生信息链表)

本题要求实现一个将输入的学生成绩组织成单向链表的简单函数。 #include <stdio.h> #include <stdlib.h> #include <string.h> struct stud_node { int num; char name[20]; int score; struct stud_node *next; }; struct stu…

又是阿里,通义灵码免费平替GitHub Copilot

毫无疑问&#xff0c;人工智能已经在影响着我们日常生活的方方面面&#xff0c;同样的在软件开发领域&#xff0c;AI正在改变我们的开发方式。在软件开发领域&#xff0c;尽管有许多强大的AI编码工具&#xff0c;但国产&#xff0c;免费&#xff0c;使用门槛低&#xff0c;用起…