背景

有一个工作邮箱,会接收许多人不断地投递的简历。由于邮件数量比较多,因此产生了一个需求。要求自动将邮件从邮件服务器取回到本地,并将邮件的基本信息存入本地的sqlite数据库。邮件的正文以单独文件的形式存放在文件夹下。

实现

备注:在python2.7下测试运行正常,如果用python3,可能需要对代码稍做修改。

1,邮件配置参数文件
mail.conf

[mail163]
#此外应写上你实际的帐号与密码
user = xxxx@163.com
password = xxxxx
pop3_server = pop3.163.com[sqlite]
dir = sqlite
fileName = mailLog.db

2.sqlite数据表的结构

3.从邮件服务器收取邮件的python代码
mailManager.py

# -*- coding:utf-8 -*-
# 读取邮件并解码存入日志数据库import poplib
import email
import ConfigParser
import os, sys, string,time
from email.parser import Parser
from email.header import decode_header
from email.utils import parseaddr
from logHelper import LogHelper#获取解码后的邮件体
def getBody(msg,guessedCharset='gb2312'):bodyText =''if (msg.is_multipart()):parts = msg.get_payload()for n, part in enumerate(parts): try:bodyText+=getBody(part)except UnicodeDecodeError,e:print e.messageelse:content_type = msg.get_content_type()if content_type=='text/plain' or content_type=='text/html':content = msg.get_payload(decode=True)            #尝试进行解码bodyText = decodeString(content, guessedCharset,'body',guessedCharset,)else:bodyText = ''return bodyText#解码邮件头中包含的字符串
def decode_strInHeader(s,guessedCharset='gb2312'):#对邮件头字符串,获取其内容与编码格式value, charset = decode_header(s)[0]   #print(value,charset) return decodeString(value, charset,'header',guessedCharset)#解码字符串
def decodeString(s,charset,extra='header',guessedCharset='gb2312'):    value = sif charset is None:charset = guessedCharsetif charset:#去除编码格式中可能存在的干扰元素,常见的是双引号charset = charset.strip('"')charset = charset.strip("'")try:value = value.decode(charset)except:if(charset=='gb2312'):#尝试用比gb2312更大的字符集gbk进行解码try:value = value.decode('gbk')except:print("decode error in decodeString!",'gbk',extra)elif (charset=='utf8'):#尝试忽略掉解码错误try:value = value.decode('utf8',errors='ignore')except:print("decode error in decodeString!",'gbk',extra)else:#从目前解码邮件的实践来看,如果不是gb231编码,就是utf-8编码               print("decode error in decodeString!",charset,extra)return value#获得msg的编码,猜测编码格式
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 today():return time.strftime("%Y-%m-%d", time.localtime()) #确保文件夹存在
def ensureDir(dir):if not os.path.exists(dir):os.mkdir(dir)   #登记一封邮件
def logOneMail(server,index,dir,logHelper,parseScope='new'):print('log Mail:', index)resp, lines, octets = server.retr(index)# lines存储了邮件的原始文本的每一行,合并得到原始文本msgRaw = b'\r\n'.join(lines)    #创建message对象,这个时候也会做基本的解码,得到message结构体msg = email.message_from_string(msgRaw) #在需要时,可输出整个message结构体,观察有哪些键值对#print msg#推测邮件的编码格式guessedCharset = guess_charset(msg)#如果subject存在就返回相应的值,否则返回''subjectRaw = msg.get("subject",'') subject = decode_strInHeader(subjectRaw,guessedCharset)#print subjectfromAddrRaw = msg.get("from",'') var1,var2 = parseaddr(fromAddrRaw)fromAddr = decode_strInHeader(var1,guessedCharset)#print fromAddrtoAddrRaw = msg.get("to",'') var1,var2 = parseaddr(toAddrRaw)toAddr = decode_strInHeader(var1,guessedCharset)#print toAddrmessageIDRaw= msg.get("Message-ID",'');messageID = decode_strInHeader(messageIDRaw,guessedCharset)print('mail message id:', messageID)uniqueIDRaw= msg.get("uniqueid",'');uniqueID = decode_strInHeader(uniqueIDRaw,guessedCharset)#print uniqueIDdateStrRaw= msg.get("Date",'');dateStr = decode_strInHeader(dateStrRaw,guessedCharset)#print dateStr#将邮件主体内容写入文件baseName = messageID.strip();baseName = baseName.replace('<', '')baseName = baseName.replace('>', '')#以日期为文件夹,存放邮件正文curDir = dir+'/'+today()+'/'ensureDir(curDir)contentFile = curDir + '/'+baseName+'.html'if not os.path.exists(contentFile):outFile =open(contentFile,'w')outFile.write(getBody(msg,guessedCharset))outFile.close()#检查是否到了解析范围的结尾处if parseScope == 'new' and logHelper.msgExists(messageID):        return 'scopeEnd'#将邮件信息写入日志数据库logHelper.append(messageID,fromAddr,subject,contentFile,dateStr)return 'ok'#登记邮件,从邮件服务器中取出最近的一些邮件,
#parseScope='all',则取出所有的邮件,'new',取出新收到的邮件,或者取出只定数量的新邮件
#progressKey是批操作计数器的标识值,目前保留备用
def logTheMails(progressKey,parseScope='new'):#读取配置文件cf = ConfigParser.ConfigParser()cf.read("mail.conf")user = cf.get("mail163", "user")password = cf.get("mail163", "password")pop3_server = cf.get("mail163", "pop3_server")# 连接到POP3服务器:server = poplib.POP3(pop3_server)# 可以打开或关闭调试信息:#server.set_debuglevel(1)# 打印POP3服务器的欢迎消息:#print(server.getwelcome())# 身份认证:server.user(user)server.pass_(password)#stat()返回邮件数量和占用空间:#print('Messages: %s. Size: %s' % server.stat())#连接日志数据库dbFileFullName =  cf.get("sqlite", "dir")+'/'+cf.get("sqlite", "fileName")logHelper=LogHelper(dbFileFullName)# list()返回所有邮件的编号:resp, mails, octets = server.list()#邮件服务器邮箱中的邮件总数total = len(mails)if parseScope == 'all':logCount = totalelif parseScope == 'new':logCount = totalelse:logCount = int(parseScope)# 获取最近的 logCount 份邮件, 注意索引号从1开始,最新的索引是len(mails):receivedCount = 0for indexAsc in range(0,logCount):index = total - indexAsc #登记一封邮件flag = logOneMail(server,index,cf.get("sqlite", "dir"),logHelper,parseScope)if flag =='scopeEnd':breakreceivedCount +=1          # 关闭到邮件服务器的连接:server.quit()return receivedCount#登记邮件,取出起始索引号与结束索引号之间的一些邮件
def logMailsByIndex(beginIndex,endIndex):#读取配置文件cf = ConfigParser.ConfigParser()cf.read("mail.conf")user = cf.get("mail163", "user")password = cf.get("mail163", "password")pop3_server = cf.get("mail163", "pop3_server")# 连接到POP3服务器:server = poplib.POP3(pop3_server)# 可以打开或关闭调试信息:#server.set_debuglevel(1)# 打印POP3服务器的欢迎消息:#print(server.getwelcome())# 身份认证:server.user(user)server.pass_(password)#stat()返回邮件数量和占用空间:#print('Messages: %s. Size: %s' % server.stat())#连接日志数据库dbFileFullName =  cf.get("sqlite", "dir")+'/'+cf.get("sqlite", "fileName")logHelper=LogHelper(dbFileFullName)# list()返回所有邮件的编号:resp, mails, octets = server.list()#邮件服务器邮箱中的邮件总数total = len(mails)if beginIndex > total:beginIndex = totalif endIndex > total:endIndex = total    # 获取最近的 logCount 份邮件, 注意索引号从1开始,最新的索引是len(mails):receivedCount = 0for index in range(beginIndex,endIndex+1):#登记一封邮件flag = logOneMail(server,index,cf.get("sqlite", "dir"),logHelper)if flag =='scopeEnd':breakreceivedCount +=1          # 关闭到邮件服务器的连接:server.quit()return receivedCount

4.根据命令行参数,读取指定时间范围内的邮件的代码
fetchMails.py

# -*- coding:utf-8 -*-
#读取邮件
import os, sys, string
import time
import getopt
import mailManager
reload(sys)
sys.setdefaultencoding( "utf-8" )  #解析命令行参数,得到进度计数器的key和邮箱代号(留作备用)
#scope指示是解析全部邮件(all)还是只解析新收到的邮件(new)
#如果给出一个数字,则解析最近收到的指定数目的邮件
try:opts, args = getopt.getopt(sys.argv[1:],'p:m:s:',['progKey=','mailBoxIdx=','scope='])
except getopt.GetoptError:print('error:','options invalid')sys.exit()progressKey = ''
parseScope = 'new'
for k, v in opts:if k in ("-p", "--progKey"):progressKey = velif k in ("-m", "--mailBoxIdx"):mailBoxIndex = int(v)elif k in ("-s", "--scope"):parseScope = vprint('oldCwd:',os.getcwd())
#将工作目录切换到当前文件所在的目录
os.chdir(os.path.dirname(os.path.abspath(__file__)))
print('newCwd:',os.getcwd())print
print('fetch mails : begin...')
print startTime = time.time()if progressKey == '':progressKey = 'tempKey1'#取回邮件并登记到sqlite数据库
receivedCount = mailManager.logTheMails(progressKey,parseScope)print
print ('receivedCount:',receivedCount)
printendTime = time.time()
print('used time/minutes: ',(endTime-startTime)/60)

用python收取邮件的一个实例相关推荐

  1. python 收取邮件 exchange_Exchange服务器之python 使用exchange发送邮件

    安装库exchangelib pip install exchangelib1 脚本内容 # coding=utf-8 # # Created on 2018/2/ from exchangelib  ...

  2. python 发邮件正文表格 html

    在 Python 中将表格作为电子邮件正文(不是附件)发送 参考 (详细 !清晰!)python发邮件总结及实例说明,中文乱码已解决(在最后一个模块) table-email-template Pyt ...

  3. java邮箱插件,初步实现 Mail 插件 —— 收取邮件

    在上篇中描述了发送邮件的主要过程,今天我想和大家分享一下 Smart Mail 插件的另外一个功能 -- 收取邮件,可能没有发送邮件那么常用. 在具体描述如何实现收取邮件之前,有必要对发送邮件与收取邮 ...

  4. python中文名的发件人邮件读取解析_如何使用python收取读取邮件?

    之前给大家介绍使用python去发送邮件了,那有小伙伴提出疑问了,既然能发送,能否读取呢?如果可以用python实现,那将是个非常有趣的事情,于是小编也去查询了下,下面就给大家演示下,都来看看吧~以下 ...

  5. python自动化发送邮件_python接口自动化(三十三)-python自动发邮件总结及实例说明番外篇——下(详解)...

    简介 发邮件前我们需要了解的是邮件是怎么一个形式去发送到对方手上的,通俗点来说就是你写好一封信,然后装进信封,写上地址,贴上邮票,然后就近找个邮局,把信仍进去,其他的就不关心了,只是关心时间,而电子邮 ...

  6. Python学习笔记:电子邮件,POP3收取邮件

    前言 最近在学习深度学习,已经跑出了几个模型,但Pyhton的基础不够扎实,因此,开始补习Python了,大家都推荐廖雪峰的课程,因此,开始了学习,但光学有没有用,还要和大家讨论一下,因此,写下这些帖 ...

  7. python中property函数_python 邮件表格Python中property函数用法实例分析

    本文实例讲述了Python中property函数用法.分享给大家供大家参考,具体如下: 通常我们在访问和赋值属性的时候,都是在直接和类(实例的)的__dict__打交道,或者跟数据描述符等在打交道.但 ...

  8. python接口自动化(三十三)-python自动发邮件总结及实例说明番外篇——下

    简介 发邮件前我们需要了解的是邮件是怎么一个形式去发送到对方手上的,通俗点来说就是你写好一封信,然后装进信封,写上地址,贴上邮票,然后就近找个邮局,把信仍进去,其他的就不关心了,只是关心时间,而电子邮 ...

  9. python提取邮件附件_详解python实现读取邮件数据并下载附件的实例

    详解python实现读取邮件数据并下载附件的实例 实现结果图: 实现代码: #!/usr/bin/python2.7 # _*_ coding: utf-8 _*_ """ ...

最新文章

  1. Attention Mechanism
  2. 2015微信商业化正式启幕 为企业开启O2O主阵地
  3. centos7下没有iptables
  4. python全栈工程师是指_Python全栈工程师(exercises)
  5. 【51单片机快速入门指南】5:软件SPI
  6. 前端学习(2149):webpack之ES6到ES5的转换
  7. c语言函数大全语法下载,C语言函数大全(语法).doc
  8. JavaScript 常用代码整理
  9. php 关于日期的知识总结
  10. div是html5新元素,HTML5编码新元素的介绍
  11. zookeeper 进入客户端_Zookeeper基础知识简单介绍
  12. java编程两个超长正整数相减_【每日编程237期】数字分类
  13. UEFI win7系统的安装
  14. 射电天文偏振线的绘制
  15. bay——RAC 表空间时数据文件误放置到本地文件系统-介质恢复.txt
  16. 八大排序算法原理及实现
  17. 2022最新简历模板
  18. Zigbee 应用层协议自定义
  19. 颜色格式转换: 最简单的基于FFmpeg的libswscale的示例(YUV转RGB)
  20. 深算院入选“数字政府建设赋能计划”成员单位

热门文章

  1. 车检预约制将对机动车检测站产生哪些影响?
  2. 实现SP端的协议开发
  3. 唐寅——《桃花庵歌》
  4. 电子货架标签----在智能零售中的真正价值
  5. 大数据时代,票房不再是唯一
  6. LTE名词解释(转)
  7. nvidia控制面板点了没反应win7_nvidia控制面板打不开如何解决 nvidia控制面板点了没反应...
  8. arcgis快速生成图框_ArcGIS中定义图框样式
  9. G001-186-07
  10. CC1310手册的射频核心介绍