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实现面向对像的ASP程序实例
Nov 10 Python
以一个投票程序的实例来讲解Python的Django框架使用
Feb 18 Python
python判断字符串编码的简单实现方法(使用chardet)
Jul 01 Python
Python实现将文本生成二维码的方法示例
Jul 18 Python
Python读取指定日期邮件的实例
Feb 01 Python
python网络应用开发知识点浅析
May 28 Python
django-rest-swagger的优化使用方法
Aug 29 Python
python如何通过pyqt5实现进度条
Jan 20 Python
Python常用库Numpy进行矩阵运算详解
Jul 21 Python
利用Selenium添加cookie实现自动登录的示例代码(fofa)
May 08 Python
Pandas实现DataFrame的简单运算、统计与排序
Mar 31 Python
Django + Taro 前后端分离项目实现企业微信登录功能
Apr 07 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代码把全角数字转为半角数字
2007/12/10 PHP
php download.php实现代码 跳转到下载文件(response.redirect)
2009/08/26 PHP
利用PHP脚本在Linux下用md5函数加密字符串的方法
2015/06/29 PHP
smarty学习笔记之常见代码段用法总结
2016/03/19 PHP
PHP Oauth授权和本地加密实现方法
2016/08/12 PHP
PHP如何通过带尾指针的链表实现'队列'
2020/10/22 PHP
Prototype使用指南之range.js
2007/01/10 Javascript
js option删除代码集合
2008/11/12 Javascript
javascript DOM编程实例(智播客学习)
2009/11/23 Javascript
利用jquery操作select下拉列表框的代码
2010/06/04 Javascript
JavaScript中的typeof操作符用法实例
2014/04/05 Javascript
javascript实现当前页导航激活的方法
2015/02/27 Javascript
Javascript中浏览器窗口的基本操作总结
2016/08/18 Javascript
jquery validate表单验证插件
2016/09/06 Javascript
浅谈JS对html标签的属性的干预以及对CSS样式表属性的干预
2017/06/25 Javascript
Vue+SpringBoot开发V部落博客管理平台
2017/12/27 Javascript
jQuery实现可以扩展的日历
2020/12/01 jQuery
[01:11:10]2014 DOTA2华西杯精英邀请赛 5 24 iG VS VG加赛
2014/05/26 DOTA
python操作数据库之sqlite3打开数据库、删除、修改示例
2014/03/13 Python
浅析python实现scrapy定时执行爬虫
2018/03/04 Python
python中的tcp示例详解
2018/12/09 Python
关于Python中的向量相加和numpy中的向量相加效率对比
2019/08/26 Python
解决Python在导入文件时的FileNotFoundError问题
2020/04/10 Python
python用Tkinter做自己的中文代码编辑器
2020/09/07 Python
使用Python绘制台风轨迹图的示例代码
2020/09/21 Python
Django contrib auth authenticate函数源码解析
2020/11/12 Python
美国医疗用品、医疗设备和家庭保健用品商店:Medical Supply Depot
2018/07/08 全球购物
公务员年总结的自我评价
2013/10/25 职场文书
保卫钓鱼岛口号
2014/06/20 职场文书
民主生活会整改措施(党员)
2014/09/18 职场文书
运动会闭幕词
2015/01/28 职场文书
早会开场白台词大全
2015/06/01 职场文书
小学数学教师研修感悟
2015/11/18 职场文书
少儿励志名言(80句)
2019/08/14 职场文书
pandas中DataFrame重置索引的几种方法
2021/05/24 Python
用JS实现飞机大战小游戏
2021/06/09 Javascript