python-批量发送指定格式的邮件(含图片的html)

环境:
win10,python3,smtplib,email,pandas

2021年9月测试通过。备份。


问题描述

同事要求批量发送催款邮件。催款邮件中包含一个包含用户信息的表格,还有图片附件。表格的内容需要根据输入文件的内容生成。为了防止被ban,中间需要暂停。

实现思路

首先使用pandas读取excel中的信息,然后准备网页模板(html格式)和附件,随后将个人信息填入模板中,再发送邮件。此外使用time包设置计时器,在合适的时候暂停。

代码

# -*- coding: utf-8 -*-
'''
功能: 批量发送催款信息
环境: python3
author: xxx
date: 2021/9/15
注意:所有图片、附件、txt、xlsx等都要放在与当前程序同级的目录下
'''

import smtplib
from email.mime.text import MIMEText
from email.mime.application import MIMEApplication
from email.mime.multipart import MIMEMultipart
from email.mime.image import MIMEImage
from email.utils import formataddr
import time
import pandas as pd

 
def addimg(src, imgid):
	'''
	添加图片附件
	src: file path
	imgid: id
	'''
    fp = open(src, 'rb')
    msgImage = MIMEImage(fp.read())
    fp.close()
    msgImage.add_header('Content-ID', imgid)
    return msgImage


def read_userinfo_excel(infile):
    '''
    提取用户信息
    infile: excel文件
    '''
    result = []
    # 读取所有sheet,读取表头
    sheets = pd.read_excel(infile, sheet_name=None, header=0)
    for sheet in list(sheets.keys()):
        df = sheets[sheet]
        cols = list(df.columns) # 可能前后有空格
        df.columns = [i.strip() for i in cols]
        nrow = df.shape[0]
        for ridx in range(nrow):
            # 跳过已经收款的
            if str(df.loc[ridx, '是否收到货款']).strip() == '是': continue
            result.append("!".join([str(df.loc[ridx, '发票号']).strip(),
            					# 此处读取一些列,略
                                    ]))

    return result


def make_info_mail(name, invoiceId, date, company, billId, amount, type):
	'''
	拼接邮件内容
	'''
    raw = """
    <!DOCTYPE html>
    <html>
    <head></head>
    <body>
    <div>
    <font face="微软雅黑">
    ...
	</body>
	</html>
    """%(name, invoiceId, date, company, billId, name, amount, type)
    return raw


def send_mail(sender, receiver, cc, subject, content, imgs, attaches, my_pass):
	'''
	发送邮件
	sender: 发件邮箱
	receiver: 收件邮箱
	cc: cc, list
	subject: 主题
	content: 正文内容(html)
	imgs: 图片附件 list
	attaches: 其他附件 list
	my_pass: 发信密码
	'''
    # ret是返回值, False表示发送失败
    ret = True
    try:
        # 发送html和附件
        msg = MIMEMultipart('related')
        msg['From'] = formataddr(["", sender])
        msg['To'] = formataddr(["", receiver])
        msg['Subject'] = subject
        msg['Cc'] = ','.join(cc)
        # 填写正文内容
        msgTxt = MIMEText(content, "html", "utf-8")
        msg.attach(msgTxt)
        # 添加img
        for img in imgs:
            att = addimg(img, '<image1>')
            att["Content-Type"] = 'application/octet-stream'
            # 这里的filename可以任意写,写什么名字,邮件中显示什么名字
            att["Content-Disposition"] = 'attachment; filename=%s' % img
            msg.attach(att)
        # 添加其他附件
        for f in attaches:
            att = MIMEApplication(open(f, 'rb').read())
            att["Content-Type"] = 'application/octet-stream'
            # 这里的filename可以任意写,写什么名字,邮件中显示什么名字
            att["Content-Disposition"] = 'attachment; filename=%s' % f
            msg.attach(att)
        # 登录邮件服务器
        server = smtplib.SMTP_SSL('smtp.exmail.qq.com', 465)
        server.login(sender, my_pass)
        server.sendmail(sender, [receiver,] + cc, msg.as_string())
        server.quit()

    except Exception as e:
        print("send_mail:failed!")
        print(e)
        ret = False
    return ret


if __name__ == "__main__":
    sender = 'xxx'
    my_pass = 'xxx'
    # 抄送的地址
    cc = ['xx']
    rece = read_userinfo_excel('自动邮件格式.xlsx')
    # 这里放图片附件的文件名。图片和其他附件应存放在【本程序同级目录】中
    imgs = ["ad-pic.png"]
    # 其他附件同理
    # 依次发送
    start = time.time() # 开始计时
    for r in rece:
        # 如果没有图片和其他附件,在send_mail()参数imgs, attaches处用空列表[]填充即可
        #send_mail(sender, r, "xxx", content, [], [], my_pass)
        infos = r.split("!")
        subject = "xxx应收款项信息-" + infos[2]
        content = make_info_mail(xxxx)
        send_mail(sender, infos[5], cc, subject, content, [], [], my_pass)
        end = time.time() # 结束时间,单位:秒
        if end - start > 1200: # 已经过了20分钟,这个数值就是20x60,可以自定义
            time.sleep(7200) # 休息2h,即2x60x60
            start = time.time() # 重置开始时间

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值