Python - smtplib 发送 Excel 邮件与数据展示

简介: ​上一篇文章Python - openpyxl Excel 操作示例与实践介绍了如何将数据自动转化至 Excel 并完成自定义标注,节省了大量人工操作的时间,但是后续如果需要将生成的 Excel 和数据发送邮件到指定同学就还需要一步人工操作时间即写邮件发邮件,非常的不奈斯,下面结合smtplib 库实现自定义邮件的发送,从而实现 数据 -> Excel -> 邮件发送的全自动需求。...

 一.引言

上一篇文章 Python - openpyxl Excel 操作示例与实践 介绍了如何将数据自动转化至 Excel 并完成自定义标注,节省了大量人工操作的时间,但是后续如果需要将生成的 Excel 和数据发送邮件到指定同学就还需要一步人工操作时间即写邮件发邮件,非常的不奈斯,下面结合 smtplib 库实现自定义邮件的发送,从而实现 数据 -> Excel -> 邮件发送的全自动需求。理想的效果是数据以表格的形式在邮件中展示,并且完整的 Excel 在附件中:

image.gif编辑

二.smtplib 库相关介绍

1.smtplib 库简介

smtplib - Simple Mail Transfer Protocol 即简单邮件传输协议,它是一组用于由源地址到目的地址传送邮件的规则,由它来控制信件的中转方式。python 的 smtplib 提供了一种很方便的途径发送电子邮件。它对smtp协议进行了简单的封装,发送邮件只需要几个简单参数即可实现邮件的自动发送:

import smtplib
# 初始化服务
smtpObj = smtplib.SMTP( [host [, port [, local_hostname]]] )

image.gif

host 服务器主机,一般由公司IP部门提供
port host 对应的端口号,一般情况为25
local_hostname SMTP 在你的本机上可以这样指定
# 发送邮件
SMTP.sendmail(from_addr, to_addrs, msg[, mail_options, rcpt_options])

image.gif

from_addr 邮件发送者地址
to_addrs 字符串列表,邮件发送地址
msg 要发送的信息,对应 email 类中的多种类型

2.smtplib 库常用数据类型

Type:

Text 发送文本信息
Multipart 用于发送连接多种类型的信息
Application 用于传输二进制数据
Message 用户包装 Email 信息
Image 用户传输图片
Audio 用于传输音频类数据
Video 用于传输视频类数据

SubType:

text - plain 纯文本
text - html HTML 文档
multipart - alternative HTML邮件的HTML形式和纯文本形式,相同内容使用不同形式表示
multipart - form-data 主要用于提交时包含附件
application/xhtml+xml XHTML文档
application/octet-stream 任意的二进制数据
application/pdf PDF文档
application/msword Microsoft Word文件
application/vnd.wap.xhtml+xml  wap1.0+
application/x-www-form-urlencoded 使用HTTP的POST方法提交的表单
message/rfc822 RFC 822形式
image/png PNG 图像
image/gif GIF 图像
image/jpeg JPEG 图像
video/mpeg MPEG 动画

可以通过上一篇文章提到的 openpyxl 库进行文件类型的推断,给定一个 png 图像,guess_type 方法会自动推断对应文件的 MainType 以及 Subtype:

ctype, encoding = mimetypes.guess_type('bash.png')
if ctype is None or encoding is not None:
    ctype = 'application/octet-stream'
maintype, subtype = ctype.split('/', 1)
print(maintype, subtype)

image.gif

image png

image.gif

3.初始化本地服务器 (不推荐)

local 模式下直接指定端口号即可,但是需要在本地启动服务器

smtpObj = smtplib.SMTP('localhost', 1025)
smtpObj.sendmail(sender, receivers, message.as_string())

image.gif

打开终端 terminal 执行:

python -m smtpd -n -c DebuggingServer localhost:999

image.gif

发送后会有如下提示:

image.gif编辑

但是有个问题是我们本地一般不会配置邮箱服务器或自己的账号系统,所以推荐使用下面的非 localhost 模式。

4.初始化官方服务器 (推荐👍)

常用的邮箱有 qq,163,分别对应的官方服务器网址为: smtp.qq.com 和 smtp.163.com,下面初始化 qq邮箱 发送的客户端:

smtpObj = smtplib.SMTP('smtp.qq.com', 25)
smtpObj.ehlo()
smtpObj.starttls()
# token - 需要通过qq网页获取
smtpObj.login("xxxxxxx@qq.com", "校验码")
smtpObj.sendmail(sender, receivers, message.as_string())

image.gif

使用 qq 邮箱时,client 需要 login 并验证你作为 sender 的资格,第一个参数为你的 qq邮箱地址,第二个校验码需要通过邮箱配置获取,下面看一下获取步骤:

A.进入网页版 qq 邮箱

image.gif编辑

B.选择账户选项

image.gif编辑

C.配置 Smtp

下拉账户菜单栏到如下位置,可以看到除了 SMTP 还有很多邮箱服务,开启 SMTP 服务

image.gif编辑

D.发送验证码

开启上述 SMTP 服务后会要求你发送验证信息到官方,成功发送后点击 '我已发送' 即可拿到官方发送的校验码,复制粘贴保存下来。

image.gif编辑

网易 163邮箱的配置方法和上面大同小异这里不多赘述。

三.smtplib 库常用操作

通过上面第二步操作我们已经初始化好 SMTP 的邮件服务器,邮件的常规操作大致如下:

A.写字 ✍️

B.发链接 🔗

C.发图 ⛰

D.发附件 📃

E.发表格 📚

首先初始化 QQ 邮箱服务器,然后一一实践:

smtpObj = smtplib.SMTP('smtp.qq.com', 25)
smtpObj.ehlo()
smtpObj.starttls()
# token - 需要通过qq网页获取
smtpObj.login("sender@qq.com", "token")

image.gif

1.写字 ✍️

写字主要使用 Text type 下的 plain 模式即可:

subject = 'Python SMTP 测试邮件标题'
message = MIMEText('Python 邮件发送测试...', 'plain', 'utf-8')
message['From'] = Header("BITDDD", 'utf-8')  # 发送者
message['To'] = Header("测试账户", 'utf-8')  # 接收者
message['Subject'] = Header(subject, 'utf-8')
sender = 'sender@qq.com'
receivers = ['receiver@qq.com']
smtpObj.sendmail(sender, receivers, message.as_string())

image.gif

执行后在 reveiver 对应的 qq 邮箱处收到如下信息:

image.gif编辑

2.发链接 🔗

发链接的操作其实很常见,很多验证信息,广告都是通过网页链接实现:

mail_msg = """
<p>Python 邮件发送链接测试...</p>
<p><a href="https://blog.csdn.net/BIT_666?type=blog">BITDDD</a></p>
"""
subject = 'Python SMTP 测试发送链接标题'
message = MIMEText(mail_msg, 'html', 'utf-8')
message['From'] = Header("BITDDD", 'utf-8')
message['To'] = Header("测试账户", 'utf-8')
message['Subject'] = Header(subject, 'utf-8')
smtpObj.sendmail(sender, receivers, message.as_string())

image.gif

发送后如下,可以修改 mail_msg 里 >BITDDD< 的内容作为链接的中文描述,例如恭喜你中奖了之类的,这样有同学就会误点这个链接了~

image.gif编辑

3.发图

image.gif编辑image.gif编辑

msgAlternative = MIMEMultipart('alternative')
msgRoot.attach(msgAlternative)
mail_msg = """
<p>Python 邮件发送图片测试...</p>
<p>图片演示:</p>
<p><img src="cid:image1"></p>
<p>图片演示:</p>
<p><img src="cid:image2"></p>
"""
msgAlternative.attach(MIMEText(mail_msg, 'html', 'utf-8'))
# 指定图片为当前目录
fp = open('A.jpg', 'rb')
msgImage = MIMEImage(fp.read())
fp.close()
# 定义图片 ID,在 HTML 文本中引用
msgImage.add_header('Content-ID', '<image1>')
msgRoot.attach(msgImage)
# 指定图片为当前目录
fp = open('B.png', 'rb')
msgImage2 = MIMEImage(fp.read())
fp.close()
# 定义图片 ID,在 HTML 文本中引用
msgImage2.add_header('Content-ID', '<image2>')
msgRoot.attach(msgImage2)
smtpObj.sendmail(sender, receivers, msgRoot.as_string())

image.gif

这里采用 MIMEMultipart 添加两幅图片, 如果需要继续添加,修改 mail_msg 里的信息,并在后面 attach 相关图片的二进制信息即可:

image.gif编辑

4.发附件 📃

发邮件很多时候需要附带 word、excel、txt 等文件信息,下述示例将添加两个附件并发送,如果有更多附件也可以模仿累加即可, Content-Disposition 里的 filename 对应该文件在邮件中展示的名字:

message = MIMEMultipart()
message['From'] = Header("BITDDD", 'utf-8')
message['To'] = Header("测试账户", 'utf-8')
subject = 'Python SMTP 邮件附件测试'
message['Subject'] = Header(subject, 'utf-8')
#构造附件1,传送当前目录下的 test.txt 文件
att1 = MIMEText(open('test1.txt', 'rb').read(), 'base64', 'utf-8')
att1["Content-Type"] = 'application/octet-stream'
att1["Content-Disposition"] = 'attachment; filename="test1.txt"'
message.attach(att1)
# 构造附件2,传送当前目录下的 runoob.txt 文件
att2 = MIMEText(open('test2.txt', 'rb').read(), 'base64', 'utf-8')
att2["Content-Type"] = 'application/octet-stream'
att2["Content-Disposition"] = 'attachment; filename="test2.txt"'
message.attach(att2)
smtpObj.sendmail(sender, receivers, message.as_string())
print("邮件发送成功")

image.gif

执行后获得如下邮件:

image.gif编辑

5.发表格 📚

表格为上一篇文章得到的自定义数据报表:

image.gif编辑

msgRoot = MIMEMultipart('mixed')
msgRoot['From'] = Header("BITDDD", 'utf-8')  # 发送者
msgRoot['To'] = Header("测试账户", 'utf-8')  # 接收者
subject = 'Python SMTP 邮件表格测试'
msgRoot['Subject'] = Header(subject, 'utf-8')
df = pd.read_excel("test123.xlsx")
# 添加表格
html_msg = get_html_msg(df.to_html(escape=False))
content_html = MIMEText(html_msg, "html", "utf-8")
msgRoot.attach(content_html)
smtpObj.sendmail(sender, receivers, msgRoot.as_string())

image.gif

通过 DataFrame 的 to_html 方法获取其对应的 HTML 格式,并添加到 Text - html 类下,执行后收到如下邮件:

image.gif编辑

Tips:

get_html_msg 函数如下,内置了生成 html-table 的标准语法,如果需要添加多个表格,可以增加多个 head 和 body 标注表格类型,从而展示多张数据表:

def get_html_msg(df_html):
    head = \
        """
        <head>
            <meta charset="utf-8">
            <STYLE TYPE="text/css" MEDIA=screen>
                table.dataframe {
                    border-collapse: collapse;
                    border: 2px solid #a19da2;
                    /*居中显示整个表格*/
                    margin: auto;
                }
                table.dataframe thead {
                    border: 2px solid #91c6e1;
                    background: #f1f1f1;
                    padding: 10px 10px 10px 10px;
                    color: #333333;
                }
                table.dataframe tbody {
                    border: 2px solid #91c6e1;
                    padding: 10px 10px 10px 10px;
                }
                table.dataframe tr {
                }
                table.dataframe th {
                    vertical-align: top;
                    font-size: 14px;
                    padding: 10px 10px 10px 10px;
                    color: #105de3;
                    font-family: arial;
                    text-align: center;
                }
                table.dataframe td {
                    text-align: center;
                    padding: 10px 10px 10px 10px;
                }
                body {
                    font-family: 宋体;
                }
                h1 {
                    color: #5db446
                }
                div.header h2 {
                    color: #0002e3;
                    font-family: 黑体;
                }
                div.content h2 {
                    text-align: center;
                    font-size: 28px;
                    text-shadow: 2px 2px 1px #de4040;
                    color: #fff;
                    font-weight: bold;
                    background-color: #008eb7;
                    line-height: 1.5;
                    margin: 20px 0;
                    box-shadow: 10px 10px 5px #888888;
                    border-radius: 5px;
                }
                h3 {
                    font-size: 22px;
                    background-color: rgba(0, 2, 227, 0.71);
                    text-shadow: 2px 2px 1px #de4040;
                    color: rgba(239, 241, 234, 0.99);
                    line-height: 1.5;
                }
                h4 {
                    color: #e10092;
                    font-family: 楷体;
                    font-size: 20px;
                    text-align: center;
                }
                td img {
                    /*width: 60px;*/
                    max-width: 300px;
                    max-height: 300px;
                }
            </STYLE>
        </head>
        """
    body = \
        """
        <body>
        <div align="center" class="header">
            <!--标题部分的信息-->
            <!-- <h1 align="center">我的python邮件,使用了Dataframe转为table </h1> -->
        </div>
        <hr>
        <div class="content">
            <!--正文内容-->
            <h2>第一个Dataframe</h2>
            <div>
                <h4></h4>
                {df_html}
            </div>
            <hr>
            <p style="text-align: center">
               <!-- —— 本次报告完 —— -->
            </p>
        </div>
        </body>
        """.format(df_html=df_html)
    html_msg = "<html>" + head + body + "</html>"
    fout = open('table.html', 'w', encoding='UTF-8', newline='')
    fout.write(html_msg)
    return html_msg

image.gif

四.smtplib 实践

上一篇文章通过 openpyxl 库实现了原始数据到 Excel 的转化:

image.gif编辑

下面结合 smtplib 库实现 Excel 到邮件的转化:

image.gif编辑

这里先分析下需要做哪些事情:

A.添加邮件图片 ①

B.添加 DataFrame ②

C.添加对应 DataFrame 的 Excel 附件 ③

完整代码:

#!/usr/bin/python
# -*- coding: UTF-8 -*-
import smtplib
from email.mime.image import MIMEImage
from email.mime.multipart import MIMEMultipart
from email.mime.text import MIMEText
from email.header import Header
import pandas as pd
import numpy as np
from openpyxl.packaging.manifest import mimetypes
# 发送者邮箱
sender = 'sender@qq.com'
receivers = ['receiver@qq.com']
# ===============================设置邮件标题==============================
fromTitle = "BITDDD"
receiverTitle = "测试账户"
msgRoot = MIMEMultipart('mixed')
msgRoot['From'] = Header(fromTitle, 'utf-8')  # 发送者
msgRoot['To'] = Header(receiverTitle, 'utf-8')  # 接收者
# 邮件主题
subject = 'Python SMTP 邮件测试 By BITDDD'
msgRoot['Subject'] = Header(subject, 'utf-8')
# ===============================连接服务器==============================
smtpObj = smtplib.SMTP('smtp.qq.com', 25)
smtpObj.ehlo()
smtpObj.starttls()
smtpObj.login("sender@qq.com", "token")
# ===============================添加图片==============================
fp = open('excel.jpg', 'rb')
msgAlternative = MIMEMultipart('alternative')
mail_msg = """
<p>Python 邮件发送测试...</p>
<p>图片演示:</p>
<p><img src="cid:image1"></p>
"""
msgAlternative.attach(MIMEText(mail_msg, 'html', 'utf-8'))
# 指定图片为当前目录
msgImage = MIMEImage(fp.read(), subtype)
msgImage.add_header('Content-ID', '<image1>')
fp.close()
msgAlternative.attach(msgImage)
msgRoot.attach(msgAlternative)
# ===============================添加df==============================
df = pd.read_excel("test123.xlsx")
# 添加表格
html_msg = get_html_msg(df.to_html(escape=False))
content_html = MIMEText(html_msg, "html", "utf-8")
msgRoot.attach(content_html)
# =============================添加附件===============================
attachCsv = MIMEText(open(savePath, 'rb').read(), 'base64', 'utf-8')
attachCsv["Content-Type"] = 'application/octet-stream'
attachCsv["Content-Disposition"] = 'attachment; filename="test.xlsx"'
msgRoot.attach(attachCsv)
smtpObj.sendmail(sender, receivers, msgRoot.as_string())

image.gif

这里补充一下添加混合类型 MIMEMultipart 时的几种模式:

mixed 混合类型
related 内嵌资源如附件
alternative 文本与超文本

上述示例同时使用了 图片、附件、超文本 ,初始化可以采用 mixed 、alternative,如果使用 related ,则会解析异常,DataFrame 的数据会变成二进制 bin 文件发送到 receiver 邮箱中:

image.gif编辑

五.smtplib 抄送

除了发送邮件外,有时还需要抄送其他同学,smtplib 同样支持该操作。

A.单独发送

sender = 'xxxxA@qq.com'
receivers = ['xxxxB@qq.com']
msgRoot = MIMEMultipart('alternative')
msgRoot['From'] = Header(fromTitle, 'utf-8')  # 发送者
msgRoot['To'] = ','.join(receiverTitle)  # 接收者
# 邮件主题
subject = 'Python SMTP 邮件测试 By BITDDD'
msgRoot['Subject'] = Header(subject, 'utf-8')
smtpObj.sendmail(sender, receivers, msgRoot.as_string())

image.gif

B.设置抄送

sender = 'xxxxA@qq.com'
receivers = ['xxxxB@qq.com']
cc = ['xxxxC.com', "xxxxD.com"]
msgRoot = MIMEMultipart('alternative')
msgRoot['From'] = Header(fromTitle, 'utf-8')  # 发送者
msgRoot['To'] = ','.join(receiverTitle)  # 接收者
msgRoot['Cc'] = ','.join(cc) # 抄送者
# 邮件主题
subject = 'Python SMTP 邮件测试 By BITDDD'
msgRoot['Subject'] = Header(subject, 'utf-8')
smtpObj.sendmail(sender, receivers + cc, msgRoot.as_string())

image.gif

可以看到增加抄送总共分三步:

-> 添加抄送列表 cc

-> 将 cc 添加至 msg 中

-> sendmail 写成 reveiver + cc

image.gif编辑

六.总结

通过 openpyxl + smtplib 实现了数据到表格到邮件的转化,网页版邮箱接收会归类到 广告 或者 垃圾邮件中,需要手动找一下,不过手机上接收没有问题,非常的奈斯~

image.gif编辑


目录
相关文章
|
1天前
|
算法 Serverless 数据处理
从集思录可转债数据探秘:Python与C++实现的移动平均算法应用
本文探讨了如何利用移动平均算法分析集思录提供的可转债数据,帮助投资者把握价格趋势。通过Python和C++两种编程语言实现简单移动平均(SMA),展示了数据处理的具体方法。Python代码借助`pandas`库轻松计算5日SMA,而C++代码则通过高效的数据处理展示了SMA的计算过程。集思录平台提供了详尽且及时的可转债数据,助力投资者结合算法与社区讨论,做出更明智的投资决策。掌握这些工具和技术,有助于在复杂多变的金融市场中挖掘更多价值。
22 12
|
6天前
|
数据采集 数据安全/隐私保护 Python
从零开始:用Python爬取网站的汽车品牌和价格数据
在现代化办公室中,工程师小李和产品经理小张讨论如何获取懂车帝网站的汽车品牌和价格数据。小李提出使用Python编写爬虫,并通过亿牛云爬虫代理避免被封禁。代码实现包括设置代理、请求头、解析网页内容、多线程爬取等步骤,确保高效且稳定地抓取数据。小张表示理解并准备按照指导操作。
从零开始:用Python爬取网站的汽车品牌和价格数据
|
1月前
|
数据采集 Web App开发 数据可视化
Python用代理IP获取抖音电商达人主播数据
在当今数字化时代,电商直播成为重要的销售模式,抖音电商汇聚了众多达人主播。了解这些主播的数据对于品牌和商家至关重要。然而,直接从平台获取数据并非易事。本文介绍如何使用Python和代理IP高效抓取抖音电商达人主播的关键数据,包括主播昵称、ID、直播间链接、观看人数、点赞数和商品列表等。通过环境准备、代码实战及数据处理与可视化,最终实现定时任务自动化抓取,为企业决策提供有力支持。
|
1月前
|
数据可视化 数据挖掘 大数据
1.1 学习Python操作Excel的必要性
学习Python操作Excel在当今数据驱动的商业环境中至关重要。Python能处理大规模数据集,突破Excel行数限制;提供丰富的库实现复杂数据分析和自动化任务,显著提高效率。掌握这项技能不仅能提升个人能力,还能为企业带来价值,减少人为错误,提高决策效率。推荐从基础语法、Excel操作库开始学习,逐步进阶到数据可视化和自动化报表系统。通过实际项目巩固知识,关注新技术,为职业发展奠定坚实基础。
|
2月前
|
数据采集 存储 XML
python实战——使用代理IP批量获取手机类电商数据
本文介绍了如何使用代理IP批量获取华为荣耀Magic7 Pro手机在电商网站的商品数据,包括名称、价格、销量和用户评价等。通过Python实现自动化采集,并存储到本地文件中。使用青果网络的代理IP服务,可以提高数据采集的安全性和效率,确保数据的多样性和准确性。文中详细描述了准备工作、API鉴权、代理授权及获取接口的过程,并提供了代码示例,帮助读者快速上手。手机数据来源为京东(item.jd.com),代理IP资源来自青果网络(qg.net)。
|
2月前
|
存储 Java easyexcel
招行面试:100万级别数据的Excel,如何秒级导入到数据库?
本文由40岁老架构师尼恩撰写,分享了应对招商银行Java后端面试绝命12题的经验。文章详细介绍了如何通过系统化准备,在面试中展示强大的技术实力。针对百万级数据的Excel导入难题,尼恩推荐使用阿里巴巴开源的EasyExcel框架,并结合高性能分片读取、Disruptor队列缓冲和高并发批量写入的架构方案,实现高效的数据处理。此外,文章还提供了完整的代码示例和配置说明,帮助读者快速掌握相关技能。建议读者参考《尼恩Java面试宝典PDF》进行系统化刷题,提升面试竞争力。关注公众号【技术自由圈】可获取更多技术资源和指导。
|
2月前
|
数据采集 Web App开发 监控
Python爬虫:爱奇艺榜单数据的实时监控
Python爬虫:爱奇艺榜单数据的实时监控
|
2月前
|
机器学习/深度学习 前端开发 数据处理
利用Python将Excel快速转换成HTML
本文介绍如何使用Python将Excel文件快速转换成HTML格式,以便在网页上展示或进行进一步的数据处理。通过pandas库,你可以轻松读取Excel文件并将其转换为HTML表格,最后保存为HTML文件。文中提供了详细的代码示例和注意事项,帮助你顺利完成这一任务。
105 0
|
2月前
|
数据采集 分布式计算 大数据
构建高效的数据管道:使用Python进行ETL任务
在数据驱动的世界中,高效地处理和移动数据是至关重要的。本文将引导你通过一个实际的Python ETL(提取、转换、加载)项目,从概念到实现。我们将探索如何设计一个灵活且可扩展的数据管道,确保数据的准确性和完整性。无论你是数据工程师、分析师还是任何对数据处理感兴趣的人,这篇文章都将成为你工具箱中的宝贵资源。
|
2月前
|
安全 API 文件存储
Yagmail邮件发送库:如何用Python实现自动化邮件营销?
本文详细介绍了如何使用Yagmail库实现自动化邮件营销。Yagmail是一个简洁强大的Python库,能简化邮件发送流程,支持文本、HTML邮件及附件发送,适用于数字营销场景。文章涵盖了Yagmail的基本使用、高级功能、案例分析及最佳实践,帮助读者轻松上手。
88 4

热门文章

最新文章

推荐镜像

更多