Exchange Web Service(EWS) 协议

EWS是微软实现的一种客户端和服务器之间的交换信息的协议。Exchange Server提供了包括从电子邮件、会议安排、团体日程管理、任务管理、文档管理、实时会议和工作流等丰富的协作应用。

EWS基于标准的web service, 使用HTTP+XML+SOAP来传输消息的。一条 SOAP 消息就是一个普通的 XML 文档,包含下列元素:

  • 必需的 Envelope 元素,可把此 XML 文档标识为一条 SOAP 消息
  • 可选的 Header 元素,包含头部信息
  • 必需的 Body 元素,包含所有的调用和响应信息
  • 可选的 Fault 元素所发生错误的信息,提供有关在处理此消息

EWS的SOAP消息,Header中指明使用的EWS版本信息:

<s:Header><t:RequestServerVersion s:mustUnderstand="1" Version="Exchange2010_SP1"/>
</s:Header>

Body中是真正的命令信息,指明要调用的接口和使用的参数:

<s:Body><m:GetFolder><m:FolderShape><t:BaseShape>IdOnly</t:BaseShape><t:AdditionalProperties><t:FieldURI FieldURI="folder:DistinguishedFolderId"/></t:AdditionalProperties></m:FolderShape><m:FolderIds><t:DistinguishedFolderId Id="deleteditems"/></m:FolderIds></m:GetFolder>
</s:Body>

当请求成功是,响应的内容也是放在Body当中:

<s:Body><m:GetFolderResponse xmlns:m="http://schemas.microsoft.com/exchange/services/2006/messages" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:t="http://schemas.microsoft.com/exchange/services/2006/types"><m:ResponseMessages><m:GetFolderResponseMessage ResponseClass="Success"><m:ResponseCode>NoError</m:ResponseCode><m:Folders><t:Folder><t:FolderId Id="AQMkADAwATMwMAItZDAyNi05ODYxLTAwAi0wMAoALgAAA428HhUZWjFJpUSRJeFqnBwBAHQq8eP3dM1JkMChdMfyLSgAAAIBCgAAAA==" ChangeKey="AQAAABYAAAB0KvHj93TNSZDAoXTH8i0oAAB17L8t" /></t:Folder></m:Folders></m:GetFolderResponseMessage></m:ResponseMessages></m:GetFolderResponse>
</s:Body>

EWS有多个实现版本,每个版本支持的请求都描述在以下三个文件中:

  • services.wsdl : 定义了客户端和服务器之间支持的消息协议
  • Messages.xds: 定义了SOAP消息请求和响应的信息类型
  • Types.xds:定义了SOAP消息使用的数据类型

要访问EWS服务器, 可以用这三个文件自动生成soap访问接口,但是生成的接口可读性比较差,使用起来很不方便。所以在我的项目中,我直接拼装SOAP消息来构建我的请求和解析服务器的响应。

在邮箱客户端中, 主要涉及到的操作如下表所示:

folder操作 item操作
FindFolder operation CopyItem operation
GetFolder operation CreateItem operation
CreateFolder operation FindItem operation
UpdateFolder operation GetItem operation
DeleteFolder operation MoveItem operation
SyncFolderHierar operation -
- SyncFolderItems operation
- SendItem operation
- UpdateItem operation
- GetItem operation

可以看到,EWS支持对邮件folder和邮件对象的增删改查,还支持对folder和item的增量同步。这几个操作是邮箱功能的核心操作,从EWS一开始的版本就开始支持,并不存在版本兼容性的问题。

EWS对每一个folder和item对象都维护了一个changeKey,来表示对象的版本。因此,可以通过changeKey是否变化来判断folder或者item是否发生了改变。EWS为了可以方便的让客户端知道服务器有哪些对象发生了改变,对folder提供了SyncFolderHierar接口用于增量同步folder,对item提供了SyncFolderItems用于增量同步item。这两个增量同步的接口使用了SyncState用于标识同步状态, 如果服务器上的数据发生了改变, 则在响应只返回变更的对象,并将最新的SyncState下发给客户端。下面是这两个命令的具体请求和返回数据示例:

SyncFolderHierar Request

<?xml version="1.0" encoding="utf-8"?>
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"xmlns:t="http://schemas.microsoft.com/exchange/services/2006/types"><soap:Body><SyncFolderHierarchy  xmlns="http://schemas.microsoft.com/exchange/services/2006/messages"><FolderShape><t:BaseShape>AllProperties</t:BaseShape></FolderShape><SyncState>H4sIA=</SyncState></SyncFolderHierarchy></soap:Body>
</soap:Envelope>

SyncFolderHierar Response

<?xml version="1.0" encoding="utf-8" ?>
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema"><soap:Header><t:ServerVersionInfo MajorVersion="8" MinorVersion="0" MajorBuildNumber="628" MinorBuildNumber="0" xmlns:t="http://schemas.microsoft.com/exchange/services/2006/types" /></soap:Header><soap:Body><SyncFolderHierarchyResponse xmlns:m="http://schemas.microsoft.com/exchange/services/2006/messages" xmlns:t="http://schemas.microsoft.com/exchange/services/2006/types" xmlns="http://schemas.microsoft.com/exchange/services/2006/messages"><m:ResponseMessages><m:SyncFolderHierarchyResponseMessage ResponseClass="Success"><m:ResponseCode>NoError</m:ResponseCode><m:SyncState>H4sIAAA==</m:SyncState><m:IncludesLastFolderInRange>true</m:IncludesLastFolderInRange><m:Changes><t:Create><t:Folder><t:FolderId Id="AQApAHR=" ChangeKey="AQAAABY" /><t:ParentFolderId Id="AQApA=" ChangeKey="AQAAAA==" /><t:FolderClass>IPF.Note</t:FolderClass><t:DisplayName>NewFolder</t:DisplayName><t:TotalCount>0</t:TotalCount><t:ChildFolderCount>0</t:ChildFolderCount><t:UnreadCount>0</t:UnreadCount></t:Folder></t:Create></m:Changes></m:SyncFolderHierarchyResponseMessage></m:ResponseMessages></SyncFolderHierarchyResponse></soap:Body>
</soap:Envelope>

其中IncludesLastFolderInRange节点是告知是否已经返回了所有的变更信息,如果没有,则需要再用新的SyncState再请求多一次,直到IncludesLastFolderInRange节点为true。

SyncFolderItems Request

<?xml version="1.0"?>
<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/" xmlns:enc="http://schemas.xmlsoap.org/soap/encoding/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:t="http://schemas.microsoft.com/exchange/services/2006/types" xmlns:m="http://schemas.microsoft.com/exchange/services/2006/messages"><s:Header><t:RequestServerVersion s:mustUnderstand="1" Version="Exchange2010_SP1" /></s:Header><s:Body><m:SyncFolderItems><m:ItemShape><t:BaseShape>IdOnly</t:BaseShape><t:IncludeMimeContent>false</t:IncludeMimeContent><t:AdditionalProperties><t:FieldURI FieldURI="item:DateTimeSent" /></t:AdditionalProperties></m:ItemShape><m:SyncFolderId><t:FolderId Id="AQMkADAwATMwMAItZDAyNi05ODYxLTAwAi0wMAoALgAAA428HhUZWjFJpUSRJeFqnBwBAHQq8eP3dM1JkMChdMfyLSgAAAIBCQAAAA==" /></m:SyncFolderId><m:SyncState>H4sIAAAAAAAEAGNgYGcAAotqE0tHE2NTA0ddZ3NHC10TR2djXSdnJ2ddNyMnC2cnczdLU1OD2vBgveDKvOTgksSSVOfEvMSiSgYr0nW65eekpBZ5pjBYkq43LLWoODM/j8GaaK3+QMuKS4JSk1Mzy1JTQjJzU0nwrU9icYlnXnFJYl5yqncqKb71zS9K9SxJzS32zwtOLSpLLSLByXDfhgNxUW5iUTYklrgYGISA0tDwAxkOUskgCJQyAGI9kJrePXKiklGGnktdJqo+zJojw8hQovXx8feSs54TDiwsOf5JVwOkipETiBn4GJhBHG6GoCfHOrpTrngwCAFFeYEYaN1aRgYGX8cAT19HP5AiBjdTtzCQ8gAgVmVAgH9AnIvELwXiTgZMkA00zwyJb2BgYAzEBropBkZmupYWZoa6YK4BEsBwOxMDAwsDg/MDZnZn86B9BwJYpFr185nl2yrt43452fdfahanntrERWEWD</m:SyncState><m:MaxChangesReturned>20</m:MaxChangesReturned></m:SyncFolderItems></s:Body>
</s:Envelope>

SyncFolderItems Response

<?xml version="1.0"?>
<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/"><s:Header><h:ServerVersionInfo xmlns:h="http://schemas.microsoft.com/exchange/services/2006/types" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" MajorVersion="15" MinorVersion="1" MajorBuildNumber="947" MinorBuildNumber="19" Version="V2017_01_07" /></s:Header><s:Body><m:SyncFolderItemsResponse xmlns:m="http://schemas.microsoft.com/exchange/services/2006/messages" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:t="http://schemas.microsoft.com/exchange/services/2006/types"><m:ResponseMessages><m:SyncFolderItemsResponseMessage ResponseClass="Success"><m:ResponseCode>NoError</m:ResponseCode><m:SyncState>H4sIAAAAAAAEAGNgYGcAAotqE0tHE2NTA0ddZ3NHC10TR2djXSdnJ2ddNyMnC2cnczdLU1OD2vBgveDKvOTgksSSVOfEvMSiSgYr0nW65eekpBZ5pjBYkq43LLWoODM/j8GaaK3+QMuKS4JSk1Mzy1JTQjJzU0nwrU9icYlnXnFJYl5yqncqKb71zS9K9SxJzS32zwtOLSpLLSLByXDfhgNxUW5iUTYklrgYGISA0tDwAxkOUskgCJQyAGI9kJrePXKiklGGnktdJqo+zJojw8hQovXx8feSs54TDiwsOf5JVwOkipETiBn4GJhBHG6GoCfHOrpTrngwCAFFeYEYaN1aRgYGX8cAT19HP5AiBjdTtzCQ8gAgVmVAgH9AnIvELwXiTgZMkA00zwyJb2BgYAzEBropBkZmupYWZoa6YK4BEsBwOxMDAwsDg/MDZnZn86B9BwJYpFr185nlwxyDzC0CWBQuJ2YxK6W7BvHwBzCretwLausPYLZeEhJ0/EQAs8s9saBbtwNY3DZHvGH2U4oIEpUMYA58eDzI1S2AOWTZsiA3zwDm8HtNQU6uAcwRLPeCGpsCmKPcHgd9+h4QgM0hzNx7vwU9egK0YZOnkxdTAJP93qAVf1cCrXZ5X+50lwlo1VG/X8x+5hlOrauAVv2ocZJiAlq1b7fTOi2gVd+2OjEB6QhZU6elQPGoBHenGasYF2G3LAgUaSVT3HcGMNwLYd+tVs/hO1n/X9VcpR972cDBychQzMDQAADqPT+hzwMAAA==</m:SyncState><m:IncludesLastItemInRange>true</m:IncludesLastItemInRange><m:Changes><t:Create><t:MeetingRequest><t:ItemId Id="AQMkADAwATMwMAItZDAyNi05ODYxLTAwAi0wMAoARgAAA428HhUZWjFJpUSRJeFqnBwHAHQq8eP3dM1JkMChdMfyLSgAAAIBCQAAAHQq8eP3dM1JkMChdMfyLSgAAAAHQze+AAAA" ChangeKey="CwAAABYAAAB0KvHj93TNSZDAoXTH8i0oAAALvfbi" /><t:DateTimeSent>2016-09-26T04:36:53Z</t:DateTimeSent></t:MeetingRequest></t:Create><t:Update><t:MeetingRequest><t:ItemId Id="AQMkADAwATMwMAItZDAyNi05ODYxLTAwAi0wMAoARgAAA428HhUZWjFJpUSRJeFqnBwHAHQq8eP3dM1JkMChdMfyLSgAAAIBCQAAAHQq8eP3dM1JkMChdMfyLSgAAAAHQze/AAAA" ChangeKey="CwAAABYAAAB0KvHj93TNSZDAoXTH8i0oAAALvfbj" /><t:DateTimeSent>2016-09-26T04:38:57Z</t:DateTimeSent></t:MeetingRequest></t:Update><t:Delete><t:MeetingRequest><t:ItemId Id="AQMkADAwATMwMAItZDAyNi05ODYxLTAwAi0wMAoARgAAA428HhUZWjFJpUSRJeFqnBwHAHQq8eP3dM1JkMChdMfyLSgAAAIBCQAAAHQq8eP3dM1JkMChdMfyLSgAAABaRuP3AAAA&quot;" ChangeKey="CQAAABYAAAB0KvHj93TNSZDAoXTH8i0oAABaYEei" /></t:MeetingRequest></t:Delete></m:Changes></m:SyncFolderItemsResponseMessage></m:ResponseMessages></m:SyncFolderItemsResponse></s:Body>
</s:Envelope>

其中IncludesLastItemInRange节点是告知是否已经返回了所有的变更信息,如果没有,则需要再用新的SyncState再请求多一次,直到IncludesLastFolderInRange节点为true。

使用这两个同步的接口,就可以方便的获取到服务器变更的内容。
理论上,同步folder中的邮件列表,使用SyncFolderItems这个命令就足够了,在将SyncState更新到最新状态时,客户端已经同步到了folder中所有的邮件的id,之后便可以拉取所有的邮件的摘要了。但是在移动客户端中,下载所有的邮件并不是非常理智的行为,非常耗费流量和存储空间。因此在移动客户端中,初始化folder时对邮件的同步数目需要进行限制。为了解决这个问题,在移动客户端中,对邮件里列表的同步分为一下三个操作:

  • 初始化阶段:获取最新的SyncState,对这个过程中返回的所有邮件id截取最新的n个id进行邮件下载,存储。
  • 下拉更新阶段:使用当前存储的SyncState拉取到所有变化的邮件id,全部进行下载存储。
  • 加载更多阶段:用当前存储的最旧邮件的发送时间time1,使用findItem命令搜索不晚于time1时间发送的最近n封邮件邮件id,进行下载存储。

结合SyncFolderItems和findItem两个请求,就可以不需要在初始化邮件列表时中同步所有邮件,但是又可以支持加载旧邮件的需求。


Exchange Web Service(EWS) 协议同步邮件相关推荐

  1. Java:ews-java-api获取Outlook/Exchange Web Services (EWS)会议日程

    文档 https://learn.microsoft.com/zh-cn/exchange/client-developer/exchange-server-development https://g ...

  2. 通过exchange web service收发邮件

    最近做通过ews收发exchange邮件,又有不小收获,下面说下遇到的问题及解决办法 主要是用ExchangeServiceBinding来进行邮件操作 1.exchange服务器安全证书,就是用于测 ...

  3. php-ews发送邮件,node.js 基于 STMP 协议和 EWS 协议发送邮件

    本文主要介绍 node.js 发送基于 STMP 协议和 MS Exchange Web Service(EWS) 协议的邮件的方法.文中所有参考代码均以 TypeScript 编码示例. 1 基于 ...

  4. exchange无法收发邮件_Python使用POP3和SMTP协议收发邮件!

    先来了解一下收/发邮件有哪些协议: SMTP协议 SMTP(Simple Mail Transfer Protocol),即简单邮件传输协议.相当于中转站,将邮件发送到客户端. POP3协议 POP3 ...

  5. 网易闪电邮收信显示连接服务器,网易闪电邮IMAP协议同步网页邮箱收发邮件的使用技巧...

    网易闪电邮是许多网友都在使用的一款邮箱,它为用户提供了非常多有用的功能,比如:使用网易闪电邮IMAP协议,就可以让网易闪电邮同步接收与发送网页邮箱的邮件,下面,就一起来了解一下网易闪电邮IMAP协议同 ...

  6. RPC协议与Web Service

    一.引入 我们每天都在使用浏览器来上网冲浪, 在查找自己需要的资源, HTTP协议自然是我们使用的最多的 一种, 我们尽情地享受着这种信息高速路的快感,却没有试图去了解我们是如何获得这些资源的? 它是 ...

  7. 几种通讯协议的比较RMI Httpinvoker = Hessian Burlap web service

    一.综述 本文比较了RMI,Hessian,Burlap,Httpinvoker,web service等5种通讯协议的在不同的数据结构和不同数据量时的传输性能.RMI是java语言本身提供的通讯协议 ...

  8. 【分布计算环境学习笔记】9 Web Service

    作者:gnuhpc 出处:http://www.cnblogs.com/gnuhpc/ 1.概述: 在现有的各种异构平台的基础上,构筑一个通用的,与应用无关.语言无关的技术层,各种不同平台之上的应用依 ...

  9. Java RESTful Web Service实战(第2版)

    Java核心技术系列 Java RESTful Web Service实战 (第2版) 韩陆 著 图书在版编目(CIP)数据 Java RESTful Web Service实战 / 韩陆著. -2版 ...

最新文章

  1. 使用Bioconda管理生信软件(以bwa为例)
  2. 【开放书】《命令行数据科学指南(第二版)》
  3. 如何监听Canvas上滚动条的出现或隐藏
  4. Python3--批量爬取数据之调金山词霸api进行翻译
  5. java 面向对象的特性 抽象_java面向对象的四个特性
  6. s2-045 java_S2-045漏洞初步分析
  7. 实验16 编写包含多个功能子程序的中断例程
  8. Facebook升级到MySQL 8.0付出的代价
  9. 苹果充电线android头断了,苹果充电线又坏了?其实一招就能搞定!还不花1分钱......
  10. 蓝桥杯 java 组素数_第四届蓝桥杯javaC组_组素数
  11. GaMD-高斯加速分子动力学模拟中文教程
  12. 联想服务器r525维修,扩展性强易管理 联想R525 G2服务器拆解
  13. 美国专利客体适格性判断标准浅析
  14. ngx_lua arg类型_使用模式,Arg和类型微调Drupal主题
  15. 余额宝提现测试点【杭州多测师】【杭州多测师_王sir】
  16. python实现插值填充有序均匀点云空洞
  17. 数学公式快速计算方法
  18. 微信小程序开发百度云分享
  19. dede织梦批量导入关键词
  20. win10查看端口号

热门文章

  1. 微信小程序组件库——colorUI 的使用方法
  2. css 文字不规则排版,CSS3文字排版
  3. Matlab操作excel格式文件
  4. JavaScript中的数据类型判断
  5. 宠物医院小程序开发,轻松引流
  6. 2012新年寄语——感谢有您
  7. SQL Server性能优化
  8. 计算机组成二进制除法,计算机组成原理:3.4.1 定点原码 除法器
  9. 递归——兔子繁殖问题
  10. Python脚本代理设置