一、前言
SMTP是发送邮件的协议,Python内置对SMTP的支持,可以发送纯文本邮件、HTML邮件以及带附件的邮件。 Python对SMTP支持有smtplib 和email 两个模块
二、模块安装
1. smtplib
smtplib不能直接使用pip install smtplib
通常发送邮件用PyEmail,所以直接pip install PyEmail就行
PyEmail (0.0.1) - Python library to send emails using SMTPLIB library
micropython-smtplib (0.0.0) - Dummy smtplib module for MicroPython
personal (0.1.1) - Easy, secure self notification via email and sms, using smtplib and twilio
aiosmtplib (0.1.4) - asyncio version of smtplib
secure-smtplib (0.1.1) - Secure SMTP subclasses for Python 2
mailclient (0.2.0) - Simplified use of smtplib for Python. Easy email sending.
smtplibaio (1.0.3) - An async version of smtplib
easyemail (0.4.0) - Simple lib abstracting email sending with smtplib.
2. email
pip install emails
三、模块使用简介
1. smtplib模块:
主要通过SMTP类与邮件系统进行交互。使用方法如下:
-
实例化一个SMTP对象: server = smtplib.SMTP(邮件服务地址,端口号) # 正常连接,可配合server.starttls() 使用 server = smtplib.SMTP_SSL(邮件服务地址,端口号) # 使用SSL连接 -
登陆邮件,权限验证: server.login(用户名,密码) -
发送邮件: server.sendmail(发件人邮箱,收件人邮箱,发送内容) -
断开连接: server.quit()
server = smtplib.SMTP(smtp_server, port)
server.starttls()
server.login(from_address, password)
server.set_debuglevel(1)
server.sendmail(From, To, msg.as_string())
server.quit()
2. email模块:
email模块:支持发送的邮件内容为纯文本、HTML内容、图片、附件。 email模块中有几大类来针对不同的邮件内容形式,常用如下:
2.1 MIMEText (文件 or HTML)
MIMEText(msg,type,chartset)
MIMEText('文本', 'plain', 'utf-8')
MIMEText('HTML字符串', 'html', 'utf-8')
msg :文本内容
type :文本类型默认为plain(纯文本),HTML类型为html(type为html时msg也要是html的格式)
chartset: 文本编码,通常使用utf-8
构造TEXT格式的消息
msg = MIMEText("hello.text","plain","utf-8") # 构造Text消息
msg["Subject"] = "xxxxx"
msg["From"] = "xxxx"
msg["To"] = "xxxx"
发送以上构造的邮件内容要使用as_string将构造的邮件内容转换为string形式。
server.sendmail(From,To,msg.as_string)
2.2 MIMEImage、MIMEMultipart:
msg = MIMEMultipart()
# 实例化一个文本对象
msg_sub = MIMEText("hello.text","plain","utf-8")
# 将text消息添加到MIMEMultipart中,作为邮件正文。
msg.attach(msg_sub)
#图片作为附件
img = open(path,"rb").read() # 以rb方式打开并读取图片
msg_img = MIMEImage(img)
# 添加头部信息
msg_img.add_header('Content-Disposition','attachment', filename = "xxxx.png" )
msg_img.add_header('Content-ID','<0>')
#将图片添加到MIMEMultiplart中,作为附件发送。
msg.attach(mag_img)
四、发送纯本文邮件
import smtplib
from email.mime.text import MIMEText
smtp_server = 'smtp.qq.com'
port = 25
from_address = 'xxxxxxxxxx@qq.com'
password = 'xxxxxxxx'
to_address = 'xxxxxxxxxx@qq.com'
subject = 'Python 邮件测试'
content = '这是使用python smtplib+email自动发送的邮件'
msg = MIMEText(content, 'plain', 'utf-8')
msg['Subject'] = subject
msg['From'] = from_address
msg['TO'] = to_address
try:
server = smtplib.SMTP(smtp_server, port)
server.starttls()
server.login(from_address, password)
server.sendmail(from_address, to_address, msg.as_string())
server.quit()
print('发送成功')
except Exception:
print('发送失败')
五、友好的邮件名和邮件主题问题
邮件主题、如何显示发件人、收件人等信息并不是通过SMTP协议发给MTA,而是包含在发给MTA的文本中的,所以,我们必须把From 、To 和Subject 添加到MIMEText中,才是一封完整的邮件。
1)email.utils.parseaddr(address)
2)email.utils.formataddr((name_encoded_by_Header, address))
写邮件的时候,Email的地址可以有两种写法。
一种写法是:xxx@qq.com,另一种写法是:name<xxx@qq.com>。
用前者写法,在邮箱中就会显示为xxx<xxx@qq.com>;
用后者,就会显示为name<xxx@qq.com>,更为清晰、专业。
【有的时候,用前者写法也会显示name,是因为对方邮箱中保存了这个地址,类似于对方手机中保存了手机号和姓名。】
而parseaddr函数就是将str “name<xxx@qq.com>”转换成一个tuple。
from email.header import Header
from email.utils import formataddr, parseaddr
def _format_address(s):
name, address = parseaddr(s)
return formataddr((Header(name, 'utf-8').encode(), address))
from_address = 'xxxxxxxxxx@qq.com'
password = 'xxxxxxxx'
to_address = 'xxxxxxxxxx@qq.com'
subject = 'Python 邮件测试'
content = '这是使用python smtplib+email自动发送的邮件'
msg['Subject'] = subject
msg['From'] = _format_address(u'Python发送<%s>' % from_address)
msg['TO'] = _format_address(u'Name<%s>' % to_address)
六、发送HTML邮件
import smtplib
from email.header import Header
from email.mime.text import MIMEText
from email.utils import formataddr, parseaddr
def _format_address(s):
name, address = parseaddr(s)
return formataddr((Header(name, 'utf-8').encode(), address))
smtp_server = 'smtp.qq.com'
port = 25
from_address = 'xxxxxxxxxx@qq.com'
password = 'xxxxxxxx'
to_address = 'xxxxxxxxxx@qq.com'
subject = 'Python 发送HTML邮件'
content = """
<p>Python 发送HTML邮件</p>
<p><a href="http://www.baidu.com">多学习</a></p>
"""
msg = MIMEText(content, 'html', 'utf-8')
msg['Subject'] = subject
msg['From'] = _format_address(u'Python发送<%s>' % from_address)
msg['TO'] = _format_address(u'Name<%s>' % to_address)
try:
server = smtplib.SMTP(smtp_server, port)
server.login(from_address, password)
server.starttls()
server.sendmail(from_address, to_address, msg.as_string())
server.quit()
print('发送成功')
except Exception:
print('发送失败')
HTML中包含图片
from email.mime.image import MIMEImage
# 添加图片
def addIMG(src, img_id):
img = open(src, 'rb') # 以rb的方式读取img文件
msgImage = MIMEImage(img.read()) # 构建MIMEImage
img.close() # 关闭连接
msgImage.add_header('Content-ID', img_id) # 指定图片文件的Content-ID,<img>标签src用到
return msgImage
msg = MIMEMultipart()
# 添加图片到正文
html = MIMEText('''
<h1>Hello</h1>
<p><img src="cid:0"></p>
<p><img src="cid:2"></p>
''', 'html', 'utf-8')
msg.attach(html)
msg.attach(addIMG("./1.jpg", "0")) # 0与HTML中的cid的对应
msg.attach(addIMG("./2.jpg", "2")) # 2与HTML中的cid的对应
import smtplib
from email.header import Header
from email.mime.image import MIMEImage
from email.mime.multipart import MIMEMultipart
from email.mime.text import MIMEText
from email.utils import formataddr, parseaddr
def _format_address(s):
name, address = parseaddr(s)
return formataddr((Header(name, 'utf-8').encode(), address))
def addIMG(src, img_id):
img = open(src, 'rb')
msgImage = MIMEImage(img.read())
img.close()
msgImage.add_header('Content-ID', img_id)
return msgImage
smtp_server = 'smtp.qq.com'
port = 25
from_address = '1531143881@qq.com'
password = 'keupinibydesjhgi'
to_address = '2303066448@qq.com'
subject = 'Python 发送带附件的邮件'
content = """
<p>Python 发送HTML邮件</p>
<p><a href="http://www.baidu.com">多学习</a></p>
"""
msg = MIMEMultipart()
msg['Subject'] = subject
msg['From'] = _format_address(u'Python发送<%s>' % from_address)
msg['TO'] = _format_address(u'Name<%s>' % to_address)
html = MIMEText('''
<h1>Hello</h1>
<p><img src="cid:0"></p>
<p><img src="cid:2"></p>
''', 'html', 'utf-8')
msg.attach(html)
msg.attach(addIMG("./1.jpg", "0"))
msg.attach(addIMG("./2.jpg", "2"))
try:
server = smtplib.SMTP(smtp_server, port)
server.login(from_address, password)
server.starttls()
server.sendmail(from_address, to_address, msg.as_string())
server.quit()
print('发送成功')
except Exception:
print('发送失败')
七、发送附件
import smtplib
from email.header import Header
from email.mime.multipart import MIMEMultipart
from email.mime.text import MIMEText
from email.utils import formataddr, parseaddr
def _format_address(s):
name, address = parseaddr(s)
return formataddr((Header(name, 'utf-8').encode(), address))
smtp_server = 'smtp.qq.com'
port = 25
from_address = 'xxxxxxxxxx@qq.com'
password = 'xxxxxxxx'
to_address = 'xxxxxxxxxx@qq.com'
subject = 'Python 发送带附件的邮件'
content = """
<p>Python 发送HTML邮件</p>
<p><a href="http://www.baidu.com">多学习</a></p>
"""
msg = MIMEMultipart()
msg['Subject'] = subject
msg['From'] = _format_address(u'Python发送<%s>' % from_address)
msg['TO'] = _format_address(u'Name<%s>' % to_address)
path = "./1.jpg"
att1 = MIMEText(open(path, 'rb').read(), 'base64', 'utf-8')
att1['Content-Type'] = 'application/octet-stream'
att1["Content-Disposition"] = 'attachment; filename="%s"' % "scenery1.jpg"
msg.attach(att1)
path = "./2.jpg"
att2 = MIMEText(open(path, 'rb').read(), 'base64', 'utf-8')
att2['Content-Type'] = 'application/octet-stream'
att2["Content-Disposition"] = 'attachment; filename="%s"' % "scenery2.jpg"
msg.attach(att2)
try:
server = smtplib.SMTP(smtp_server, port)
server.login(from_address, password)
server.starttls()
server.sendmail(from_address, to_address, msg.as_string())
server.quit()
print('发送成功')
except Exception:
print('发送失败')
八、多个收件人
server.sendmail(from_address, [to_address], msg.as_string())
九、发送一个包含HTML(带图片)+ 附件的邮件
import smtplib
from email.header import Header
from email.mime.image import MIMEImage
from email.mime.multipart import MIMEMultipart
from email.mime.text import MIMEText
from email.utils import formataddr, parseaddr
def _format_address(s):
name, address = parseaddr(s)
return formataddr((Header(name, 'utf-8').encode(), address))
def addIMG(src, img_id):
img = open(src, 'rb')
msgImage = MIMEImage(img.read())
img.close()
msgImage.add_header('Content-ID', img_id)
return msgImage
def add_attachment(src,filename):
att = MIMEText(open(src, 'rb').read(), 'base64', 'utf-8')
att['Content-Type'] = 'application/octet-stream'
att["Content-Disposition"] = 'attachment; filename="%s"' % filename
return att
smtp_server = 'smtp.qq.com'
port = 25
from_address = 'xxxxxxxxxx@qq.com'
password = 'xxxxxxxx'
to_address = 'xxxxxxxxxx@qq.com'
subject = 'Python 发送带附件的邮件'
content = """
<p>Python 发送HTML邮件</p>
<p><a href="http://www.baidu.com">多学习</a></p>
"""
msg = MIMEMultipart()
msg['Subject'] = subject
msg['From'] = _format_address(u'Python发送<%s>' % from_address)
msg['TO'] = _format_address(u'Name<%s>' % to_address)
html = MIMEText('''
<div style="width:200px">
<h1>Hello</h1>
<p><img style="width:100%" src="cid:0"></p>
<p><img style="width:100%" src="cid:2"></p>
</div>
''', 'html', 'utf-8')
msg.attach(html)
msg.attach(addIMG("./1.jpg", "0"))
msg.attach(addIMG("./2.jpg", "2"))
att1 = add_attachment('./1.jpg', "1.jpg")
msg.attach(att1)
att2 = add_attachment('./2.jpg', "2.jpg")
msg.attach(att2)
att3 = add_attachment('./dome.xlsx', "dome.xlsx")
msg.attach(att3)
try:
server = smtplib.SMTP(smtp_server, port)
server.login(from_address, password)
server.starttls()
server.sendmail(from_address, to_address, msg.as_string())
server.quit()
print('发送成功')
except Exception:
print('发送失败')
|