python SMTP 发送邮件

SMTP 发送邮件过程

1.连接到服务器

2.登录(根据需要)

3.发出服务请求

4.退出

保证邮件能发送成功, 一般需要配置好邮箱设置. 网页登录邮件, 检查 "POP3/SMTP服务" 状态是否开启, 同时可找到SMTP服务器(如 smtp.sina.cn).

登录时使用自己的邮箱账号和密码即可.

Python 有一个 smtplib 模块用于发送邮件, 发送邮件只需实例化 smtplib.SMTP 类.

SMTP类方法

sendmail(from, to, msg[, mopts, ropts])      将 msg  从 from(发件人) 发送至 to(收件人列表或无组表示). 还可以选择性地设置 ESMTP 邮件(mopts) 和收件人 (ropts) 选项.

ehlo() 或 helo()  使用 EHLO 或 HELO 初始化 SMTP 或 ESMTP 服务器对话. 这是可选的, 因为 sendmail() 会在需要时自动调用相关内容.

starttls(keyfile = None, certfile = None)   让服务器启用 TLS 模式, 如果给定了 keyfile 或 cerfile, 则它们用来创建安全套接字.

set_debuglevel(level)  为服务器通信设置调试级别.

quit()  关闭连接并退出

login(user, passwd)   使用用户名和密码登录 SMTP 服务器

邮件消息对象

邮件对象使用 Messag 类, 如果构造一个 MIMEText 对象, 就表示一个文本邮件对象, 如果构造一个 MIMEImage 对象, 就表示一个作为附件的图片, 要把多个对象组合起来, 就用 MIMEMultipart 对象, 而 MIMEBase 可以表示任何对象.

它们之间的关系如下:

Message
+- MIMEBase
   +- MIMEMultipart
   +- MIMENonMultipart
      +- MIMEMessage
      +- MIMEText
      +- MIMEImage

将一个图片嵌入到正文

邮件服务商大都会自动屏蔽带有外链的图片, 因为不知道这些链接是否指向恶意网站. 因此要把图片嵌入到邮件正文中, 我们需先按照发送附件的方式, 先把邮件作为附件添加进去, 然后在 HTML 中通过引用 src="cid:0"这种方式嵌入, 注意其中的id为插入附件时指定的id.

htmlText = '<html><body><h1>{}</h1><p><img src="cid:{}"></p></body></html>'.format(text, imgId)
        mimeText = MIMEText(htmlText, 'html', "utf-8")
        self.msg.attach(mimeText)

完整源码示例 

from email import encoders
from email.mime.text import MIMEText
from email.mime.multipart import MIMEMultipart
from email.header import Header
from email.mime.base import MIMEBase
from smtplib import SMTP
import os.path


class SmtpEmail():
    def __init__(self, serverAddr, user, passwd):
        self.serverAddr = serverAddr
        self.user = user
        self.passwd = passwd
        self.id = 0
        self.msg = MIMEMultipart()
        self.msg['Subject'] = Header("无主题", "utf-8")
        self.msg['From'] = Header(user)
        self.toAddrs = []

    def addToAddr(self, toAddr):
        self.toAddrs.append(toAddr)

    def setSubject(self, subject):
        self.msg['Subject'] = Header(subject, "utf-8")

    def addPlainText(self, text):
        # 这里本可以像下面这样创建一个 plain 的消息, 但是部分客户端软件不能同时显示 plain 和 html, 因此将 plain 转换为 html.
        # mimeText = MIMEText(text, "plain", "utf-8")
        htmlText = '<html><body><h1>{}</h1></body></html>'.format(text)
        mimeText = MIMEText(htmlText, 'html', "utf-8")
        self.msg.attach(mimeText)
        
    def addTextImage(self, text, imgId):
        htmlText = '<html><body><h1>{}</h1><p><img src="cid:{}"></p></body></html>'.format(text, imgId)
        mimeText = MIMEText(htmlText, 'html', "utf-8")
        self.msg.attach(mimeText)

    def addAttachment(self, filePath, mainType, subType):
        with open(filePath, 'rb') as f:
            id = self.id
            self.id += 1
            fileBaseName = os.path.basename(filePath);
            mime = MIMEBase(mainType, subType, filename = fileBaseName)
            mime.add_header("Content-Disposition", "attachment", filename = fileBaseName)
            mime.add_header("Content-ID", "<{}>".format(id))
            mime.add_header("X-Attachment-Id", "{}".format(id))
            mime.set_payload(f.read())
            encoders.encode_base64(mime)
            self.msg.attach(mime)
            return id
        return None

    def sendTo(self):
        assert self.toAddrs, "收件人不能为空"
        self.smtp = SMTP(self.serverAddr, 25)
        self.smtp.set_debuglevel(1)
        self.smtp.login(self.user, self.passwd)
        self.smtp.sendmail(self.user, self.toAddrs, self.msg.as_string())
        self.smtp.quit()
        self.smtp.close()

def main():
    import argparse
    parser = argparse.ArgumentParser()
    parser.add_argument("-user", "--user")
    parser.add_argument("-passwd", "--passwd")
    args = parser.parse_args()
    user = args.user
    passwd = args.passwd
    assert user and passwd, "invalid user or passwd."

    smtpEmail = SmtpEmail("smtp.sina.cn", user, passwd)
    smtpEmail.addToAddr(user) # 发送一个邮件给自己
    smtpEmail.setSubject("测试邮件")
    id = smtpEmail.addAttachment("file/come_on.png", "image", "png")
    if id is not None:
        smtpEmail.addTextImage("Come on", id)
    smtpEmail.addPlainText("This is an automatically sent email, please do not reply! 
Thank you.
")
    smtpEmail.addPlainText("This is an automatically sent email, please do not reply! 
Thank you.
")
    smtpEmail.addPlainText("This is an automatically sent email, please do not reply! 
Thank you.
")
    smtpEmail.addAttachment("file/test.xlsx", "file", "xlsx")
    smtpEmail.sendTo()



if __name__ == "__main__":
    main()
原文地址:https://www.cnblogs.com/diysoul/p/10631235.html