.net6 core Worker Service项目,使用Exchange Web Services (EWS) 分页获取电子邮件收件箱列表,邮件信息字段
Program.cs
安装包:Microsoft.AspNetCore.Hosting.WindowsServices、Microsoft.Extensions.Hosting、Microsoft.Extensions.Hosting.WindowsServices、Microsoft.Extensions.Logging.Log4Net.AspNetCore
新建Configs/log4net.config
using Com.Chinahorn.Exchange.WorkerService;IHost host = Host.CreateDefaultBuilder(args).UseWindowsService().ConfigureLogging(logging => logging.AddLog4Net("Configs/log4net.config")).ConfigureServices(services =>{services.AddHostedService<Worker>();}).Build();await host.RunAsync();
log4net.config
<?xml version="1.0" encoding="utf-8" ?>
<log4net><!-- Define some output appenders --><appender name="rollingAppender" type="log4net.Appender.RollingFileAppender"><!-- value="logs/log.log"--><file value="logs/" /><!--追加日志内容--><appendToFile value="true" /><!--防止多线程时不能写Log,官方说线程非安全--><lockingModel type="log4net.Appender.FileAppender+MinimalLock" /><!--可以为:Once|Size|Date|Composite--><!--Composite为Size和Date的组合--><rollingStyle value="Composite" /><!--当备份文件时,为文件名加的后缀--><datePattern value="yyyyMMddhh'.log'" /><!--日志最大个数,都是最新的--><!--rollingStyle节点为Size时,只能有value个日志--><!--rollingStyle节点为Composite时,每天有value个日志--><maxSizeRollBackups value="20" /><!--可用的单位:KB|MB|GB--><maximumFileSize value="3MB" /><!--置为true,当前最新日志文件名永远为file节中的名字--><staticLogFileName value="false" /><!--输出级别在INFO和ERROR之间的日志--><filter type="log4net.Filter.LevelRangeFilter"><param name="LevelMin" value="ALL" /><param name="LevelMax" value="FATAL" /></filter><layout type="log4net.Layout.PatternLayout"><conversionPattern value="%date [%thread] %-5level %logger - %message%newline"/></layout></appender><root><!--控制级别,由低到高: ALL|DEBUG|INFO|WARN|ERROR|FATAL|OFF--><!--OFF:0--><!--FATAL:FATAL--><!--ERROR: ERROR,FATAL--><!--WARN: WARN,ERROR,FATAL--><!--INFO: INFO,WARN,ERROR,FATAL--><!--DEBUG: INFO,WARN,ERROR,FATAL--><!--ALL: DEBUG,INFO,WARN,ERROR,FATAL--><priority value="ALL"/><level value="INFO"/><!--使用上面配置的那个规则,ref指定上面的规则名称--><appender-ref ref="rollingAppender" /></root>
</log4net>
Worker.cs
namespace Com.Chinahorn.Exchange.WorkerService
{public class Worker : BackgroundService{private readonly ILogger<Worker> _logger;public Worker(ILogger<Worker> logger){_logger = logger;}protected override async Task ExecuteAsync(CancellationToken stoppingToken){while (!stoppingToken.IsCancellationRequested){_logger.LogInformation("Com.Chinahorn.Exchange.Service Worker running Start: {time}", DateTimeOffset.Now);IConfiguration configuration = new ConfigurationBuilder().SetBasePath(AppDomain.CurrentDomain.BaseDirectory).AddJsonFile("appsettings.json").Build();try{ExchangeMailFind exchangeMail = new ExchangeMailFind(_logger);exchangeMail.doWork();}catch (Exception ex){_logger.LogError("Com.Chinahorn.Exchange.Service Worker error: {ex}", ex);}_logger.LogInformation("Com.Chinahorn.Exchange.Service Worker running End : {time}", DateTimeOffset.Now);int workSplit = Convert.ToInt32(configuration.GetConnectionString("workSplit"));//workSplit = workSplit <= 5 ? 5 : workSplit;await Task.Delay(workSplit * 1000, stoppingToken);}}}
}
ExchangeMailFind.cs
using System;
using System.Collections.Generic;
using System.Data;
using System.IO;
using System.Net;
using System.Net.Security;
using System.Security.Cryptography.X509Certificates;
using System.Text;
using System.Threading;
using System.Web;
using Com.Chinahorn.Exchange.DBHelper;
using Com.Chinahorn.Exchange.WorkerService;
using Microsoft.Exchange.WebServices.Data;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Logging;
using Newtonsoft.Json;public class ExchangeMailFind
{private readonly ILogger<Worker> _logger;public ExchangeMailFind(ILogger<Worker> logger){_logger = logger;}public void doWork(){IConfiguration configuration = new ConfigurationBuilder().SetBasePath(AppDomain.CurrentDomain.BaseDirectory).AddJsonFile("appsettings.json").Build();string[] exchangeUrl = configuration.GetConnectionString("EWSUrl").Split(new char[1] { ';' }, StringSplitOptions.RemoveEmptyEntries);string[] username = configuration.GetConnectionString("MailUserName").Split(new char[1] { ';' }, StringSplitOptions.RemoveEmptyEntries);string[] password = configuration.GetConnectionString("MailPWD").Split(new char[1] { ';' }, StringSplitOptions.RemoveEmptyEntries);string[] MailDateFilter = configuration.GetConnectionString("MailDateFilter").Split(new char[1] { ';' }, StringSplitOptions.RemoveEmptyEntries);if (exchangeUrl.Length != username.Length && username.Length != password.Length && password.Length != MailDateFilter.Length){_logger.LogInformation("配置信息:EWSUrl、MailUserName、MailPWD设置有误,多套需对应设置");return;}int pagerSize = Convert.ToInt32(configuration.GetConnectionString("MailPagerSize"));SQLHelper db_helper = new SQLHelper();for (int k = 0; k < exchangeUrl.Length; k++){try{ServicePointManager.ServerCertificateValidationCallback = (RemoteCertificateValidationCallback)Delegate.Combine(ServicePointManager.ServerCertificateValidationCallback, (RemoteCertificateValidationCallback)((object sender, X509Certificate? cert, X509Chain? chain, SslPolicyErrors sslPolicyErrors) => true));ExchangeService service = new ExchangeService(ExchangeVersion.Exchange2013_SP1);service.Url = new Uri(exchangeUrl[k]);string pwd = password[k];service.Credentials = new WebCredentials(username[k], pwd);_logger.LogInformation("doWork ExchangeService EWSUrl:" + exchangeUrl[k] + " 凭据验证成功");DateTime startDate = Convert.ToDateTime(DateTime.Now.ToString("yyyy-MM-dd"));if (MailDateFilter.Length > 0 && !string.IsNullOrWhiteSpace(MailDateFilter[k])){startDate = Convert.ToDateTime(MailDateFilter[k]);}SearchFilter.IsGreaterThanOrEqualTo timeFilter = new SearchFilter.IsGreaterThanOrEqualTo(ItemSchema.DateTimeReceived, startDate);ItemView view = new ItemView(pagerSize);view.PropertySet = new PropertySet(BasePropertySet.IdOnly, ItemSchema.Subject, ItemSchema.DateTimeReceived);int offset = 0;//int i = 1;FindItemsResults<Item> findResults;do{view.Offset = offset;findResults = service.FindItems(WellKnownFolderName.Inbox, timeFilter, view);_logger.LogInformation("doWork 获取收件箱Count:" + findResults.Items.Count);foreach (Item item in findResults){EmailMessage email = EmailMessage.Bind(service, item.Id, new PropertySet(BasePropertySet.FirstClassProperties));//Console.WriteLine("序号: " + i);//Console.WriteLine("发件人: " + email.Sender.Name);//Console.WriteLine("发件邮箱: " + email.Sender.Address);//Console.WriteLine("主题: " + email.Subject);//Console.WriteLine("内容: " + email.Body);//Console.WriteLine("发送时间: " + email.DateTimeSent);//Console.WriteLine("收件人: " + email.ReceivedBy.Name);//Console.WriteLine("收件邮箱: " + email.ReceivedBy.Address);string AttachmentName = string.Empty;string AttachmentStream = string.Empty;try{foreach (Attachment attachment in email.Attachments){if (attachment is FileAttachment){FileAttachment fileAttachment = attachment as FileAttachment;Console.WriteLine("附件名称: " + fileAttachment.Name);AttachmentName = AttachmentName + fileAttachment.Name + ";";// 使用内存流读取文件内容using (MemoryStream ms = new MemoryStream()){fileAttachment.Load(ms);byte[] buffer = ms.ToArray();Console.WriteLine("附件文件流: " + Convert.ToBase64String(buffer));AttachmentStream = AttachmentStream + Convert.ToBase64String(buffer) + ";";}}}}catch (Exception ex){_logger.LogError("doWork email.Attachments循环报错:" + ex.Message, ex);}string CcRecipientsMail = string.Empty;foreach (EmailAddress cc in email.CcRecipients){Console.WriteLine("抄送人: " + cc.Address);CcRecipientsMail = CcRecipientsMail + cc.Address + ";";}string messageId = email.InternetMessageHeaders.Find("Message-ID").Value;_logger.LogInformation("doWork Message-ID:" + messageId);//Console.WriteLine("Message-ID:" + messageId); }offset += findResults.Items.Count;Thread.Sleep(1000);}while (findResults.MoreAvailable);}catch (Exception ex){_logger.LogError("doWork exchangeUrl for k:" + k.ToString() + "报错:" + ex.Message, ex);}}}
appsettings.json
{"Logging": {"LogLevel": {"Default": "Information","Microsoft.Hosting.Lifetime": "Information"}},"ConnectionStrings": {"SQLConnStr": "server=.;uid=sa;pwd=xx;database=xx;Encrypt=True;TrustServerCertificate=True;",//Exchange WebService,多套用;标识(多套需对应设置)"EWSUrl": "https://mail.xx.com/EWS/Exchange.asmx",//Exchange用户名,多套用;标识(多套需对应设置)"MailUserName": "xx",//Exchange密码,多套用;标识(多套需对应设置)"MailPWD": "Vm1GbFkyNDNPREl3TWpJeEl5UndZWE56Y0c5eWRBPT0=",//获取特定时间之后的邮件(如果为空则获取当天的),多套用;标识(多套需对应设置)"MailDateFilter": "2024-04-28",//分页获取邮件数"MailPagerSize": "50","WorkSplit": "60" //服务轮询时间,秒}
}
项目结构图

相关文章:
.net6 core Worker Service项目,使用Exchange Web Services (EWS) 分页获取电子邮件收件箱列表,邮件信息字段
Program.cs 安装包:Microsoft.AspNetCore.Hosting.WindowsServices、Microsoft.Extensions.Hosting、Microsoft.Extensions.Hosting.WindowsServices、Microsoft.Extensions.Logging.Log4Net.AspNetCore 新建Configs/log4net.config using Com.Chinahorn.Exchange.W…...
通过 EMR Serverless Spark 提交 PySpark 流任务
在大数据快速发展的时代,流式处理技术对于实时数据分析至关重要。EMR Serverless Spark提供了一个强大而可扩展的平台,它不仅简化了实时数据处理流程,还免去了服务器管理的烦恼,提升了效率。本文将指导您使用EMR Serverless Spark…...
【Linux网络】epoll实现的echo服务器{nocopy类/智能指针/echo服务器}
文章目录 1.代码基础1.1某类唯一存在1.2C智能指针 2.epoll实现的echo服务器日志套接字CMakeepoll封装主函数服务器 1.代码基础 1.1某类唯一存在 这段代码定义了一个名为 nocopy 的类,它旨在防止该类的实例被复制或赋值。这是通过在类中显式删除拷贝构造函数&#…...
[数据集][目标检测]拐杖检测数据集VOC+YOLO格式2778张1类别
数据集格式:Pascal VOC格式YOLO格式(不包含分割路径的txt文件,仅仅包含jpg图片以及对应的VOC格式xml文件和yolo格式txt文件) 图片数量(jpg文件个数):2778 标注数量(xml文件个数):2778 标注数量(txt文件个数):2778 标注…...
长按加速- 解决react - setInterval下无法更新问题
最开始直接setInterval里,useState硬写,发现更新不,固定值 换let,发现dom更新不了 正确做法是用ref 并且pc端可以长按的,只是要用onTouchStart,不要用onMouseDown onTouchStart{handleMouseDown} onTou…...
路网双线合并单线——ArcGIS 解决方法
路网双线合并成单线是一个在地图制作、交通规划以及GIS分析中常见的需求。双线路网定义:具有不同流向、不同平面结构的道路。此外,车道数较多的道路(例如,双黄实线车道数大于4的道路)也可以视为双线路网,本…...
【.NET全栈】ASP.NET开发Web应用——ADO.NET数据访问技术
文章目录 前言一、ADO.NET基础1、ADO.NET架构2、ADO.NET数据提供者 二、连接数据库1、SqlConnection数据库连接类2、使用SqlConnectionStringBuilder连接字符串3、关闭和释放连接4、在web.config配置文件中保存连接字符串5、连接池技术 三、与数据库交互1、使用SqlCommand操作数…...
【机器学习】无监督学习和自监督学习
1. 什么是机器学习 机器学习是一种使计算机系统能够从数据中学习并做出预测或决策的技术和科学领域。它不需要显式地编程来执行特定任务,而是通过使用算法来分析数据和识别模式,以此“学习”如何做出准确的预测或决策。 以下是机器学习的几个关键点&…...
蓝牙新篇章:WebKit的Web Bluetooth API深度解析
蓝牙新篇章:WebKit的Web Bluetooth API深度解析 在物联网(IoT)时代,Web应用与物理设备的交互变得越来越重要。WebKit的Web Bluetooth API开启了一个新时代,允许Web页面直接与蓝牙设备通信。这一API不仅提高了用户体验,还为创新的…...
2024可信数据库发展大会:TDengine CEO 陶建辉谈“做难而正确的事情”
在当前数字经济快速发展的背景下,可信数据库技术日益成为各行业信息化建设的关键支撑点。金融、电信、能源和政务等领域对数据处理和管理的需求不断增加,推动了数据库技术的创新与进步。与此同时,人工智能与数据库的深度融合、搜索与分析型数…...
Guns v7.3.0:基于 Vue3、Antdv 和 TypeScript 打造的开箱即用型前端框架
摘要 本文深入探讨了Guns v7.3.0前端项目,该项目是基于Vue3、Antdv和TypeScript的前端框架,以Vben Admin的脚手架为基础进行了改造。文章分析了Guns 7.3.0的技术特点,包括其使用Vue3、vite2和TypeScript等最新前端技术栈,以及提供…...
掌握构建艺术:在Gradle中配置自定义的源代码管理(SCM)
掌握构建艺术:在Gradle中配置自定义的源代码管理(SCM) 在软件开发过程中,源代码管理(Source Code Management,简称SCM)是不可或缺的一部分。它帮助开发者管理代码的变更历史,支持团…...
如何在 Mac 上下载安装植物大战僵尸杂交版? 最新版本 2.2 详细安装运行教程问题详解
植物大战僵尸杂交版已经更新至2.2了,但作者只支持 Windows、手机等版本并没有支持 MAC 版本,最近搞到了一个最新的杂交 2.2 版本的可以在 Macbook 上安装运行的移植安装包,试了一下非常完美能够正常在 MAC 上安装运行,看图&#x…...
前端Vue组件技术实践:打造自定义精美悬浮菜单按钮组件
随着前端技术的迅猛发展,复杂的应用场景和不断迭代的产品需求使得开发的复杂度日益提升。传统的整体式开发方式已经难以满足现代前端应用的灵活性和可维护性需求。在这样的背景下,组件化开发逐渐崭露头角,成为解决复杂前端应用问题的有效手段…...
数据仓库的一致性维度
一致性维度的定义: 一致性维度是指在数据仓库中,具有相同属性和含义的维度在不同的事实表中保持一致。它确保了通过不同事实表进行查询和分析时,维度数据的一致性和准确性。 一致性维度的作用: 数据一致性:一致性维度…...
【ffmpeg命令】RTMP推流
文章目录 前言推流是什么RTMP协议简介RTMP的基本概念RTMP的工作原理RTMP的优缺点 ffmpeg RTMP推流推流命令综合解释ffplay播放RTMP流 总结 前言 在现代的视频直播中,RTMP(Real-Time Messaging Protocol)是一种广泛使用的流媒体传输协议。它允…...
人工智能大模型发展的新形势及其省思
作者简介 肖仰华,复旦大学计算机科学技术学院教授、博导,上海市数据科学重点实验室主任。研究方向为知识图谱、知识工程、大数据管理与挖掘。主要著作有《图对称性理论及其在数据管理中的应用》、《知识图谱:概念与技术》(合著&a…...
Linux云计算 |【第一阶段】SERVICES-DAY4
主要内容: DHCP概述、PXE批量装机、配置PXE引导、Kickstart自动应答、Cobbler装机平台 一、DHCP服务概述及原理 DHCP动态主机配置协议(Dynamic Host Configuration Protocol),由IETF(Internet网络工程师任务小组&…...
微信小程序 button样式设置为图片的方法
微信小程序 button样式设置为图片的方法 background-image background-size与background-repeat与border:none;是button必须的 <view style" position: relative;"><button class"customer-service-btn" style"background-image: url(./st…...
2024 HNCTF PWN(hide_flag Rand_file_dockerfile Appetizers TTOCrv_)
文章目录 参考hide_flag思路exp Rand_file_dockerfile libc 2.31思路exp Appetizers glibc 2.35绕过关闭标准输出实例客户端 关闭标准输出服务端结果exp TTOCrv_🎲 glibc 2.35逆向DT_DEBUG获得各个库地址随机数思路exp 参考 https://docs.qq.com/doc/p/641e8742c39…...
<6>-MySQL表的增删查改
目录 一,create(创建表) 二,retrieve(查询表) 1,select列 2,where条件 三,update(更新表) 四,delete(删除表…...
技术栈RabbitMq的介绍和使用
目录 1. 什么是消息队列?2. 消息队列的优点3. RabbitMQ 消息队列概述4. RabbitMQ 安装5. Exchange 四种类型5.1 direct 精准匹配5.2 fanout 广播5.3 topic 正则匹配 6. RabbitMQ 队列模式6.1 简单队列模式6.2 工作队列模式6.3 发布/订阅模式6.4 路由模式6.5 主题模式…...
【笔记】WSL 中 Rust 安装与测试完整记录
#工作记录 WSL 中 Rust 安装与测试完整记录 1. 运行环境 系统:Ubuntu 24.04 LTS (WSL2)架构:x86_64 (GNU/Linux)Rust 版本:rustc 1.87.0 (2025-05-09)Cargo 版本:cargo 1.87.0 (2025-05-06) 2. 安装 Rust 2.1 使用 Rust 官方安…...
Kafka入门-生产者
生产者 生产者发送流程: 延迟时间为0ms时,也就意味着每当有数据就会直接发送 异步发送API 异步发送和同步发送的不同在于:异步发送不需要等待结果,同步发送必须等待结果才能进行下一步发送。 普通异步发送 首先导入所需的k…...
rknn toolkit2搭建和推理
安装Miniconda Miniconda - Anaconda Miniconda 选择一个 新的 版本 ,不用和RKNN的python版本保持一致 使用 ./xxx.sh进行安装 下面配置一下载源 # 清华大学源(最常用) conda config --add channels https://mirrors.tuna.tsinghua.edu.cn…...
【深度学习新浪潮】什么是credit assignment problem?
Credit Assignment Problem(信用分配问题) 是机器学习,尤其是强化学习(RL)中的核心挑战之一,指的是如何将最终的奖励或惩罚准确地分配给导致该结果的各个中间动作或决策。在序列决策任务中,智能体执行一系列动作后获得一个最终奖励,但每个动作对最终结果的贡献程度往往…...
客户案例 | 短视频点播企业海外视频加速与成本优化:MediaPackage+Cloudfront 技术重构实践
01技术背景与业务挑战 某短视频点播企业深耕国内用户市场,但其后台应用系统部署于东南亚印尼 IDC 机房。 随着业务规模扩大,传统架构已较难满足当前企业发展的需求,企业面临着三重挑战: ① 业务:国内用户访问海外服…...
Redis上篇--知识点总结
Redis上篇–解析 本文大部分知识整理自网上,在正文结束后都会附上参考地址。如果想要深入或者详细学习可以通过文末链接跳转学习。 1. 基本介绍 Redis 是一个开源的、高性能的 内存键值数据库,Redis 的键值对中的 key 就是字符串对象,而 val…...
标注工具核心架构分析——主窗口的图像显示
🏗️ 标注工具核心架构分析 📋 系统概述 主要有两个核心类,采用经典的 Scene-View 架构模式: 🎯 核心类结构 1. AnnotationScene (QGraphicsScene子类) 主要负责标注场景的管理和交互 🔧 关键函数&…...
构建Docker镜像的Dockerfile文件详解
文章目录 前言Dockerfile 案例docker build1. 基本构建2. 指定 Dockerfile 路径3. 设置构建时变量4. 不使用缓存5. 删除中间容器6. 拉取最新基础镜像7. 静默输出完整示例 docker runDockerFile 入门syntax指定构造器FROM基础镜像RUN命令注释COPY复制ENV设置环境变量EXPOSE暴露端…...
