使用python smtplib 模块,用QQ邮箱发送邮件

1,589 阅读8分钟

本文已参与「新人创作礼」活动,一起开启掘金创作之路。

1 SMTP协议介绍

简单邮件传输协议 / 发送邮件服务器(SMTPSimple Mail Transfer Protocol)是用于电子邮件传输的通信协议。 Is 是一个 Internet 标准,该标准于 1982 年由 RFC 821 首次定义,并于 2008 年由 RFC 5321 更新为扩展 SMTP 添加。 邮件服务器和其他邮件传输代理使用 SMTP 发送和接收邮件。

2 python smtplib模块使用

smtplib是一个 Python 库,用于使用简单邮件传输协议(SMTP)发送电子邮件。 smtplib是内置模块; 我们不需要安装它。 它抽象了 SMTP 的所有复杂性。

2.1 发送邮件到本地邮件服务器

1、要实际发送电子邮件,我们需要有权访问邮件服务器。 Python 带有一个简单的开发邮件服务器。 Mailslurper 是易于使用的本地开发服务器。 共享的虚拟主机提供商使我们可以访问邮件服务器。 我们可以在帐户中找到详细信息。

注意:避免使用 Gmail,因为它是高度安全的服务器,并且使其工作非常复杂。 实际上,Internet 上的大多数(如果不是全部)示例演示了如何通过 Gmail 服务器发送电子邮件,这些示例都无法正常工作。 而是使用开发服务器或共享的虚拟主机服务器。

最后,我们可以使用 Web 服务。 有开发 Web 服务(例如 MailTrap MailSlurp)或生产服务(例如 Mailgun 或 Mandrill)。

2、使用 Python 内置邮件服务器

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

运行上面的命令,就可以在端口1025上启动 Python 内置邮件服务器

3、向服务器上发送邮件信息

我们向上面python本地的邮件服务器,发送邮件,发送脚本如下:

import smtplib
from email.mime.text import MIMEText

# 向本地开发邮件服务器发送一条简单的文本信息

# 发送者的邮箱  example.com是专门用于文档中的说明性示例的域名
sender = 'admin@example.com'
# 接收者的邮箱
receivers = ['info@example.com']

# 服务器的端口
port = 1025
# 发送到服务器的文本信息
msg = MIMEText('This is test mail')
# print(msg, type(msg))  # This is test mail <class 'email.mime.text.MIMEText'>

msg['Subject'] = 'Test mail'
msg['From'] = 'admin@example.com'
msg['To'] = 'info@example.com'

# MimeText用于发送文本电子邮件。我们提供主题,从选项到选项
# SMTP类管理 与 SMTP服务器的连接
with smtplib.SMTP('localhost', port) as server:

    # 由于我们使用本地开发服务器,因此不用登录
    # server.login('username', 'password')

    # 电子邮件带有sendmail()发送
    server.sendmail(sender, receivers, msg.as_string())
    print("Successfully sent email")

发送电子邮件后,我们会在开启的本地邮件服务器的一端,接收到发送的消息

(base) PS C:\Users\shl> python -m smtpd -c DebuggingServer -n localhost:1025
---------- MESSAGE FOLLOWS ----------
b'Content-Type: text/plain; charset="us-ascii"'
b'MIME-Version: 1.0'
b'Content-Transfer-Encoding: 7bit'
b'Subject: Test mail'
b'From: admin@example.com'
b'To: info@example.com'
b'X-Peer: ::1'
b''
b'This is test mail'
------------ END MESSAGE ------------

在这里插入图片描述

2.2 发送邮件到Mailtrap服务器

Mailtrap提供了一项免费计划,使我们每个月可以发送 500 封邮件。 设置 Mailtrap 非常容易。 如果我们拥有 Github Google 帐户,则只需几秒钟。

设置页面中提供了必要的凭据。 另外,还有一些简短的代码示例显示了如何使用服务,包括smtplibDjangoFlask

mailtrap_simple.py

import smtplib
from email.mime.text import MIMEText

# 向本地开发邮件服务器发送一条简单的文本信息

# 发送者的邮箱  example.com是专门用于文档中的说明性示例的域名
sender = 'admin@example.com'
# 接收者的邮箱
receivers = ['info@example.com']

# 服务器的端口
port = 1025
# 发送到服务器的文本信息
msg = MIMEText('This is test mail')
# print(msg, type(msg))  # This is test mail <class 'email.mime.text.MIMEText'>

msg['Subject'] = 'Test mail'
msg['From'] = 'admin@example.com'
msg['To'] = 'info@example.com'

user = 'xxxx@gmail.com'
password = 'xxx@bxx'


# MineText用于发送文本电子邮件。我们提供主题,从选项到选项
# SMTP类管理 与 SMTP服务器的连接
with smtplib.SMTP('smtp.mailtrap.io', 2525) as server:
    server.login(user, password)

    # 电子邮件带有sendmail()发送
    server.sendmail(sender, receivers, msg.as_string())
    print("Successfully sent email")

报错:smtplib.SMTPServerDisconnected: Connection unexpectedly closed

说解决方案是在:server.login()前加上如下两行代码,但是我尝试并不可行(参考

server.ehlo()
server.starttls()

2.3 发送邮件到qq服务器

这里用到了Python的两个包来发送邮件: smtplibemail

Python 的 email 模块里包含了许多实用的邮件格式设置函数,可以用来创建邮件“包裹”。使用的 MIMEText 对象,为底层的 MIME(Multipurpose Internet MailExtensions多用途互联网邮件扩展类型)协议传输创建了一封空邮件,最后通过高层的SMTP 协议发送出去。 MIMEText 对象 msg 包括收发邮箱地址邮件正文主题,Python 通过它就可以创建一封格式正确的邮件。smtplib 模块用来设置服务器连接的相关信息。

要想通过QQ邮箱来发送邮件,需要开启QQ邮箱的设置-账户SMTP服务,接下来会通过发送短信验证来获得授权码,有了授权码后就可以在代码里添加了。(参考)

使用qq邮箱其他的邮箱发送简单的文本信息

1、首先获取发送者邮箱的授权码,这里我发送者用的是QQ邮箱,下面说下QQ邮箱如何获取授权码

1)首先登录qq账号邮箱,然后在设置-账户下找到SMTP服务

在这里插入图片描述

2)点击生成授权码,之后会让你发送短信,用户获取授权码

在这里插入图片描述

3)发送短信成功之后,会看到16位长度的授权码,如下图(后面使用授权码的时候,不要加空格)

在这里插入图片描述

2、下面是获取发送者邮箱服务器的域名和端口,这里我们的发送者使用的是QQ邮箱,其邮件服务器和端口为:

  • QQ发送邮件服务器:smtp.qq.com
  • 使用SSL,端口号为465587

在这里插入图片描述

def send_text_info():
    import smtplib
    from email.mime.text import MIMEText

    # 向本地开发邮件服务器发送一条简单的文本信息

    # 发送者的邮箱  example.com是专门用于文档中的说明性示例的域名
    sender = '931762054@qq.com'
    password = 'xnsgcuuavelrbbdj'   # 发送者邮箱的授权码
    # 接收者的邮箱,接收者可以是多个,因此是一个列表
    receivers = ['shliang0603@gmail.com']

    # 发送到服务器的文本信息
    subject = '这个是邮件主题'
    content = '这是使用python smtplib及email模块发送的邮件'
    msg = MIMEText(content)
    # print(msg, type(msg))  # This is test mail <class 'email.mime.text.MIMEText'>

    # msg['Subject']是发送邮件的主题
    msg['Subject'] = subject
    msg['From'] = sender
    msg['To'] = receivers[0]


    # 发送邮件时qq邮箱,对应qq邮箱服务器域名时smtp.qq.com  对应端口时465
    with smtplib.SMTP_SSL(host='smtp.qq.com', port=465) as server:
        # 登录发送者的邮箱
        server.login(sender, password)

        # 开始发送邮件
        server.sendmail(sender, receivers, msg.as_string())
        print("Successfully sent email")


    '''
    上面发送邮件部分也可以写成:
    server = smtplib.SMTP_SSL(host='smtp.qq.com', port=465) 
    server.login(sender, password)

    server.sendmail(sender, receivers, msg.as_string())
    server.quit()
    '''


if __name__ == '__main__':
    send_text_info()
    

2.4 发送邮件添加附件

# 发送文本和附件
# reference: https://blog.csdn.net/weixin_46211269/article/details/121243675
def send_text_and_file():
    import os
    import smtplib
    from email.mime.text import MIMEText
    from email.mime.image import MIMEImage
    from email.mime.multipart import MIMEMultipart
    from email.mime.application import MIMEApplication

    
    def send_email(msg_from, passwd, msg_to, text_content, file_path=None):
        # 发送的消息内容分多个部分,MIMEMultipart类可以放任何内容
        msg = MIMEMultipart()
        subject = 'python 实现发送文本和附件邮件'  # 主题
        text = MIMEText(text_content)
        # 把要发送的消息添加到msg中
        msg.attach(text)
        
        if os.path.exists(file_path):
            docFile = file_path
            # 读取文本和图片文件都可以正常发送
            docApart = MIMEApplication(open(docFile, 'rb').read())
            # filename 附件的名字,这个可以重新命名,不重新指定发送附件的名可能就是文件的路径名了
            filename = os.path.split(file_path)[-1]
            docApart.add_header('Content-Disposition', 'attachment', filename=filename)
            msg.attach(docApart)
            print('发送附件!')

        msg['subject'] = subject
        msg['From'] = msg_from
        msg['To'] = msg_to
        try:
            server = smtplib.SMTP_SSL(host='smtp.qq.com', port=465)
            server.login(msg_from, passwd)
            server.sendmail(msg_from, msg_to, msg.as_string())
            print('发送成功')
        except smtplib.SMTPException as e:
            print('发送失败')
        finally:
            server.quit()

    msg_from = '931762054@qq.com'   # 发送者邮箱
    passwd = 'xnsgcuuavelrbbdj'   # 发送者邮箱的授权码
    msg_to = 'shliang0603@gmail.com'  # 接收者邮箱
    msg_to = '931762054@qq.com'
    text_content = 'This is a test demo!'
    # 发送文件和图片附件都是可以的!
    # file_path = 'read.md'
    file_path = 'imgs/email1.png'
    send_email(msg_from, passwd, msg_to, text_content, file_path)

if __name__ == '__main__':
    send_text_and_file()

在这里插入图片描述

在这里插入图片描述

2.5 发送HTML格式的邮件

# 发送html本文,同时发送两个附件
# reference:https://blog.csdn.net/MATLAB_matlab/article/details/106240424
def send_html_file():
    import os
    import datetime
    import smtplib
    from email.mime.text import MIMEText
    from email.mime.image import MIMEImage
    from email.mime.multipart import MIMEMultipart
    from email.mime.application import MIMEApplication

    
    def send_email(msg_from, passwd, msg_to, text_content, *args):
        # 发送的消息内容分多个部分,MIMEMultipart类可以放任何内容
        msg = MIMEMultipart()
        subject = 'python 实现发送文本和附件邮件'  # 主题
        text = MIMEText(text_content)
        # 把要发送的消息添加到msg中
        msg.attach(text)
        
        # 添加附件
        def add_file(file_path):
            if os.path.exists(file_path):
                docFile = file_path
                docApart = MIMEApplication(open(docFile, 'rb').read())
                # filename 附件的名字,这个可以重新命名,不重新指定发送附件的名可能就是文件的路径名了
                filename = os.path.split(file_path)[-1]
                docApart.add_header('Content-Disposition', 'attachment', filename=filename)
                msg.attach(docApart)
                print('发送附件!')
        # 添加多个附件
        for file in args:
            add_file(file)

        
        now_time = datetime.datetime.now()
        year = now_time.year
        month = now_time.month
        day = now_time.day
        mytime = str(year) + " 年 " + str(month) + " 月 " + str(day) + " 日 "
        fayanren="爱因斯坦"
        zhuchiren="牛顿"
        #构造HTML
        content = '''
                        <html>
                        <body>
                            <h1 align="center">这个是标题,xxxx通知</h1>
                            <p><strong>您好:</strong></p>
                            <blockquote><p><strong>以下内容是本次会议的纪要,请查收!</strong></p></blockquote>
                            
                            <blockquote><p><strong>发言人:{fayanren}</strong></p></blockquote>
                            <blockquote><p><strong>主持人:{zhuchiren}</strong></p></blockquote>
                            <p align="right">{mytime}</p>
                        <body>
                        <html>
                        '''.format(fayanren=fayanren, zhuchiren=zhuchiren, mytime=mytime)
        
        msg.attach(MIMEText(_text=content, _subtype='html', _charset='utf-8'))


        msg['subject'] = subject
        msg['From'] = msg_from
        msg['To'] = msg_to
        try:
            server = smtplib.SMTP_SSL(host='smtp.qq.com', port=465)
            server.login(msg_from, passwd)
            server.sendmail(msg_from, msg_to, msg.as_string())
            print('发送成功')
        except smtplib.SMTPException as e:
            print('发送失败')
        finally:
            server.quit()

    msg_from = '931762054@qq.com'   # 发送者邮箱
    passwd = 'xnsgcuuavelrbbdj'   # 发送者邮箱的授权码
    msg_to = 'shliang0603@gmail.com'  # 接收者邮箱
    msg_to = '931762054@qq.com'
    text_content = 'This is a test demo!'
    # 发送文件和图片附件都是可以的!
    file_path1 = 'read.md'
    file_path2 = 'imgs/email1.png'
    send_email(msg_from, passwd, msg_to, text_content, file_path1, file_path2)


if __name__ == '__main__':
    send_html_file()

在这里插入图片描述

flask web开发电子邮箱

参考geek-docs.com/python/pyth… 参考cloud.tencent.com/developer/a… 参考www.cnblogs.com/lovealways/… 参考blog.csdn.net/MATLAB_matl… 参考blog.csdn.net/weixin_4621…