-
Notifications
You must be signed in to change notification settings - Fork 1
/
Gmail.py
138 lines (108 loc) · 3.71 KB
/
Gmail.py
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
133
134
135
136
137
138
# -*- coding: utf-8-*-
import imaplib
import email
import re
from dateutil import parser
WORDS = ["EMAIL", "INBOX"]
def getSender(email):
"""
Returns the best-guess sender of an email.
Arguments:
email -- the email whose sender is desired
Returns:
Sender of the email.
"""
sender = email['From']
m = re.match(r'(.*)\s<.*>', sender)
if m:
return m.group(1)
return sender
def getDate(email):
return parser.parse(email.get('date'))
def getMostRecentDate(emails):
"""
Returns the most recent date of any email in the list provided.
Arguments:
emails -- a list of emails to check
Returns:
Date of the most recent email.
"""
dates = [getDate(e) for e in emails]
dates.sort(reverse=True)
if dates:
return dates[0]
return None
def fetchUnreadEmails(profile, since=None, markRead=False, limit=None):
"""
Fetches a list of unread email objects from a user's Gmail inbox.
Arguments:
profile -- contains information related to the user (e.g., Gmail
address)
since -- if provided, no emails before this date will be returned
markRead -- if True, marks all returned emails as read in target inbox
Returns:
A list of unread email objects.
"""
conn = imaplib.IMAP4_SSL('imap.gmail.com')
conn.debug = 0
conn.login(profile['gmail_address'], profile['gmail_password'])
conn.select(readonly=(not markRead))
msgs = []
(retcode, messages) = conn.search(None, '(UNSEEN)')
if retcode == 'OK' and messages != ['']:
numUnread = len(messages[0].split(' '))
if limit and numUnread > limit:
return numUnread
for num in messages[0].split(' '):
# parse email RFC822 format
ret, data = conn.fetch(num, '(RFC822)')
msg = email.message_from_string(data[0][1])
if not since or getDate(msg) > since:
msgs.append(msg)
conn.close()
conn.logout()
return msgs
def handle(text, mic, profile):
"""
Responds to user-input, typically speech text, with a summary of
the user's Gmail inbox, reporting on the number of unread emails
in the inbox, as well as their senders.
Arguments:
text -- user-input, typically transcribed speech
mic -- used to interact with the user (for both input and output)
profile -- contains information related to the user (e.g., Gmail
address)
"""
try:
msgs = fetchUnreadEmails(profile, limit=5)
if isinstance(msgs, int):
response = "You have %d unread emails." % msgs
mic.say(response)
return
senders = [getSender(e) for e in msgs]
except imaplib.IMAP4.error:
mic.say(
"I'm sorry. I'm not authenticated to work with your Gmail.")
return
if not senders:
mic.say("You have no unread emails.")
elif len(senders) == 1:
mic.say("You have one unread email from " + senders[0] + ".")
else:
response = "You have %d unread emails" % len(
senders)
unique_senders = list(set(senders))
if len(unique_senders) > 1:
unique_senders[-1] = 'and ' + unique_senders[-1]
response += ". Senders include: "
response += '...'.join(senders)
else:
response += " from " + unique_senders[0]
mic.say(response)
def isValid(text):
"""
Returns True if the input is related to email.
Arguments:
text -- user-input, typically transcribed speech
"""
return bool(re.search(r'\bemail\b', text, re.IGNORECASE))