用python提取并统计指定邮箱里的特定邮件

 
 

1.需求描述:

我们经常有这样的需求,需要某个邮箱中提取一个mailist的人员,发来的特定邮件,比如他们的周报,提交的patch等等。由于这是一个周期性的工作,有很大的重复和繁杂性,我们这里编写了一个脚本来实现它。这里,我们的需求是:统计指定人员,发来的邮件主题是"weekly report"的邮件,然后查看有哪些人提交了相关的周报。

2.设计

我们可以使用python的imaplib库,来与特定的邮件服务器进行交互,提取相关的邮件,然后把这些找到的邮件都标记为“已读”。

3.代码实现与解析

配置文件部分:

  1 [server]
  2 hostname=imap.163.com//邮件服务器地址
  3 
  4 [account]
  5 username=yourusername
  6 password=********

这个是针对python的特定配置文件,里面存放了相应的邮件服务器地址和相应的用户名和密码。

核心代码:

  1 #!/usr/bin/python
  2 import imaplib
  3 from pprint import pprint
  4 import ConfigParser
  5 import os
  6 import re
  7 import datetime
  8 import string
  9 import csv
 10 Maillist=['Wei NN Yang','Li AG Zhang','Ya Zhou L Li','Wan Peng WP Li','Guo Wen Shan','Jian Long Hei','Chen    g Jie He','Sheng SH Liu','Jia AH He','Zhi Yong Wu','Yun YY Wang','Da Yu Qiu','Cong Meng','Guo SH Chao','Hu    ai Cheng HC Zheng','Tian Hong BJ Wang','Man ML Li']
 11 pattern=re.compile(r'\((?P<flags>.*)\) "(?P<delimiter>.*)" (?P<name>.*)')
 12 def parse_list_response(line):
 13   match=pattern.match(line)#进行模式匹配
 14   flags,delimiter,mailbox_name=match.groups()
 15   mailbox_name=mailbox_name.strip('"')#去掉分号
 16   return (flags,delimiter,mailbox_name)#注意返回的是“结构体类型”
 17 
 18 def open_connection(verbose=False):
 19   config=ConfigParser.ConfigParser()#初始化config对象
 20   config.read([os.path.expanduser('./.pymotw')])读取配置文件
 21 
 22   hostname=config.get('server','hostname')
 23   username=config.get('account','username')
 24   password=config.get('account','password')#读取相应配置文件的值
 25 
 26   connection=imaplib.IMAP4_SSL(hostname)#初始化一个链接对象
 27   try:
 28     connection.login(username,password)
 29   except Exception as err:
 30     print "Errot:",err
 31   return connection
 32 
 33 def search_count(username,sincetime):
 34   c=open_connection(verbose=True)
 35   try:
 36     typ,data=c.select('ibm')#注意这种赋值方式,返回值是状态和消息数目,但是这个函数改变了connection对象的组成
 37     count=0
 38     typ,msg_ids=c.search(None,'(FROM "'+username+'")','(TO "LTC")','(SENTSINCE "'+sincetime+'")')#注意search函数的使用
 39     #print "msg_ids:",msg_ids
 40     if msg_ids[0]=="":
 41       return 0
 42 
 43     ids=msg_ids[0].split(" ")#分割消息号
 44    # print "ids:", ids
 45     for msgid in ids:
 46     #  print msgid
 47       content=c.fetch(msgid,'(BODY.PEEK[HEADER])')#提取消息体
  52       count+=string.count((str)(content),"eekly")#查看消息体中是否含有weekly字样
 53     #print count
 54   except Exception as err:
 55     print "error:" , err
 56   finally:
 57     return count
 58 #    c.close()
 59 #    c.logout()
 
 68 def mounth_translate(mounth):#这是一个把数字月份转化成相关月份简称的函数
 69   if mounth==1:
 70     return 'JAN'
 71   if mounth==2:
 72     return 'FEB'
 73   if mounth==3:
 74     return 'MAR'
 75   if mounth==4:
 76     return 'APR'
 77   if mounth==5:
 78     return 'MAY'
 79   if mounth==6:
 80     return 'JUN'
 81   if mounth==7:
 82     return 'JUL'
 83   if mounth==8:
 84     return 'AUG'
 85   if mounth==9:
 86     return 'SEPT'
 87   if mounth==10:
 88     return 'OCT'
 89   if mounth==11:
 90     return 'NOV'
 91   if mounth==12:
 92     return 'DEC'
 93   return 'NULL'
 94 
 95 if __name__=='__main__':
 96   mouth=input("please input the mounth of since time:")
 97   strmouth=mounth_translate(mouth)
 98   print strmouth
 99   day=str(input("please input the day of since time:"))#python中的类型转化与C语言的差别从这一句中可以看出来
100   since=day+"-"+strmouth+"-2013"#这里的转化是为了符合后来的函数调用参数规范
101   print since
102   with open('ltc_weekly_report.csv','wt') as f:
103     writer=csv.writer(f)
104     writer.writerow(('name','state'))#这是一个简单的csv文件读写格式
105     for username in Maillist:
106       count=search_count(username,since)
107       writer.writerow((string.join(username),count))
108     today=datetime.date.today()#时间函数,提取当前年月日
109     print today
110     writer.writerow(("the information is get before 17:00 on",str(today)))
111   #print count

下面针对具体的函数和库进行相关解析:

(1)__name__=='__main__'的作用

__name__,__name__作为模块的内置属性,简单点说呢,就是.py文件的调用方式。

最后是__main__,刚才我也提过,.py文件有两种使用方式:作为模块被调用和直接使用。如果它等于"__main__"就表示是直接执行。

总结:在if __name__ == "__main__":之后的语句作为模块被调用的时候,语句之后的代码不执行;直接使用的时候,语句之后的代码执行。通常,此语句用于模块测试中使用。

(2 )python中的switch case语句

代码中有一段很长的if分支,因为python没有switch可以利用,此时我们可以用dict来实现switch的功能:

dict = {"a" : "apple", "b" : "banana", "g" : "grape", "o" : "orange"}
dict["w"] = "watermelon"

(3) 写文件的时候,程序可以实现进度条的功能

此时,可以利用sys.stdout.write()或者print后面加上逗号来实现不还行

你可能感兴趣的:(python,提取特定邮件并统计数目)