Python 发送邮件


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

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

发送纯文本内容

???? 代码如下:

# 引入相应的模块
import smtplib
from email.mime.text import MIMEText
from email.mime.multipart import MIMEMultipart
from email.mime.multipart import MIMEBase
from email import encoders
from email.utils import parseaddr, formataddr

class SendMail(object):
   def __init__(self):
       self.fromUser = "xxxxxx@qq.com" 
       self.userPasswd = "xxxxxx"      # 此处是qq邮箱授权码, 不是登录密码
       self.smtpAddr = "smtp.qq.com"

   # 构造邮件结构
   # toAddrs 收件人可以是多个,["xxx@qq.com","xxx@qq.com"], subject 邮件的主题, msg 邮件的内容
   def mailStructure(self, toAddrs, subject, msg):
       # 邮件对象:
       mailMsg = MIMEMultipart()
       mailMsg['Subject'] = ("Hello <%s>" % subject)
       mailMsg['From'] = ("Python管理员 <%s>" % self.fromUser)
       mailMsg['To'] = ','.join(toAddrs)
       # 邮件正文是MIMEText :
       mailMsg.attach(MIMEText(msg, 'html', 'utf-8'))
       return mailMsg.as_string()

   # 发送邮件
   def sendMail(self, toAddrs, subject, msg):
       mailMsg_as_string = self.mailStructure(toAddrs, subject, msg)
       # 连接服务器发送邮件
       try:
           server = smtplib.SMTP_SSL(self.smtpAddr, 465)
           server.connect(self.smtpAddr)  # 连接smtp服务器
           server.login(self.fromUser, self.userPasswd)  # 登录邮箱
           server.sendmail(self.fromUser, toAddrs, mailMsg_as_string)  # 发送邮件
           server.quit()
       except Exception:
           print("Error: unable to send email")


a = SendMail()
a.sendMail(["381347268@qq.com", "44934875@qq.com"], "测试主题", "测试内容")

  • 效果图
    发送纯文本内容效果图

 

发送附件图片

???? 代码如下:

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

其实就是打开图片并引入(加上这段内容)

with open(r"C:\Users\YJ\Desktop\favicon.png", "rb") as f:
            # 设置附件的MIME和文件名,这里是png类型:
            mime = MIMEBase("image", "png", filename="test.png")
            # 加上必要的头信息:
            mime.add_header('Content-Disposition', 'attachment', filename='test.png')
            mime.add_header('Content-ID', '<0>')
            mime.add_header('X-Attachment-Id', '0')
            # 把附件的内容读进来:
            mime.set_payload(f.read())
            # 用Base64编码:
            encoders.encode_base64(mime)
            # 添加到MIMEMultipart:
            mailMsg.attach(mime)
  • 发送附件图片 (完整代码如下:)
# 引入相应的模块
import smtplib
from email.mime.text import MIMEText
from email.mime.multipart import MIMEMultipart
from email.mime.multipart import MIMEBase
from email import encoders
from email.utils import parseaddr, formataddr

class SendMail(object):
    def __init__(self):
        self.fromUser = "xxxxxx@qq.com" 
        self.userPasswd = "xxxxxx"      # 此处是qq邮箱授权码, 不是登录密码
        self.smtpAddr = "smtp.qq.com"

    # 构造邮件结构
    # toAddrs 收件人可以是多个,["xxx@qq.com","xxx@qq.com"], subject 邮件的主题, msg 邮件的内容
    def mailStructure(self, toAddrs, subject, msg):
        # 邮件对象:
        mailMsg = MIMEMultipart()
        mailMsg['Subject'] = ("Hello <%s>" % subject)
        mailMsg['From'] = ("Python管理员 <%s>" % self.fromUser)
        mailMsg['To'] = ','.join(toAddrs)
        # 邮件正文是MIMEText :
        mailMsg.attach(MIMEText(msg, 'html', 'utf-8'))

        # 发送图片附件, 需要用到附件对象MIMEBase对象, 需要引入from email.mime.multipart import MIMEBase
        # 添加附件就是加上一个MIMEBase,从本地读取一个图片:
        with open(r"C:\Users\YJ\Desktop\favicon.png", "rb") as f:
            # 设置附件的MIME和文件名,这里是png类型:
            mime = MIMEBase("image", "png", filename="test.png")
            # 加上必要的头信息:
            mime.add_header('Content-Disposition', 'attachment', filename='test.png')
            mime.add_header('Content-ID', '<0>')
            mime.add_header('X-Attachment-Id', '0')
            # 把附件的内容读进来:
            mime.set_payload(f.read())
            # 用Base64编码:
            encoders.encode_base64(mime)
            # 添加到MIMEMultipart:
            mailMsg.attach(mime)
        return mailMsg.as_string()
    # 发送邮件
    def sendMail(self, toAddrs, subject, msg):
        mailMsg_as_string = self.mailStructure(toAddrs, subject, msg)
        # 连接服务器发送邮件
        try:
            server = smtplib.SMTP_SSL(self.smtpAddr, 465)
            server.connect(self.smtpAddr)  # 连接smtp服务器
            server.login(self.fromUser, self.userPasswd)  # 登录邮箱
            server.sendmail(self.fromUser, toAddrs, mailMsg_as_string)  # 发送邮件
            server.quit()
        except Exception:
            print("Error: unable to send email")

a = SendMail()
a.sendMail(["381347268@qq.com", "44934875@qq.com"], "测试主题", "测试内容")

  • 效果图
    附件图片效果图

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

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

其实就是将MIMEText 格式改变一下

mailMsg.attach(MIMEText('<html><body><h1>%s</h1>' % (msg) + '<p><img raw="cid:0"></p>' + '</body></html>', 'html','utf-8'))
  • 将附件图片包含在邮件内容中(完整代码如下:)
# 引入相应的模块
import smtplib
from email.mime.text import MIMEText
from email.mime.multipart import MIMEMultipart
from email.mime.multipart import MIMEBase
from email import encoders
from email.utils import parseaddr, formataddr

class SendMail(object):
    def __init__(self):
        self.fromUser = "xxxxxx@qq.com" 
        self.userPasswd = "xxxxxx"      # 此处是qq邮箱授权码, 不是登录密码
        self.smtpAddr = "smtp.qq.com"

    # 构造邮件结构
    # toAddrs 收件人可以是多个,["xxx@qq.com","xxx@qq.com"], subject 邮件的主题, msg 邮件的内容
    def mailStructure(self, toAddrs, subject, msg):
        # 邮件对象:
        mailMsg = MIMEMultipart()
        mailMsg['Subject'] = ("Hello <%s>" % subject)
        mailMsg['From'] = ("Python管理员 <%s>" % self.fromUser)
        mailMsg['To'] = ','.join(toAddrs)
        # 邮件正文是MIMEText :
        # 加载图片并引入到邮件内容中来
        mailMsg.attach(MIMEText('<html><body><h1>%s</h1>' % (msg) + '<p><img raw="cid:0"></p>' + '</body></html>', 'html','utf-8'))
        # 发送图片附件, 需要用到附件对象MIMEBase对象, 需要引入from email.mime.multipart import MIMEBase
        # 添加附件就是加上一个MIMEBase,从本地读取一个图片:
        with open(r"C:\Users\YJ\Desktop\favicon.png", "rb") as f:
            # 设置附件的MIME和文件名,这里是png类型:
            mime = MIMEBase("image", "png", filename="test.png")
            # 加上必要的头信息:
            mime.add_header('Content-Disposition', 'attachment', filename='test.png')
            mime.add_header('Content-ID', '<0>')
            mime.add_header('X-Attachment-Id', '0')
            # 把附件的内容读进来:
            mime.set_payload(f.read())
            # 用Base64编码:
            encoders.encode_base64(mime)
            # 添加到MIMEMultipart:
            mailMsg.attach(mime)
        return mailMsg.as_string()

    # 发送邮件
    def sendMail(self, toAddrs, subject, msg):
        mailMsg_as_string = self.mailStructure(toAddrs, subject, msg)
        # 连接服务器发送邮件
        try:
            server = smtplib.SMTP_SSL(self.smtpAddr, 465)
            server.connect(self.smtpAddr)  # 连接smtp服务器
            server.login(self.fromUser, self.userPasswd)  # 登录邮箱
            server.sendmail(self.fromUser, toAddrs, mailMsg_as_string)  # 发送邮件
            server.quit()
        except Exception:
            print("Error: unable to send email")

a = SendMail()
a.sendMail(["381347268@qq.com", "44934875@qq.com"], "测试主题", "测试内容")

  • 效果图
    邮件内容包含附件图片

 

发送纯文本附件

???? 代码如下:

# 引入相应的模块
import smtplib
from email.mime.text import MIMEText
from email.mime.multipart import MIMEMultipart
from email.mime.multipart import MIMEBase
from email import encoders
from email.utils import parseaddr, formataddr

class SendMail(object):
    def __init__(self):
        self.fromUser = "xxxxxx@qq.com" 
        self.userPasswd = "xxxxxx"      # 此处是qq邮箱授权码, 不是登录密码
        self.smtpAddr = "smtp.qq.com"


    # 构造邮件结构
    # toAddrs 收件人可以是多个,["xxx@qq.com","xxx@qq.com"], subject 邮件的主题, msg 邮件的内容
    def mailStructure(self, toAddrs, subject, msg):
        # 邮件对象:
        mailMsg = MIMEMultipart()
        mailMsg['Subject'] = ("Hello <%s>" % subject)
        mailMsg['From'] = ("Python管理员 <%s>" % self.fromUser)
        mailMsg['To'] = ','.join(toAddrs)
        # 邮件正文是MIMEText :
        mailMsg.attach(MIMEText(msg, 'html', 'utf-8'))


        # 发送文件附件, 需要用到附件对象MIMEBase对象, 需要引入from email.mime.multipart import MIMEBase
        # 添加附件就是加上一个MIMEBase,从本地读取一个文件:
        with open(r"C:\Users\YJ\Desktop\aaa.txt", "rb") as f:
            # 设置附件的MIME和文件名,这里是png类型:
            mime = MIMEBase("txta", "txt", filename="test.txt")
            # 加上必要的头信息:
            mime.add_header('Content-Disposition', 'attachment', filename='test.txt')
            mime.add_header('Content-ID', '<0>')
            mime.add_header('X-Attachment-Id', '0')
            # 把附件的内容读进来:
            mime.set_payload(f.read())
            # 用Base64编码:
            encoders.encode_base64(mime)
            # 添加到MIMEMultipart:
            mailMsg.attach(mime)
        return mailMsg.as_string()
    # 发送邮件
    def sendMail(self, toAddrs, subject, msg):
        mailMsg_as_string = self.mailStructure(toAddrs, subject, msg)
        # 连接服务器发送邮件
        try:
            server = smtplib.SMTP_SSL(self.smtpAddr, 465)
            server.connect(self.smtpAddr)  # 连接smtp服务器
            server.login(self.fromUser, self.userPasswd)  # 登录邮箱
            server.sendmail(self.fromUser, toAddrs, mailMsg_as_string)  # 发送邮件
            server.quit()
        except Exception:
            print("Error: unable to send email")

a = SendMail()
a.sendMail(["381347268@qq.com", "44934875@qq.com"], "测试主题", "测试内容")

  • 效果图
    纯文本附件效果图

 

发送excel表格附件

???? 代码如下:

#! /usr/bin/env python
# _*_ coding: utf-8 _*_
# @Time   :2020/6/30 9:51
# @Auther :yanjie.li
# @Email  :381347268@qq.com
# @File   :sedMailExcel.py
import smtplib, time
from email.mime.text import MIMEText
from email.mime.multipart import MIMEMultipart


class EmailSender(object):
    def __init__(self):
        self.sender_user = 'ryb.monitor@yottacloud.cn'   #发件人邮箱地址
        self.sender_password = 'xxxxxxxxxx'        #发件人邮箱密码
        self.smtp_server_addr = 'smtp.exmail.qq.com'     #smtp服务器地址
        self.smtp_server_port = 465                      #smtp服务器端口


    def main_email(self, text, xlsx_path, xlsx_name):
        '''
        邮件主题,包含邮件正文 + excel 附件
        Args:
            text:邮件正文内容
            xlsx_path: excel文件路径
            xlsx_name: excel文件,例如a.xlsx
        Returns: 返回要发送的数据,正文和附件
        '''
        msg =MIMEMultipart()

        #添加纯文本,邮件文本内容,字符串格式
        text_msg = MIMEText(text, 'html', 'utf-8')
        msg.attach(text_msg)

        #将xlsx文件作为内容发送到对方的邮箱读取excel,rb形式读取,对于MIMEText()来说默认的编码形式是base64 对于二进制文件来说没有设置base64,会出现乱码
        excel_msg = MIMEText(open(xlsx_path, 'rb').read(), 'base64', 'utf-8')
        #设置文件再附件当中的名字
        excel_msg.add_header('Content-Disposition', 'attachment', filename=('gbk', '', xlsx_name))
        #添加到邮件内容msg中
        msg.attach(excel_msg)

        return msg


    def login_email(self):
        server = smtplib.SMTP_SSL(self.smtp_server_addr, self.smtp_server_port)   #连接smtp服务器
        server.connect(self.smtp_server_addr)     #连接smtp服务器
        result = server.login(self.sender_user, self.sender_password)    #登陆邮箱
        print("登陆结果: ", result)
        return server


    def send_email(self, title, to_receiver, msg):
        '''
        发送邮件
        Args:
            title: 邮件的主题
            to_receiver: 收件人邮箱地址,可以是列表
            msg: main_email函数返回的邮件主体
        Returns:
        '''
        server = self.login_email()

        msg['Subject'] = title
        msg['From'] = self.sender_user
        msg['To'] = ','.join(to_receiver)
        server.sendmail(self.sender_user, to_receiver, msg.as_string())   #发送邮件


sed_mail = EmailSender()
text = time.strftime('%Y-%m-%d') + "数据统计,详情见附件"
msg = sed_mail.main_email(text, r'小程序日报V2.0(试行版).xlsx', '小程序日报.xlsx')
sed_mail.send_email(title='数据统计', to_receiver=['yanjie.li@yottacloud.cn', '381347268@qq.com'], msg=msg)

作者:别来无恙-,发布于:2020/06/30
原文:https://www.cnblogs.com/yanjieli/p/13214276.html