2022年 11月 9日

python从邮箱获取指定邮件_用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.)

“(?P.*)” (?P.*)’)

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后面加上逗号来实现不还行