← 返回首页
Python3基础教程(七十四)
发表时间:2022-05-09 09:12:27
SMTP发送邮件

SMTP是发送邮件的协议,Python内置对SMTP的支持,可以发送纯文本邮件、HTML邮件以及带附件的邮件。

1.SMTP

Python对SMTP支持有smtplib和email两个模块,email负责构造邮件,smtplib负责发送邮件。

以下是国内常见的邮件服务的端口号。

# 协议  服务器         SSL   非 SSL
# SMTP smtp.163.com   465   25
# IMAP imap.163.com   993   143
# POP3 pop.163.com    995   110
# -------------------------------
# SMTP smtp.qq.com    465/587
# IMAP imap.qq.com    993
# POP3 pop.qq.com     995
# -------------------------------
# SMTP smtp.gmail.com 465(SSL)/587(TLS/STARTTLS)
# IMAP imap.gmail.com 993
# POP3 pop.gmail.com  995
# -------------------------------
# 163/qq: password 为授权码
# gmail: password 为邮箱密码

2.实例

使用QQ邮箱发送邮件。首先必须开启qq邮箱的smtp服务。 如何打开POP3/SMTP/IMAP功能? 为了保障用户邮箱的安全,QQ邮箱设置了POP3/SMTP/IMAP的开关。系统缺省设置是“关闭”,在用户需要这些功能时请“开启”。 首先,登录邮箱,进入设置-帐户;

# -*- coding: utf-8 -*-
# @Time : 2022/5/9 18:56
# @File : smtpdemo.py
# @Software : PyCharm

import smtplib
from email.mime.text import MIMEText
from email.utils import formataddr

my_sender='403357832@qq.com'    # 发件人邮箱账号
my_pass = 'erfwftyewertbiab'    # 发件人邮箱密码(当时申请smtp给的授权码)
my_user='tester@163.com'       # 收件人邮箱账号,我这边发送给自己,可以自己发给自己

def mail():
    ret=True
    try:
        msg=MIMEText('主人,有新域名,快来看看吧!','plain','utf-8')
        msg['From']=formataddr(["simoniu",my_sender])  # 括号里的对应发件人邮箱昵称、发件人邮箱账号
        msg['To']=formataddr(["bob",my_user])       # 括号里的对应收件人邮箱昵称、收件人邮箱账号
        msg['Subject']="邮件主题-测试"                # 邮件的主题,也可以说是标题

        server=smtplib.SMTP_SSL("smtp.qq.com", 465)  # 发件人邮箱中的SMTP服务器,端口是465
        server.login(my_sender, my_pass)  # 括号中对应的是发件人邮箱账号、邮箱密码
        server.sendmail(my_sender,[my_user,],msg.as_string())  # 括号中对应的是发件人邮箱账号、收件人邮箱账号、发送邮件
        server.quit()# 关闭连接
    except Exception as e:# 如果 try 中的语句没有执行,则会执行下面的 ret=False
        print(e)
        ret=False
    return ret

ret=mail()

if ret:
    print("邮件发送成功")
else:
    print("邮件发送失败")

运行结果:

邮件发送成功

发送附件 如果Email中要加上附件怎么办?带附件的邮件可以看做包含若干部分的邮件:文本和各个附件本身,所以,可以构造一个MIMEMultipart对象代表邮件本身,然后往里面加上一个MIMEText作为邮件正文,再继续往里面加上表示附件的MIMEBase对象即可。


import smtplib
from email import encoders
from email.mime.base import MIMEBase
from email.mime.multipart import MIMEMultipart
from email.mime.text import MIMEText
from email.utils import formataddr

my_sender='403357832@qq.com'    # 发件人邮箱账号
my_pass = 'erfwftyewertbiab'    # 发件人邮箱密码(当时申请smtp给的授权码)
my_user='tester@163.com'       # 收件人邮箱账号,我这边发送给自己,可以自己发给自己


def mail():
    ret = True
    try:
        # 发送附件必须构造一个MIMEMultipart对象
        msg = MIMEMultipart()
        msg['From'] = formataddr(["simoniu", my_sender])  # 括号里的对应发件人邮箱昵称、发件人邮箱账号
        msg['To'] = formataddr(["bob", my_user])  # 括号里的对应收件人邮箱昵称、收件人邮箱账号
        msg['Subject'] = "邮件主题-测试"  # 邮件的主题,也可以说是标题

        # 邮件正文是MIMEText:
        msg.attach(MIMEText('send with file...', 'plain', 'utf-8'))
        # 添加附件就是加上一个MIMEBase,从本地读取一个图片:
        with open('D:/uploadFiles/test.jpg', 'rb') as f:
            # 设置附件的MIME和文件名,这里是png类型:
            mime = MIMEBase('image', 'jpg', filename='test.jpg')
            # 加上必要的头信息:
            mime.add_header('Content-Disposition', 'attachment', filename='test.jpg')
            mime.add_header('Content-ID', '<0>')
            mime.add_header('X-Attachment-Id', '0')
            # 把附件的内容读进来:
            mime.set_payload(f.read())
            # 用Base64编码:
            encoders.encode_base64(mime)
            # 添加到MIMEMultipart:
            msg.attach(mime)

        server = smtplib.SMTP_SSL("smtp.qq.com", 465)  # 发件人邮箱中的SMTP服务器,端口是465
        server.login(my_sender, my_pass)  # 括号中对应的是发件人邮箱账号、邮箱密码
        server.sendmail(my_sender, [my_user, ], msg.as_string())  # 括号中对应的是发件人邮箱账号、收件人邮箱账号、发送邮件
        server.quit()  # 关闭连接
    except Exception as e:  # 如果 try 中的语句没有执行,则会执行下面的 ret=False
        print(e)
        ret = False
    return ret


ret = mail()

if ret:
    print("邮件发送成功")
else:
    print("邮件发送失败")

发送图片

如果要把一个图片嵌入到邮件正文中怎么做?直接在HTML邮件中链接图片地址行不行?答案是,大部分邮件服务商都会自动屏蔽带有外链的图片,因为不知道这些链接是否指向恶意网站。

要把图片嵌入到邮件正文中,我们只需按照发送附件的方式,先把邮件作为附件添加进去,然后,在HTML中通过引用src="cid:0"就可以把附件作为图片嵌入了。如果有多个图片,给它们依次编号,然后引用不同的cid:x即可。

把上面代码加入MIMEMultipart的MIMEText从plain改为html,然后在适当的位置引用图片:


import smtplib
from email import encoders
from email.mime.base import MIMEBase
from email.mime.multipart import MIMEMultipart
from email.mime.text import MIMEText
from email.utils import formataddr

my_sender='403357832@qq.com'    # 发件人邮箱账号
my_pass = 'erfwftyewertbiab'    # 发件人邮箱密码(当时申请smtp给的授权码)
my_user='tester@163.com'       # 收件人邮箱账号,我这边发送给自己,可以自己发给自己


def mail():
    ret = True
    try:
        # 发送附件必须构造一个MIMEMultipart对象
        msg = MIMEMultipart()
        msg['From'] = formataddr(["simoniu", my_sender])  # 括号里的对应发件人邮箱昵称、发件人邮箱账号
        msg['To'] = formataddr(["bob", my_user])  # 括号里的对应收件人邮箱昵称、收件人邮箱账号
        msg['Subject'] = "邮件主题-测试"  # 邮件的主题,也可以说是标题

        # 添加附件就是加上一个MIMEBase,从本地读取一个图片:
        with open('D:/uploadFiles/test.jpg', 'rb') as f:
            # 设置附件的MIME和文件名,这里是png类型:
            mime = MIMEBase('image', 'jpg', filename='test.jpg')
            # 加上必要的头信息:
            mime.add_header('Content-Disposition', 'attachment', filename='test.jpg')
            mime.add_header('Content-ID', '<0>')
            mime.add_header('X-Attachment-Id', '0')
            # 把附件的内容读进来:
            mime.set_payload(f.read())
            # 用Base64编码:
            encoders.encode_base64(mime)
            # 添加到MIMEMultipart:
            msg.attach(mime)

        msg.attach(MIMEText('<html><body><h1>邮件中的图片</h1>' +
                            '<p><img src="cid:0"></p>' +
                            '</body></html>', 'html', 'utf-8'))

        server = smtplib.SMTP_SSL("smtp.qq.com", 465)  # 发件人邮箱中的SMTP服务器,端口是465
        server.login(my_sender, my_pass)  # 括号中对应的是发件人邮箱账号、邮箱密码
        server.sendmail(my_sender, [my_user, ], msg.as_string())  # 括号中对应的是发件人邮箱账号、收件人邮箱账号、发送邮件
        server.quit()  # 关闭连接
    except Exception as e:  # 如果 try 中的语句没有执行,则会执行下面的 ret=False
        print(e)
        ret = False
    return ret


ret = mail()

if ret:
    print("邮件发送成功")
else:
    print("邮件发送失败")

小结: 使用Python的smtplib发送邮件十分简单,只要掌握了各种邮件类型的构造方法,正确设置好邮件头,就可以顺利发出。