python3发送邮件(格式:html,带多个附件,解决乱码)

废话不多说,先来上代码。

import smtplib
from email.message import EmailMessage
from email.headerregistry import Address, Group
import email.policy
import mimetypes
import base64


class SendEmail(object):
    """
    python3 发送邮件类
    格式: html
    可发送多个附件
    """
    def __init__(self, smtp_server, smtp_user, smtp_passwd, sender, recipient):
        # 发送邮件服务器,常用smtp.163.com
        self.smtp_server = smtp_server
        # 发送邮件的账号
        self.smtp_user = smtp_user
        # 发送账号的客户端授权码
        self.smtp_passwd = smtp_passwd
        # 发件人
        self.sender = sender
        # 收件人
        self.recipient = recipient

        # Use utf-8 encoding for headers. SMTP servers must support the SMTPUTF8 extension
        # https://docs.python.org/3.6/library/email.policy.html
        self.msg = EmailMessage(email.policy.SMTPUTF8)

    def set_header_content(self, subject, content):
        """
        设置邮件头和内容
        :param subject: 邮件题头
        :param content: 邮件内容
        :return:
        """
        self.msg['From'] = self.sender
        self.msg['To'] = self.recipient
        self.msg['Subject'] = subject
        self.msg.set_content(content, subtype="html")

    def set_accessories(self, path_list: list):
        """
        添加附件
        :param path_list: [{"path": ""}, {"name": ""}]
        :return:
        """
        for path_dict in path_list:
            filename = path_dict['path']
            name = path_dict['name']
            ctype, encoding = mimetypes.guess_type(filename)
            if ctype is None or encoding is not None:
                # No guess could be made, or the file is encoded (compressed), so
                # use a generic bag-of-bits type.
                ctype = 'application/octet-stream'
            maintype, subtype = ctype.split('/', 1)
            with open(filename, 'rb') as fp:
                self.msg.add_attachment(fp.read(), maintype, subtype, filename=self.dd_b64(name))

    def send_email(self):
        """
        发送邮件
        :return:
        """
        with smtplib.SMTP_SSL(self.smtp_server) as smtp:
            # HELO向服务器标志用户身份
            smtp.ehlo_or_helo_if_needed()
            # 登录邮箱服务器
            smtp.login(self.smtp_user, self.smtp_passwd)
            print("Email:{}==>{}".format(self.sender, self.recipient))
            smtp.send_message(self.msg)
            print("Sent succeed!")

    @staticmethod
    def dd_b64(param):
        """
        对邮件header及附件的文件名进行两次base64编码,防止outlook中乱码。
        email库源码中先对邮件进行一次base64解码然后组装邮件
        :param param: 需要防止乱码的参数
        :return:
        """
        param = '=?utf-8?b?' + base64.b64encode(param.encode('UTF-8')).decode() + '?='
        param = '=?utf-8?b?' + base64.b64encode(param.encode('UTF-8')).decode() + '?='
        return param


if __name__ == '__main__':
    smtp_server = "smtp.163.com"
    smtp_user = "a.163.com"  # 发送邮件的账号
    smtp_passwd = "aaaaaa"  # 发送账号的客户端授权码
    # 直接用字符串也行,这里为了方便使用 display name, 相当于 "测试-发送者 <a@163.com>"
    # 发送号码要与登录号码一致
    sender = Address("测试-发送者", "a", "163.com")
    # 发送多个人
    recipient = Group(addresses=(Address("测试-接受者", "b", "qq.com"), Address("测试-接受者", "c", "qq.com")))
    subject = "测试专用"
    content = """
        <html>
            <h2 style='color:red'>将进酒</h2>
            <p>人生得意须尽欢,莫使金樽空对月。</p>
            <p>天生我材必有用,千金散尽还复来。</p>
        </html>
        """
    path_list = [{"path": r"./测试文件123abc.txt",
                  "name":  "测试文件123abc.txt"}]
    sd = SendEmail(smtp_server, smtp_user, smtp_passwd, sender, recipient)  # 创建对象
    sd.set_header_content(subject, content)  # 设置题头和内容
    sd.set_accessories(path_list)  # 添加附件
    sd.send_email()  # 发送邮件

效果图:
在这里插入图片描述
容易出现的问题
1.smtplib.SMTPAuthenticationError: (535, b’Error: authentication failed’):认证失败,这里检查账号和授权码,一定是授权码,不是密码!!!
2.smtplib.SMTPSenderRefused: (553, b’Mail from must equal authorized user’, ‘a@163.com’):这是sender和smtp_user 不一致导致的错误,注意,昵称可以随便起,但是发送邮箱一定要一致。
3.‘Address’ object is not iterable:发送多个人的时候,Group(addresses=(Address(),))注意这里是元组,逗号不要掉。
4.还有就是附件的地址要写对, 附件的名字不要丢了格式(.txt,.docx)

再有出现问题或者看不懂的,可以留言

  • 2
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值