一、简介
IMAP(Internet Message Access Protocol),这个协议与POP一样,也是从邮件服务器上下载邮件到本机,不过IMAP比POP的功能要更加强大些,IMAP除支持POP所有功能外,还支持以下功能:

  • 多个邮件文件夹(收件箱、发件箱、垃圾邮件...)
  • IMAP服务器上进行标记如:Seen, Replied, Read, Deleted
  • 在服务器端的文件夹之间拷贝和移动邮件
  • ...

  在IMAP的各版本中,最流行的是IMAP4。我们就使用IMAP4
  由于,我需要搜索是否有未读邮件,也就是利用邮件服务器的Flag,所以IMAP是非常适合的,我的程序就利用的是IMAP。
  在Python的标准库包含一个imaplib模块,可以利用这个模块。但是,这个模块的缺陷就是把大量解析的工作留给客户端程序员。
二、IMAPClient
  IMAPClient是一个非常受欢迎的IMAPCLient包,这个模块不在标准Python库中。IMAPClient包是由一名叫做Menno Smits的Python程序员编写的。官网网址:http://imapclient.freshfoo.com/。可以在这里查看手册文档。这个包是基于标准库imaplib,不过要更强大。下面我们来介绍下怎样安装。
1. virtualenv
  说实话,我本人对virtualenv的理解也不透彻,以字面上来理解为虚拟环境。可以把一些模块、包安装在特定的virtualenv里,一旦安装了virtualenv,你就创建任意多个自组织的虚拟python环境,在这个环境里,可以安装、下载包。
  好吧,废话就不多说,直接说方法。
  这里是virtualenv的详细说明,上面介绍了非常详细的安装方法,按照我自己的经验,可以简化为以下步骤:

$ [sudo] pip install virtualenv
$ [sudo] pip install https://github.com/pypa/virtualenv/tarball/develop
$ curl -O https://pypi.python.org/packages/source/v/virtualenv/ virtualenv-X.X.tar.gz
$ tar xvfz virtualenv-X.X.tar.gz
$ cd virtualenv-X.X
$ [sudo] python setup.py install

  注意,上面下载的 virtualenv-X.X.tar.gz 中的X是型号,需要把它改成数字,详细版本类型可以参考:https://pypi.python.org/packages/source/v/virtualenv/

  这样,virtualenv已经安装好。下面需要创建虚拟环境实例,步骤如下:
$ virtualenv --no-site-packages myenv
$ cd myenv
2. 安装IMAPClient
  myenv 为自己定义的虚拟环境的名字。这样,我们已经在myenv里面,接下来就可一安装IMAPClient包了。步骤如下:
$ sudo pip install imapclient
$ python -c 'import imapclient'

  此时,可以在python下使用imapclient模块,但是不能在python3下使用,在网上查了一些资料,尤其是看了上面的那个介绍virtualenv的网页,没找到有用的,但是,回头发现,这个imapclient是好使的了,不用进入gmapenv,直接使用即可,got it!
  注意,上面用到了pip工具,如果没有的话一定要安装啊。
$ sudo apt-get install pip

三、开始正式学习IMAP
1. 因为可能会出现中文,因此在程序的最上面,必须加上如下代码:

#-*- encoding: utf-8 -*-
#-*- encoding: gbk -*-

2. 所需模块

import getpass, email, sys
from imapclient import IMAPClient

3. 连接服务、登录账户
  这一步也没什么好讲的。代码如下:

# 通过以下方式连接smtp服务器,没有考虑异常情况,详细请参考官方文档
c = IMAPClient(hostname = 'imap.gmail.com', ssl= True)
try:
c.login(username, passwd) #登录个人帐号
except c.Error:
print('Could not log in')
sys.exit(1)

4. 进入收件箱,查看未读邮件

c.select_folder('INBOX', readonly = True)
result = c.search('UNSEEN')

  利用select_folder()函数进行文件夹,'INBOX'为收件箱,readonly = True 表明只读并不修改任何信息
  利用search()函数选择想要的邮件,'UNSEEN'是邮件的flag,关于邮件的flag就不特别说明了,返回邮件的message-id
5. 有了未读邮件的ID(result),下面利用fetch()函数将邮件取来(下载到本机)

msgdict = c.fetch(result, ['BODY.PEEK[]'] )

  通过fetch()函数取得邮件内容,fetch()的详细介绍请见这里
      fetch(self, message, data) 其中self参数可忽略,message为message_id, data 的作用是抓取message中的哪些部分。  官方文档中没有给出data的其他可选的参数,我一开始怎么都不找到,最终在stackoverflow中进行提问,一位大哥把这个文档介绍给我,在 6.4.5 FETCH Command 。这里面非常详细的介绍了各个函数的各种细节,当然也可以查到data其他可选的参数 6.4.5 表示的是原书的节。特别感谢这位哥们,人类的力量是无穷的啊!

  我们只需要'BODY.PEEK[]'即可。
6. 已经把邮件取出,下面开始解析邮件

for message_id, message in msgdict.items():
e = email.message_from_string(message['BODY[]']) # 生成Message类型

7. 得到的 e 即为Message类型的邮件,先面开始将又将中解析出'From', 'Subject'

  还记得上面在POP讲解中,我们遇到的不能显示中文的问题吗?在IMAP中仍会出现,下面就讲解解决办法
  由于'From', 'Subject' header有可能有中文,必须把它转化为中文,在这个点上,耽误了我很长时间,最终在网上查到了一个方法:http://blog.csdn.net/bonnshore/article/details/8729984 虽然不是很明白,但是能把问题解决就是王道。代码如下:

subject = email.header.make_header(email.header.decode_header(e['SUBJECT'])) #必须保证包含subject
mail_from = email.header.make_header(email.header.decode_header(e['From']))

8. 从Message e中解析出content正文
  同上一篇的POP一样,根据get_payload()返回的不同类型,选择解析方法,代码如下:

maintype = e.get_content_maintype()
if maintype == 'multipart':
for part in e.get_payload():
if part.get_content_maintype() == 'text':
mail_content = part.get_payload(decode=True).strip()
elif maintype == 'text':
mail_content = e.get_payload(decode=True).strip() # 此时,需要把content转化成中文,利用如下方法:
try:
mail_content = mail_content.decode('gbk')
except UnicodeDecodeError:
print('decode error')
sys.exit(1)

9. 至此,我们已经完成了查看是否有未读邮件。如果有的话将未读邮件的'From', 'Subject', content解析出来。正如上面完成的 mail_from, subject, mail_content一样,现在可以完美的显示,即使有中文!

四、完整代码

#-*- encoding: utf-8 -*-
#-*- encoding: gbk -*- # 因为可能会用到中文,所以必须有上面的这两句话 # 引入模块及IMAPClient类
import getpass, email, sys
from imapclient import IMAPClient hostname = 'imap.gmail.com' #gmail的smtp服务器网址
username = 'myUserName@gmail.com'
passwd = '***' c = IMAPClient(hostname, ssl= True) # 通过一下方式连接smtp服务器,没有考虑异常情况,详细请参考官方文档
try:
c.login(username, passwd) #登录个人帐号
except c.Error:
print('Could not log in')
sys.exit(1)
else:
c.select_folder('INBOX', readonly = True)
# 利用select_folder()函数进行文件夹,'INBOX'为收件箱,readonly = True 表明只读并不修改任何信息
result = c.search('UNSEEN')
msgdict = c.fetch(result, ['BODY.PEEK[]'] ) # 现在已经把邮件取出来了,下面开始解析邮件
for message_id, message in msgdict.items():
e = email.message_from_string(message['BODY[]']) # 生成Message类型
     # 由于'From', 'Subject' header有可能有中文,必须把它转化为中文
subject = email.header.make_header(email.header.decode_header(e['SUBJECT']))
mail_from = email.header.make_header(email.header.decode_header(e['From']))
     
     # 解析邮件正文
maintype = e.get_content_maintype()
if maintype == 'multipart':
for part in e.get_payload():
if part.get_content_maintype() == 'text':
mail_content = part.get_payload(decode=True).strip()
elif maintype == 'text':
mail_content = e.get_payload(decode=True).strip()

     # 此时,需要把content转化成中文,利用如下方法:
try:
mail_content = mail_content.decode('gbk')
except UnicodeDecodeError:
print('decode error')
sys.exit(1)
else:
print('new message')
print('From: ', mail_from)
print('Subject: ', subject)
getstr = input('if you wanna read it, input y: ')
if getstr.startswith('y'):
print('-'*10, 'mail content', '-'*10)
print(mail_content.replace('<br>', '\n'))
print('-'*10, 'mail content', '-'*10)
finally:
  c.logout()

五、总结
  至此,我们已经学习了利用Python编写邮件服务的所有非常基本的内容,由于我的需求不是很高,目标不是做成一个功能强大的邮箱客户端,所以诸如:MIME、附件、图片等功能都没有学习,当然也没有介绍。
  因为我们现在接收的邮件,大多数都是MIME格式的,不过上文的包含了点解析MIME格式邮件的代码。详细请参考《Foundations of Python3 Network Programming. 2nd Edition》Chaper E-mail Composition and Decoding。

Python 用IMAP接收邮件的更多相关文章

  1. python 利用imap接收邮件,并保存附件

    def SaveAttachImap():# login the imap server ,retrive the  new mails ,and download the attachments. ...

  2. 使用python发送和接收邮件

    关于电子邮件 大学之前,基本不用邮箱,所以基本感觉不到它的存在,也不知道有什么用:然而大学之后,随着认识的人越来越多,知识越来越广泛,邮箱已然成为很重要的通讯工具,大学一些课程作业需要有邮箱发给老师, ...

  3. Python 用POP接收邮件

    一.简介 POP(Post Office Protocal)最长用的POP版本是POP3,因此本文是以POP3为主.POP3非常简单,可以用来从邮件服务器上下载邮件,然后删除这些邮件.功能非常有限,后 ...

  4. python 利用pop3接收邮件并保存附件

    def SaveAttach():# login the pop3 server ,retrive the new mails ,and download the attachments dstdir ...

  5. 使用imap协议接收邮件

    之前一直使用PHPMail类进行发送邮件,这个是一个非常强大的类,但是其实底层就是使用mail()函数来进行发送的. 但是现在公司有个需求是  写个程序需要实时的接收邮件,主要是判断邮件发出去了,并且 ...

  6. python接收邮件

    # -*- coding: utf-8 -*- import poplib import email from email.parser import Parser from email.header ...

  7. Python接收邮件并保存至MySQL

    转自:http://www.360doc.com/content/14/0103/13/11789990_342303735.shtml 参考了一些网络上的资料,做了个简单程序,使用python接收邮 ...

  8. Android javaMail使用imap协议接收邮件

    在这里说明一下,pop3和imap协议都是接收邮件的,但是他们还是有很多不同的. IMAP和POP有什么区别? POP允许电子邮件客户端下载服务器上的邮件,但是您在电子邮件客户端的操作(如:移动邮件. ...

  9. JAVA+PHP+阿里云组件纯手工实现POP、SMTP、IMAP开发邮件服务器(二)

    java开发邮件服务器的接收模块 用java建立socket服务端,监听端口25,实现SMTP协议.即可完成邮件服务器的接收模块. 这里要注意的是,SMTP协议其实可以分为两种.一种是你用手机.PC等 ...

随机推荐

  1. C#二维码生成

    C#二维码生成,这里使用开源的ThoughtWorks.QRCode.dll库. 1.下载ThoughtWorks.QRCode.dll库文件,并引用到项目中. 2.创建QRCodeHandler.c ...

  2. oracle_根据ID(字符型)建立分区表

    方案思路:有一张暴增的数据表(10亿级别),以后需求需要提高单条查询性能, 这个表有个唯一ID, 假设是UUID,采用区分首字母的方法,不同字母的数据入到不同的物理文件中. 第一步: 查找数据库服务器 ...

  3. python_random随机

    在数据清洗,评估 ,抽验等等过程中,经常有这样的应用场景 : 需要在一个大的数据集合中随机出来样本,进行人工评估.为了保证足够随机,借助脚本来实现. 下面一个脚本  ,用于应对这种应用场景. 使用方法 ...

  4. P31RestKit.dll 2.0 Unity3d json

    using System.Collections.Generic; using UnityEngine; using System.Collections; using Prime31; public ...

  5. UVA 11426 - GCD - Extreme (II) (数论)

    UVA 11426 - GCD - Extreme (II) 题目链接 题意:给定N.求∑i<=ni=1∑j<nj=1gcd(i,j)的值. 思路:lrj白书上的例题,设f(n) = gc ...

  6. 前端学习笔记(zepto或jquery)——对li标签的相关操作(二)

    对li标签的相关操作——8种方式获取li标签的第一个元素的内容 1.alert($("ul>li").first().html());2.alert($('ul>li' ...

  7. 通过私有协议Chrome浏览器页面打开本地程序

    近期方有这样的要求:这两个系统,根据一组Chrome开展,根据一组IE开展,需要Chrome添加一个链接,然后进入IE该系统的开发.这,需要Chrome跳转到创建一个链接IE浏览器指定的页面.同时也实 ...

  8. 【百度地图API】如何使用suggestion--下拉列表方式的搜索建议

    原文:[百度地图API]如何使用suggestion--下拉列表方式的搜索建议 摘要: 百度地图上有一个很强大的搜索建议功能,以下拉列表的方式展示出来.比如,输入“百度”,下拉列表中就会出现“北京市海 ...

  9. 【百度地图API】多家地图API内存消耗对比测验(带源码)

    原文:[百度地图API]多家地图API内存消耗对比测验(带源码) 任务描述: 啊,美妙的春节结束了.酸奶小妹和妈妈的山西平遥之旅也宣告成功!距离平遥古城7km,有一个同样身为“世界文化遗产”的寺庙,叫 ...

  10. 【百度地图API】自定义可编辑的交通路线

    原文:[百度地图API]自定义可编辑的交通路线 任务描述: 我想自己绘制一条从地铁站出口到天安门的道路,而且还需要根据我的喜好来改变这条路线. 如何实现: 鼠标左击地图,绘制路线:双击后,绘制结束:绘 ...