.net6 core Worker Service项目,使用Exchange Web Services (EWS) 分页获取电子邮件收件箱列表,邮件信息字段

news2024/11/23 19:02:26

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" //服务轮询时间,秒
  }
}

项目结构图

项目结构图

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

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

相关文章

鸿蒙开发StableDiffusion绘画应用

Stable Diffusion AI绘画 基于鸿蒙开发的Stable Diffusion应用。 Stable Diffusion Server后端代码 Stable Diffusion 鸿蒙应用代码 AI绘画 ​ 使用Axios发送post网络请求访问AI绘画服务器 api &#xff0c;支持生成图片保存到手机相册。后端服务是基于flaskStable Diffusion …

MySQL实现主从复制的步骤,包括配置读写分离的方法。—— 慧哥充电桩开源平台

下载源码 【慧哥开源充电桩平台】 https://liwenhui.blog.csdn.net/article/details/134773779?spm1001.2014.3001.5502 MySQL主从复制是一种常见的数据备份和读写分离策略。下面是实现MySQL主从复制的步骤&#xff1a; 配置主服务器&#xff08;Master&#xff09;&#xff1…

鸿蒙开发入门——ArkTS语法简介(万字简介)

ArkTS 作为鸿蒙开发的编程语言&#xff0c;我们先来一图看看这个语言&#xff0c;我们可以看到ArkTS是在TS&#xff08;TypeScript&#xff09;的基础上改造的&#xff0c;而TS又是在JS&#xff08;JavaSript&#xff09;上改造的&#xff0c;一句话总结就是ArkTS是TS的超集&a…

为 android编译 luajit库、 交叉编译

时间&#xff1a;20200719 本机环境&#xff1a;iMac2017 macOS11.4 参考: 官方的文档&#xff1a;Use the NDK with other build systems 写在前边&#xff1a;交叉编译跟普通编译类似&#xff0c;无非是利用特殊的编译器、链接器生成动态或静态库; make 本质上是按照 Make…

鸿蒙 next 5.0 版本页面跳转传参 接受参数 ,,接受的时候 要先定义接受参数的类型, 代码可以直接CV使用 [教程]

1, 先看效果 2, 先准备好两个页面 index 页面 传递参数 import router from ohos.routerEntry Component struct Index {Statelist: string[] [星期一, 星期二,星期三, 星期四,星期五]StateactiveIndex: number 0build() {Row() {Column({ space: 10 }) {ForEach(this.list,…

笔记 3 : 继续彭老师课本第 3 章的 arm 的汇编指令

&#xff08;26&#xff09; 指令 LDR &#xff1a; &#xff08;27&#xff09; STR &#xff1a; 可见&#xff0c;从语法上将&#xff0c; &#xff01; 提示编译器进行更复杂的编译&#xff0c;对应内涵更复杂的指令。 &#xff08;28&#xff09; LDR 与 STR 指令还可…

【银河麒麟服务器操作系统】java进程oom现象分析及处理建议

了解银河麒麟操作系统更多全新产品&#xff0c;请点击访问麒麟软件产品专区&#xff1a;https://product.kylinos.cn 现象描述 某服务器系统升级内核至4.19.90-25.22.v2101版本后仍会触发oom导致java进程被kill。 现象分析 oom现象分析 系统messages日志分析&#xff0c;故…

pikachu之暴力破解

1基于表单的暴力破解 随便输入然后抓包 选中添加账号密码 添加分别添加payload1&#xff0c;2&#xff0c;的字典 开始攻击 2验证码绕过on server 和基于表单的暴力破解相比&#xff0c;多了一个验证码功能 这个验证码是前端的验证码&#xff08;和前面那个一样选中添加账号密码…

计算机网络入门 -- 常用网络协议

计算机网络入门 – 常用网络协议 1.分类 1.1 模型回顾 计算机网络细分可以划为七层模型&#xff0c;分别是物理层、数据链路层、网络层、传输层、会话层、表示层和应用层。而上三层可以划为应用层中。 1.2 分类 1.2.1 应用层 为用户的应用进程提供网络通信服务&#xff0…

第一百七十三节 Java IO教程 - Java缓冲区读写

Java IO教程 - Java缓冲区读写 缓冲区读取 有两种方法从缓冲区读取数据: 绝对位置相对位置 使用四个版本重载的get()方法用于从缓冲区读取数据。 get(int index)返回给定索引处的数据。 get()从缓冲区中的当前位置返回数据&#xff0c;并将位置增加1。 get(byte [] dest…

vmware配置centos+配置静态ip联网+更换镜像

centos7配置参考【实战】VMware17虚拟机以及Centos7详细安装教程-CSDN博客 ip配置步骤&#xff1a; 先更改编辑虚拟网络编辑器中的内容 就按照还原默认设置来&#xff0c;设定后就是以上内容&#xff0c;然后一定要记住子网ip和子网掩码 接下来就是NAT设置&#xff1a; 网关…

Spring Boot集成SFTP快速入门Demo

1.什么是SFTP&#xff1f; SFTP&#xff08;SSH File Transfer Protocol&#xff0c;也称 Secret File Transfer Protocol&#xff09;&#xff0c;是一种基于SSH&#xff08;安全外壳&#xff09;的安全的文件传输协议。使用SFTP协议可以在文件传输过程中提供一种安全的加密算…

ABAP打印WORD的解决方案

客户要求按照固定格式输出到WORD模板中&#xff0c;目前OLE和DOI研究了均不太适合用于这种需求。 cl_docx_document类可以将WORD转化为XML文件&#xff0c;利用替换字符串方法将文档内容进行填充同 时不破坏WORD现有格式。 首先需要将WORD的单元格用各种预定义的字符进行填充…

Redis的AOF持久化策略(AOF的工作流程、AOF的重写流程,操作演示、注意事项等)

文章目录 缓冲AOF 策略(append only file)AOF 的工作流程AOF 缓冲区策略AOF 的重写机制重写完的AOF文件为什么可以变小&#xff1f;AOF 重写流程 缓冲AOF 策略(append only file) AOF 的核心思路是 “实时备份“&#xff0c;只要我添加了新的数据或者更新了新的数据&#xff0…

价格较低,功能最强?OpenAI 推出 GPT-4o mini,一个更小、更便宜的人工智能模型

OpenAI美东时间周四推出“GPT-4o mini”&#xff0c;入局“小而精”AI模型竞争&#xff0c;称这款新模型是“功能最强、成本偏低的模型”&#xff0c;计划今后整合图像、视频、音频到这个模型中。 OpenAI表示&#xff0c;GPT-4o mini 相较于 OpenAI 目前最先进的 AI 模型更加便…

FairGuard游戏加固入选《嘶吼2024网络安全产业图谱》

2024年7月16日&#xff0c;国内网络安全专业媒体——嘶吼安全产业研究院正式发布《嘶吼2024网络安全产业图谱》(以下简称“产业图谱”)。 本次发布的产业图谱&#xff0c;共涉及七大类别&#xff0c;127个细分领域。全面展现了网络安全产业的构成和重要组成部分&#xff0c;探…

微软发布iOS/安卓正式版Designer应用,AI修图功能助力创意设计

一、Microsoft Designer应用正式上线 AITOP100平台获悉&#xff0c;微软一直致力于为用户提供优质的创意工具&#xff0c;此次推出的Microsoft Designer应用正是其在移动端的重要布局。这款应用已正式上线iOS、Android、Windows和网页版本&#xff0c;满足不同用户的需求。微软…

Stable Diffusion 使用详解(2)---- 图生图原理,操作,参数

目录 背景 图生图原理 基本原理 1. 扩散模型基础 2. 图生图的具体流程 3. 关键技术点 4. 应用实例 CLIP 原理 1.基本概念 2. 核心特点 使用及参数 随机种子 重绘幅度 图像宽高 采样方法 1. DPM&#xff08;扩散概率模型&#xff09; 2. SDE&#xff08;随机微…

大语言模型-检索测评指标

1. MRR &#xff08;Mean Reciprocal Rank&#xff09;平均倒数排名&#xff1a; 衡量检索结果排序质量的指标。 计算方式&#xff1a; 对于每个查询&#xff0c;计算被正确检索的文档的最高排名的倒数的平均值&#xff0c;再对所有查询的平均值取均值。 意义&#xff1a; 衡量…

ChatTTS超强的真人AI语音助手下载使用教程

简介 ChatTTS是专门为对话场景设计的文本转语音模型&#xff0c;支持多人同时对话&#xff0c;适用的场景非常丰富&#xff0c;比如LLM助手对话任务&#xff0c;视频配音、声音克隆等。同时支持英文和中文两种语言。最大的模型使用了10万小时以上的中英文数据进行训练&#xf…