forked from x4nth055/pythoncode-tutorials
- Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathread_emails.py
More file actions
Latest commit
132 lines (122 loc) · 5.7 KB
/
Copy pathread_emails.py
File metadata and controls
132 lines (122 loc) · 5.7 KB
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
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
importos
importsys
# for encoding/decoding messages in base64
frombase64importurlsafe_b64decode
fromcommonimportgmail_authenticate, search_messages
defget_size_format(b, factor=1024, suffix="B"):
"""
Scale bytes to its proper byte format
e.g:
1253656 => '1.20MB'
1253656678 => '1.17GB'
"""
forunitin ["", "K", "M", "G", "T", "P", "E", "Z"]:
ifb<factor:
returnf"{b:.2f}{unit}{suffix}"
b/=factor
returnf"{b:.2f}Y{suffix}"
defclean(text):
# clean text for creating a folder
return"".join(cifc.isalnum() else"_"forcintext)
defparse_parts(service, parts, folder_name):
"""
Utility function that parses the content of an email partition
"""
ifparts:
forpartinparts:
filename=part.get("filename")
mimeType=part.get("mimeType")
body=part.get("body")
data=body.get("data")
file_size=body.get("size")
part_headers=part.get("headers")
ifpart.get("parts"):
# recursively call this function when we see that a part
# has parts inside
parse_parts(service, part.get("parts"), folder_name)
ifmimeType=="text/plain":
# if the email part is text plain
ifdata:
text=urlsafe_b64decode(data).decode()
print(text)
elifmimeType=="text/html":
# if the email part is an HTML content
# save the HTML file and optionally open it in the browser
ifnotfilename:
filename="index.html"
filepath=os.path.join(folder_name, filename)
print("Saving HTML to", filepath)
withopen(filepath, "wb") asf:
f.write(urlsafe_b64decode(data))
else:
# attachment other than a plain text or HTML
forpart_headerinpart_headers:
part_header_name=part_header.get("name")
part_header_value=part_header.get("value")
ifpart_header_name=="Content-Disposition":
if"attachment"inpart_header_value:
# we get the attachment ID
# and make another request to get the attachment itself
print("Saving the file:", filename, "size:", get_size_format(file_size))
attachment_id=body.get("attachmentId")
attachment=service.users().messages() \
.attachments().get(id=attachment_id, userId='me', messageId=msg['id']).execute()
data=attachment.get("data")
filepath=os.path.join(folder_name, filename)
ifdata:
withopen(filepath, "wb") asf:
f.write(urlsafe_b64decode(data))
defread_message(service, message_id):
"""
This function takes Gmail API `service` and the given `message_id` and does the following:
- Downloads the content of the email
- Prints email basic information (To, From, Subject & Date) and plain/text parts
- Creates a folder for each email based on the subject
- Downloads text/html content (if available) and saves it under the folder created as index.html
- Downloads any file that is attached to the email and saves it in the folder created
"""
msg=service.users().messages().get(userId='me', id=message_id['id'], format='full').execute()
# parts can be the message body, or attachments
payload=msg['payload']
headers=payload.get("headers")
parts=payload.get("parts")
folder_name="email"
ifheaders:
# this section prints email basic info & creates a folder for the email
forheaderinheaders:
name=header.get("name")
value=header.get("value")
ifname=='From':
# we print the From address
print("From:", value)
ifname=="To":
# we print the To address
print("To:", value)
ifname=="Subject":
# make a directory with the name of the subject
folder_name=clean(value)
# we will also handle emails with the same subject name
folder_counter=0
whileos.path.isdir(folder_name):
folder_counter+=1
# we have the same folder name, add a number next to it
iffolder_name[-1].isdigit() andfolder_name[-2] =="_":
folder_name=f"{folder_name[:-2]}_{folder_counter}"
eliffolder_name[-2:].isdigit() andfolder_name[-3] =="_":
folder_name=f"{folder_name[:-3]}_{folder_counter}"
else:
folder_name=f"{folder_name}_{folder_counter}"
os.mkdir(folder_name)
print("Subject:", value)
ifname=="Date":
# we print the date when the message was sent
print("Date:", value)
parse_parts(service, parts, folder_name)
print("="*50)
if__name__=="__main__":
service=gmail_authenticate()
# get emails that match the query you specify from the command lines
results=search_messages(service, sys.argv[1])
# for each email matched, read it (output plain/text to console & save HTML and attachments)
formsginresults:
read_message(service, msg)