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

序言:

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

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

swing快速入门(二十四)绘画板-可调色

注释很详细&#xff0c;直接上代码 上一篇 Look here~ 听我说完再继续看更容易理解&#xff1a; 如果说用之前的绘图方法写一个绘画板你会怎么做&#xff1f;重绘会让之前的内容消失呀&#xff0c;用各种数据结构记录每个像素点的位置或颜色&#xff1f;嘶&#xff0c;感觉很麻…

【数据结构】递归与分治

一.递归 1.递归的概念&#xff1a; 子程序&#xff08;或函数&#xff09;. 接调用自己或通过一系列调用语句间接调用自己&#xff0c;成为递归。 递归是一种描述问题和解决问题的基本方法。 重复地把问题转化为与原问题相似的新问题&#xff0c;直到问题解决为止。 2.递归…

MyBatis 架构分析

文章目录 三层架构一、基础支撑层1.1 类型转换模块1.2 日志模块1.3 反射工具模块1.4 Binding 模块1.5 数据源模块1.6 缓存模块1.6 解析器模块1.7 事务管理模块 二、核心处理层2.1 配置解析2.2 SQL 解析与 scripting 模块。2.3 MyBatis 中的 scripting 模块就是负责动态生成 SQL…

111基于matlab的粒子滤波进行锂离子电池的循环寿命预测

基于matlab的粒子滤波进行锂离子电池的循环寿命预测&#xff0c;输出实验、粒子滤波及自然预测数据结果。程序已调通&#xff0c;可直接运行。 111matlab锂离子电池寿命预测 (xiaohongshu.com)

Git安装和使用教程,并以gitee为例实现远程连接远程仓库

文章目录 1、Git简介及安装2、使用方法2.1、Git的启动与配置2.2、基本操作2.2.1、搭建自己的workspace2.2.2、git add2.2.3、git commit2.2.4、忽略某些文件不予提交2.2.5、以gitee为例实现git连接gitee远程仓库来托管代码 1、Git简介及安装 版本控制&#xff08;Revision cont…

C/C++ 连接访问 MySQL数据库

前面我们已经讲述了MySQL的基础使用&#xff0c;现在我们来看一下如何使用语言来操作数据库。在实际开发中&#xff0c;语言连接MySQL是为了能够在编程语言中与MySQL数据库进行交互和操作。大部分情况我们都是通过语言连接MySQL&#xff0c;建立与MySQL数据库的连接&#xff0c…

springboot实现发送邮件开箱即用

springboot实现发送邮件开箱即用 环境依赖包yml配置Service层Controller层测试 环境 jdk17 springboot版本3.2.1 依赖包 <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-mail</artifactId><ver…

分布式系统架构设计之分布式数据管理

随着互联网时代的不断发展&#xff0c;分布式系统架构成为支撑大规模用户和高并发访问的基础。在构建分布式系统时&#xff0c;分布式系统有着一系列的要求以及对应的核心技术&#xff0c;涉及到数据管理、通信安全性、性能优化、可扩展性设计以及架构演进与版本管理等很多方面…

N字形变换(麻烦的方法)

class Solution:def convert(self, s: str, numRows: int) -> str:#先判断z有多少隔开s_new""index_now0if len(s)<numRows or numRows1:return sfor i in range(numRows-1,-1,-1):exchange0index_exchangeindex_nows_news[index_now]#计算每一层的差距gap_but…

【零基础入门Python】Python参数

✍面向读者&#xff1a;所有人 ✍所属专栏&#xff1a;零基础入门Pythonhttps://blog.csdn.net/arthas777/category_12455877.html 目录 print&#xff08;&#xff09;中的Python结束参数 print&#xff08;&#xff09;中的Python|sep参数 Python的格式转换规则 使用格式…

Vue如何请求接口——axios请求

1、安装axios 在cmd或powershell打开文件后&#xff0c;输入下面的命令 npm install axios 可在项目框架中的package.json中查看是否&#xff1a; 二、引用axios import axios from axios 在需要使用的页面中引用 三、get方式使用 get请求使用params传参,本文只列举常用参数…

java中线程相关的面试题

什么是线程安全&#xff0c;造成线程安全的本质是什么&#xff1f; 什么是线程安全呢&#xff1f; 咱们初步去理解话记住一句话就行&#xff1a;如果一个对象可以安全地被多个线程同时使用&#xff0c;那它就是线程安全的。 为什么并发编程会导致线程不安全&#xff1f; 可见…

用户认证篇

文章目录 1. 如何生成用户认证token令牌1.1 相关表1.2 生成令牌逻辑1.3 最终结果 2. 如何认证用户token令牌2.1 前端组件2.2 TokenAuthenticationFilter2.3 获得登陆用户 3. 如何刷新用户认证 Token 令牌3.1 前端组件3.2 刷新令牌接口 4. 如何模拟用户认证token令牌5. 如何实现…

php学习03-php注释

<?php //单行注释 echo ;//单行注释//单行注释嵌套 /*** 多行注释* 多行注释不允许嵌套*/ $c 12; # 这也是单行注释 #嵌套 /*** 文档注释*/ class Util{/*** 方法注释* param int $num* return int*/function add($num){return 11$num;} }echo 这样会出错的//不会看打到?…

linux的主线程提前子线程退出以及线程分离

主线程提前退出 如果主线程没有等待子线程提前退出&#xff0c;可能会发生以下情况&#xff1a; 子线程继续运行&#xff1a;如果主线程退出&#xff0c;但子线程仍在执行任务&#xff0c;子线程将继续独立运行。子线程的生命周期不受主线程控制&#xff0c;直到子线程自行完成…

基于Springboot的留守儿童爱心网站(有报告)。Javaee项目,springboot项目。

演示视频&#xff1a; 基于Springboot的留守儿童爱心网站(有报告)。Javaee项目&#xff0c;springboot项目。 项目介绍&#xff1a; 采用M&#xff08;model&#xff09;V&#xff08;view&#xff09;C&#xff08;controller&#xff09;三层体系结构&#xff0c;通过Spring…

蓝牙物联网在智能家居中的应用前景

物联网智能家居系统是应用物联网技术&#xff0c;在传统家居环境下将各种零散无序的电器整合成统一整体&#xff0c;实现家电的全程自动控制&#xff0c;满足用户高效管理需求的一种新型家居模式。 其主要的子系统有家居感知系统、家庭网络系统、智能家居控制管理系统等&#x…

LINUX 嵌入式应用开发层细节知识(入职体验)

1. 后台进程 一些辅助监测的工作&#xff08;日志系统&#xff0c;OTA升级&#xff0c;云-本地中转) 进程可以设置为守护进程 nohup nohub、&、setsid nohup 是可以忽略所有信号&#xff0c;让程序进入后台进程模式。‘ 2. IPCS -ipc_index 查询IPC目前的使用情况 3.…

微信小程序开发学习(上强度):从0开始写项目

前置知识 1、配置插件 微信小程序 基础模板引入sass的两种方法_微信小程序使用sass-CSDN博客 之后在对应页面里新建一个scss文件&#xff0c;写css 2、注册小程序&#xff0c;有个自己的appid&#xff0c;不用测试号了 5.1.注册小程序账号获取appid及个人和企业版差异_哔哩…