本文以第三方QQ邮箱服务器演示如何使用python的smtplib+email完成邮箱发送功能
一、设置开启SMTP服务并获取授权码
开启QQ邮箱SMTP服务
开启的最后一步是发送短信验证,获取 authorization。 QQ官方获取授权码的帮助文档。
使用SMTP服务有POP和IMAP(Internet Message Access Protocol)两种协议,我们选择使用IMAP,具体差异查看QQ邮箱帮助文档。
使用IMAP服务的SSL加密方式的通用配置如下:
接收邮件服务器:imap.qq.com,使用SSL,端口号993
发送邮件服务器:smtp.qq.com,使用SSL,端口号465或587
账户名:您的QQ邮箱账户名(如果您是VIP帐号或Foxmail帐号,账户名需要填写完整的邮件地址)
密码:您的QQ邮箱authorization
电子邮件地址:您的QQ邮箱的完整邮件地址
二、发送文本类型的邮箱
import smtplib from email.mime.text import MIMEText # 1.连接邮件服务器 smtpHost = "smtp.qq.com" # 邮件服务器地址 port = 465 # 邮件服务器端口 server = smtplib.SMTP_SSL(smtpHost, port) # 2.登录服务 sender = '418***167@qq.com' # 发件人邮箱账号 authorization = 'spi********idj' # QQ邮箱授权码 server.login(sender, authorization) # 括号中对应的是发件人邮箱账号、邮箱密码 # 3.构造邮件内容 # 3.1 创建邮箱容器 mailboxContainer = MIMEText('Hello Python!', "plain", "utf-8") # 创建文本类型容器 # 3.2 定义容器内容 mailboxContainer['Subject'] = "python发送的邮件" # 邮箱主题 mailboxContainer['From'] = sender # 邮箱发送人 receiver_to = ['y****@****.com'] mailboxContainer["To"] = ",".join(receiver_to) # 邮箱接收人 receiver_cc = [] mailboxContainer['Cc'] = ",".join(receiver_cc) # 邮箱抄送人 # 4.发送邮件 receiver = receiver_to + receiver_cc # 接收邮箱的人(包含接收和抄送) server.sendmail(sender, receiver, mailboxContainer.as_string()) # 5.关闭连接 server.quit()
收件结果如下:
三、发送HTML类型的邮件
import smtplib from email.mime.image import MIMEImage from email.mime.multipart import MIMEMultipart from email.mime.text import MIMEText # 1.连接邮件服务器 smtpHost = "smtp.qq.com" # 邮件服务器地址 port = 465 # 邮件服务器端口 server = smtplib.SMTP_SSL(smtpHost, port) # 2.登录服务 sender = '418XXXX167@qq.com' # 发件人邮箱账号 authorization = 'spiXXXXXXXidj' # QQ邮箱授权码 server.login(sender, authorization) # 括号中对应的是发件人邮箱账号、邮箱密码 # 3.构造邮件内容 # 3.1 创建邮箱容器 # mailboxContainer = MIMEText('邮件正文内容', "plain", "utf-8") # 创建文本类型容器 mailboxContainer = MIMEMultipart() # 创建混合类型容器 # 3.2 定义容器内容 mailboxContainer['Subject'] = "测试python发送邮件" # 邮箱主题 mailboxContainer['From'] = sender # 邮箱发送人 receiver_to = ['yXXo@XXXXX.com'] mailboxContainer["To"] = ",".join(receiver_to) # 邮箱接收人 receiver_cc = [] mailboxContainer['Cc'] = ",".join(receiver_cc) # 邮箱抄送人 # 混合类型,添加html内容 mail_msg = """ <p>Python 邮件发送测试...</p> <p>图片演示:</p> <p><img src="cid:image1"></p> """ mailboxContainer.attach(MIMEText(mail_msg, 'html', 'utf-8')) # 读取图片信息 with open(r".h5_img.jpg", "rb") as f: msg = f.read() msgImage = MIMEImage(msg) # 定义图片 ID,在 HTML 文本中引用 msgImage.add_header('Content-ID', '<image1>') mailboxContainer.attach(msgImage) # 4.发送邮件 receiver = receiver_to + receiver_cc # 接收邮箱的人(包含接收和抄送) server.sendmail(sender, receiver, mailboxContainer.as_string()) # 5.关闭连接 server.quit()
接收结果如下:
四、发送带附件的邮件
import smtplib from email.mime.image import MIMEImage from email.mime.multipart import MIMEMultipart from email.mime.text import MIMEText # 1.连接邮件服务器 smtpHost = "smtp.qq.com" # 邮件服务器地址 port = 465 # 邮件服务器端口 server = smtplib.SMTP_SSL(smtpHost, port) # 2.登录服务 sender = '41XXXX7@qq.com' # 发件人邮箱账号 authorization = 'spXXXXXXdj' # QQ邮箱授权码 server.login(sender, authorization) # 括号中对应的是发件人邮箱账号、邮箱密码 # 3.构造邮件内容 # 3.1 创建邮箱容器 # mailboxContainer = MIMEText('邮件正文内容', "plain", "utf-8") # 创建文本类型容器 mailboxContainer = MIMEMultipart() # 创建混合类型容器 # 3.2 定义容器内容 mailboxContainer['Subject'] = "带附件的邮箱" # 邮箱主题 mailboxContainer['From'] = sender # 邮箱发送人 receiver_to = ['yXXX@XXXXX.com'] mailboxContainer["To"] = ",".join(receiver_to) # 邮箱接收人 receiver_cc = [] mailboxContainer['Cc'] = ",".join(receiver_cc) # 邮箱抄送人 # # 混合类型,添加文本内容 mailboxContainer.attach(MIMEText('测试带附件的邮箱', "plain", "utf-8")) # 构造文本附件 with open(r". ext.txt", "rb") as f: msg = f.read() att1 = MIMEText(msg, 'base64', 'utf-8') att1["Content-Type"] = 'application/octet-stream' att1["Content-Disposition"] = 'attachment; filename="text.txt"' # 这里的filename可以任意写,写什么名字,邮件附件中显示什么名字 mailboxContainer.attach(att1) # 构造图片附件 with open(r".h5_img.jpg", "rb") as f: msg = f.read() att2 = MIMEText(msg, 'base64', 'utf-8') att2["Content-Type"] = 'application/octet-stream' # att2["Content-Disposition"] = 'attachment; filename="h5_img"' # 这里的filename可以任意写,写什么名字,邮件中显示什么名字 att2.add_header('content-disposition', 'attachment', filename='h5.jpg') # 与上面注释代码功能一样 mailboxContainer.attach(att2) # 4.发送邮件 receiver = receiver_to + receiver_cc # 接收邮箱的人(包含接收和抄送) server.sendmail(sender, receiver, mailboxContainer.as_string()) # 5.关闭连接 server.quit()
接收结果如下:
五、初步封装
import os import smtplib from email.mime.image import MIMEImage from email.mime.multipart import MIMEMultipart from email.mime.text import MIMEText from utils.file import file class SMTP: def __init__(self, smtp_host="smtp.qq.com", port=465): # 连接邮件服务器 self.__server = smtplib.SMTP_SSL(smtp_host, port) self.__sender = None # 发件人邮箱账号 self.__mailboxContainer = MIMEMultipart() # 创建邮箱容器 self.__receiver = [] def quit(self): self.__server.quit() def login(self, account, authorization): """登录邮箱服务器""" self.__sender = account self.__server.login(account, authorization) # 括号中对应的是发件人邮箱账号、邮箱密码 def add_subject(self, subject): """添加邮件主题""" self.__mailboxContainer['Subject'] = subject # 邮箱主题 def add_receiver(self, receiver_to: list, receiver_cc: list = None): """ 添加邮件接收人 receiver_to:收件人 receiver_cc:抄送人 """ self.__mailboxContainer["From"] = self.__sender self.__mailboxContainer["To"] = ",".join(receiver_to) # 邮箱接收人 self.__mailboxContainer['Cc'] = ",".join(receiver_cc) # 邮箱抄送人 self.__receiver = receiver_to + receiver_cc def add_content(self, content, mail_type="plain", append_imgs: list = None): """ 添加邮箱内容 content:邮箱内容 mail_type:内容的类型 append_imgs:当为html类型时追加图片内容 """ if mail_type != "html" and append_imgs is not None: raise ValueError(f"main_type的值不为html,但append_img不是空") if mail_type == "html" and append_imgs is not None: for append_img in append_imgs: img_tag = f"<p><img src='cid:image{append_imgs.index(append_img)}'></p>" content += img_tag # 读取图片信息 with open(append_img, "rb") as f: msg = f.read() msgImage = MIMEImage(msg) # 定义图片 ID,在 HTML 文本中引用 msgImage.add_header('Content-ID', f'<image{append_imgs.index(append_img)}>') self.__mailboxContainer.attach(msgImage) self.__mailboxContainer.attach(MIMEText(content, mail_type, "utf-8")) def add_attach(self, file_path): """添加单个附件""" if not os.path.exists(file_path): raise ValueError(f"文件【{file_path}】不存在") if not os.path.isfile(file_path): raise ValueError(f"【{file_path}】不是文件") # 构造文本附件 with open(file_path, "rb") as f: msg = f.read() att = MIMEText(msg, 'base64', 'utf-8') att["Content-Type"] = 'application/octet-stream' filename = file.get_path_last_name(file_path) att["Content-Disposition"] = f'attachment; filename="{filename}"' # 这里的filename可以任意写,写什么名字,邮件附件中显示什么名字 self.__mailboxContainer.attach(att) def add_attachs(self, file_paths: list): """添加多个附件""" for file_path in file_paths: self.add_attach(file_path) def send(self): """发送邮件""" self.__server.sendmail(self.__sender, self.__receiver, self.__mailboxContainer.as_string()) if __name__ == '__main__': mailbox = SMTP() # 登录邮箱服务器 account = '418XXXX167@qq.com' authorization = 'spiXXXXXidj' # QQ邮箱授权码 mailbox.login(account, authorization) # 添加邮箱主题 mailbox.add_subject("使用SMTP封装类发送的邮件") # 添加邮箱接收人 receiver_to = ['yXXXo@XXX.com'] # 收件人 receiver_cc = ['41XXX7@qq.com'] # 抄送人 mailbox.add_receiver(receiver_to, receiver_cc) # 添加邮箱内容 mail_content = """ <p>Python 邮件发送测试...</p> <p>追加图片如下</p> """ append_imgs = [r".h5_img.jpg", r".doudou.png"] mailbox.add_content(mail_content, mail_type="html", append_imgs=append_imgs) # 添加附件 mailbox.add_attach("text.txt") mailbox.add_attachs([r".h5_img.jpg", r".doudou.png"]) # 发送邮箱 mailbox.send()
发送结果如下