22import mimetypes
33import requests
44from microsoftgraph import exceptions
5+ from microsoftgraph .decorators import token_required
56from urllib .parse import urlencode , urlparse
67
78
@@ -11,6 +12,10 @@ class Client(object):
1112 TOKEN_ENDPOINT = '/oauth2/v2.0/token'
1213 RESOURCE = 'https://graph.microsoft.com/'
1314
15+ OFFICE365_AUTHORITY_URL = 'https://login.live.com'
16+ OFFICE365_AUTH_ENDPOINT = '/oauth20_authorize.srf?'
17+ OFFICE365_TOKEN_ENDPOINT = '/oauth20_token.srf'
18+
1419 def __init__ (self , client_id , client_secret , api_version = 'v1.0' , account_type = 'common' ):
1520 self .client_id = client_id
1621 self .client_secret = client_secret
@@ -19,8 +24,9 @@ def __init__(self, client_id, client_secret, api_version='v1.0', account_type='c
1924
2025 self .base_url = self .RESOURCE + self .api_version + '/'
2126 self .token = None
27+ self .office365_token = None
2228
23- def authorization_url (self , redirect_uri , scope , state = None ):
29+ def authorization_url (self , redirect_uri , scope , state = None , office365 = False ):
2430 """
2531
2632 Args:
@@ -49,10 +55,13 @@ def authorization_url(self, redirect_uri, scope, state=None):
4955
5056 if state :
5157 params ['state' ] = None
58+ if office365 :
59+ response = self .OFFICE365_AUTHORITY_URL + self .OFFICE365_AUTH_ENDPOINT + urlencode (params )
60+ else :
61+ response = self .AUTHORITY_URL + self .account_type + self .AUTH_ENDPOINT + urlencode (params )
62+ return response
5263
53- return self .AUTHORITY_URL + self .account_type + self .AUTH_ENDPOINT + urlencode (params )
54-
55- def exchange_code (self , redirect_uri , code ):
64+ def exchange_code (self , redirect_uri , code , office365 = False ):
5665 """Exchanges a code for a Token.
5766
5867 Args:
@@ -72,9 +81,13 @@ def exchange_code(self, redirect_uri, code):
7281 'code' : code ,
7382 'grant_type' : 'authorization_code' ,
7483 }
75- return requests .post (self .AUTHORITY_URL + self .account_type + self .TOKEN_ENDPOINT , data = data ).json ()
84+ if office365 :
85+ response = requests .post (self .OFFICE365_AUTHORITY_URL + self .OFFICE365_TOKEN_ENDPOINT , data = data )
86+ else :
87+ response = requests .post (self .AUTHORITY_URL + self .account_type + self .TOKEN_ENDPOINT , data = data )
88+ return self ._parse (response )
7689
77- def refresh_token (self , redirect_uri , refresh_token ):
90+ def refresh_token (self , redirect_uri , refresh_token , office365 = True ):
7891 """
7992
8093 Args:
@@ -95,17 +108,25 @@ def refresh_token(self, redirect_uri, refresh_token):
95108 'refresh_token' : refresh_token ,
96109 'grant_type' : 'refresh_token' ,
97110 }
98- return requests .post (self .AUTHORITY_URL + self .account_type + self .TOKEN_ENDPOINT , data = data ).json ()
111+ if office365 :
112+ response = requests .post (self .OFFICE365_AUTHORITY_URL + self .OFFICE365_TOKEN_ENDPOINT , data = data )
113+ else :
114+ response = requests .post (self .AUTHORITY_URL + self .account_type + self .TOKEN_ENDPOINT , data = data )
115+ return self ._parse (response )
99116
100- def set_token (self , token ):
117+ def set_token (self , token , office365 = True ):
101118 """Sets the Token for its use in this library.
102119
103120 Args:
104121 token: A string with the Token.
105122
106123 """
107- self .token = token
124+ if office365 :
125+ self .office365_token = token
126+ else :
127+ self .token = token
108128
129+ @token_required
109130 def get_me (self , params = None ):
110131 """Retrieve the properties and relationships of user object.
111132
@@ -122,6 +143,7 @@ def get_me(self, params=None):
122143 """
123144 return self ._get (self .base_url + 'me' , params = params )
124145
146+ @token_required
125147 def get_message (self , message_id , params = None ):
126148 """Retrieve the properties and relationships of a message object.
127149
@@ -134,6 +156,7 @@ def get_message(self, message_id, params=None):
134156 """
135157 return self ._get (self .base_url + 'me/messages/' + message_id , params = params )
136158
159+ @token_required
137160 def create_subscription (self , change_type , notification_url , resource , expiration_datetime , client_state = None ):
138161 """Creating a subscription is the first step to start receiving notifications for a resource.
139162
@@ -156,6 +179,7 @@ def create_subscription(self, change_type, notification_url, resource, expiratio
156179 }
157180 return self ._post ('https://graph.microsoft.com/beta/' + 'subscriptions' , json = data )
158181
182+ @token_required
159183 def renew_subscription (self , subscription_id , expiration_datetime ):
160184 """The client can renew a subscription with a specific expiration date of up to three days from the time
161185 of request. The expirationDateTime property is required.
@@ -172,6 +196,7 @@ def renew_subscription(self, subscription_id, expiration_datetime):
172196 }
173197 return self ._patch ('https://graph.microsoft.com/beta/' + 'subscriptions/{}' .format (subscription_id ), json = data )
174198
199+ @token_required
175200 def delete_subscription (self , subscription_id ):
176201 """The client can stop receiving notifications by deleting the subscription using its ID.
177202
@@ -183,6 +208,7 @@ def delete_subscription(self, subscription_id):
183208 """
184209 return self ._delete ('https://graph.microsoft.com/beta/' + 'subscriptions/{}' .format (subscription_id ))
185210
211+ @token_required
186212 def list_notebooks (self ):
187213 """Retrieve a list of notebook objects.
188214
@@ -192,6 +218,7 @@ def list_notebooks(self):
192218 """
193219 return self ._get (self .base_url + 'me/onenote/notebooks' )
194220
221+ @token_required
195222 def get_notebook (self , notebook_id ):
196223 """Retrieve the properties and relationships of a notebook object.
197224
@@ -204,6 +231,7 @@ def get_notebook(self, notebook_id):
204231 """
205232 return self ._get (self .base_url + 'me/onenote/notebooks/' + notebook_id )
206233
234+ @token_required
207235 def get_notebook_sections (self , notebook_id ):
208236 """Retrieve the properties and relationships of a notebook object.
209237
@@ -216,6 +244,7 @@ def get_notebook_sections(self, notebook_id):
216244 """
217245 return self ._get (self .base_url + 'me/onenote/notebooks/{}/sections' .format (notebook_id ))
218246
247+ @token_required
219248 def create_page (self , section_id , files ):
220249 """Create a new page in the specified section.
221250
@@ -227,12 +256,9 @@ def create_page(self, section_id, files):
227256 A dict.
228257
229258 """
230- # headers = {
231- # 'Content-Type': 'text/html'
232- # }
233- headers = None
234- return self ._post (self .base_url + '/me/onenote/sections/{}/pages' .format (section_id ), headers = headers , files = files )
259+ return self ._post (self .base_url + '/me/onenote/sections/{}/pages' .format (section_id ), files = files )
235260
261+ @token_required
236262 def get_me_events (self ):
237263 """Get a list of event objects in the user's mailbox. The list contains single instance meetings and
238264 series masters.
@@ -245,6 +271,7 @@ def get_me_events(self):
245271 """
246272 return self ._get (self .base_url + 'me/events' )
247273
274+ @token_required
248275 def create_calendar_event (
249276 self , subject , content ,
250277 start_datetime , start_timezone , end_datetime ,
@@ -322,6 +349,7 @@ def create_calendar_event(
322349 url = 'me/calendars/{}/events' .format (calendar ) if calendar is not None else 'me/events'
323350 return self ._post (self .base_url + url , json = body )
324351
352+ @token_required
325353 def create_calendar (self , name ):
326354 """Create an event in the user's default calendar or specified calendar.
327355
@@ -341,6 +369,7 @@ def create_calendar(self, name):
341369 }
342370 return self ._post (self .base_url + 'me/calendars' , json = body )
343371
372+ @token_required
344373 def get_me_calendar (self , calendar_id = None ):
345374 """Get the properties and relationships of a calendar object. The calendar can be one for a user,
346375 or the default calendar of an Office 365 group.
@@ -354,6 +383,7 @@ def get_me_calendar(self, calendar_id=None):
354383 url = 'me/calendar/{}' .format (calendar_id ) if calendar_id is not None else 'me/calendar'
355384 return self ._get (self .base_url + url )
356385
386+ @token_required
357387 def get_me_calendars (self ):
358388 """
359389
@@ -362,6 +392,7 @@ def get_me_calendars(self):
362392 """
363393 return self ._get (self .base_url + 'me/calendars' )
364394
395+ @token_required
365396 def send_mail (self , subject = None , recipients = None , body = '' , content_type = 'HTML' , attachments = None ):
366397 """Helper to send email from current user.
367398
@@ -404,26 +435,30 @@ def send_mail(self, subject=None, recipients=None, body='', content_type='HTML',
404435 # Do a POST to Graph's sendMail API and return the response.
405436 return self ._post (self .base_url + 'me/microsoft.graph.sendMail' , json = email_msg )
406437
407- # Outlook Contacts Methods
438+ @ token_required
408439 def outlook_get_me_contacts (self , data_id = None , params = None ):
409440 if data_id is None :
410441 url = "{0}me/contacts" .format (self .base_url )
411442 else :
412443 url = "{0}me/contacts/{1}" .format (self .base_url , data_id )
413444 return self ._get (url , params = params )
414445
446+ @token_required
415447 def outlook_create_me_contact (self , ** kwargs ):
416448 url = "{0}me/contacts" .format (self .base_url )
417449 return self ._post (url , ** kwargs )
418450
451+ @token_required
419452 def outlook_create_contact_in_folder (self , folder_id , ** kwargs ):
420453 url = "{0}/me/contactFolders/{1}/contacts" .format (self .base_url , folder_id )
421454 return self ._post (url , ** kwargs )
422455
456+ @token_required
423457 def outlook_get_contact_folders (self , params = None ):
424458 url = "{0}me/contactFolders" .format (self .base_url )
425459 return self ._get (url , params = params )
426460
461+ @token_required
427462 def outlook_create_contact_folder (self , ** kwargs ):
428463 url = "{0}me/contactFolders" .format (self .base_url )
429464 return self ._post (url , ** kwargs )
@@ -454,7 +489,6 @@ def _request(self, method, url, headers=None, **kwargs):
454489 return self ._parse (requests .request (method , url , headers = _headers , ** kwargs ))
455490
456491 def _parse (self , response ):
457- print (response .text )
458492 status_code = response .status_code
459493 if 'application/json' in response .headers ['Content-Type' ]:
460494 r = response .json ()
0 commit comments