"需要将你的Python脚本连接到Exchange服务器?我们将告诉你一个简单的方法,通过使用一个叫做Connect Bridge的工具来实现。"
介紹
本文介绍了如何使Python连接到Exchange,即如何使用Python语言脚本从微软Exchange服务器(Exchange 2010、2013、2016、2019、Online)读取邮件。
数据传输是通过ODBC层进行的,因此从脚本方面来看,它与使用python访问Microsoft SQL Server或通过ODBC访问任何数据库完全相同。你只需使用 pyodbc模块 我们使用的是python 3.7版本和pyodbc 4.0.26版本)。实际的API集成是由一个叫做Connect Bridge的工具完成的,然后在你的Python脚本上,你就像读取数据库一样读取数据。
请注意,Connect Bridge是一种商业产品。您可以 获得免费试用 为,所以你可以免费为自己尝试这种方法。
这个 "Connect Bridge "是什么?
Connect Bridge 是一个由Connecting Software开发的集成平台。它允许你的脚本通过ODBC驱动、JDBC驱动或Web服务连接任何软件......避免了研究和学习你要连接的程序的API的需要!
在这篇文章中,我们使用Connect Bridge连接到微软Exchange,但你也可以从微软SharePoint或Salesforce或Dynamics等CRM中获取数据。而且数据传输实际上可以是双向的。也就是说,你也可以向这些系统输入数据,尽管这次我们的重点是读取数据。
我从哪里开始呢?
我们的目标是创建一个简单的Python脚本来访问Exchange服务器并从中读取电子邮件。我们假设Exchange实例已经存在。这些是你需要遵循的简单步骤。
1. 请确保您手头有Exchange的登录凭证。
2. 申请免费试用并安装Connect Bridge。
3. 安装Python for Windows ver.3.7+。3.7+.你可以使用你选择的编辑器来编写脚本。
4. 安装pyodbc模块4.0.26+。
5. 运行Connect Bridge管理工作室并。
5.1. 为Exchange添加一个账户(账户-添加账户)。为了添加账户,你应该选择连接器MGEXPlugin2010,并使用第1点中提到的证书。
5.2. 打开 "新建查询 "选项,然后打开 "连接浏览器"。找到Exchange连接器并展开它,直到看到DefaultConnection。右键单击DefaultConnection并选择Get Connection string。复制ODBC连接字符串,因为你需要它来传递给脚本。
5.3. 使用 "新建查询 "选项来测试一个可以在Exchange中访问所需内容的查询。
我们将在这里做一个查询的例子,但你应该在这里输入你在Exchange中寻找的东西。一旦你点击了 "新查询",打开左边的连接浏览器。找到Exchange连接器(MGEXPlugin2010)并打开,直到看到表选项。我们可以看到模式包含一个名为Message的 "表",所以我们可以构建我们的查询为SELECT * FROM Message WHERE CreationDate >= '2019-01-01 00:00:00' LIMIT 10; 从Exchange的电子邮件列表中选择2019年1月1日之后创建的10个条目。再次,请注意,虽然看起来我们是直接使用数据库,但事实并非如此。Connect Bridge正在访问API,然后把它当作一个数据库来呈现。一旦你有了你的查询,请复制它,因为你将需要把它传递给脚本。
手把手教你写脚本!
我们的解决方案只有一个文件。CBExchange.py完整的源代码在下面。请关注描述核心解决方案的第70-92行。关于这个脚本如何工作的完整描述如下。
#!/usr/local/bin/python3.7 # encoding: utf-8 ''' CBExchange -- query data from, write data to Exchange CBExchange is a script that allows to read Exchange mail using SQL queries via Connect Bridge's ODBC driver @author: Ana Neto @copyright: 2019 @contact: ana@connecting-software.com @deffield updated: 22.07.2019 ''' import sys import os import pyodbc from argparse import ArgumentParser from argparse import RawDescriptionHelpFormatter __all__ = [] __version__ = 0.2 __date__ = '2019-07-22' __updated__ = '2019-07-22' DEBUG = 1 TESTRUN = 0 PROFILE = 0 class CLIError(Exception): '''Generic exception to raise and log different fatal errors.''' def __init__(self, msg): super(CLIError).__init__(type(self)) self.msg = "E: %s" % msg def __str__(self): return self.msg def __unicode__(self): return self.msg def main(argv=None): # IGNORE:C0111 '''Command line options.''' if argv is None: argv = sys.argv else: sys.argv.extend(argv) program_name = os.path.basename(sys.argv[0]) program_version = "v%s" % __version__ program_build_date = str(__updated__) program_version_message = '%%(prog)s %s (%s)' % (program_version, program_build_date) program_shortdesc = __import__('__main__').__doc__.split("n")[1] program_license = '''%s Created by Ana Neto on %s. Licensed under the Apache License 2.0 http://www.apache.org/licenses/LICENSE-2.0 Distributed on an "AS IS" basis without warranties or conditions of any kind, either express or implied. USAGE ''' % (program_shortdesc, str(__date__)) try: # Setup argument parser parser = ArgumentParser(description=program_license, formatter_class=RawDescriptionHelpFormatter) parser.add_argument('connstr') parser.add_argument('query') # Process arguments args = parser.parse_args() query = args.query connstr = args.connstr conn = pyodbc.connect(connstr) cursor = conn.cursor() cursor.execute(query) while 1: row = None try: row = cursor.fetchone() except: print(sys.exc_info()[1]) break if not row: break print(row) except KeyboardInterrupt: ### handle keyboard interrupt ### return 0 except: print(sys.exc_info()[1]) #indent = len(program_name) * " " #sys.stderr.write(program_name + ": " + repr(e) + "n") #sys.stderr.write(indent + " for help use --help") return 2 if __name__ == "__main__": if TESTRUN: import doctest doctest.testmod() if PROFILE: import cProfile import pstats profile_filename = 'CBExchange_profile.txt' cProfile.run('main()', profile_filename) statsfile = open("profile_stats.txt", "wb") p = pstats.Stats(profile_filename, stream=statsfile) stats = p.strip_dirs().sort_stats('cumulative') stats.print_stats() statsfile.close() sys.exit(0) sys.exit(main())
下面说一下我们使用的变量。
- 解析器用来解析我们从命令行得到的参数。
- args拥有这些参数
- query存放着我们要运行的查询,它作为一个参数出现在
- connstr保存了作为参数的ODBC连接字符串,我们将其传递给pyodbc模块以创建ODBC连接。
- conn为ODBC连接
下面是我们的脚本在做什么
- 在第70行到78行中,目标是从命令行参数输入中获取变量connstr和query,为了简单起见,使用了pydev的argparse脚本模板。
- 在第80行,我们使用conn打开一个数据库游标。
- 在第82行,我们执行从命令行得到的SQL查询。
- 在第83到92行,我们循环浏览结果,并从光标上逐行读取。
-当cursor.fetchone返回None时,我们中断循环。
- 如果在ODBC获取过程中出现异常,我们也会中断循环,并将问题打印出来输出。
- 如果fetchone方法成功并返回一个数据行,我们将原始数据行原封不动地打印到输出。这样做是为了演示的目的,但是在现实世界中,你自然可以格式化为xml、json、csv......或者其他任何一种数据交换格式。或者你也可以简单地使用原始数据行对象在后续代码中执行自定义任务。
如何运行CBExchange.py脚本?
CBExchange.py脚本接受两个位置命令行参数:connstr和query。
我们需要从Connect Bridge管理工作室复制这些内容,如上所述(5.2点)。当你手头有了它们,打开一个命令行,cd到你保存脚本的文件夹,然后 运行你的Python脚本 将2个参数传递给它。
我还能做什么?进一步探索...
如前所述,可以建立更复杂的查询,这样你就能得到你想要的邮件。例如,如果你只想获得带有附件和特定创建日期的邮件,查询将是
SELECT * FROM Message
WHERE [HasAttachment] = true and [CreationDate] >= '2019-07-01 00:00:00';
你也可以探索可用的 "存储程序"。找到Exchange连接器(MGEXPlugin2010)并展开,直到你能看到 "存储程序 "选项。同样,这些存储程序是Connect Bridge的API集成,不是实际的数据库存储程序。但使用它们的方法和它们是一样的。
在此截图中可以看到一些可用的存储程序。
限制因素
Connect Bridge工具只适用于Windows操作系统,因为没有ODBC Linux客户端库。所以,要想使用这个工具,你需要一台Windows机器。
结论
我们已经看到了如何使用Connect Bridge集成平台在Python中访问Exchange数据,这很容易做到。现在想象一下,你在这篇文章中所看到的,在微软Dynamics CRM和微软Exchange中也是可以实现的是的,在Connect Bridge中这是可能的,而且方法也是类似的......你只需要为你想要的特定软件挑选连接器,然后就可以了。
如果你想了解目前Connect Bridge的连接器,可以去的地方是 https://www.connecting-software.com/connectors/
如果你好奇这套大礼包里有哪些最新的连接器,可以看看Connect Bridges的。 Dynamics 365 财务和运营 和 Dynamics 365业务中心 连接器,两者都建立在OData协议上。 或者看一下OPC UA连接器。是的,我知道这似乎是一个完全不同的用例....。但事实是你可以使用相同的工具访问OPC UA服务器。为了让你了解这种类型的集成会产生什么结果,请看Connect Bridge的 IIoT展示.
我们希望这篇文章对你有所帮助
这里还有一些我们在博客上讨论其他整合可能性的帖子。