-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathGoogle.py
More file actions
209 lines (184 loc) · 8.75 KB
/
Google.py
File metadata and controls
209 lines (184 loc) · 8.75 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
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
import httplib2, base64, email
from email.mime.multipart import MIMEMultipart
from email.mime.text import MIMEText
from apiclient.discovery import build
from apiclient import errors
from oauth2client import tools
from oauth2client.file import Storage
from oauth2client.client import flow_from_clientsecrets
import logging, os
BASE_DIR = os.path.dirname(os.path.abspath(__file__))
class GoogleError(Exception):
def __init__(self, message):
# Call the base class constructor with the parameters it needs
super(ValidationError, self).__init__(message)
class Google:
def __init__(self,scopes=None):
# Need to have Drive API and Gmail API enabled
if scopes is None:
scopes = ['https://spreadsheets.google.com/feeds', # Read google docs
'https://www.googleapis.com/auth/gmail.readonly',
'https://www.googleapis.com/auth/gmail.compose', # Send emails
'https://www.googleapis.com/auth/userinfo.email'] # Get users email address
self.scopes = scopes
self.authenticated = False
self.user_info = None
self.credentials = None
self.gmail = None # Build in authenticate method
self.googlesheets = None # Build in method if needed
self.resultSizeEstimate = None # Set in search method
def authenticate(self):
flow = flow_from_clientsecrets(os.path.join(BASE_DIR,'client_secret.json'), scope=' '.join(self.scopes))
storage = Storage(os.path.join(BASE_DIR,'creds.data'))
self.credentials = storage.get()
# If no credentials are found or the credentials are invalid due to
# expiration, new credentials need to be obtained from the authorization
# server. The oauth2client.tools.run_flow() function attempts to open an
# authorization server page in your default web browser. The server
# asks the user to grant your application access to the user's data.
# If the user grants access, the run_flow() function returns new credentials.
# The new credentials are also stored in the supplied Storage object,
# which updates the credentials.dat file.
if self.credentials is None or self.credentials.invalid:
flow.params['access_type'] = 'offline'
flow.params['approval_prompt'] = 'force' # Force oauth server to return refresh token
self.credentials = tools.run_flow(flow,storage,tools.argparser.parse_args())
logging.debug('Ran flow')
if self.credentials is not None and self.credentials.access_token_expired:
self.credentials.refresh(httplib2.Http())
logging.debug('Refreshed token')
self.user_info = self._get_user_info()
self.authenticated = True
http = self.credentials.authorize(httplib2.Http())
self.gmail = build(serviceName='gmail', version='v1', http=http,cache_discovery=False)
if 'name' in self.user_info:
logging.debug('%s (%s) authenticated.'%(self.user_info['name'],self.user_info['email']))
else:
logging.debug('%s authenticated.'%(self.user_info['email']))
def _get_user_info(self):
"""Send a request to the UserInfo API to retrieve the user's information.
Args:
credentials: oauth2client.client.OAuth2Credentials instance to authorize the
request.
Returns:
User information as a dict.
"""
user_info_service = build(serviceName='oauth2', version='v2', http=self.credentials.authorize(httplib2.Http()),cache_discovery=False)
user_info = user_info_service.userinfo().get().execute()
if user_info and user_info.get('id'):
return user_info
else:
raise GoogleError('No user ID.')
def get_spreadsheet(self,fileName=None,fileId=None,fileURL=None):
import gspread
if not self.googlesheets:
self.googlesheets = gspread.authorize(self.credentials)
if fileName is not None:
sh = self.googlesheets.open(fileName)
elif fileId is not None:
sh = self.googlesheets.open_by_key(fileId)
elif fileURL is not None:
sh = self.googlesheets.open_by_url(fileURL)
return sh
def CreateMessage(self,to,msg,subject,cc=None,html_msg=None):
# Send mail from current user's gmail default address (can't seem to change that)
if type(to)==list or type(to)==tuple:
to = ', '.join(to)
# Prepare payload
if html_msg:
message = MIMEMultipart('alternative')
mt = MIMEText(None,'plain','utf-8')
mt.replace_header('content-transfer-encoding', 'quoted-printable')
mt.set_payload(msg.encode('utf-8'))
message.attach(mt)
mt = MIMEText(None,'html','utf-8')
mt.replace_header('content-transfer-encoding', 'quoted-printable')
mt.set_payload(html_msg.encode('utf-8'))
message.attach(mt)
else:
message = MIMEText(msg,'plain','utf-8')
# Prepare subject, to and cc
message['to'] = to
if cc:
if type(cc)==list or type(cc)==tuple:
cc = ', '.join(cc)
message['cc'] = cc
message['subject'] = subject
# Encode and send to gmail servers
return {'raw':base64.urlsafe_b64encode(message.as_string())}
def CreateDraft(self,message,threadId=None):
assert self.authenticated, Exception('Authenticate google first!')
try:
message = {'message': message}
if threadId:
message['threadId'] = threadId
draft = self.gmail.users().drafts().create(userId="me", body=message).execute()
except errors.HttpError, error:
raise GoogleError(error)
return draft
def SendMessage(self,message):
assert self.authenticated, Exception('Authenticate google first!')
try:
message = (self.gmail.users().messages().send(userId="me", body=message).execute())
except errors.HttpError, error:
raise GoogleError(error)
return message
def GetMessage(self, msg_id):
"""Get a Message with given ID.
Args:
service: Authorized Gmail API service instance.
user_id: User's email address. The special value "me"
can be used to indicate the authenticated user.
msg_id: The ID of the Message required.
Returns:
A Message.
"""
assert self.authenticated, Exception('Authenticate google first!')
try:
message = self.gmail.users().messages().get(userId='me', id=msg_id).execute()
return message
except errors.HttpError, error:
raise GoogleError(error)
def GetMimeMessage(self,msg_id):
"""Get a Message and use it to create a MIME Message.
Args:
service: Authorized Gmail API service instance.
user_id: User's email address. The special value "me"
can be used to indicate the authenticated user.
msg_id: The ID of the Message required.
Returns:
A MIME Message, consisting of data from Message.
"""
assert self.authenticated, Exception('Authenticate google first!')
try:
message = self.gmail.users().messages().get(userId='me', id=msg_id,format='raw').execute()
msg_str = base64.urlsafe_b64decode(message['raw'].encode('ASCII'))
mime_msg = email.message_from_string(msg_str)
return mime_msg
except errors.HttpError, error:
raise GoogleError(error)
def search(self,query):
# Generator that will keep yielding results and fetching more chunks when needed
assert self.authenticated, Exception('Authenticate google first!')
try:
response = self.gmail.users().messages().list(userId='me',q=query).execute()
self.resultSizeEstimate = response['resultSizeEstimate']
messages = []
if 'messages' in response:
for msg in response['messages']:
yield msg
while 'nextPageToken' in response:
page_token = response['nextPageToken']
response = self.gmail.users().messages().list(userId='me', q=query,
pageToken=page_token).execute()
self.resultSizeEstimate = response['resultSizeEstimate']
for msg in response['messages']:
yield msg
except errors.HttpError, error:
raise GoogleError(error)
finally:
self.resultSizeEstimate = None
if __name__ == '__main__':
g = Google()
g.authenticate()
print 'Google() authenticated in instance "g"'