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的源码浅要剖析Python的内存管理
Apr 16 Python
使用Python编写一个简单的tic-tac-toe游戏的教程
Apr 16 Python
python传递参数方式小结
Apr 17 Python
利用python发送和接收邮件
Sep 27 Python
详解用python自制微信机器人,定时发送天气预报
Mar 25 Python
python接口自动化测试之接口数据依赖的实现方法
Apr 26 Python
python操作文件的参数整理
Jun 11 Python
Python音频操作工具PyAudio上手教程详解
Jun 26 Python
Python接口开发实现步骤详解
Apr 26 Python
python代码如何注释
Jun 01 Python
Python3实现英文字母转换哥特式字体实例代码
Sep 01 Python
全网最细 Python 格式化输出用法讲解(推荐)
Jan 18 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.ini中文版(1)
2006/10/09 PHP
php数组函数序列之array_splice() - 在数组任意位置插入元素
2011/11/07 PHP
Ajax+PHP快速上手及简单应用说明
2013/07/24 PHP
使用phpstorm和xdebug实现远程调试的方法
2015/12/29 PHP
php自定义函数实现JS的escape的方法示例
2016/07/07 PHP
解决FLASH需要点击激活的代码
2006/12/20 Javascript
使用javascript:将其它类型值转换成布尔类型值的解决方法详解
2013/05/07 Javascript
jQuery中Form相关知识汇总
2015/01/06 Javascript
jquery获取及设置outerhtml的方法
2015/03/09 Javascript
学习javascript面向对象 理解javascript对象
2016/01/04 Javascript
javascript学习指南之回调问题
2016/04/23 Javascript
AngularJS入门教程之ng-checked 指令详解
2016/08/01 Javascript
input 禁止输入特殊字符的四种实现方式
2016/08/24 Javascript
解决Vue2.0自带浏览器里无法打开的原因(兼容处理)
2017/07/28 Javascript
JavaScript实现旋转轮播图
2020/08/18 Javascript
基于JS实现带动画效果的流程进度条
2018/06/01 Javascript
vue 1.0 结合animate.css定义动画效果
2018/07/11 Javascript
原生JS封装_new函数实现new关键字的功能
2018/08/12 Javascript
微信小程序实现卡片层叠滑动效果
2019/06/21 Javascript
Js通过AES加密后PHP用Openssl解密的方法
2019/07/12 Javascript
layui富文本编辑器前端无法取值的解决方法
2019/09/18 Javascript
layui实现下拉复选功能的例子(包括数据的回显与上传)
2019/09/24 Javascript
vue结合el-upload实现腾讯云视频上传功能
2020/07/01 Javascript
10款最好的Web开发的 Python 框架
2015/03/18 Python
requests和lxml实现爬虫的方法
2017/06/11 Python
Python读取txt某几列绘图的方法
2018/10/14 Python
python 划分数据集为训练集和测试集的方法
2018/12/11 Python
flask利用flask-wtf验证上传的文件的方法
2020/01/17 Python
python程序需要编译吗
2020/06/19 Python
Amcal中文官网:澳洲综合性连锁药房
2019/03/28 全球购物
自然健康的概念:Natural Healthy Concepts
2020/01/26 全球购物
汽车电子与维修专业大学生求职信
2013/09/28 职场文书
遗嘱继承公证书
2014/04/09 职场文书
内勤岗位职责范本
2015/04/13 职场文书
观后感的写法
2015/06/19 职场文书
JS不要再到处使用绝对等于运算符了
2021/04/30 Javascript