目录
- 1.概述
- 2.邮件模块介绍
- 2.1. 建立连接类型
- 3.发送邮件
- 3.1.发送非安全连接邮件
- 3.2.发送安全连接邮件
- 4.设置邮件内容格式
- 4.1.邮件文本三种类型
1.概述
这篇文章主要介绍python调用工具包实现发送邮件服务。在第二篇文章中介绍封装邮件服务工具类,该工具类将可以应用到其他的项目中。
2.邮件模块介绍
python内置了发送邮件的模块,因此不需要单独安装。
- smtplib 模块负责发送邮件
- email 模块负责格式化邮件内容样式
2.1. 建立连接类型
当使用smtplib模块建立发送邮件连接时可以分为非安全和安全连接两种方式。
安全连接: 当python使用smtplib模块调用邮箱服务端发送邮件过程,传输层使用了SSL加密,避免了明文传递邮件内容,通过拦截请求获取邮件内容和登录账号密码。
非安全连接:邮箱服务端采用明文发送邮件,通过连接请求可以获取邮件内容和登录账号密码。
3.发送邮件
使用python发送邮件之前,需要登录邮箱开启SMTP服务才可以发送邮件。每家的邮箱开启入口不同,开启方式搜索具体产品的邮箱。
3.1.发送非安全连接邮件
建立非安全连接邮箱服务端默认使用25端口发送邮件。
import smtplib | |
from email.mime.text import MIMEText | |
#设置服务器所需信息 | |
#邮箱服务器地址 | |
mail_host = 'mail.******.com' | |
#邮箱登录用户名 | |
mail_user = '******@qq.com' | |
#密码(部分邮箱为授权码) | |
mail_pass = '123456' | |
#邮件发送方邮箱地址 | |
sender = '******@qq.com' | |
#邮件接受方邮箱地址,注意需要[]包裹,这意味着你可以写多个邮件地址群发 | |
receivers = ['32321232@qq.com'] | |
#设置email信息 | |
#邮件内容设置 | |
message = MIMEText('content','plain','utf-8') | |
#邮件主题 | |
message['Subject'] = 'title' | |
#发送方信息 | |
message['From'] = sender | |
#接受方信息 | |
message['To'] = receivers[0] | |
#登录并发送邮件 | |
try: | |
# 建立非安全连接smtplib.SMTP() | |
smtpObj = smtplib.SMTP() | |
smtpObj.connect(mail_host,25) | |
#登录到服务器 | |
smtpObj.login(mail_user,mail_pass) | |
#发送 | |
smtpObj.sendmail( | |
sender,receivers,message.as_string()) | |
#退出 | |
smtpObj.quit() | |
print('success') | |
except smtplib.SMTPException as e: | |
print('error',e) #打印错误 |
3.2.发送安全连接邮件
建立非安全连接邮箱服务端默认使用465端口发送邮件。
import smtplib | |
from email.mime.text import MIMEText | |
#设置服务器所需信息 | |
#邮箱服务器地址 | |
mail_host = 'mail.******.com' | |
#邮箱登录用户名 | |
mail_user = '******@qq.com' | |
#密码(部分邮箱为授权码) | |
mail_pass = '123456' | |
#邮件发送方邮箱地址 | |
sender = '******@qq.com' | |
#邮件接受方邮箱地址,注意需要[]包裹,这意味着你可以写多个邮件地址群发 | |
receivers = ['32321232@qq.com'] | |
#设置email信息 | |
#邮件内容设置 | |
message = MIMEText('content','plain','utf-8') | |
#邮件主题 | |
message['Subject'] = 'title' | |
#发送方信息 | |
message['From'] = sender | |
#接受方信息 | |
message['To'] = receivers[0] | |
# 登录并发送邮件 | |
# 建立安全连接SMTP_SSL,注意端口号默认使用465 | |
with smtplib.SMTP_SSL(mail_host, timeout=10, port=465) as smtpObj: | |
try: | |
# 登录到服务器 | |
smtpObj.login(mail_user, mail_pass) | |
# 发送 | |
smtpObj.sendmail( | |
sender, receivers, message.as_string()) | |
print('success') | |
except Exception as e: | |
print(e) |
在使用安全连接发送邮件时可能会抛出下面的异常,这个异常的含义是Python端与邮箱服务端建立连接SSL版本号不对。
ssl.SSLError: [SSL: WRONG_VERSION_NUMBER] wrong version number (_ssl.c:997)
这个异常出现的原因:
发送邮件的邮箱服务端没有开启SSL或者不支持,这种清空可以登录邮箱服务端确认,如果不支持只能使用非安全建立连接。
端口号错误造成,邮箱服务端模式使用465端口号连接SSL连接,如果python端设置的端口号与邮箱服务端端口号不一致建立连接也会报上面的异常。
4.设置邮件内容格式
python内置的email模块负责设置邮件内容格式,它包含三个模块对应邮件三种类型的格式。下面具体介绍他们的区别。
from email.mime.text import MIMEText | |
from email.mime.image import MIMEImage | |
from email.mime.multipart import MIMEMultipart |
4.1.邮件文本三种类型
1.MIMEText文本类型
发送普通的文本邮件内容,MIMEText对象中有三个需要我们设置的参数,一个是正文内容,一个是正文内容的类型,例如:”text/plain”和”text/html”,一个是正文内容的编码。
plain构造普通文本
# 文本内容 | |
text_info = 'hello world ' | |
# 构造普通文本对象,包含三个参数,邮件内容,类型,编码 | |
text_sub = MIMEText(text_info,'plain', 'utf-8') |
完整代码
import smtplib | |
from email.mime.text import MIMEText | |
# 创建邮件连接 | |
def create_email_connect(mail_host, timeout, port): | |
try: | |
return smtplib.SMTP_SSL(host=mail_host, timeout=timeout, port=port) | |
except Exception as e: | |
print(e) | |
# 构建邮件内容模板 | |
def email_content(): | |
# 邮件内容设置 | |
text_info = 'hello world ' | |
message = MIMEText(text_info, 'plain', 'utf-8') | |
# 邮件主题 | |
message['Subject'] = 'title' | |
# 发送方信息 | |
message['From'] = sender_account | |
# 接受方信息 | |
message['To'] = receivers_account[0] | |
return message | |
def sent_email(mail_user, mail_pass, mail_host, sender_account, receivers_account, timeout=10, port=465): | |
with create_email_connect(mail_host, timeout, port) as smtpObj: | |
try: | |
smtpObj.login(mail_user, mail_pass) | |
# 发送邮件 | |
smtpObj.sendmail( | |
sender_account, receivers_account, email_content().as_string()) | |
print('scusses') | |
except Exception as e: | |
print(e) | |
if __name__ == '__main__': | |
# 设置服务器所需信息 | |
# 163邮箱服务器地址 | |
mail_host = 'smtp.163.com' | |
# 163用户名 | |
mail_user = '******@163.com' | |
# 密码(部分邮箱为授权码) | |
mail_pass = '******' | |
# 邮件发送方邮箱地址 | |
sender_account = '******@163.com' | |
# 邮件接受方邮箱地址,注意需要[]包裹,这意味着你可以写多个邮件地址群发 | |
receivers_account = ['******@qq.com'] | |
sent_email(mail_user, mail_pass, mail_host, sender_account, receivers_account) |
构造html文本
# 邮件内容 | |
url = "https://xxxxx.com" | |
html_info = """ | |
<p>点击以下链接,查看邮件详情</p> | |
<p><a href="%s">click me</a></p> | |
<p>i am very glasses for you</p> | |
""" % url | |
# 构建邮件类型html对象 | |
html_sub = MIMEText(html_info, 'html', 'utf-8') | |
# 如果不加下边这行代码的话,上边的文本是不会正常显示的,会把超文本的内容当做文本显示 | |
html_sub["Content-Disposition"] = 'attachment; filename="email.html"' |
构造base64数据流,用于发送文件的时候使用,构造附件代码
txt_file = open(r'D:\python_files\files\hello_world.txt', 'rb').read() | |
txt = MIMEText(txt_file, 'base64', 'utf-8') | |
txt["Content-Type"] = 'application/octet-stream' | |
# 命名发送的附件 | |
txt.add_header('Content-Disposition', 'attachment', filename='hello_world.txt') |
2.MIMEImage图片类型
构造图片类型对象
image_file = open(r'D:\python_files\images\test.png', 'rb').read() | |
image = MIMEImage(image_file) | |
image.add_header('Content-ID', '<image1>') | |
# 命名发送的图片 | |
image["Content-Disposition"] = 'attachment; filename="red_people.png"' |
完整代码
import smtplib | |
from email.mime.image import MIMEImage | |
from email.mime.text import MIMEText | |
# 创建邮件连接 | |
def create_email_connect(mail_host, timeout, port): | |
try: | |
return smtplib.SMTP_SSL(host=mail_host, timeout=timeout, port=port) | |
except Exception as e: | |
print(e) | |
# 构建邮件内容模板 | |
def email_content(): | |
# 邮件内容设置 | |
image_file = open(r'./白玉堂.jpg', 'rb').read() | |
message = MIMEImage(image_file) | |
# 命名发送的图片 | |
message["Content-Disposition"] = 'attachment; filename="red_people.png"' | |
# 邮件主题 | |
message['Subject'] = 'title' | |
# 发送方信息 | |
message['From'] = sender_account | |
# 接受方信息 | |
message['To'] = receivers_account[0] | |
return message | |
def sent_email(mail_user, mail_pass, mail_host, sender_account, receivers_account, timeout=10, port=465): | |
with create_email_connect(mail_host, timeout, port) as smtpObj: | |
try: | |
smtpObj.login(mail_user, mail_pass) | |
# 发送邮件 | |
smtpObj.sendmail( | |
sender_account, receivers_account, email_content().as_string()) | |
print('scusses') | |
except Exception as e: | |
print(e) | |
if __name__ == '__main__': | |
# 设置服务器所需信息 | |
# 163邮箱服务器地址 | |
mail_host = 'smtp.163.com' | |
# 163用户名 | |
mail_user = '******@163.com' | |
# 密码(部分邮箱为授权码) | |
mail_pass = '******' | |
# 邮件发送方邮箱地址 | |
sender_account = '******@163.com' | |
# 邮件接受方邮箱地址,注意需要[]包裹,这意味着你可以写多个邮件地址群发 | |
receivers_account = ['******@qq.com'] | |
sent_email(mail_user, mail_pass, mail_host, sender_account, receivers_account) |
3.MIMEMultipart
对象创建的类型有三种,此模块主要是通过attach方法把上边构造的内容传入到邮件的整体内容中
邮件类型为”multipart/alternative”的邮件正文中包括纯文本正文(text/plain)和超文本正文(text/html)。
邮件类型为”multipart/related”的邮件正文中包括图片,声音等内嵌资源。
邮件类型为”multipart/mixed”的邮件包含附件,图片,文本等都可以添加,所以发的内容多的话一般是用这个的,选择mixed类型,什么内容都可以发。
MIMEMultipart使用方法
MIMEMultipart(‘mixed’).attach(MIMEText或者MIMEImage对象),因为MIMEMultipart对象代表邮件本身,把其他的构造内容添加到MIMEMultipart对象中就可以把文本,html,附件等一起发送。
构造图片类型内容
import smtplib | |
from email.mime.image import MIMEImage | |
from email.mime.multipart import MIMEMultipart | |
from email.mime.text import MIMEText | |
# 创建邮件连接 | |
def create_email_connect(mail_host, timeout, port): | |
try: | |
return smtplib.SMTP_SSL(host=mail_host, timeout=timeout, port=port) | |
except Exception as e: | |
print(e) | |
# 构建邮件内容模板 | |
def email_content(): | |
# 邮件内容设置 | |
image_file = open(r'./白玉堂.jpg', 'rb').read() | |
# 创建MIMEImage类型对象 | |
mimei_image = MIMEImage(image_file) | |
message = MIMEMultipart('mixed') | |
# attach包装MIMEImage对象 | |
message.attach(mimei_image) | |
# 命名发送的图片 | |
message["Content-Disposition"] = 'attachment; filename="red_people.png"' | |
# 邮件主题 | |
message['Subject'] = 'title' | |
# 发送方信息 | |
message['From'] = sender_account | |
# 接受方信息 | |
message['To'] = receivers_account[0] | |
return message | |
def sent_email(mail_user, mail_pass, mail_host, sender_account, receivers_account, timeout=10, port=465): | |
with create_email_connect(mail_host, timeout, port) as smtpObj: | |
try: | |
smtpObj.login(mail_user, mail_pass) | |
# 发送邮件 | |
smtpObj.sendmail( | |
sender_account, receivers_account, email_content().as_string()) | |
print('scusses') | |
except Exception as e: | |
print(e) | |
if __name__ == '__main__': | |
# 设置服务器所需信息 | |
# 163邮箱服务器地址 | |
mail_host = 'smtp.163.com' | |
# 163用户名 | |
mail_user = '******@163.com' | |
# 密码(部分邮箱为授权码) | |
mail_pass = '******' | |
# 邮件发送方邮箱地址 | |
sender_account = '******@163.com' | |
# 邮件接受方邮箱地址,注意需要[]包裹,这意味着你可以写多个邮件地址群发 | |
receivers_account = ['******@qq.com'] | |
sent_email(mail_user, mail_pass, mail_host, sender_account, receivers_account) |
构造普通类型发送附件邮件
import smtplib | |
from email.mime.image import MIMEImage | |
from email.mime.multipart import MIMEMultipart | |
from email.mime.text import MIMEText | |
# 创建邮件连接 | |
def create_email_connect(mail_host, timeout, port): | |
try: | |
return smtplib.SMTP_SSL(host=mail_host, timeout=timeout, port=port) | |
except Exception as e: | |
print(e) | |
# 构建邮件内容模板 | |
def email_content(): | |
# 邮件内容设置 | |
text_file = open(r'./白玉堂.jpg', 'rb').read() | |
# 创建MIMEImage类型对象 | |
mime_obj = MIMEText(text_file, 'base64', 'utf-8') | |
# 命名发送的图片 | |
mime_obj.add_header('Content-Disposition', 'attachment', filename='red_people.jpg') | |
mime_obj.add_header('Content-Type', 'application/octet-stream') | |
# 构建mime对象 | |
message = MIMEMultipart('mixed') | |
# attach包装MIMEImage对象 | |
message.attach(mime_obj) | |
# 邮件主题 | |
message['Subject'] = '测试邮件' | |
# 发送方信息 | |
message['From'] = sender_account | |
# 接受方信息 | |
message['To'] = receivers_account[0] | |
return message | |
def sent_email(mail_user, mail_pass, mail_host, sender_account, receivers_account, timeout=10, port=465): | |
with create_email_connect(mail_host, timeout, port) as smtpObj: | |
try: | |
smtpObj.login(mail_user, mail_pass) | |
# 发送邮件 | |
smtpObj.sendmail( | |
sender_account, receivers_account, email_content().as_string()) | |
print('scusses') | |
except Exception as e: | |
print(e) | |
if __name__ == '__main__': | |
# 设置服务器所需信息 | |
# 163邮箱服务器地址 | |
mail_host = 'smtp.163.com' | |
# 163用户名 | |
mail_user = '******@163.com' | |
# 密码(部分邮箱为授权码) | |
mail_pass = '******' | |
# 邮件发送方邮箱地址 | |
sender_account = '******@163.com' | |
# 邮件接受方邮箱地址,注意需要[]包裹,这意味着你可以写多个邮件地址群发 | |
receivers_account = ['******@qq.com'] | |
sent_email(mail_user, mail_pass, mail_host, sender_account, receivers_account) |