Flask Mail(2)

Flask Mail(2)
10322

3.POP3收取邮件

1.简介

POP是指邮局协议,目的是让用户可以访问邮箱服务器中的邮件,允许用户从服务器上把邮件存储到本地主机(即自己的计算机)上,同时删除保存在邮件服务器上的邮件,而POP3服务器则是遵循POP3协议的接收邮件服务器,用来接收电子邮件的

2.函数

Python提供了poplib模块来支持pop3 收取邮件的过程

  1. 连接pop3服务器 (poplib.POP3.init)
  2. 发送用户名和密码进行验证 (poplib.POP3.user poplib.POP3.pass_)
  3. 获取邮箱中信件信息 (poplib.POP3.stat)
  4. 收取邮件 (poplib.POP3.retr)
  5. 删除邮件 (poplib.POP3.dele)
  6. 退出 (poplib.POP3.quit)

1.函数方法

方法 描述
POP3(server) 实例化POP3对象,server是pop服务器地址
user(username) 发送用户名到服务器,等待服务器返回消息
pass_(password) 发送密码
stat() 返回邮箱的状态,返回2元组(消息的数量,消息的总字节数目)–>邮件总数,总字节数
list([msgnum]) stat()的扩展,返回一个3元组(返回信息,消息列表,消息的大小),如果指定msgnum,就只返回指定消息的数据 —返回邮件数量和每个邮件的大小
retr(msgnum) 获取详细的msgnum,设置为已读,返回3元组(返回信息, 消息msgnum的所以内容, 消息的字节数),如果指定msgnum,就只返回指定消息的数据—返回由参数标识的邮件的全部文本
dele(msgnum) 将指定消息标记为删除
quit() 登出,保存修改,解锁邮箱,结束连接,退出
top() 服务器返回由参数标识的邮件前n行内容,n必须是整数
noop() 服务器返回一个肯定的相应
uidl 返回邮件的唯一标识符,pop3回话的每个标识符都是唯一的
apop(name,digest) digest是md5消息摘要

2.接收邮件

from  poplib import POP3
#pop3服务器地址
host = 'pop3.163.com'
#用户名
username = 'xxx@163.com'
#密码
password = 'xxx'
#创建一个pop3对象,这个时候已经连接上服务器了
pp = POP3(host)
#设置调试模式
pp.set_debuglevel(1)
#向服务器发送用户名
pp.user(username)
#向服务器发送密码
pp.pass_(password)
#获取服务器上信件信息,返回时一个列表,第一项是一共有多少邮件,第二项是有多少字节
ret = pp.stat()
print(ret)
# 需要取出所有信件的头部,信件id是从1开始的
for i in range(1,ret[0]+1):
   #去除信件头部,注意:top指定的行数是以信件头为基数的,也就是说当取0行
 #其实是返回头部信息,取一行其实是返回头部信息之外再多1行 
   """   
   POP3.top(which, howmuch)
  Retrieves the message header plus howmuch lines of the message after the header of message number which. Result is in form (response, ['line', ...], octets).
 The POP3 TOP command this method uses, unlike the RETR command, doesn’t set the message’s seen flag; unfortunately, TOP is poorly specified in the RFCs and is frequently broken in off-brand servers. Test this method by hand against the POP3 servers you will use before trusting it.
   which:表示的是第几封信
   howmuch: 指的是头部以后的第几行
   """

   mlist = pp.top(i,0)
   print('line:' ,len(mlist[1]))
#取出第一份邮件的头部
mlist = pp.top(1,0)
print('line0:') + str(len(mlist[0])) + 'line1:' + str(len(mlist[1])) 
print(mlist[0]) #这份邮件的状态。邮件总字节数
print(mlist[1]) #邮件头内容
print(mlist[2]) #邮件头字节数
print(mlist)
#列出服务器上邮件信息,这个会对没一封邮件都输出id和大小, stat输出的是总的统计信息
ret = pp.list()
print(ret)
# 取第一封邮件完整信息,在返回值里,是按行存储在down[1]的列表里的。down[0]是返回的状态信息
"""
POP3.retr(which)
Retrieve whole message number which, and set its seen flag. Result is in form (response, ['line', ...], octets).
"""

down = pp.retr(1)
print('lines:', len(down))
#输出邮件,按行存在down[1]中,打印出每一行
for line in down[1]:
 print(line) 
#退出
pp.quit()

如果需要安全邮件,则是对pop3做了ssl加密,这样要使用POP3_SSL类

pp = poplib.POP3_SSL(host,port=x)

3.收取邮件并使用smtp解析

解析邮件很容易

import email
from email.parser import Parser
from email.header import decode_header
from email.utils  import parseaddr
import poplib

# pop3服务器地址
host = 'pop3.163.com'
#用户名
username = 'xxx@163.com'
#密码
password = 'xxx'
#创建一个pop3对象,这个时候已经连接上服务器
server = poplib.POP3(host)
# 设置调试模式
server.set_debuglevel(1)
# 登录
server.user(username)
server.pass_(password)
#stat()返回二元组(邮件总数,邮件总字节数)
print('Messages: %s. Size: %s' % server.stat())
# list()返回3元组(消息状态,[每个邮件编号和大小],消息的字节数)
resp, mails, octets = server.list()
# 获取最新一封邮件, 注意索引号从1开始:
resp, lines, octets = server.retr(len(mails))
# 解析邮件
msg = Parser().parsestr('rn'.join(lines))
# 打印邮件内容:
print_info(msg)
# 慎重:将直接从服务器删除邮件:
# server.dele(len(mails))
# 关闭连接:
server.quit()

但是Message对象本省可能是一个MIMEMultipart对象,即包含其他MIMEBase对象,嵌套可能还不止一层。所以我们要递归的打印出Message对象的层次结构:

import poplib
import email
from email.parser import Parser
from email.header import decode_header
from email.utils import parseaddr
def guess_charset(msg):
   charset = msg.get_charset()
   if charset is None:
       content_type = msg.get('Content-Type''').lower()
       pos = content_type.find('charset=')
       if pos >= 0:
           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
#-------------------------------------------------------
#递归的打印出message对象的层次结构(可能不止一层)
#
#
#
#
def print_info(msg, indent=0):  #indent用于缩进显示
   if indent == 0:
       #邮件的From,To,Subject存在于根对象上
       for header in ['From''To''Subject']:
           value = msg.get(header, '')
           if value:
               if header=='Subject':
                   #需要解码Subject字符串
                   value = decode_str(value)
               else:
                   #需要解码Email地址
                   hdr, addr = parseaddr(value)
                   name = decode_str(hdr)
                   value = u'%s <%s>' % (name, addr)
           print('%s%s: %s' % ('  ' * indent, header, value))
   if (msg.is_multipart()):
       #如果邮件对象是一个MIMEMultipart
       #get_payload()返回一个list,包含所有的子对象
       parts = msg.get_payload()
       for n, part in enumerate(parts):
           print('%spart %s' % ('  ' * indent, n))
           print('%s--------------------' % ('  ' * indent))
           #递归打印每一个子对象
           print_info(part, indent + 1)
   else:
       #邮件对象不是一个MIMEMultipart
       # 就根据content_type判断
       content_type = msg.get_content_type()
       if content_type=='text/plain' or content_type=='text/html':
           #纯文本或者html
           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))

– END –


原文始发于微信公众号(Flask学习笔记):Flask Mail(2)

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/36463.html

(0)
小半的头像小半

相关推荐

发表回复

登录后才能评论
极客之音——专业性很强的中文编程技术网站,欢迎收藏到浏览器,订阅我们!