SMTP发送邮件
SMTP是发送邮件的协议,Python内置对SMTP的支持,可以发送纯文本邮件、HTML邮件以及带附件的邮件。Python对SMTP支持有smtplib
和email
两个模块,email
负责构造邮件,smtplib
负责发送邮件。
import smtplib
smtpObj = smtplib.SMTP( [host [, port [, local_hostname]]] )
host
- 这是运行SMTP服务器的主机。可以指定主机的IP
地址或域名。这是一个可选参数。port
- 如果提供主机参数,则需要指定SMTP服务器正在侦听的端口。通常这个端口默认值是:25
。local_hostname
-如果SMTP服务器在本地计算机上运行,那么可以只指定localhost
选项。
1、发送纯文本文件
- 给单人发送邮件
#! /usr/bin/env python
# coding=utf-8
from email.mime.text import MIMEText
from email.header import Header
from smtplib import SMTP_SSL
# qq邮箱smtp服务器
host_server = 'smtp.qq.com'
# sender_qq为发件人的qq号码
sender_qq = '...@qq.com'
# pwd为qq邮箱的授权码
pwd = 'nz....hf' ## nz....hf
# 发件人的邮箱
sender_qq_mail = '..@qq.com'
# 收件人邮箱
receiver = '183...@163.com'
# 邮件的正文内容
mail_content = '你好,这是使用python登录qq邮箱发邮件的测试'
# 邮件标题
mail_title = 'Eureka的邮件'
# ssl登录
smtp = SMTP_SSL(host_server)
# set_debuglevel()是用来调试的。参数值为1表示开启调试模式,参数值为0关闭调试模式
smtp.set_debuglevel(1)
smtp.ehlo(host_server)
smtp.login(sender_qq, pwd)
msg = MIMEText(mail_content, "plain", 'utf-8')
msg["Subject"] = Header(mail_title, 'utf-8')
msg["From"] = sender_qq_mail
msg["To"] = receiver
smtp.sendmail(sender_qq_mail, receiver, msg.as_string())
smtp.quit()
- 群发邮件
#! /usr/bin/env python
#coding=utf-8
from email.mime.text import MIMEText
from email.header import Header
from smtplib import SMTP_SSL
#qq邮箱smtp服务器
host_server = 'smtp.qq.com'
#sender_qq为发件人的qq号码
sender_qq = '...@qq.com'
#pwd为qq邮箱的授权码
pwd = 'nzi...bchf'
#发件人的邮箱
sender_qq_mail = '...@qq.com'
#收件人邮箱(读取脚本)
with open('D:/code/PycharmProjects/PythonStudy/venv/Include/电子邮件/email.txt') as f:
for email in f.readlines():
emails = email.strip(',')
receivers = list(emails.split(','))
#邮件的正文内容
mail_content = 'Hi,使用Python登录qq邮箱群发邮件的测试'
#邮件标题
mail_title = '^_^的邮件'
#ssl登录
smtp = SMTP_SSL(host_server)
#set_debuglevel()是用来调试的。参数值为1表示开启调试模式,参数值为0关闭调试模式
smtp.set_debuglevel(1)
smtp.ehlo(host_server)
smtp.login(sender_qq, pwd)
msg = MIMEText(mail_content, "plain", 'utf-8')
msg["Subject"] = Header(mail_title, 'utf-8')
msg["From"] = sender_qq_mail
msg["To"] = Header("receivers test", 'utf-8') ## 接收者的别名
smtp.sendmail(sender_qq_mail, receivers, msg.as_string())
smtp.quit()
- 发送HTML格式的邮件
#! /usr/bin/env python
# coding=utf-8
from email.mime.text import MIMEText
from email.header import Header
from smtplib import SMTP_SSL
# qq邮箱smtp服务器
host_server = 'smtp.qq.com'
# sender_qq为发件人的qq号码
sender_qq = '...@qq.com'
# pwd为qq邮箱的授权码
pwd = 'nz...hf'
# 发件人的邮箱
sender_qq_mail = '...@qq.com'
# 收件人邮箱
with open('D:/code/PycharmProjects/PythonStudy/venv/Include/电子邮件/email.txt') as f:
for email in f.readlines():
emails = email.strip(',')
receiver = list(emails.split(','))
# 邮件的正文内容
mail_content = "你好,<p>这是使用python登录qq邮箱发送HTML格式邮件的测试:</p><p><a href='http://www.baidu.com'>baidu</a></p><img src='https://timgsa.baidu.com/timg?image&quality=80&size=b9999_10000&sec=1583990072584&di=cfc04c054a9f33fb000fd4f207c70ff9&imgtype=0&src=http%3A%2F%2F5b0988e595225.cdn.sohucs.com%2Fimages%2F20190715%2F0c2b2d67886c4d72a90fee16e3fc8659.jpeg'></p>"
# 邮件标题
mail_title = 'Python测试HTML邮件'
# ssl登录
smtp = SMTP_SSL(host_server)
# set_debuglevel()是用来调试的。参数值为1表示开启调试模式,参数值为0关闭调试模式
smtp.set_debuglevel(1)
smtp.ehlo(host_server)
smtp.login(sender_qq, pwd)
msg = MIMEText(mail_content, "html", 'utf-8')
msg["Subject"] = Header(mail_title, 'utf-8') # 发送者别名
msg["From"] = sender_qq_mail
msg["To"] = Header("receiver test", 'utf-8') # 接收者的别名
smtp.sendmail(sender_qq_mail, receiver, msg.as_string())
smtp.quit()
- 发送带附件的邮件
发送带附件的邮件,首先要创建MIMEMultipart()
实例,然后构造附件,如果有多个附件,可依次构造,最后使用smtplib.smtp
发送:
#! /usr/bin/env python
# coding=utf-8
import smtplib
from email.mime.text import MIMEText
from email.header import Header
from smtplib import SMTP_SSL
from email.mime.text import MIMEText
from email.mime.multipart import MIMEMultipart
from email.header import Header
# qq邮箱smtp服务器
host_server = 'smtp.qq.com'
# sender_qq为发件人的qq号码
sender_qq = '...@qq.com'
# pwd为qq邮箱的授权码
pwd = 'nz...chf'
# 发件人的邮箱
sender_qq_mail = '...@qq.com'
# 收件人邮箱
with open('D:/code/PycharmProjects/PythonStudy/venv/Include/电子邮件/email.txt') as f:
for email in f.readlines():
emails = email.strip(',')
receiver = list(emails.split(','))
# 邮件的正文内容
mail_content = "你好,<p>这是使用python登录qq邮箱发送HTML格式邮件的测试</p><img src='https://timgsa.baidu.com/timg?image&quality=80&size=b9999_10000&sec=1583990072584&di=cfc04c054a9f33fb000fd4f207c70ff9&imgtype=0&src=http%3A%2F%2F5b0988e595225.cdn.sohucs.com%2Fimages%2F20190715%2F0c2b2d67886c4d72a90fee16e3fc8659.jpeg'></p>"
# 邮件标题
mail_title = 'Python测试HTML邮件'
# 邮件正文内容
msg = MIMEMultipart()
msg["Subject"] = Header(mail_title, 'utf-8')
msg["From"] = sender_qq_mail
msg["To"] = Header("receiver test", 'utf-8') ## 接收者的别名
msg.attach(MIMEText(mail_content, 'html', 'utf-8'))
# 构造附件1,传送当前目录下的 email.txt 文件
att1 = MIMEText(open('email.txt', 'rb').read(), 'base64', 'utf-8')
att1["Content-Type"] = 'application/octet-stream'
# 这里的filename可以任意写,写什么名字,邮件中显示什么名字
att1["Content-Disposition"] = 'attachment; filename="email.txt"'
msg.attach(att1)
# 构造附件2,传送当前目录下的 demo.txt 文件
att2 = MIMEText(open('demo.txt', 'rb').read(), 'base64', 'utf-8')
att2["Content-Type"] = 'application/octet-stream'
att2["Content-Disposition"] = 'attachment; filename="demo.txt"'
msg.attach(att2)
# ssl登录
smtp = SMTP_SSL(host_server)
# set_debuglevel()是用来调试的。参数值为1表示开启调试模式,参数值为0关闭调试模式
smtp.set_debuglevel(1)
smtp.ehlo(host_server)
smtp.login(sender_qq, pwd)
smtp.sendmail(sender_qq_mail, receiver, msg.as_string())
smtp.quit()
POP3收取邮件
Python内置一个poplib
模块,实现了POP3
协议,可以直接用来收邮件
- 收取邮件分两步:
1、用poplib
把邮件的原始文本下载到本地;
2、用email
解析原始文本,还原为邮件对象。
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
from email.parser import Parser
from email.header import decode_header
from email.utils import parseaddr
import poplib
# 输入邮件地址, 口令和POP3服务器地址:
email = '...@qq.com'
password = 'nzii...bchf'
pop3_server = 'smtp.qq.com'
def guess_charset(msg):
# 得到字符集
charset = msg.get_charset()
if charset is None:
# lower:所有大写字符为小写
content_type = msg.get('Content-Type', '').lower()
# find:检测字符串中是否包含子字符串
# 返回charset=头字符的位置
pos = content_type.find('charset=')
if pos >= 0:
# strip:移除字符串头尾指定的字符(默认为空格)
charset = content_type[pos + 8:].strip()
return charset
def decode_str(s):
value, charset = decode_header(s)[0]
if charset:
value = value.decode(charset)
return value
# indent用于缩进显示
def print_info(msg, indent=0):
# 初始分析
if indent == 0:
# 遍历获取 发件人,收件人,主题
for header in ['From', 'To', 'Subject']:
# 获得内容
value = msg.get(header, '')
# 如果有内容
if value:
# 内容是主题
if header == 'Subject':
# 解码主题
value = decode_str(value)
else:
# parseaddr:解析字符串中的email地址
hdr, addr = parseaddr(value)
# 解码主题
name = decode_str(hdr)
# 合成内容
value = u'%s <%s>' % (name, addr)
print('%s%s: %s' % (' ' * indent, header, value))
# 如果消息由多个部分组成,则返回True
if (msg.is_multipart()):
# 返回list,包含所有的子对象
parts = msg.get_payload()
# enumerate将其组成一个索引序列,利用它可以同时获得索引和值
for n, part in enumerate(parts):
print('%spart %s' % (' ' * indent, n))
print('%s--------------------' % (' ' * indent))
print_info(part, indent + 1)
else:
# 递归结束条件,打印最基本模块
# 返回消息的内容类型。
content_type = msg.get_content_type()
if content_type == 'text/plain' or content_type == 'text/html':
# 返回list,包含所有的子对象,开启解码
content = msg.get_payload(decode=True)
# 猜测字符集
charset = guess_charset(msg)
# 字符集不为空
if charset:
# 解密
content = content.decode(charset)
print('%sText: %s' % (' ' * indent, content + '...'))
else:
print('%sAttachment: %s' % (' ' * indent, content_type))
# 连接到POP3服务器:
server = poplib.POP3_SSL(pop3_server, port=995)
# 可以打开或关闭调试信息:
server.set_debuglevel(1)
# 可选:打印POP3服务器的欢迎文字:
print(server.getwelcome().decode('utf-8'))
# 身份认证:
server.user(email)
server.pass_(password)
# stat()返回邮件数量和占用空间:
print('Messages: %s. Size: %s' % server.stat())
# list()返回所有邮件的编号:
resp, mails, octets = server.list()
# 可以查看返回的列表类似[b'1 82923', b'2 2184', ...]
print(mails)
# 获取最新一封邮件, 注意索引号从1开始:
index = len(mails)
resp, lines, octets = server.retr(index)
# lines存储了邮件的原始文本的每一行,
# 可以获得整个邮件的原始文本:
msg_content = b'\r\n'.join(lines).decode('utf-8')
# 稍后解析出邮件:
msg = Parser().parsestr(msg_content)
if __name__ == '__main__':
print_info(msg)
# 可以根据邮件索引号直接从服务器删除邮件:
# server.dele(index)
# 关闭连接:
server.quit()