收发邮件
打开IMAP/SMTP服务
以QQ邮箱为例,打开IMAP/SMTP服务,生成授权码,设置收取选项
QQ邮箱->设置->账户->开启,IMAP/SMTP服务->生成授权码->收取选项
收取邮件
在Python中,poplib和imaplib库都支持邮件的接收协议,可以让我们登陆服务器接收邮件
imaplib库支持IMAP协议,而poplib库支持POP3协议,IMAP协议在支持双向操作的功能上更加强大
并且能把客户端对邮件的删除等操作同步到服务端,也能把服务端对邮件删除的操作同步到客户端
与POP3协议只能把服务端的操作单向同步给客户端相比,会更加灵活
import imaplib
import config
import email
from pathlib import Path
from email.header import decode_header
# 附件路径
attachments_dir = Path.cwd()
conn = imaplib.IMAP4_SSL(host="imap.qq.com", port=993)
conn.login("123456789@qq.com", config.MAIL_AUTH_CODE)
# 列出邮箱中所有的列表,如:收件箱、垃圾箱、草稿箱
# conn.list()
# 只查收件箱
conn.select("INBOX")
# 搜索最近30天(可以在QQ邮箱中设置)的未读邮件的id
# 可以用ALL搜索全部,也可以按照发件人使用FROM过滤,也可以使用日期过滤
# _, data = conn.search(None, 'unseen')
_, data = conn.search(None, 'FROM', '张三')
# 解析邮件头
def parse_header(message):
# 主题、发件人、收件人、抄送人
result = {
'subject': message.get('subject'),
'from': email.utils.parseaddr(message.get('from'))[1],
'to': email.utils.parseaddr(message.get('to'))[1],
'cc': email.utils.parseaddr(message.get_all('cc'))[1]
}
# 解码标题
result['subject'] = email.header.decode_header(result['subject'])[0][0]
# 再次解码标题
result['subject'] = result['subject'].decode('utf-8')
return result
# 解析邮件内容
def parse_body(message):
if message.is_multipart():
return parse_body(message.get_payload(0))
else:
result = message.get_payload(None, decode=True)
return result.decode('utf-8')
# 保存附件
def save_attachments(message):
file_paths = []
for part in message.walk():
if part.get_content_maintype() == 'multipart':
continue
if part.get('Content-Disposition') is None:
continue
filename = part.get_filename()
# 如果文件名为纯数字、字母时不需要解码,否则需要解码
filename = decode_header(filename)[0][0].decode(decode_header(filename)[0][1])
if bool(filename):
filepath = attachments_dir.joinpath(filename)
with open(filepath, 'wb') as f:
f.write(part.get_payload(decode=True))
file_paths.append(filepath)
return file_paths
for mail_id in data[0].decode().split(" "):
# 获取每一封未读邮件的内容,不判断code了,用_接收掉
_, mail_data = conn.fetch(str(mail_id), '(RFC822)')
# 对每一封邮件的内容进行解析
message = email.message_from_string(mail_data[0][1].decode('utf-8'))
# 解析头信息
header = parse_header(message)
print(header)
# 解析内容
body = parse_body(message)
print(body)
# 保存附件
attachments = save_attachments(message)
print(attachments)
# 将邮件标记为已读
# conn.store(mail_id, '+FLAGS', '\\seen')
conn.close()
conn.logout()
发送邮件
在邮件服务的协议规范中,规定发送邮件采用的是SMTP协议,因此,我们可以使用smtplib库来实现发送邮件的功能
由于smtplib需要配置较多的通用参数,所以还有一个对它进行了更高级的封装的第三方库yagmail库
SMTP()函数默认端口为465,SMTP-MSA端口改为587
import yagmail
import config
conn = yagmail.SMTP(
user="666666@qq.com",
password=config.MAIL_AUTH_CODE,
host="smtp.qq.com",
port=465
)
conn.send(to="123456.qq.com", subject="标题", cc="1234567.qq.com", contents="内容",
attachments="附件.excel")
conn.close()