前段时间有位朋友问到了一个Excel中的VBA脚本的问题,大致需求是批量给不同的人发不同内容的邮件,但是那个VBA脚本有些问题一直无法运行起来。本着钻研的精神看看是否能够debug,看了之后决定放弃= =VBA也太难了吧,但是大致的实现原理还是可以搞明白的,于是乎打算用Python重构一下。
需求大致是业务人员在Excel表格中填入邮件的title,收件人,正文内容,附件的本地路径,然后实现一键发送给不同的收件人
我们先来看一下这个Excel表格长什么样:
那么我们用Python如何去实现这个需求呢?其实原理也比较简单:构建好邮件的头部信息,收件人,发件人,发送的内容,上传附件,调用发送功能即可。
话不多说,我们上代码。
这里需要用到以下几个Python库:
import smtplibfrom email.mime.text import MIMETextfrom email.mime.multipart import MIMEMultipartfrom email.mime.application import MIMEApplicationimport pandas as pd
smtplib与email这两个是Python自带的两个库,非常好用;而pandas库是用于打开Excel表格处理表格数据的,如果没有安装pandas的话,记得在终端键入:
pip install pandas
第一步我们需要构建一个第三方的邮件服务器,包含你自己的邮件地址、邮箱密码或者授权码(关于如何获取邮箱授权码请自行百度)、第三方邮件STMP服务地址:
# 邮件地址
FROMADDR = '417xxx@163.com'# 邮箱密码或授权码
PASSWORD = 'xxxxx'# 第三方邮件STMP服务地址
STMPADDR = 'smtp.163.com'
这里我们使用163的邮件服务,这个看需求,如果是QQ邮箱的话,就用QQ的STMP地址
脚本核心部分,我们实现两种不同的功能:
1.群发邮件,就是所有人都收到同样的内容
2.批量发送功能,每个人收到的内容都不一样
首先我们实现第一种功能:
def Mass_Email():"""
群发邮件脚本
需要手动配置:
1.群发的收件邮箱地址
2.邮件头
3.正文内容
4.附件地址
:return:
"""# 收件人列表
TOADDR = ['xxx@qq.com', '123@qq.com']# 头部信息
title = '6月大促商品清单'# 创建正文文本内容
content = '(测试)你好呀,这是2020年6月的大促清单。'
textApart = MIMEText(content)# 创建附件
filepath = './测试一下.csv'
fileApart = MIMEApplication(open(filepath, 'rb').read())
fileApart.add_header('Content-Disposition', 'attachment', filename=filepath)# 创建邮件对象并插入正文与附件
objMail = MIMEMultipart()
objMail.attach(textApart)
objMail.attach(fileApart)
objMail['Subject'] = titletry:
server = smtplib.SMTP(STMPADDR)
server.login(FROMADDR, PASSWORD)
server.sendmail(FROMADDR, TOADDR, objMail.as_string())
print('发送成功')
server.quit()except smtplib.SMTPException as e:# 打印错误日志
print(f'错误信息:{e}')
这个功能实现起来比较简单:
首先构建好收件人的地址,因为存在多个,这里我们使用列表来表示;
其次构建邮件标题、正文内容以及附件,附件内容需要预读取后加入到对象中。
然后我们创建邮件对象并插入正文与附件;
最后我们启用smtplib模块来替我们完成群发邮件的操作,这里使用try..except来捕获异常,如果成功则打印发送成功,如果失败则返回错误日志。
这样一个简单的群发功能就完成了,接下来我们实现第二个功能:批量发送邮件:
df = pd.read_excel('./批量发送邮件的内容.xlsx')# 获取邮件内容,包含头部、正文、附件
TOADDRLIST = df['toaddr']
contentLst = df['content']
titleList = df['title']
filepathList = df['filepath']
首先我们需要使用pandas来读取Excel表格,以Dataframe的方式获取到我们所需要的收件人、正文、附件地址等数据
然后最关键的部分来了,我们需要在一个大的for循环中,去循环读取每一行数据,并发送一次邮件,当循环完成后,我们的批量发送任务也就完成了
# 这里使用zip函数同时进行循环读取,注意每列的数据要一致,不允许有空行,否则会自动忽略!for i, j, k, l in zip(TOADDRLIST, contentLst, titleList, filepathList):
toaddr = [i]
content = j
textApart = MIMEText(content)
title = k
filepath = l
fileApart = MIMEApplication(open(filepath, 'rb').read())
fileApart.add_header('Content-Disposition', 'attachment', filename=filepath)
objMail = MIMEMultipart()
objMail.attach(textApart)
objMail.attach(fileApart)
objMail['Subject'] = titletry:
server = smtplib.SMTP(STMPADDR)
server.login(FROMADDR, PASSWORD)
server.sendmail(FROMADDR, toaddr, objMail.as_string())
print(f'发送成功至:{toaddr}')
server.quit()except smtplib.SMTPException as e:# 打印错误日志
print(f'错误信息:{e}')
这里注意一下,我使用了zip函数去同时循环多个列表,注意每个列表的长度要一致,也就是Excel表格中每一列的长度要一样,不要出现部分单元格为空的情况,否则在循环的过程中程序会自动忽略掉部分数据,导致数据缺失。
最后我们调用函数来实现发送功能,需要用到那个就将哪个函数的注释去掉。
if __name__ == '__main__':# 群发邮件入口# Mass_Email()# 批量逐个发送邮件入口
Bulk_mail()
完整代码如下:
import smtplibfrom email.mime.text import MIMETextfrom email.mime.multipart import MIMEMultipartfrom email.mime.application import MIMEApplicationimport pandas as pd####################################################################################### 构建公共头部,需要自行定义发件人信息,以及第三方的STMP服务器地址# 邮件地址
FROMADDR = '417xxx@163.com'# 邮箱密码或授权码
PASSWORD = 'xxxxx'# 第三方邮件STMP服务地址
STMPADDR = 'smtp.163.com'######################################################################################def Mass_Email():"""
群发邮件脚本
需要手动配置:
1.群发的收件邮箱地址
2.邮件头
3.正文内容
4.附件地址
:return:
"""# 收件人列表
TOADDR = ['xxx@qq.com', '123@qq.com']# 头部信息
title = '6月大促商品清单'# 创建正文文本内容
content = '(测试)你好呀,这是2020年6月的大促清单。'
textApart = MIMEText(content)# 创建附件
filepath = './测试一下.csv'
fileApart = MIMEApplication(open(filepath, 'rb').read())
fileApart.add_header('Content-Disposition', 'attachment', filename=filepath)# 创建邮件对象并插入正文与附件
objMail = MIMEMultipart()
objMail.attach(textApart)
objMail.attach(fileApart)
objMail['Subject'] = titletry:
server = smtplib.SMTP(STMPADDR)
server.login(FROMADDR, PASSWORD)
server.sendmail(FROMADDR, TOADDR, objMail.as_string())
print('发送成功')
server.quit()except smtplib.SMTPException as e:# 打印错误日志
print(f'错误信息:{e}')def Bulk_mail():"""
批量发送邮件脚本
需要配置:
1.需要批量发送的内容,Excel表格,其中数据源需要确定好格式,可以查看附件【批量发送邮件的内容】
2.原始数据由pandas Dataframe读取
:return:
"""
df = pd.read_excel('./批量发送邮件的内容.xlsx')# 获取邮件内容,包含头部、正文、附件
TOADDRLIST = df['toaddr']
contentLst = df['content']
titleList = df['title']
filepathList = df['filepath']# 这里使用zip函数同时进行循环读取,注意每列的数据要一致,不允许有空行,否则会自动忽略!for i, j, k, l in zip(TOADDRLIST, contentLst, titleList, filepathList):
toaddr = [i]
content = j
textApart = MIMEText(content)
title = k
filepath = l
fileApart = MIMEApplication(open(filepath, 'rb').read())
fileApart.add_header('Content-Disposition', 'attachment', filename=filepath)
objMail = MIMEMultipart()
objMail.attach(textApart)
objMail.attach(fileApart)
objMail['Subject'] = titletry:
server = smtplib.SMTP(STMPADDR)
server.login(FROMADDR, PASSWORD)
server.sendmail(FROMADDR, toaddr, objMail.as_string())
print(f'发送成功至:{toaddr}')
server.quit()except smtplib.SMTPException as e:# 打印错误日志
print(f'错误信息:{e}')if __name__ == '__main__':# 群发邮件入口# Mass_Email()# 批量逐个发送邮件入口
Bulk_mail()
其实有了思路之后,实现起来还是非常简单的,这不马上618大促了嘛,一些小伙伴会有批量发送邮件进行促销的需求,那么如果没有专业的第三方后台来进行批量发送的话,这个程序应该能解决你的问题。