Python 发送邮件的几种情况

本次记录一下Python发送邮件的几种情况:

1、正常发送

2、正文带图片

3、正文带表格

4、正文带附件

 

首先来看一下Python发送邮件使用到的模块

## 导入模块
from email.mime.text import MIMEText
import smtplib

先说一下email模块的mime

from email.mime.text import MIMEText    
from email.mime.image import MIMEImage
from email.mime.multipart import MIMEMultipart    

MIMEText对象:表示一个文本邮件对象;

MIMEImage对象:表示一个邮件正文图片对象;

MIMEMultipart对象:代表将个多对象组合在一起

MIMEText对象中有三个需要我们设置的参数,一个是正文内容,一个是正文内容的类型,例如:”text/plain”和”text/html”,一个是正文内容的编码

MIMEMultipart对象:三种类型型:mixed、alternative、related

(1)mixed:默认值,基本都使用这种,邮件中有附件,则必须使用该种

(2)alternative:邮件中同时存在纯文本和超文本内容

(3)related:发送html格式的邮件内容时,可能使用图像作为 html的背景,html文本会被存储在alternative段中,而作为背景的图像则会存储在multipart/related类型定义的段中

一、正常发送

## 导入模块
from email.mime.text import MIMEText
import smtplib mail_host = "xxx.163.com" #SMTP服务器地址 mail_sender = "xxx.com" #账号 mail_passwd = "xxx" #密码 ## 构造邮件内容 msg = MIMEText("这里是邮件正文内容",'plain','utf-8') msg["Subject"] = "这里是邮件主题" msg["From"] = mail_sender #发送人 to_receiver=['xxx'] #收件人邮箱,多个人就是要list cc_reciver=['xxx'] #抄送邮箱 receiver = cc_reciver + to_receiver msg["To"] = ";".join(receiver) #接收人 但是这个不区分收件人和抄送,不过也无关痛痒 ## 发送邮件 s = smtplib.SMTP() #实例化对象 s.connect(mail_host) #连接163邮箱服务器,端口号为465,注意,这里不需要写端口号,有些需要写端口,需要写的话就直接写数字 s.login(mail_sender, mail_passwd) #登录邮箱 s.sendmail(mail_sender, receiver, msg.as_string()) s.quit()

看效果

 

 

 二、正文带图片

from email.mime.text import MIMEText
from email.mime.image import MIMEImage
from email.mime.multipart import MIMEMultipart
import smtplib

mail_host = "xxx.163.com" #SMTP服务器地址
mail_sender = "xxx.com" #账号
mail_passwd = "xxx" #密码

msg = MIMEMultipart('related')
msg["Subject"] = "测试Python-发送邮件在正文带图片"
msg["From"] = mail_sender #发送人
to_receiver=['xxx'] #收件人邮箱,多个人就是要list
cc_reciver=['xxx']  #抄送邮箱
receiver = cc_reciver  + to_receiver
msg["To"] = ";".join(receiver) #接收人

#html格式的邮件正文
content = '''
<body>
<p>元宝</p>
<p>图片如下:</p>
<p><img src="cid:testimage" alt="testimage"></p>
</body>
'''
msg.attach(MIMEText(content,'html','utf-8'))

#读取图片
fp = open('元宝.jpg', 'rb')  #打开文件
msgImage = MIMEImage(fp.read(), _subtype=False) #读入 msgImage 中
fp.close() #关闭文件

# 定义图片 ID,在 HTML 文本中引用
msgImage.add_header('Content-ID', 'testimage') #
msg.attach(msgImage)

## 发送邮件
s = smtplib.SMTP() #实例化对象
s.connect(mail_host) #连接163邮箱服务器,端口号为465,注意,这里不需要写端口号
s.login(mail_sender, mail_passwd) #登录邮箱
s.sendmail(mail_sender, receiver, msg.as_string())
s.quit()

看效果

 

 

 如果想插入2张(或者2张以上)图片,则可以这样

#html格式的邮件正文
content = '''
<body>
<p>元宝</p>
<p>图片如下:</p>
<p><img src="cid:testimage1" alt="testimage1"></p>
<p><img src="cid:testimage2" alt="testimage2"></p>
</body>
'''
msg.attach(MIMEText(content,'html','utf-8'))

#读取图片
fp = open('元宝.jpg', 'rb')  #打开文件
msgImage1 = MIMEImage(fp.read(), _subtype=False) #读入 msgImage 中
fp.close() #关闭文件

fp = open('粽子.jpg', 'rb')  #打开文件
msgImage2 = MIMEImage(fp.read(), _subtype=False) #读入 msgImage 中
fp.close() #关闭文件

# 定义图片 ID,在 HTML 文本中引用
msgImage1.add_header('Content-ID', 'testimage1') 
msg.attach(msgImage1)
msgImage2.add_header('Content-ID', 'testimage2') 
msg.attach(msgImage2)

最后效果

 

 

 

 

 

 三、正文带表格

正文带表格有2中方式,一种直接在邮件正文里面增加html,然后再html里面一行一列写入数据,但是这种方法太笨重

from email.mime.text import MIMEText
from email.mime.multipart import MIMEMultipart
import smtplib
from email.mime.image import MIMEImage

mail_host = "xxx.com" #SMTP服务器地址
mail_sender = "xxx.com" #账号
mail_passwd = "xxx" #密码

msg = MIMEMultipart('related')
msg["Subject"] = "测试Python-发送邮件在正文带表格"
msg["From"] = mail_sender #发送人
to_receiver=['xxx.com'] #收件人邮箱,多个人就是要list
#cc_reciver=['xxx.com']  #抄送邮箱
receiver = cc_reciver  + to_receiver
msg["To"] = ";".join(receiver) #接收人

#html格式的邮件正文
content = '''
<html>
<body>
<p><strong>这是加粗字体,可以是一个标题</strong></p>
<p>下面是一个表格,表格格式可以随意设置</p>
<table width="500" bordercolor="black" border="1" cellspacing="0">
 <tr>
  <td><strong>列名1</strong></td>
  <td><strong>列名2</strong></td>
  <td><strong>列名3</strong></td>
 </tr>
 <tr>
  <td>str1</td>
  <td>10</td>
  <td>2019-01-01</td>
 </tr>
 <tr>
  <td>str2</td>
  <td>20</td>
  <td>2019-01-02</td>
 </tr>
 <tr>
  <td>str3</td>
  <td>30</td>
  <td>2019-01-03</td>
 </tr>
</table>
</body>
</html>
'''
msg.attach(MIMEText(content,'html','utf-8'))

## 发送邮件
s = smtplib.SMTP() #实例化对象
s.connect(mail_host) #连接163邮箱服务器,端口号为465,注意,这里不需要写端口号
s.login(mail_sender, mail_passwd) #登录邮箱
s.sendmail(mail_sender, receiver, msg.as_string())
s.quit()

结果如下:

 

 

 我们想要的是直接将pandas 的df 放到里面,或者Excel表放到里面,而不是手动一行一列写。

#上面虽然介绍了正文带表格,但是这个不能符合我们的要求
from email.mime.text import MIMEText
from email.mime.multipart import MIMEMultipart
import smtplib
from email.mime.image import MIMEImage

mail_host = "xxx.163.com" #SMTP服务器地址
mail_sender = "xxx.com" #账号
mail_passwd = "xxx" #密码

msg = MIMEMultipart('related')
msg["Subject"] = "测试Python-发送邮件正文带表格"
msg["From"] = mail_sender #发送人
to_receiver=['xxx.com'] #收件人邮箱,多个人就是要list
cc_reciver=['xxx.com']  #抄送邮箱
receiver = cc_reciver  + to_receiver
msg["To"] = ";".join(receiver) #接收人

#你只需要将你的表df放在这里
#表格1
filter_merge_data1 = pd.DataFrame()
filter_merge_data1['节点id'] = [0]*2
filter_merge_data1['节点名称'] = [0]*2

#表格2
filter_merge_data2 = pd.DataFrame()
filter_merge_data2['最后重跑时间'] = [0]*2
filter_merge_data2['失败次数'] = [0]*2

#filter_merge_data = pd.read_excel('工作簿3.xlsx')

df_html = filter_merge_data1.to_html(escape=False)  # DataFrame数据转化为HTML表格形式
df_htm2 = filter_merge_data2.to_html(escape=False)  # DataFrame数据转化为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">表格中的数据为当天运行失败超过6次的节点,请查看运维中心处理</h1>
        </div>
        <hr>
        <div class="content">
            <!--正文内容-->
            <h2> </h2>
            </div>
                <p>这是表格1</p> 
            <div>
                <h4></h4>
                {df_html}
            </div>
                <p>这是表格2</p> 
            </div>
                <h4></h4>
                {df_htm2}
            <hr>
            <p style="text-align: center">
            </p>
        </div>
        </body>
        """.format(yesterday='20211012', df_html=df_html,df_htm2=df_htm2)
html_msg = "<html>" + head + body + "</html>"
html_msg = html_msg.replace('\n', '').encode("utf-8")

msg.attach(MIMEText(html_msg,"html",'utf-8'))


## 发送邮件
s = smtplib.SMTP() #实例化对象
s.connect(mail_host) #连接163邮箱服务器,端口号为465,注意,这里不需要写端口号
s.login(mail_sender, mail_passwd) #登录邮箱
s.sendmail(mail_sender, receiver, msg.as_string())
s.quit()

 

 

效果如下:

 

 

 第四、邮件带附件

from email.mime.text import MIMEText
from email.mime.multipart import MIMEMultipart
import smtplib
from email.mime.image import MIMEImage

mail_host = "xxx.163.com" #SMTP服务器地址
mail_sender = "xxx.com" #账号
mail_passwd = "xxx" #密码

msg = MIMEMultipart('related')
msg["Subject"] = "测试Python-发送邮件在带附件"
msg["From"] = mail_sender #发送人
to_receiver=['xxx.com'] #收件人邮箱,多个人就是要list
cc_reciver=['xxx.com']  #抄送邮箱
receiver = cc_reciver  + to_receiver
msg["To"] = ";".join(receiver) #接收人

# 邮件正文
content = '''
这是一封带有附件的邮件...
有两个附件
'''
msg.attach(MIMEText(content,'plain','utf-8'))

# 构造附件1,txt文件
att1 = MIMEText(open('test.txt', 'rb').read(), 'base64', 'utf-8')
att1["Content-Type"] = 'application/octet-stream'
# 这里的filename可以任意写,写什么名字,邮件中显示什么名字
att1["Content-Disposition"] = 'attachment; filename="test.txt"'
msg.attach(att1)

# 构造附件2,xlsx文件
att2 = MIMEText(open('test.xlsx', 'rb').read(), 'base64', 'utf-8')
att2["Content-Type"] = 'application/octet-stream'
att2["Content-Disposition"] = 'attachment; filename="test.xlsx"'
msg.attach(att2)

## 发送邮件
s = smtplib.SMTP() #实例化对象
s.connect(mail_host) #连接163邮箱服务器,端口号为465,注意,这里不需要写端口号
s.login(mail_sender, mail_passwd) #登录邮箱
s.sendmail(mail_sender, receiver, msg.as_string())
s.quit()

 

参考:

https://www.jianshu.com/p/ab739cf42169

blog.csdn.net/weixin_43199103/article/details/89681221

https://blog.csdn.net/songszp/article/details/126316900

https://blog.csdn.net/qq_34864753/article/details/120769126

posted on 2022-10-21 17:38  小小喽啰  阅读(1241)  评论(0编辑  收藏  举报