Python 调用 Outlook 发送邮件过程解析


Posted in Python onAugust 08, 2019

微软 Office 提供基于 COM 接口的编程。Python 通过 pywin32 可以方便地调用各组件。如果下载和安装 pywin32 有困难,可以到 Sourceforge 的镜像网摘查找合适的版本。

单一账号

import win32com.client as win32
def send_mail():
  outlook = win32.Dispatch('Outlook.Application')
  mail_item = outlook.CreateItem(0) # 0: olMailItem
  mail_item.Recipients.Add('someone@qq.com')
  mail_item.Subject = 'Mail Test'
  mail_item.BodyFormat = 2     # 2: Html format
  mail_item.HTMLBody = '''
    <H2>Hello, This is a test mail.</H2>
    Hello Guys. 
    '''
  mail_item.Send()
if __name__ == '__main__':
  send_mail()

多账号发送邮件

如果 Outlook 有多个账号,需要选择账号发送邮件,需要在代码中对账号进行判断,代码如下:

def send_mail():
  outlook_app = win32.Dispatch('Outlook.Application')
  # choose sender account
  send_account = None
  for account in outlook_app.Session.Accounts:
    if account.DisplayName == 'sender@hotmail.com':
      send_account = account
      break
  mail_item = outlook_app.CreateItem(0)  # 0: olMailItem
  # mail_item.SendUsingAccount = send_account not working
  # the following statement performs the function instead
  mail_item._oleobj_.Invoke(*(64209, 0, 8, 0, send_account))
  mail_item.Recipients.Add('receipient@qq.com')
  mail_item.Subject = 'Test sending using particular account'
  mail_item.BodyFormat = 2  # 2: Html format
  mail_item.HTMLBody = '''
    <H2>Hello, This is a test mail.</H2>
    Hello Guys. 
    '''
  mail_item.Send()
if __name__ == '__main__':
  send_mail()

这里有点黑魔法,直接设置 mail_item.SendUsingAccount 不会起作用,返回值是 None, 永远从第一个邮箱账号发送邮件,我使用的是 Office 365 版。需要调用 _oleobj_.Invoke() 方法。后面列出了参考链接。

本质上,这种方法是调用 COM 组件,可以查询微软的开发帮助了解相关对象的属性和方法,比如我想知道 Account 的细节,就特意参考了下面这篇帮助:https://docs.microsoft.com/zh-cn/office/vba/api/outlook.account 。COM 编程与语言无关。另外可以在 Outlook 中 ALT + F11,进入 VBE 环境,然后 F2 进入对象浏览器界面查看比如下面的界面显示了 Account 的属性和方法:

Python 调用 Outlook 发送邮件过程解析

关于调试

python 作为动态语言,通过 Debug 获取 COM 对象信息并不是很方便,比如下面代码:

import win32com.client as win32
def print_outlook_accounts():
  outlook_app = win32.Dispatch('Outlook.Application')
  for account in outlook_app.Session.Accounts:
    print (account.DeliveryStore.DisplayName)
if __name__ == '__main__':
  send_mail()

设置断点的调试界面:

Python 调用 Outlook 发送邮件过程解析

我们只知道 account 是一个 COM Object,account 包含的信息很多都是 unknown 的。碰到这种情况,我一般用 C# 或者 VBA 编写代码进行调试。如果我需要详细了解 account 的属性和方法,在 Office 的任何组件中,比如 Excel,写一段下面的代码:

Public Sub Print_Outlook_Accounts()
  ' 工具 -> 引用:添加 Microsoft Outook Object Library 引用  
  Dim outlookApp As New Outlook.Application
  Dim accounts As Outlook.accounts  
  Set accounts = outlookApp.Session.accounts  
  Dim account As Outlook.account
  For Each account In accounts
    Debug.Print account.DisplayName
  Next
End Sub

显示出监视窗口,设置断点,获取 accounts 信息:

Python 调用 Outlook 发送邮件过程解析

在监视窗口添加变量 accounts:

Python 调用 Outlook 发送邮件过程解析

展开:

Python 调用 Outlook 发送邮件过程解析

Item 1 和 Item 2 表示有两个账号,现在我们想看到 Item 2 的账号信息,将 Item 2 展开:

Python 调用 Outlook 发送邮件过程解析

DeliveryStore 属性也包含 account 的信息,可以展开查看。

参考

SendUsingAccount Does Not Work in Outlook 2010, possible bug?

python win32com outlook 2013 SendUsingAccount return exception

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

Python 相关文章推荐
Python完全新手教程
Feb 08 Python
python判断端口是否打开的实现代码
Feb 10 Python
python多线程编程方式分析示例详解
Dec 06 Python
Python实现的爬取网易动态评论操作示例
Jun 06 Python
Python标准库shutil用法实例详解
Aug 13 Python
linux安装Python3.4.2的操作方法
Sep 28 Python
11个Python3字典内置方法大全与示例汇总
May 13 Python
python中bytes和str类型的区别
Oct 21 Python
Python字符串、列表、元组、字典、集合的补充实例详解
Dec 20 Python
Tensorflow读取并输出已保存模型的权重数值方式
Jan 04 Python
解决Django no such table: django_session的问题
Apr 07 Python
Python编写memcached启动脚本代码实例
Aug 14 Python
python判断自身是否正在运行的方法
Aug 08 #Python
Python 日期区间处理 (本周本月上周上月...)
Aug 08 #Python
python各类经纬度转换的实例代码
Aug 08 #Python
Python3.0 实现决策树算法的流程
Aug 08 #Python
Python使用ffmpy将amr格式的音频转化为mp3格式的例子
Aug 08 #Python
Django rest framework jwt的使用方法详解
Aug 08 #Python
使用Python实现文字转语音并生成wav文件的例子
Aug 08 #Python
You might like
PHP 之Section与Cookie使用总结
2012/09/14 PHP
win平台安装配置Nginx+php+mysql 环境
2016/01/12 PHP
PHP递归实现层级树状展开
2016/04/01 PHP
PHP多维数组元素操作类的方法
2016/11/14 PHP
Javascript弹出窗口的各种方法总结
2013/11/11 Javascript
IE6中链接A的href为javascript协议时不在当前页面跳转
2014/06/05 Javascript
使用JS+plupload直接批量上传图片到又拍云
2014/12/01 Javascript
jQuery制作可自定义大小的拼图游戏
2015/03/30 Javascript
简介AngularJS中使用factory和service的方法
2015/06/17 Javascript
微信页面倒计时代码(解决safari不兼容date的问题)
2016/12/13 Javascript
JS得到当前时间的方法示例
2017/03/24 Javascript
老生常谈Bootstrap媒体对象
2017/07/06 Javascript
JS中跳出循环的示例代码
2017/09/14 Javascript
详解webpack3编译兼容IE8的正确姿势
2017/12/21 Javascript
微信小程序实现自动定位功能
2018/10/31 Javascript
vue+SSM实现验证码功能
2018/12/07 Javascript
JavaScript解析机制与闭包原理实例详解
2019/03/08 Javascript
微信小程序调用天气接口并且渲染在页面过程详解
2019/06/24 Javascript
微信小程序实现3D轮播图效果(非swiper组件)
2019/09/21 Javascript
解决layui批量传值到后台操作时出现传值为空的问题
2019/09/28 Javascript
如何在Vue中使localStorage具有响应式(思想实验)
2020/07/14 Javascript
[01:03:36]Ti4 循环赛第三日DK vs Titan
2014/07/12 DOTA
[01:01]青春无憾,一战成名——DOTA2全国高校联赛开启
2018/02/25 DOTA
Python ZipFile模块详解
2013/11/01 Python
python 获取网页编码方式实现代码
2017/03/11 Python
pyQT5 实现窗体之间传值的示例
2019/06/20 Python
纯python进行矩阵的相乘运算的方法示例
2019/07/17 Python
详解python路径拼接os.path.join()函数的用法
2019/10/09 Python
Python random模块制作简易的四位数验证码
2020/02/01 Python
Python实现加密的RAR文件解压的方法(密码已知)
2020/09/11 Python
澳大利亚领先的时尚内衣零售商:Bras N Things
2020/07/28 全球购物
护士上岗前培训自我鉴定
2014/04/20 职场文书
廉政承诺书
2015/01/19 职场文书
初二数学教学反思
2016/02/17 职场文书
2019初中学生入团申请书
2019/06/27 职场文书
导游词之上海东方明珠塔
2019/09/25 职场文书