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 list使用示例 list中找连续的数字
Jan 27 Python
Python使用ntplib库同步校准当地时间的方法
Jul 02 Python
python并发2之使用asyncio处理并发
Dec 21 Python
python实现装饰器、描述符
Feb 28 Python
python实现汉诺塔算法
Mar 01 Python
对python调用RPC接口的实例详解
Jan 03 Python
Python实现 版本号对比功能的实例代码
Apr 18 Python
ORM Django 终端打印 SQL 语句实现解析
Aug 09 Python
Python线程障碍对象Barrier原理详解
Dec 02 Python
Pytorch对Himmelblau函数的优化详解
Feb 29 Python
python实现IOU计算案例
Apr 12 Python
python中如何打包用户自定义模块
Sep 23 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学习之php4与php5之间会穿梭一点点感悟
2007/05/03 PHP
php数组应用之比较两个时间的相减排序
2008/08/18 PHP
WordPress中对访客评论功能的一些优化方法
2015/11/24 PHP
详解PHP处理密码的几种方式
2016/11/30 PHP
PHP模糊查询技术实例分析【附源码下载】
2019/03/07 PHP
php中对象引用和复制实例分析
2019/08/14 PHP
JS自定义功能函数实现动态添加网址参数修改网址参数值
2013/08/02 Javascript
解析JavaScript中delete操作符不能删除的对象
2013/12/03 Javascript
用box固定长宽实现图片自动轮播js代码
2014/06/09 Javascript
javascript实现获取cookie过期时间的变通方法
2014/08/14 Javascript
js获取当前时间显示在页面上并每秒刷新
2014/12/24 Javascript
javascript中apply、call和bind的使用区别
2016/04/05 Javascript
javascript实现仿百度图片的瀑布流加载效果
2016/04/20 Javascript
jQuery实现背景弹性滚动的导航效果
2016/06/01 Javascript
基于jQuery实现表格内容的筛选功能
2016/08/21 Javascript
JS+Canvas实现的俄罗斯方块游戏完整实例
2016/12/12 Javascript
jfinal与bootstrap的登出实战详解
2017/11/27 Javascript
Node.js之删除文件夹(含递归删除)代码实例
2019/09/09 Javascript
基于JS实现操作成功之后自动跳转页面
2020/09/25 Javascript
[02:05]2014DOTA2西雅图邀请赛 老队长全明星大猜想谁不服就按进显示器
2014/07/08 DOTA
[32:30]夜魇凡尔赛茶话会 第一期01:谁是卧底
2021/03/11 DOTA
python 3利用BeautifulSoup抓取div标签的方法示例
2017/05/28 Python
实践Vim配置python开发环境
2018/07/02 Python
python中count函数知识点浅析
2020/12/17 Python
html5实现微信打飞机游戏
2014/03/27 HTML / CSS
新奇的小玩意:IWOOT
2016/07/21 全球购物
Trunki英国官网:儿童坐骑式行李箱
2017/05/30 全球购物
圣诞树世界:Christmas Tree World
2019/12/10 全球购物
英国领先的高级美容和在线皮肤诊所:Face the Future
2020/06/17 全球购物
学校创先争优活动总结
2014/08/28 职场文书
预备党员学习十八届三中全会精神思想汇报
2014/09/13 职场文书
2014保险公司内勤工作总结
2014/12/16 职场文书
企业愿景口号
2015/12/25 职场文书
课改心得体会范文
2016/01/25 职场文书
血轮眼轮回眼特效 html+css
2021/03/31 HTML / CSS
一篇文章搞懂python混乱的切换操作与优雅的推导式
2021/08/23 Python