目录
待续
1 IMAP
IMAP(Internet Mail Access Protocol,Internet邮件访问协议):和POP一样,用于客户端从服务器管理邮件,但是提供更多服务,比如同步,加标签,搜索,上传message,文件夹管理,部分下载等。
1.1 IMAP Basics
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
import getpass, imaplib, sys
def main():
if len(sys.argv) !=3:
print("usage: {} hostname, username".format(sys.argv[0]))
sys.exit(2)
SERVER, USERNAME = sys.argv[1:]
m = imaplib.IMAP4_SSL(SERVER)
m.login(USERNAME,getpass.getpass())
try:
print('Capabilities {}'.format(m.capability()))
print('Listing mailboxes ')
status, data = m.list()
print('Status: {}'.format(status))
print('Data:')
for datum in data:
print(repr(datum))
finally:
m.logout()
if __name__=='__main__':
main()
"""
输出:
Capabilities ('OK', [b'IMAP4rev1 UNSELECT IDLE NAMESPACE QUOTA ID XLIST CHILDREN X-GM-EXT-1 UIDPLUS XXXXXXXXXXXXXXXX ENABLE MOVE XXXXXXXXX ESEARCH UTF8=ACCEPT LIST-EXTENDED LIST-STATUS LITERAL- APPENDLIMIT=35651584', b'IMAP4rev1 UNSELECT IDLE NAMESPACE QUOTA ID XLIST CHILDREN X-GM-EXT-1 UIDPLUS XXXXXXXXXXXXXXXX ENABLE MOVE XXXXXXXXX ESEARCH UTF8=ACCEPT LIST-EXTENDED LIST-STATUS LITERAL- APPENDLIMIT=35651584'])
Listing mailboxes
Status: OK
Data:
b'(\\HasNoChildren) "/" "Deleted Items"'
b'(\\HasNoChildren) "/" "Google Calendar"'
b'(\\HasNoChildren) "/" "HKU"'
b'(\\HasNoChildren) "/" "HKU_EEE"'
b'(\\HasNoChildren) "/" "INBOX"'
b'(\\HasNoChildren) "/" "Junk E-mail"'
b'(\\HasNoChildren) "/" "Mar_1"'
b'(\\HasNoChildren) "/" "Travel"'
b'(\\HasNoChildren) "/" "Work"'
b'(\\Noselect \\HasChildren) "/" "[Gmail]"'
b'(\\HasChildren \\HasNoChildren) "/" "[Gmail]/All Mail"'
b'(\\HasNoChildren) "/" "[Gmail]/Drafts"'
b'(\\HasChildren \\HasNoChildren) "/" "[Gmail]/Sent Mail"'
b'(\\HasNoChildren) "/" "[Gmail]/Spam"'
b'(\\HasNoChildren) "/" "[Gmail]/Starred"'
b'(\\HasChildren \\HasNoChildren) "/" "[Gmail]/Trash"'
"""
imaplib没有提供对data的解析(只显示raw data,例如上面的b'(\\HasNoChildren) "/" "INBOX"'
),这个时候就需要1个更强大的IMAP client library了。
1.1.1 IMAP Client
第三方库IMAPClient提供了更强大的IMAP client功能。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
import getpass, sys
from imapclient import IMAPClient
def main():
if len(sys.argv) !=3:
print("usage: {} hostname, username".format(sys.argv[0]))
sys.exit(2)
SERVER, USERNAME = sys.argv[1:]
c = IMAPClient(SERVER,ssl=False)
try:
c.login(USERNAME, getpass.getpass())
except c.Error as e:
print('Could not log in:', e)
else:
print('Capabilities {}'.format(c.capabilities()))
print('Listing mailboxes ')
data = c.xlist_folders()
for flags, delimiter, folder_name in data:
print('{:30s} {} {}'.format(''.join(str(flags)), delimiter, folder_name))
finally:
c.logout()
if __name__=='__main__':
main()
"""
输出
Capabilities: ('IMAP4REV1', 'UNSELECT', 'IDLE', 'NAMESPACE', 'QUOTA', 'XLIST', 'CHILDREN', 'XYZZY',
'SASL-IR', 'AUTH=XOAUTH')
Listing mailboxes:
\HasNoChildren / INBOX
\HasNoChildren / Personal
\HasNoChildren / Receipts
\HasNoChildren / Travel
\HasNoChildren / Work
\Noselect \HasNoChildren / [Gmail]
\HasChildren \HasNoChildren / [Gmail]/All Mail
\HasNoChildren / [Gmail]/Drafts
\HasChildren \HasNoChildren / [Gmail]/Sent Mail
\HasNoChildren / [Gmail]/Spam
\HasNoChildren / [Gmail]/Starred
\HasChildren \HasNoChildren / [Gmail]/Trash
"""
1.1.2 Examining Folders
IMAP protocol is stateful,即当你进行下载,搜索或者修改任何message等操作时,你需要选择要操作的文件夹。当你选择了某个文件夹作为当前文件夹后,你的操作就在该文件夹下。
1.1.3 Message Numbers vs. UIDs
IMAP协议提供了两个数字来追踪message:
-
Message Number:某个连接下的特定文件夹内的message的编号,1,2,3等。如果关闭该次连接,下次在连接式,同样的message,其message nnumber可能会不一样。
-
UIDs:每次连接都一样的编号。对于同步特别有用,也是IMAP优于POP的1个特点。
1.1.4 Message Ranges
IMAP提供了1次操作1个或者多个message的机制,比如下面命令:
1
2
2,4:6,20:*
#表示message2,4到6,20及20以后所有的message。
1.1.5 Summary Information
IMAPClient的select_folder(foldername)
返回foldername的元信息,存储在dict里。不同key代表不同含义:
-
EXISTS:该folder里的message个数。
-
READ-WRITE:是否可读写。
-
UIDNEXT:server对下个新来的message预备的UID。
-
RECENT:上次登录之后新来的message个数。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
import getpass, sys
from imapclient import IMAPClient
def main():
if len(sys.argv) !=4:
print("usage: {} hostname, username foldername".format(sys.argv[0]))
sys.exit(2)
SERVER, USERNAME, FOLDERNAME = sys.argv[1:]
c = IMAPClient(SERVER,ssl=False)
try:
c.login(USERNAME, getpass.getpass())
except c.Error as e:
print('Could not log in:', e)
else:
select_dict = c.select_folder(FOLDERNAME,readonly=True)
for k,v in sorted(select_dict.items()):
print('%s: %r' % (k,v))
finally:
c.logout()
if __name__=='__main__':
main()
"""
输出
EXISTS: 3
PERMANENTFLAGS: ('\\Answered', '\\Flagged', '\\Draft', '\\Deleted',
'\\Seen', '\\*')
READ-WRITE: True
UIDNEXT: 2626
FLAGS: ('\\Answered', '\\Flagged', '\\Draft', '\\Deleted', '\\Seen')
UIDVALIDITY: 1
RECENT: 0
"""
1.2 IMAP Tasks
1.2.1 Downloading
1.2.1.1 Downloading an Entire Maibox
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
import getpass, sys, email
from imapclient import IMAPClient
def main():
if len(sys.argv) !=4:
print("usage: {} hostname, username foldername".format(sys.argv[0]))
sys.exit(2)
SERVER, USERNAME, FOLDERNAME = sys.argv[1:]
c = IMAPClient(SERVER,ssl=False)
try:
c.login(USERNAME, getpass.getpass())
except c.Error as e:
print('Could not log in:', e)
else:
print('Login succesfully')
print_information(c, FOLDERNAME)
finally:
c.logout()
def print_information(c,foldername):
c.select_folder(foldername,readonly=True)
msgdict = c.fetch('1:*',['BODY.PEEK[]'])
for message_ID, message in list(msgdict.items()):
e = email.message_from_bytes(message[b'BODY[]'])
print(e['From'])
payload = e.get_payload()
if isinstance(payload,list):
part_content_types = [part.get_content_type() for part in payload]
print(' Parts:', ' '.join(part_content_types), '...')
else:
print(' ', ' '.join(payload[:60].split()), '...')
if __name__=='__main__':
main()
这是下载邮件的最简单形式,当然如果文件夹很大而且附件很大的话,就需要很长的下载时间。
1.2.1.2 Downloading Messages Individually
上面下载整个文件夹里的message这种使用情境在实际情况中比较少见,通常是下载某一个message。
略。
1.2.2 Flagging Messages
前面对每一个Message都有会mark 1个attribute称为flag,它们在\之后显示,通常有下面几种:
-
\Answered: The user has replied to the message.
-
\Draft: The user has not finished composing the message.
-
\Flagged: The message has somehow been singled out specially; the purpose and meaning of this flag vary between e-mail readers.
-
\recent: No IMAP client has seen this message before. This flag is unique int hat the flag cannot be added or removed by normal commands; it is automatically removed after the mailbox is selected.
-
\Seen: The message has been read.
你可以通过下面命令来读写message的flag。
1
2
3
c.get_flags(2703)
c.remove_flags(2703, ['\\Seen'])
c.add_flags(2703, ['\\Answered'])
1.2.3 Deleting Messages
删除message有两个步骤:
-
mark message as “\delete”;
-
call
expunge()
。
1
2
c.delete_messages([2703, 2704])
c.expunge()
1.2.4 Searching
1
2
3
>>> c.select_folder('INBOX')
>>> c.search('SINCE 13-Jul-2013 TEXT Apress')
[2590L, 2652L, 2653L, 2654L, 2655L, 2699L] #UID
1.2.5 Manipulating Folders and Messages
通过IMAPClient创建和删除文件夹比较简单。
1
2
c.create_folder('Personal')
c.delete_folder('Work')
1.2.6 Asynchrony
IMAPClient本身没提供Asynchrony,但是在其他包含IMAPClient的库里有提供,例如Twisted Python。