python 使用SMTP发送邮件[HTML格式,带附件]

今天百度学习了如何在python中使用SMTP发送邮件,包括带HTML格式和附件。
基本套路就是定义一个MIMEText(不带附件)或者MIMEMultipart(可带多个附件),然后再连接、登录邮件服务器并发送即可。(发送HTML格式的邮件与纯文本消息的邮件不同之处就是将MIMEText中_subtype设置为html。

套路如下:不带附件

from email.mime.text import MIMEText
import smtplib

mail = MIMEText('邮件正文') # 简单纯文本消息的邮件
# mail = MIMEText('邮件正文', _subtype='html', _charset='utf-8') # HTML格式的邮件
mail['Subject'] = '邮件主题'
mail['From'] = '发件人地址' # 需与邮件服务器的认证用户一致
mail['To'] = '收件人地址'

smtp = smtplib.SMTP('smtp.qq.com', port=25) # 设置邮件服务器地址与端口
smtp.login('帐号', '密码') # 登录邮件服务器
smtp.sendmail('发件人地址', '收件人地址', mail.as_string()) # 发送邮件
self.smtp.quit() # 关闭邮件服务器

带附件

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

mail = MIMEMultipart()
mail.attach(MIMEText('邮件正文', _subtype='html', _charset='utf-8'))
# 构造附件att1,若是要带多个附件,可根据下边的格式构造
att1 = MIMEText(open('文件', 'rb').read(), 'base64', 'utf-8')
att1['Content-Type'] = 'application/octet-stream'
att1["Content-Disposition"] = 'attachment; filename="%s"' % 文件名
mail.attach(att1)

mail['Subject'] = '邮件主题'
mail['From'] = '发件人地址' # 需与邮件服务器的认证用户一致
mail['To'] = '收件人地址'

smtp = smtplib.SMTP('smtp.qq.com', port=25) # 设置邮件服务器地址与端口
smtp.login('帐号', '密码') # 登录邮件服务器
smtp.sendmail('发件人地址', '收件人地址', mail.as_string()) # 发送邮件
self.smtp.quit() # 关闭邮件服务器

我将其构造成一个类,以在构造类时是否传入file参数来判断是否要带附件。

说明:
  1. 需要在邮件服务器上设置打开smtp功能。【阿里云上禁用25端口,需使用SMTP_SSL、端口465连接。这次一并修改了。】
  2. SMTP服务器地址和端口可以在邮件服务器的设置里找到(在设置上边 1 时,应该就可以看到)
  3. 发件人与登录邮件服务器的认证用户应该一致,所以我把它写死在代码里了。(或许使用一个常量定义会更好?)
  4. 若是多个收件人则需在to_email参数中用逗号隔开。另外:MIMEText()[“To”]的数据类型与sendmail(from_addrs,to_addrs,…)的to_addrs不同;前者为str类型,多个地址使用逗号分隔,后者为list类型。所以在sendmail()函数中使用split(’,’)来分离多个收件人。

代码如下:

# -*- coding:utf-8 -*-
""" 发送邮件 """
import smtplib, os, base64
from email.mime.text import MIMEText
from email.mime.multipart import MIMEMultipart

email_server_user = 'QQ邮箱帐号'
email_server_pwd = 'QQ邮箱密码'


class Email(object):
    """
    :param: to_email:字串,收件人地址,多个收件人时用逗号隔开
    :param: from_email:发件人地址
    :param: subject:邮件主题
    :param: content:邮件正文
    :param: files:列表,附件地址,支持多个附件
    :return: 则返发送状态和信息

    attachment是附件:
        attachment = MIMEText(f.read(), 'base64', 'utf-8')
        attachment['Content-Type'] = 'application/octet-stream'
        attachment["Content-Disposition"] = 'attachment; filename="%s"' % file_name
        self.mail.attach(attachment)

    因为阿里云禁用了25端口,smtp = smtplib.SMTP('smtp.qq.com', port=25)将不可用。
    需改用:smtp = smtplib.SMTP_SSL('smtp.qq.com', port=465)

    范例:
        email = Email(
            to_email='****@qq.com',
            from_email='****@qq.com',
            subject='Test',
            content='''
                <b>测试测试</b><br>
                这是我的Email模块!
                <center>send by python_mail</center>
                ''' + str(datetime.now())[:19]
            # file=['./1.png','./2.png']
        )
        email.sent()
    """

    def __init__(self, to_email, from_email, subject='无主题', content=None, files=None):
        self.to_email = to_email  # 收件人
        self.from_email = from_email  # 发件人
        self.subject = subject  # 主题
        self.content = content  # 邮件正文
        self.files = files  # 附件

    def sent(self):
        if self.content or self.files:
            try:
                # 构造邮件
                mail = MIMEMultipart()
                mail['From'] = self.from_email
                mail['To'] = self.to_email
                mail['Subject'] = self.subject

                if self.content:
                    mail.attach(MIMEText(self.content, _subtype='html', _charset='utf-8'))

                # 添加附件
                if self.files:
                    for file in self.files:
                        # 构造附件并添加至邮件
                        try:
                            with open(file, 'rb') as f:
                                attachment = MIMEText(f.read(), 'base64', 'utf-8')
                        except Exception as e:
                            return False, '发送失败:附件["{}"]读取错误【{}】'.format(file, str(e))
                        else:
                            attachment['Content-Type'] = 'application/octet-stream'
                            file_name = os.path.split(file)[1]
                            # 下面一句是处理附件名是中文的情况
                            file_name = '=?utf-8?b?' + base64.b64encode(file_name.encode()).decode() + '?='
                            attachment["Content-Disposition"] = 'attachment; filename="%s"' % file_name
                            mail.attach(attachment)

                # 发送邮件
                smtp = None
                try:
                    smtp = smtplib.SMTP_SSL('smtp.qq.com', port=465)  # 设置邮件服务器
                    smtp.login(email_server_user, email_server_pwd)  # 登录邮件服务器
                    smtp.sendmail(mail['From'], mail['To'].split(','), mail.as_string())  # 发送邮件
                except Exception as e:
                    return False, '发送失败:服务器连接/发送失败【{}】'.format(str(e))
                finally:
                    if smtp:
                        smtp.quit()  # 关闭邮件服务器

                return True, '发送成功'
            except Exception as e:
                return False, '发送失败:{}'.format(str(e))
        else:
            return False, '发送失败:【邮件正文与附件都为空】'

如果本文对您有帮助,请给我留个言。谢谢!

猜你喜欢

转载自blog.csdn.net/qq_41090453/article/details/82772490