I'm new to Python as well as in Flask... I have developed an python file which sets up the Oauth2 authentication with googele and fetching the list of messages from GMAIL API. Here is my code
import json
import flask
import httplib2
import base64
import email
from apiclient import discovery, errors
from oauth2client import client
app = flask.Flask(__name__)
#app.route('/')
def index():
if 'credentials' not in flask.session:
return flask.redirect(flask.url_for('oauth2callback'))
credentials = client.OAuth2Credentials.from_json(flask.session['credentials'])
if credentials.access_token_expired:
return flask.redirect(flask.url_for('oauth2callback'))
else:
http_auth = credentials.authorize(httplib2.Http())
gmail_service = discovery.build('gmail', 'v1', http_auth)
threads = gmail_service.users().threads().list(userId='me').execute()
return json.dumps(threads)
#app.route('/oauth2callback')
def oauth2callback():
flow = client.flow_from_clientsecrets(
'client_secrets.json',
scope='https://mail.google.com/',
redirect_uri=flask.url_for('oauth2callback', _external=True)
)
if 'code' not in flask.request.args:
auth_uri = flow.step1_get_authorize_url()
return flask.redirect(auth_uri)
else:
auth_code = flask.request.args.get('code')
credentials = flow.step2_exchange(auth_code)
flask.session['credentials'] = credentials.to_json()
return flask.redirect(flask.url_for('index'))
#app.route('/getmail')
def getmail():
if 'credentials' not in flask.session:
return flask.redirect(flask.url_for('oauth2callback'))
credentials = client.OAuth2Credentials.from_json(flask.session['credentials'])
if credentials.access_token_expired:
return flask.redirect(flask.url_for('oauth2callback'))
else:
http_auth = credentials.authorize(httplib2.Http())
gmail_service = discovery.build('gmail', 'v1', http_auth)
query = 'is:inbox'
"""List all Messages of the user's mailbox matching the query.
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.
query: String used to filter messages returned.
Eg.- 'from:user#some_domain.com' for Messages from a particular sender.
Returns:
List of Messages that match the criteria of the query. Note that the
returned list contains Message IDs, you must use get with the
appropriate ID to get the details of a Message.
"""
try:
response = gmail_service.users().messages().list(userId='me', q=query).execute()
messages = []
if 'messages' in response:
print 'test %s' % response
messages.extend(response['messages'])
while 'nextPageToken' in response:
page_token = response['nextPageToken']
response = gmail_service.users().messages().list(userId='me', q=query, pageToken=page_token).execute()
messages.extend(response['messages'])
return messages
except errors.HttpError, error:
print 'An error occurred: %s' % error
if __name__ == '__main__':
import uuid
app.secret_key = str(uuid.uuid4())
app.debug = True
app.run()
Authentication works fine and when I go to /getmail URL I am getting this error TypeError: 'list' object is not callable
Any thoughts what I am doing wrong?
I changed return object in Flask from return messages to this piece of code.
First I imported to from flask.json import jsonify
try:
response = gmail_service.users().messages().list(userId='me', q=query).execute()
messages = []
if 'messages' in response:
print 'test %s' % response
messages.extend(response['messages'])
while 'nextPageToken' in response:
page_token = response['nextPageToken']
response = gmail_service.users().messages().list(userId='me', q=query, pageToken=page_token).execute()
messages.extend(response['messages'])
return jsonify({'data': messages}) # changed here
except errors.HttpError, error:
print 'An error occurred: %s' % error
all credit goes to #doru
Related
I have been using the youtube API to upload remotely. But after a while of messing around with the code all the videos that get uploaded gets "Private (locked)" due to Terms and policies. I cant appeal it either due to "Appealing this violation is not available". Just to clarify I have been able to upload before and only recently started getting this error.
Code:
youtube-uploader
#!/usr/bin/python
import argparse
import http.client
import httplib2
import os
import random
import time
import videoDetails
import google.oauth2.credentials
import google_auth_oauthlib.flow
from googleapiclient.discovery import build
from googleapiclient.errors import HttpError
from googleapiclient.http import MediaFileUpload
from google_auth_oauthlib.flow import InstalledAppFlow
from oauth2client import client # Added
from oauth2client import tools # Added
from oauth2client.file import Storage # Added
# Explicitly tell the underlying HTTP transport library not to retry, since
# we are handling retry logic ourselves.
httplib2.RETRIES = 1
# Maximum number of times to retry before giving up.
MAX_RETRIES = 10
# Always retry when these exceptions are raised.
RETRIABLE_EXCEPTIONS = (httplib2.HttpLib2Error, IOError, http.client.NotConnected,
http.client.IncompleteRead, http.client.ImproperConnectionState,
http.client.CannotSendRequest, http.client.CannotSendHeader,
http.client.ResponseNotReady, http.client.BadStatusLine)
# Always retry when an apiclient.errors.HttpError with one of these status
# codes is raised.
RETRIABLE_STATUS_CODES = [500, 502, 503, 504]
CLIENT_SECRETS_FILE = 'client_secrets.json'
SCOPES = ['https://www.googleapis.com/auth/youtube.upload']
API_SERVICE_NAME = 'youtube'
API_VERSION = 'v3'
VALID_PRIVACY_STATUSES = ('public', 'private', 'unlisted')
def get_authenticated_service(): # Modified
credential_path = os.path.join('./', 'credentials.json')
store = Storage(credential_path)
credentials = store.get()
if not credentials or credentials.invalid:
flow = client.flow_from_clientsecrets(CLIENT_SECRETS_FILE, SCOPES)
credentials = tools.run_flow(flow, store)
return build(API_SERVICE_NAME, API_VERSION, credentials=credentials)
def initialize_upload(youtube, options):
tags = None
if options.keywords:
tags = options.keywords.split(',')
body=dict(
snippet=dict(
title=options.getFileName("video").split(".", 1)[0],
description=options.description,
tags=tags,
categoryId=options.category
),
status=dict(
privacyStatus=options.privacyStatus
)
)
# Call the API's videos.insert method to create and upload the video.
videoPath = "/Users\caspe\OneDrive\Documents\Övrigt\Kodning\AwsCSGO\Video\%s" % (options.getFileName("video"))
insert_request = youtube.videos().insert(
part=','.join(body.keys()),
body=body,
media_body=MediaFileUpload(videoPath, chunksize=-1, resumable=True)
)
resumable_upload(insert_request, options)
# This method implements an exponential backoff strategy to resume a
# failed upload.
def resumable_upload(request, options):
response = None
error = None
retry = 0
while response is None:
try:
print('Uploading file...')
status, response = request.next_chunk()
if response is not None:
if 'id' in response:
print ('The video with the id %s was successfully uploaded!' % response['id'])
# upload thumbnail for Video
options.insertThumbnail(youtube, response['id'])
else:
exit('The upload failed with an unexpected response: %s' % response)
except HttpError as e:
if e.resp.status in RETRIABLE_STATUS_CODES:
error = 'A retriable HTTP error %d occurred:\n%s' % (e.resp.status,
e.content)
else:
raise
except RETRIABLE_EXCEPTIONS as e:
error = 'A retriable error occurred: %s' % e
if error is not None:
print (error)
retry += 1
if retry > MAX_RETRIES:
exit('No longer attempting to retry.')
max_sleep = 2 ** retry
sleep_seconds = random.random() * max_sleep
print ('Sleeping %f seconds and then retrying...') % sleep_seconds
time.sleep(sleep_seconds)
if __name__ == '__main__':
args = videoDetails.Video()
youtube = get_authenticated_service()
try:
initialize_upload(youtube, args)
except HttpError as e:
print ('An HTTP error %d occurred:\n%s') % (e.resp.status, e.content)
videoDetails
import os
from googleapiclient.http import MediaFileUpload
class Video:
description = "test description"
category = "22"
keywords = "test"
privacyStatus = "public"
def getFileName(self, type):
for file in os.listdir("/Users\caspe\OneDrive\Documents\Övrigt\Kodning\AwsCSGO\Video"):
if type == "video" and file.split(".", 1)[1] != "jpg":
return file
break
elif type == "thumbnail" and file.split(".", 1)[1] != "mp4":
return file
break
def insertThumbnail(self, youtube, videoId):
thumnailPath = "/Users\caspe\OneDrive\Documents\Övrigt\Kodning\AwsCSGO\Video\%s" % (self.getFileName("thumbnail"))
request = youtube.thumbnails().set(
videoId=videoId,
media_body=MediaFileUpload(thumnailPath)
)
response = request.execute()
print(response)
If you check the documentation for Video.insert you will find the following at the top of the page. This is a new policy that is recently beginning to be enforced.
Until your application has been verified all videos you upload will be set to private. You need to go though the audit first then you will be able to upload public videos.
Note once your application has been verified this will not automatically set all existing previously uploaded videos to public you will need to do that yourself.
Using the Azure Python SDK, I would like to return a KeyVaultClient using the get_client_from_auth_file method in order to get secrets from a KeyVault without going through a KeyVaultManagementClient.
According to the documentation, it appears to be possible to create a client from any SDK client class.
I am able to do this:
from azure.common.client_factory import get_client_from_auth_file
from azure.mgmt.keyvault import KeyVaultManagementClient
_kv_mgmt_client = get_client_from_auth_file(KeyVaultManagementClient)
but not this:
from azure.common.client_factory import get_client_from_auth_file
from azure.keyvault import KeyVaultClient
_kv_client = get_client_from_auth_file(KeyVaultClient)
This is the error message: TypeError: __init__() got an unexpected keyword argument 'base_url'
Update:
Upon review, get_client_from_auth_file returns several results including base_url, so the following helper function resolves the TypeError.
class KeyVaultClientHelper:
def __init__(self, credentials, **kwargs):
self._credentials = credentials
And the KeyVaultClient is successful until it tries to get a secret and it returns Unauthorized.
helper = get_client_from_auth_file(KeyVaultClientHelper)
client = KeyVaultClient(helper._credentials)
print(client.get_secret("http://my-vault-url...", "MY-KEY", '').value))
However, I am successful in getting secrets using a ServicePrincipalCredential with the same auth file.
this was a bug in azure-common, fixed in 1.1.22:
https://pypi.org/project/azure-common/1.1.22/
Thanks!
Kristin,
you can try something like below, it has a working sample for getting the keyvault client
import adal
from azure.keyvault import KeyVaultClient, KeyVaultAuthentication
from azure.common.credentials import ServicePrincipalCredentials
from msrestazure.azure_active_directory import AADTokenCredentials
client_id = '<client_id>'
client_secret = '<client_secret>'
tenant = '<tenant>'
vault_address = '<vault_address>'
secret_name = '<secret_name>'
resource_uri = 'https://vault.azure.net'
def auth_with_adal(server, resource, scope):
authority_host_uri = 'https://login.windows.net'
authority_uri = authority_host_uri + '/' + tenant
context = adal.AuthenticationContext(authority_uri, api_version=None)
mgmt_token = context.acquire_token_with_client_credentials(resource_uri, client_id, client_secret)
credentials = AADTokenCredentials(mgmt_token, client_id)
token = credentials.token
return token['token_type'], token['access_token']
def auth_with_spc(server, resource, scope):
credentials = ServicePrincipalCredentials(
client_id = client_id,
secret = client_secret,
tenant = tenant,
resource = resource_uri
)
token = credentials.token
return token['token_type'], token['access_token']
try:
client = KeyVaultClient(KeyVaultAuthentication(auth_with_adal))
secret_bundle = client.get_secret(vault_address, secret_name, '')
print('1) I got the secret using AADTokenCredentials!')
except Exception as e:
print('1) Failed to get a secret!')
print(e)
try:
client = KeyVaultClient(KeyVaultAuthentication(auth_with_spc))
secret_bundle = client.get_secret(vault_address, secret_name, '')
print('2) I got the secret using ServicePrincipalCredentials!')
except Exception as e:
print('2) Failed to get a secret!')
print(e)
You can use below function to achieve it.
client = KeyVaultClient(KeyVaultAuthentication(auth_with_spc))
Hope it helps.
I am writing a small python script to automate a workflow in my company. I have been testing the code on by inbox so far, as I did not want to mess up anything in the inbox of the actual account this script will be working on. The rest of the code was written, and after testing, I wanted to switch to the other account. So I logged into the new account, made a new project in the console, generated that projects unique client_secret file, and I then swapped out the old client_secret file with the new one, and also updated the project name to the one linked with the new account. However, upon running the script, I realized that the script was still running with my account linked. Im really not sure what else there is I need to replace, or if I am simply missing something?
Here are the relevant parts of my code for this issue:
import...
try:
import argparse
flags = argparse.ArgumentParser(parents=[tools.argparser]).parse_args()
except ImportError:
lags = None
requests.packages.urllib3.disable_warnings(InsecureRequestWarning)
def get_credentials():
"""Gets valid user credentials from storage.
If nothing has been stored, or if the stored credentials are invalid,
the OAuth2 flow is completed to obtain the new credentials.
Returns:
Credentials, the obtained credential.
"""
home_dir = os.path.expanduser('~')
credential_dir = os.path.join(home_dir, '.credentials')
if not os.path.exists(credential_dir):
os.makedirs(credential_dir)
credential_path = os.path.join(credential_dir,
'gmail-python-quickstart.json')
store = oauth2client.file.Storage(credential_path)
credentials = store.get()
if not credentials or credentials.invalid:
flow = client.flow_from_clientsecrets(CLIENT_SECRET_FILE, SCOPES)
flow.user_agent = APPLICATION_NAME
if flags:
credentials = tools.run_flow(flow, store, flags)
else: # Needed only for compatability with Python 2.6
credentials = tools.run(flow, store)
print('Storing credentials to ' + credential_path)
return credentials
def GetMessage(service, user_id, msg_id, fmt, flds ,mdh):
"""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.
"""
try:
message = service.users().messages().get(userId=user_id, id=msg_id, format=fmt,fields=flds ,metadataHeaders=mdh).execute()
#print ('Message snippet: %s' % message['snippet'])
return message
except errors.HttpError, error:
print ('An error occurred: %s' % error)
def GetMimeMessage(service, user_id, 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.
"""
try:
message = service.users().messages().get(userId=user_id, id=msg_id, format='raw').execute()
#print ('Message snippet: %s' % message['snippet'])
msg_str = base64.urlsafe_b64decode(message['raw'].encode('ASCII'))
mime_msg = email.message_from_string(msg_str)
return mime_msg
except errors.HttpError, error:
print ('An error occurred: %s' % error)
def ListMessagesMatchingQuery(service, user_id, query=''):
"""List all Messages of the user's mailbox matching the query.
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.
query: String used to filter messages returned.
Eg.- 'from:user#some_domain.com' for Messages from a particular sender.
Returns:
List of Messages that match the criteria of the query. Note that the
returned list contains Message IDs, you must use get with the
appropriate ID to get the details of a Message.
"""
try:
response = service.users().messages().list(userId=user_id,
q=query).execute()
messages = []
if 'messages' in response:
messages.extend(response['messages'])
while 'nextPageToken' in response:
page_token = response['nextPageToken']
response = service.users().messages().list(userId=user_id, q=query,
pageToken=page_token).execute()
messages.extend(response['messages'])
return messages
except errors.HttpError, error:
print ('An error occurred: %s' % error)
def SendMessage(service, user_id, message):
"""Send an email 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.
message: Message to be sent.
Returns:
Sent Message.
"""
try:
message = (service.users().messages().send(userId=user_id, body=message)
.execute())
print ('Message Id: %s' % message['id'])
return message
except errors.HttpError, error:
print ('An error occurred: %s' % error)
def CreateMessage(sender, to, subject, message_text):
"""Create a message for an email.
Args:
sender: Email address of the sender.
to: Email address of the receiver.
subject: The subject of the email message.
message_text: The text of the email message.
Returns:
An object containing a base64url encoded email object.
"""
message = MIMEText.MIMEText(message_text)
message['to'] = to
message['from'] = sender
message['subject'] = subject
return {'raw': base64.urlsafe_b64encode(message.as_string())}
def GmailInput():
'''
:return:
'''
credentials = get_credentials()
http = credentials.authorize(httplib2.Http())
service = discovery.build('gmail', 'v1', http=http)
defaultList= ListMessagesMatchingQuery(service, 'me', 'subject: claimed infringement label:unread ')
currentMSG=[]
ips=[]
DraftedMessages=[]
for msg in defaultList:
currentMSG=GetMimeMessage(service, 'me', msg['id'])
strCurrentMessage=str(currentMSG)
#Extract the IP Address Field using the XML included in DMCA emails
#get a string value of the current message
if '<IP_Address>' not in strCurrentMessage:
pass
#print("XML TAG DOES NOT EXIST")
else:
loc1 = strCurrentMessage.find('<IP_Address>')
if '</IP_Address>' not in strCurrentMessage:
pass
#print("XML TAG DOES NOT EXIST")
else:
loc2 = strCurrentMessage.find('</IP_Address>')
#extract the IP address:
#get rid of the XML identifier in the beginning of the string:
LOC1=loc1+12
#determine legth of ip field
length=loc2-LOC1
ipaddress = strCurrentMessage[LOC1 : LOC1+length]
ips.append(ipaddress)
print(ips)
return ips
def main():
try:
import argparse
flags = argparse.ArgumentParser(parents=[tools.argparser]).parse_args()
except ImportError:
flags = None
SCOPES = 'https://mail.google.com/'
CLIENT_SECRET_FILE = 'client_secret.json'
APPLICATION_NAME = 'name'
requests.packages.urllib3.disable_warnings(InsecureRequestWarning)
GmailInstance=GmailInput()
InfobloxComments=InfobloxLookup(GmailInstance)
SEPERATED_COLS=[]
for eachComment in InfobloxComments:
DividedComments=SplitComments(eachComment)
SEPERATED_COLS.append(DividedComments)
columns=defaultdict(list)
with open('entities_table.csv', 'rb') as ENTITIES:
reader=csv.DictReader(ENTITIES)
for row in reader:
for (k,v) in row.items():
columns[k].append(v)
CEN_ENTITIES=columns['Common Name']
SEPERATED_ENT=[]
for eachEntity in CEN_ENTITIES:
DividedEntities=SplitComments(eachEntity)
SEPERATED_ENT.append(DividedEntities)
CallGlobalNocScript()
MakeJSON(InfobloxComments)
file='email_list.json'
input_data=json.loads(open(file).read())
print(input_data)
for each in input_data:
pass
# GmailOutput(each)
if __name__ == '__main__':
sys.exit(main())
I'm trying to get calendar events from google api. (Flask API and Angular)
The problem is when the i'm redirecting the user to the authorize url (using step1_get_authorize_url method) the origin header is null and I keep getting No 'Access-Control-Allow-Origin' header error.
#oauth_api.route('/google/<action>')
def getGoogleCalendarRequest(action):
if 'credentials' not in session:
return redirect(url_for('oauth_controller.google'+action.title()+'Callback'))
credentials = client.OAuth2Credentials.from_json(session['credentials'])
if credentials.access_token_expired:
return redirect(url_for('oauth_controller.google'+action.title()+'Callback'))
else:
return session['credentials']
#oauth_api.route('/googleCallback')
def googleCalendarCallback():
flow = client.OAuth2WebServerFlow(
client_id='client_id',
client_secret='client_secret',
scope='https://www.googleapis.com/auth/calendar.readonly',
redirect_uri=url_for('oauth_controller.googleCalendarCallback',
approval_prompt='force',
access_type='offline'))
if 'code' not in request.args:
auth_uri = flow.step1_get_authorize_url()
return redirect(auth_uri)
else:
auth_code = request.args.get('code')
credentials = flow.step2_exchange(auth_code)
session['credentials'] = credentials.to_json()
return redirect(url_for('oauth_controller.getGoogleCalendarRequest'))
I am trying to write a simple script to get a list of my Google Apps users using Google's python API. So far it looks like this (based on a Google example):
!/usr/bin/python
import httplib2
from apiclient import errors
from apiclient.discovery import build
from oauth2client.client import OAuth2WebServerFlow
from oauth2client.client import SignedJwtAssertionCredentials
client_email = 'service_account_email#developer.gserviceaccount.com'
with open("Python GAPS-98dfb88b4c9f.p12") as f:
private_key = f.read()
OAUTH_SCOPE = 'https://www.googleapis.com/auth/admin.directory.user'
credentials = SignedJwtAssertionCredentials(client_email, private_key, OAUTH_SCOPE )
http = httplib2.Http()
http = credentials.authorize(http)
directory_service = build('admin', 'directory_v1', http=http)
all_users = []
page_token = None
params = {'customer': 'my_customer'}
while True:
try:
if page_token:
param['pageToken'] = page_token
current_page = directory_service.users().list(**params).execute()
all_users.extend(current_page['users'])
page_token = current_page.get('nextPageToken')
if not page_token:
break
except errors.HttpError as error:
print 'An error occurred: %s' % error
break
for user in all_users:
print user['primaryEmail']
The service account has been authorized on google developer console for the following API's:
https://www.googleapis.com/auth/admin.directory.user
https://www.googleapis.com/auth/admin.directory.user.alias
However, when I run the code, I get this error:
An error occurred: <HttpError 404 when requesting https://www.googleapis.com/admin/directory/v1/users?customer=my_customer&alt=json returned "Resource Not Found: domain">
Any hints on what am I missing?
E.
Even when using a service account, you still need to "act as" a Google Apps user in the domain with the proper rights (e.g. a super admin). Try:
credentials = SignedJwtAssertionCredentials(client_email, private_key,
OAUTH_SCOPE, sub='admin#domain.com')
where admin#domain.com is the email of a super admin in your domain.