python-o365: ValueError: Protocol not provided to Api Component

Hi, I’ve trouble initializing Calendar or Schedule object. It throws me an error: ValueError: Protocol not provided to Api Component

I follow your documentation and example but it uses Account for authentication and account.schedule to get schedule data. but problem with Account is that it print the url and then user needs to paste it in browser and copy the resultant url to console. So it is not suitable for what i am trying to achive. I am trying to achive it through the web based authentication. I already have one web app where i want to integrate the calendar and events. So i am using Flask and want to do it web based. So There are two end points:

  1. /api/O365api - For authentication and redirecting to my other end point (2) if success
  2. /api/GetCode - This method is where i want to get the appropriate calender/schedule object and further getting events etc.

Below is my code:

from O365 import Connection
from O365 import Calendar, Schedule, MSGraphProtocol
from O365.utils import ApiComponent
import datetime as dt
from O365 import oauth_authentication_flow
from flask import Blueprint
from flask import redirect, request 
 

outlookApi = Blueprint('outlook_api', __name__)

appid = 'MYAPPID'
clientSecret = 'MYAPPSECRET'

credentials = (appid, clientSecret)
scopes = ['https://graph.microsoft.com/Calendars.Read']

def redirectToMs(url):
    return redirect(url, code=302)


@outlookApi.route("/api/O365api")
def O365Api():
    global con
    con = Connection(credentials, scopes=scopes)
    url = con.get_authorization_url(scopes, redirect_uri="http://localhost:31544/api/GetCode")
    return redirectToMs(url)

@outlookApi.route("/api/GetCode")
def GetCode():
    val = request.url
    result = con.request_token(val)
    if result:
        print('Authentication Flow Completed. Oauth Access Token Stored. '
              'You can now use the API.')

        # s = Schedule() ## Even this is also not working and trhwoing same exception
        c = Calendar() ## This line throws the exception
        q = c.new_query('start').greater_equal(dt.datetime(2018, 5, 20))
        q.chain('and').on_attribute('end').less_equal(dt.datetime(2018, 5, 24))

        birthdays = c.get_events(query=q,
                                 include_recurring=True)   
        for event in birthdays:
            print(event.subject)
    else:
        print('Something go wrong. Please try again.')

    return 'Success'

About this issue

  • Original URL
  • State: closed
  • Created 5 years ago
  • Comments: 15 (9 by maintainers)

Most upvoted comments

Do you have a database?

If yes:

  • Subclass a new BaseTokenBackend that will implement the logic to save and retrieve the token from the database as I told you early.

If no:

  • If your web app uses multiple instances then you pretty much need a database.

The O365 library will obtain a token:

  1. When the user authenticates:
    • This will be a fresh new token so It will be cached in the instance and stored in the TokenBackend for later use.
  2. When the user makes the first request (like getting events):
    • Whenever a new instances of the O365 library makes the first request will check if there is a token cached. If not, it will retrieve it from the TokenBackend and then cache it for later use.
  3. When the token is expired:
    • The library will then request a new token, cache it and store it in the TokenBackend.

All this works automatically. You just have to define the TokenBackend.

You can check if there is a token stored in the TokenBackend and if this token is valid with account.is_authenticated property.

account = Account(credentials)
if account.is_authenticated:
    events = account.schedule().get_events(limit=25)
    # ...
else:
   return redirect('O365 authentication endpoint')

I think this is the most I can help you.