Querying Office 365 Service Communications API with Python - python

I am trying to get the name of all Office 365 services by querying the Service Communications API.
I have been able to complete the task using a PowerShell script, but am unable to do the same using Python.
When using Python, I get a 200 response code, but have been unable to parse what is returned. Any help would be much appreciated.
My attempt to convert the PowerShell script to Python is below.
import json
import requests
from requests.auth import HTTPBasicAuth
username = "username"
password = "password"
# Base Service Communications URI
baseuri = "https://api.admin.microsoftonline.com/shdtenantcommunications.svc"
headers = {"accept": "application/json;odata=verbose"}
auth = {"username": username, "password": password}
# URI Paths
serviceinfo = "/GetServiceInformation"
register = "/Register"
response = requests.options(baseuri+register, auth=HTTPBasicAuth(username, password))
print("Registration status code: %s" % response.status_code)
if (response is not None and 200 == response.status_code):
info = requests.options(baseuri+serviceinfo, auth=HTTPBasicAuth(username, password))
print("Info status code: %s" % info.status_code)
data = json.loads(info.text)
The Python script returns an error. Specifically, it returns the following:
Registration status code: 200
Info status code: 200
Traceback (most recent call last):
File "o365_option.py", line 22, in <module>
data = json.loads(info.text)
File "/usr/local/lib/python2.7/json/__init__.py", line 326, in loads
return _default_decoder.decode(s)
File "/usr/local/lib/python2.7/json/decoder.py", line 366, in decode
obj, end = self.raw_decode(s, idx=_w(s, 0).end())
File "/usr/local/lib/python2.7/json/decoder.py", line 384, in raw_decode
raise ValueError("No JSON object could be decoded")
ValueError: No JSON object could be decoded

There are a few issues with your python script. Here is the correct python script to duplicate the results from the powershell script you posted.
import json
import requests
from requests.auth import HTTPBasicAuth
username = "username"
password = "password"
# Base Service Communications URI
baseuri = "https://api.admin.microsoftonline.com/shdtenantcommunications.svc"
headers = {"accept": "application/json;odata=verbose"}
auth = {"username": username, "password": password}
# URI Paths
serviceinfo = "/GetServiceInformation"
register = "/Register"
payload = {'userName': username, 'password': password}
myheaders = {'Content-Type': 'application/json'}
data=json.dumps(payload)
response = requests.post(baseuri+register,data=json.dumps(payload),headers=myheaders)
responsedata = json.loads(response.text)
cookie = responsedata.get("RegistrationCookie")
payload1 = {'lastCookie':cookie,'locale':"en-US"}
response = requests.post(baseuri+serviceinfo,data=json.dumps(payload1),headers=myheaders)
responsedata = json.loads(response.text)
for myobject in responsedata:
print myobject.get("ServiceName")
This is the response you will get:
"Exchange Online"
"Office Subscription"
"Identity Service"
"Office 365 Portal"
"Skype for Business"
"SharePoint Online"
"Rights Management Service"
"Yammer Enterprise"
"OneDrive for Business"
"Mobile Device Management"
Additionally, please note that there is a new version of the Office 365 Service Communications API in public preview which is available here:
https://msdn.microsoft.com/en-us/library/office/dn707385.aspx
It has a few new methods that might be interesting to you, and is a bit easier to develop against. The new API follows the OAuth 2.0 flow that the other Microsoft APIs are using. If you are using multiple Microsoft APIs, than you will be familiar with the flow already.
Let me know if this answers your question or if have any additional questions.

Related

Download file from API server

I need to upload a file to the system from the API server. post method, the server accepts an authorization token and a file id. I tried to do this by writing to a file(.write(responce.content)), but the text of the saved file is: "Unable to get a response from the server."
code:
import requests
def test_download():
headers = {"Authorization": "token"}
data = {"fileId": "43232-31621-51923-31515-59031"}
responce = requests.post("url/api/integration/file/download",
headers=headers, json=data)
with open("download_file.txt", "wb") as code: code.write(responce.content)
print(responce.text)
assert responce.status_code == 200
but I need the text of the file from the server. is it possible to download the file in another way? thank you in advance)

When hitting SOAP Request using zeep module then getting execption "The given SOAPAction None does not match an operation."

I am executing SOAP webservice using WS-Security #PAsswordDigest using Zeep module in python. But when hitting request then getting like "The given SOAPAction None does not match an operation."
from zeep.wsse.username import UsernameToken
from zeep import Client , Settings , xsd
username = 'username'
password = 'password'
WSDL_URL = 'http://0.0.0.0:0000/wsdl/sdpService.wsdl'
settings = Settings(strict=False, xml_huge_tree=True)
token = UsernameToken(username, password, use_digest=True)
client = Client(wsdl=WSDL_URL, wsse=token, service_name="UserService", port_name="UserServiceSOAP", settings=settings)
header_value = {
"SOAPAction" : ""
}
with client.settings(raw_response=True):
response = client.service.Authenticate()
print(response.text)
Hitting above request getting error
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"><soap:Body><soap:Fault><faultcode>soap:Server</faultcode><faultstring>The given SOAPAction None does not match an operation.</faultstring></soap:Fault></soap:Body></soap:Envelope>
I got the solution using python >> zeep >> Plugin >> egress.
def egress(self, envelope, http_headers, operation, binding_options):
self.log.info("Request XML to SERVER :: \n"+parseString(etree.tostring(envelope)).toprettyxml()+"\n")
http_headers = {
'Content-Type': 'text/xml; charset=utf-8',
'SOAPAction': b'""'
}
return envelope, http_headers
I am able to modify the "SOAPAction" key value from "None" to ""
This is a bug in Zeep.
I've just run into the same problem and created a PR with a fix

How to retrieve json file from Twiter Search API with CURL using urllib library

I just learnt how to access data thru application API and I stumble to a trouble.
I am currently trying to retrieve json file from Twitter Search API. The documentation of the API says CURL is used in order to access the data through HTTP GET. Below is the curl format:
curl "https://api.twitter.com/1.1/tweets/search/:product/:label.json?query=TwitterDev%20%5C%22search%20api%5C%22&maxResults=500&fromDate=<yyyymmddhhmm>&toDate=<yyyymmddhhmm>" -H "Authorization: Bearer TOKEN"
-curl api format
I have already tried to access it using urllib but still got error message during the run.
Below is the code I used.
import urllib.request, urllib.parse, urllib.error
import twurl
import ssl
import json
#TWITTER_URL = 'https://api.twitter.com/1.1/statuses/user_timeline.json'
TWITTER_URL = 'https://api.twitter.com/1.1/tweets/search/30day/data1.json'
# Ignore SSL certificate errors
ctx = ssl.create_default_context()
ctx.check_hostname = False
ctx.verify_mode = ssl.CERT_NONE
while True:
#acct = input('Enter Twitter Account: ')
#if (len(acct) < 1): break
parameters = {
#'screen_name': acct,
#'COunT': '3',
'query': 'inline skate',
'fromDate': '201906010000',
'toDate': '201906102359',
'maxResults': '20',
}
url = twurl.augment(TWITTER_URL, parameters)
print('\nRetrieving', url, '\n')
connection = urllib.request.urlopen(url, context=ctx)
data = connection.read().decode()
js = json.loads(data)
jsdmp = json.dumps(js, indent=2)
print(jsdmp, '\n')
#for data in js:
#print(data['text'])
headers = dict(connection.getheaders())
print('\nRemaining', headers['x-rate-limit-remaining'], '\n')
break
Here's the error message I keep getting:
File "C:\ProgramData\Anaconda3\lib\urllib\request.py", line 649, in http_error_default
raise HTTPError(req.full_url, code, msg, hdrs, fp)
HTTPError: Unprocessable Entity
It works when I try to access user_timeline tweets retriever above
TWITTER_URL = 'https://api.twitter.com/1.1/statuses/user_timeline.json'
But it doesn't with the search API I guess it is because of the CURL.
I already check the parameter I use is necessary as the docs tell to use.
Also, the twurl library used to access the token and process the url and parameters simultaneously to produce final url. (as far as I understand)
Below is the twurl code:
import urllib.request, urllib.parse, urllib.error
import oauth
import hidden
# https://apps.twitter.com/
# Create App and get the four strings, put them in hidden.py
def augment(url, parameters):
secrets = hidden.oauth()
consumer = oauth.OAuthConsumer(secrets['consumer_key'], secrets['consumer_secret'])
token = oauth.OAuthToken(secrets['token_key'], secrets['token_secret'])
oauth_request = oauth.OAuthRequest.from_consumer_and_token(consumer,
token, http_method='GET', http_url=url,
parameters=parameters)
#below is the main function galls!!
oauth_request.sign_request(oauth.OAuthSignatureMethod_HMAC_SHA1(),
consumer, token)
return oauth_request.to_url()
Below is hidden, where all the key and token stored:
def oauth():
return {"consumer_key": "2HZq407wF.................",
"consumer_secret": "OsemLubDmCcQq5Y3q............",
"token_key": "75230340-2SGPJWWn..............",
"token_secret": "NZcII332Y3EI.............."}
I have looked for solution and most of them seem to use urllib2 for CURL which I dont think is compatible with python 3?
Do you have any suggestion? I kind of stuck in this step and not going anywhere.
Thanks yall

MailChimp bad request JSONParseError with Python

I am trying to hook up to MailChimp's api, in my Django application, to add an email to one of my lists. Seems pretty simple enough. I add my api key to the header of the request, with the email address and other variable in the body of the request. every time I try and connect though, I get a response status code of 400. The message says there is a JSON parsing error, and that my JSON is either formatted incorrectly, or there is missing data required for the request. I am making this same api call however with Postman, and am getting a good response back.
view function
import requests
def join_newsletter(request, email):
# hash the user's email for mailchimp's API
# m = hashlib.md5()
# c_email = email
# m.update(c_email.encode('utf-8'))
# email_hash = m.hexdigest()
api_key = 'apikey ' + settings.MAILCHIMP_API
api_endpoint = api_endpoint
data = {
"email_address": email,
"status": "subscribed"
}
header = {
'Authorization': api_key
}
r = requests.post(api_endpoint, data=data, headers=header)
message = r.content
return message

SSLCertificateError - "The handshake operation timed out" when trying to get an access token from facebook

I am building an application which authenticates the user with javascript, and then reads the facebook signed_request info from the cookie in order to obtain an access token for use in the server.
I keep on hitting a timeout error in the ssl handshake.
this is the code i am using
logger.debug("authenticate with %s" % facebook_id)
payload = {'client_id': settings.FACEBOOK_APP_ID,
'client_secret': settings.FACEBOOK_APP_SECRET,
'code': code ,
'redirect_uri': settings.FACEBOOK_DEFAULT_REDIRECT_URI}
url = 'https://graph.facebook.com/oauth/access_token?' + urllib.urlencode(payload)
access_token, status, headers = urlfetch.fetch(
url=url,
deadline=30,
validate_certificate=False
)
logger.debug("recieved access token from fb %s" % access_token)
fails with this error:
DEBUG 2012-05-09 21:27:33,956 backends.py:24] authenticate with 546941722
DEBUG 2012-05-09 21:27:33,956 urlfetch_stub.py:317] Making HTTP request: host = graph.facebook.com, url = https://graph.facebook.com/oauth/access_token?client_secret=999&code=999&client_id=229985173769038&redirect_uri=http%3A%2F%2Fdev.bitesizedbeautyapp.appspot.com%2F, payload = , headers = {'Host': 'graph.facebook.com', 'Accept-Encoding': 'gzip', 'User-Agent': 'AppEngine-Google; (+http://code.google.com/appengine)'}
ERROR 2012-05-09 21:28:04,130 __init__.py:63] Exception in request:
Traceback (most recent call last):
File "/work/glow/bitesizedbeauty/django/core/handlers/base.py", line 89, in get_response
response = middleware_method(request)
File "/work/glow/bitesizedbeauty/bitesizedbeautyapp/facebook_glue/middleware.py", line 27, in process_request
user = authenticate(facebook_id = fb_uid, code = code)
File "/work/glow/bitesizedbeauty/django/contrib/auth/__init__.py", line 55, in authenticate
user = backend.authenticate(**credentials)
File "/work/glow/bitesizedbeauty/bitesizedbeautyapp/facebook_glue/backends.py", line 33, in authenticate
validate_certificate=False
File "/usr/local/google_appengine/google/appengine/api/urlfetch.py", line 263, in fetch
return rpc.get_result()
File "/usr/local/google_appengine/google/appengine/api/apiproxy_stub_map.py", line 592, in get_result
return self.__get_result_hook(self)
File "/usr/local/google_appengine/google/appengine/api/urlfetch.py", line 374, in _get_fetch_result
raise SSLCertificateError(str(err))
SSLCertificateError: ApplicationError: 6 _ssl.c:488: The handshake operation timed out
Edit
changed the code as #BluesRockAddict suggested, still getting the error
Edit #2
solved it! turned out to be a number of random different things.
add the parameters to the url as required by a GET request. (payload is only used in POST requests) as suggested by BlueRockAddict
i am using the client SDK to authenticate the user, and reading the code element from the fbsr_ cookie. In this case the redirect_uri should be empty
urlfetch in app-engine does not return a 3-tuple like i thought. so i assigned the method result to a single variable
here is the code that works for me:
def get_auth_token(code=None):
if not code:
return Null
try:
payload = {'client_id': settings.FACEBOOK_APP_ID,
'client_secret': settings.FACEBOOK_APP_SECRET,
'code': code,
'redirect_uri': ''}
url = 'https://graph.facebook.com/oauth/access_token?' + urllib.urlencode(payload)
logging.debug("url going to be called = (%s)" % url)
result = urlfetch.fetch(
url=url,
deadline=10,
validate_certificate=False
)
access_token = result.content
logging.info("recieved access_token from fb %s" % access_token)
except SSLCertificateError as error:
logging.error("SSLCertificateError when accessing oauth/access_token, error = %s " % error)
return None
except Exception as error2:
logging.error("Other Error, error = %s " % error2)
return None
payload argument should only be used for POST/PUT requests. Since you're using GET, your payload data needs to be included in the URL. Try the following:
access_token, status, headers = urlfetch.fetch(
"https://graph.facebook.com/oauth/access_token?" +
urllib.urlencode(payload))

Categories