.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;}}}#endregionif (index == 0)//excel附件找不到 "aaa" 的列名信息{errorMessage += "标题为'" + emailTitle + "'的邮件,在附件信息中找不到aaa的列名信息";isSuccees = false;break;}#region 获取 需要保存数据库的数据var cellIndex = index + 1;//对应Excel中 开始获取aaa数据的行索引var code = "";//codevar 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);}
相关文章:
.Net 访问电子邮箱-LumiSoft.Net,好用
序言: 网上找了很多关于.Net如何访问电子邮箱的方法,但是大多数都达不到想要的需求,只有一些 收发邮件。因此 花了很大功夫去看 LumiSoft.Net.dll 的源码,总算做出自己想要的结果了,果然学习诗人进步。 介绍ÿ…...
谷粒商城-商品服务-新增商品功能开发(商品图片无法展示问题没有解决)
在网关配置路由 - id: member_routeuri: lb://gulimemberpredicates:- Path/api/gulimember/**filters:- RewritePath/api/(?<segment>.*),/$\{segment}并将所有逆向生成的工程调式出来 获取分类关联的品牌 例如:手机(分类)-> 品…...
Open3D 点云数据处理基础(Python版)
Open3D 点云数据处理基础(Python版) 文章目录 1 概述 2 安装 2.1 PyCharm 与 Python 安装 2.3 Anaconda 安装 2.4 Open3D 0.13.0 安装 2.5 新建一个 Python 项目 3 点云读写 4 点云可视化 2.1 可视化单个点云 2.2 同一窗口可视化多个点云 2.3…...
使用vue-qr,报错in ./node_modules/vue-qr/dist/vue-qr.js
找到node_modules—>vue-qr/dist/vue-qr.js文件,搜…e,将…去掉,然后重新运行项目。...
百川2大模型微调问题解决
之前用https://github.com/FlagAlpha/Llama2-Chinese微调过几个模型,总体来说llama2的生态还是比较好的,过程很顺利。微调百川2就没那么顺利了,所以简单做个记录 1. 数据准备,我的数据是单轮对话,之前微调llama2已经按…...
MySQL的事务-原子性
MySQL的事务处理具有ACID的特性,即原子性(Atomicity)、一致性(Consistency)、隔离性(Isolation)和持久性(Durability)。 1. 原子性指的是事务中所有操作都是原子性的,要…...
D3839|完全背包
完全背包: 首先01背包的滚动数组中的解法是内嵌的循环是从大到小遍历,为了保证每个物品仅被添加一次。 for(int i 0; i < weight.size(); i) { // 遍历物品for(int j bagWeight; j > weight[i]; j--) { // 遍历背包容量dp[j] max(dp[j], dp[j…...
Java之Synchronized与锁升级
Synchronized与锁升级 一、概述 在多线程并发编程中 synchronized 一直是元老级角色,很多人都会称呼它为重量级锁。但是,随着 Java SE 1.6 对 synchronized 进行了各种优化之后,有些情况下它就并不那么重了。 本文详细介绍 Java SE 1.6 中为…...
kitex出现:open conf/test/conf.yaml: no such file or directory
open conf/test/conf.yaml: no such file or directory https://github.com/cloudwego/cwgo/issues/120 https://github.com/cloudwego/cwgo/issues/29 在使用Kitex生成的代码中,单元测试时回报错,如标题所示。出现该错的原因是,biz/servic…...
sql server多表查询
查询目标 现在有学生表和学生选课信息表,stu和stuSelect,stu中包含学生用户名、名字,stuSelect表中包含学生用户名,所选课程名 学生表: nameusername李明Li Ming李华Li Hua 学生选课表: usernameCourse…...
如何利用PPT绘图并导出清晰图片
在写论文的过程中,免不了需要绘图,但是visio等软件绘图没有在ppt上绘图比较熟练,尤其流程图结构图. 但是ppt导出的图片也不够清晰,默认分辨率是96dpi,而杂志投稿一般要求至300dpi。解决办法如下: 1.打开注…...
1.倒排索引 2.逻辑斯提回归算法
1.倒排索引 https://help.aliyun.com/zh/open-search/retrieval-engine-edition/introduction-to-inverted-indexes 倒排索引(Inverted Index)是一种数据结构,用于快速查找包含某个特定词或词语的文档。它主要用于全文搜索引擎等应用&#…...
Kafka消费者组
消费者总体工作流程 Consumer Group(CG):消费者组,由多个consumer组成。形成一个消费者组的条件,是所有消费者的groupid相同。 • 消费者组内每个消费者负责消费不同分区的数据,一个分区只能由一个组内消费…...
四. 基于环视Camera的BEV感知算法-BEVDepth
目录 前言0. 简述1. 算法动机&开创性思路2. 主体结构3. 损失函数4. 性能对比总结下载链接参考 前言 自动驾驶之心推出的《国内首个BVE感知全栈系列学习教程》,链接。记录下个人学习笔记,仅供自己参考 本次课程我们来学习下课程第四章——基于环视Cam…...
CentOS系统环境搭建(二十五)——使用docker compose安装mysql
centos系统环境搭建专栏🔗点击跳转 文章目录 使用docker compose安装mysqlMySQL81.新建文件夹2.创建docker-compose.yaml3.创建my.cnf4.mysql容器的启动和关闭 MySQL5.71.新建文件夹2.创建docker-compose.yaml3.创建my.cnf4.mysql容器的启动和关闭 使用docker comp…...
协作机器人(Collaborative-Robot)安全碰撞的速度与接触力
协作机器人(Collaborative-Robot)的安全碰撞速度和接触力是一个非常重要的安全指标。在设计和使用协作机器人时,必须确保其与人类或其他物体的碰撞不会对人员造成伤害。 对于协作机器人的安全碰撞速度,一般会设定一个上限值&…...
第11章 GUI Page400~402 步骤二 画直线
运行效果: 源代码: /**************************************************************** Name: wxMyPainterApp.h* Purpose: Defines Application Class* Author: yanzhenxi (3065598272qq.com)* Created: 2023-12-21* Copyright: yanzhen…...
华为gre隧道全部跑静态路由
最终实现: 1、pc1能用nat上网ping能pc3 2、pc1能通过gre访问pc2 3、全部用静态路由做,没有用ospf,如果要用ospf,那么两边除了路由器上跑ospf,核心交换机也得用ospf r2配置: acl number 3000 rule 5 deny…...
【c++】入门1
c关键字 命名空间 在C/C中,变量、函数和后面要学到的类都是大量存在的,这些变量、函数和类的名称将都存在于全局作用域中,可能会导致很多冲突。使用命名空间的目的是对标识符的名称进行本地化,以避免命名冲突或名字污染ÿ…...
Python之Django项目的功能配置
1.创建Django项目 进入项目管理目录,比如:D盘 执行命令:diango-admin startproject demo1 创建项目 如果提示diango命令不存在,搜索diango-admin程序的位置,然后加入到环境变量path中。 进入项目,cd demo…...
实战应用解析:基于快马平台实现openclaw切换模型赋能电商数据爬取与可视化项目
最近在做一个电商数据分析的小项目时,发现不同环节对AI模型的需求差异很大。比如爬虫需要严谨的逻辑,而可视化则需要创意和美观。正好在InsCode(快马)平台上尝试了openclaw切换模型的功能,整个过程特别顺畅,分享下我的实战经验。 …...
DAMOYOLO-S惊艳效果:低分辨率监控截图中识别车牌区域与行人姿态
DAMOYOLO-S惊艳效果:低分辨率监控截图中识别车牌区域与行人姿态 你有没有遇到过这样的场景?从一段模糊的监控录像里截了一张图,想看清车牌号码,但画面糊得跟打了马赛克一样。或者,想分析一下画面里行人的姿态…...
OpenClaw+Qwen3.5-4B-Claude:3个提升开发效率的自动化技巧
OpenClawQwen3.5-4B-Claude:3个提升开发效率的自动化技巧 1. 为什么开发者需要OpenClaw? 作为一名长期奋战在代码一线的开发者,我一直在寻找能够真正减轻重复劳动的工具。直到遇到OpenClaw与Qwen3.5-4B-Claude的组合,才发现原来…...
AD23导出Gerber文件保姆级教程:从PCB到嘉立创下单,新手避坑指南
AD23导出Gerber文件全流程实战:从设计检查到嘉立创安全下单 第一次将精心设计的PCB转化为可生产的Gerber文件,就像新手司机首次独立上路——每个操作都可能隐藏着意想不到的陷阱。作为使用Altium Designer 23(AD23)的设计师&…...
SenseVoice语音识别在客服场景的应用:自动转写通话录音实战
SenseVoice语音识别在客服场景的应用:自动转写通话录音实战 1. 引言:客服录音转写的痛点与机遇 想象一下这样的场景:每天有成千上万的客服通话录音堆积在服务器上,里面包含了客户反馈、产品问题和市场洞察的宝贵信息。但现实是&…...
告别手动gc.collect()!2026 Python内存自适应策略上线:动态分代阈值、对象生命周期AI建模、NUMA感知分配器三合一
第一章:Python 智能体内存管理策略 2026 最新趋势Python 在 2026 年已深度融入 AI 基础设施与边缘智能体(Intelligent Agent)系统,其内存管理机制正从传统引用计数 循环检测双层模型,演进为感知式、上下文驱动的动态调…...
AI选型与配置:让快马智能推荐npm包并生成个人博客系统前端代码
最近在尝试用AI辅助开发个人博客系统,发现整个过程比想象中顺畅很多。特别是依赖管理和技术选型这个环节,AI能帮我们省去大量查文档和试错的时间。下面记录下我的实践过程,或许对同样想快速搭建博客的朋友有帮助。 需求明确化阶段 首先需要…...
Qwen-Image-Layered场景实战:用AI图层技术为你的产品图换背景
Qwen-Image-Layered场景实战:用AI图层技术为你的产品图换背景 1. 引言 1.1 电商设计的痛点 在电商运营中,产品主图的质量直接影响转化率。传统换背景流程需要设计师手动抠图、调整边缘、匹配光影,一个产品图往往需要30分钟以上的处理时间。…...
OpenClaw+GLM-4.7-Flash自动化写作:3小时生成30篇技术笔记实战
OpenClawGLM-4.7-Flash自动化写作:3小时生成30篇技术笔记实战 1. 为什么需要自动化知识管理 作为一个技术博主,我每天需要消化大量技术文档和论文。过去两年里,我尝试过各种笔记工具——从Notion到Obsidian,从语雀到飞书文档。但…...
SeqGPT-560M金融信贷申请:申请人/收入证明/抵押物/授信额度结构化
SeqGPT-560M金融信贷申请:申请人/收入证明/抵押物/授信额度结构化 1. 项目概述 SeqGPT-560M是一个专门针对金融信贷场景深度优化的智能信息抽取系统。与通用聊天模型不同,这个系统专注于从复杂的非结构化文本中精准提取关键金融信息,特别适…...
