I've connected Gmail API to Django project. I have a problem with storing credentials of every user. What is the most correct way to store them, so every users can log in? Without storing it just creates one file for one user and that's all. Should I create a database?
This is my "quickstart" file from Google:
from __future__ import print_function
from googleapiclient.discovery import build
from httplib2 import Http
from oauth2client import file, client, tools
from django.contrib.auth.models import User
# user = User
# storage = (CredentialsModel, 'id', user, 'credential') As you see I tried it here but it didn't go well
# credential = storage
#
# storage.__add__(credential)
# Setup the Gmail API
SCOPES = 'https://www.googleapis.com/auth/gmail.readonly'
store = file.Storage('credentials.json')
creds = store.get()
if not creds or creds.invalid:
flow = client.flow_from_clientsecrets('client_secret.json', SCOPES)
creds = tools.run_flow(flow, store)
service = build('gmail', 'v1', http=creds.authorize(Http()))
def go():
# Call the Gmail API
results = service.users().labels().list(userId='me').execute()
labels = results.get('labels', [])
# if not labels:
# print('No labels found.')
# else:
# print('Labels:')
# for label in labels:
# print(label['name'])
pass
Related
I have a Python script that interacts with the Gmail API and searches mails that are unread, with certain description and from specific email addresses. But I want it so when it reads the mail it removes the UNREAD label so it doesn't detect it when I run the script again.
from __future__ import print_function
import pickle
import os.path
from googleapiclient.discovery import build
from google_auth_oauthlib.flow import InstalledAppFlow
from google.auth.transport.requests import Request
# If modifying these scopes, delete the file token.pickle.
SCOPES = ['https://www.googleapis.com/auth/gmail.readonly']
def main():
"""Shows basic usage of the Gmail API.
Lists the user's Gmail labels.
"""
email_address1 = "mensajeria#bancoestado.cl"
email_address2 = "noreply#correo.bancoestado.cl"
creds = None
if os.path.exists('token.pickle'):
with open('token.pickle', 'rb') as token:
creds = pickle.load(token)
# If there are no (valid) credentials available, let the user log in.
if not creds or not creds.valid:
if creds and creds.expired and creds.refresh_token:
creds.refresh(Request())
else:
flow = InstalledAppFlow.from_client_secrets_file(
'credentials.json', SCOPES)
creds = flow.run_local_server(port=0)
# Save the credentials for the next run
with open('token.pickle', 'wb') as token:
pickle.dump(creds, token)
service = build('gmail', 'v1', credentials=creds)
# Call the Gmail API
results = service.users().labels().list(userId='me').execute()
labels = results.get('labels', [])
#Get Messages
results = service.users().messages().list(userId='me', labelIds=['INBOX'], q=f'from:{email_address1} OR from:{email_address2} is:unread').execute()
messages = results.get('messages', [])
#Messages Filter
message_count = 100
for message in messages[:message_count]:
msg = service.users().messages().get(userId='me', id=message['id']).execute()
email = (msg['snippet'])
if "que recibiste Monto $" in email:
print(f'{email}\n')
service.users().messages().modify(userId='me', id=message['id'], body={'removeLabelIds': ['UNREAD']}).execute()
if __name__ == '__main__':
main()
The script works just fine until it reaches my attempt of removing the UNREAD label so it doesn't detect it again. Here
service.users().messages().modify(userId='me', id=message['id'], body={'removeLabelIds': ['UNREAD']}).execute()
I know it can be done, because in the labels section of the Gmail API documentation it says that the UNREAD label can be manually changed.
So if someone could give me a hand I would appreciate it.
I've already found a solution. The problem was that the scope that I was using didn't had the permissions needed to remove a label from a message, so I changed the scope to this instead and it worked just fine.
SCOPES = ['https://mail.google.com/']
I'm looking for a Google API to get the size of the drive of the users associated with university email/directory api, but I can't find anything. The code to delete a user's email using the Google API is provided below. Similarly, I need to know the size of the user's drive. Could someone please assist me? Is there a way to get the drive's size via an API? Thanks.
from __future__ import print_function
import os.path
from google.auth.transport.requests import Request
from google.oauth2.credentials import Credentials
from google_auth_oauthlib.flow import InstalledAppFlow
from googleapiclient.discovery import build
# If modifying these scopes, delete the file token.json.
SCOPES = ['https://www.googleapis.com/auth/admin.directory.group', 'https://www.googleapis.com/auth/admin.directory.user']
def main():
"""Shows basic usage of the Admin SDK Directory API.
Prints the emails and names of the first 10 users in the domain.
"""
creds = None
# The file token.json stores the user's access and refresh tokens, and is
# created automatically when the authorization flow completes for the first
# time.
if os.path.exists('token.json'):
creds = Credentials.from_authorized_user_file('token.json', SCOPES)
# If there are no (valid) credentials available, let the user log in.
if not creds or not creds.valid:
if creds and creds.expired and creds.refresh_token:
creds.refresh(Request())
else:
flow = InstalledAppFlow.from_client_secrets_file(
'credentials.json', SCOPES)
creds = flow.run_local_server(port=0)
# Save the credentials for the next run
with open('token.json', 'w') as token:
token.write(creds.to_json())
service = build('admin', 'directory_v1', credentials=creds)
return service
def test():
# user = service.users().get(userKey="user1#matador.csun.edu").execute()
# members = service.groups().list(domain='my.csun.edu', userKey=user['primaryEmail'], pageToken=None, maxResults=500).execute()
# print(user)
# Call the Admin SDK Directory API
print('Getting the first 10 users in the domain')
results = service.users().list(customer='my_customer', maxResults=10,
orderBy='email').execute()
print(results)
users = results.get('users', [])
if not users:
print('No users in the domain.')
else:
print('Users:')
for user in users:
print(user)
# print(dir(user))
# print(u'{0} ({1})'.format(user['primaryEmail'],
# user['name']['fullName']))
def del_user(user):
try:
service.users().delete(userKey=user).execute()
print("Deleted!")
except:
print("User doesn't exist!")
if __name__ == '__main__':
service = main()
nameExt='23'
# with open('NewGmailInProd/gmailUser'+nameExt+'.txt') as fileToRead:
# with open('NewGmailInProd/test.txt') as fileToRead:
# emails = fileToRead.readlines()
emails = ['user1#matador.csun.edu']
for email in emails:
del_user(email.strip())
I would like to list all message ID's from a Gmail account utilizing the Gmail API. So far I've been able to list the first and second page of message ID's. I know I have to use the pageToken to get to the next page of results, but I can't figure out how to restructure my code so I'm not using 1,2,3, etc variables to call each page. Source code is below.
get_email_ids.py:
from __future__ import print_function
import os.path
from collections import Counter
from googleapiclient.discovery import build
from google_auth_oauthlib.flow import InstalledAppFlow
from google.auth.transport.requests import Request
from google.oauth2.credentials import Credentials
# If modifying these scopes, delete the file token.json.
SCOPES = ['https://www.googleapis.com/auth/gmail.readonly']
def main():
"""Shows basic usage of the Gmail API.
"""
creds = None
user_id = "me"
# The file token.json stores the user's access and refresh tokens, and is
# created automatically when the authorization flow completes for the first
# time.
if os.path.exists('token.json'):
creds = Credentials.from_authorized_user_file('token.json', SCOPES)
# If there are no (valid) credentials available, let the user log in.
if not creds or not creds.valid:
if creds and creds.expired and creds.refresh_token:
creds.refresh(Request())
else:
flow = InstalledAppFlow.from_client_secrets_file(
'credentials.json', SCOPES)
creds = flow.run_local_server(port=0)
# Save the credentials for the next run
with open('token.json', 'w') as token:
token.write(creds.to_json())
service = build('gmail', 'v1', credentials=creds)
### Call the Gmail API
### Show messages
token = ''
messages = service.users().messages().list(userId=user_id,pageToken=token).execute().get('messages', [])
token = service.users().messages().list(userId=user_id,pageToken=token).execute().get('nextPageToken', [])
print(messages,token)
messages2 = service.users().messages().list(userId=user_id,pageToken=token).execute().get('messages', [])
token2 = service.users().messages().list(userId=user_id,pageToken=token).execute().get('nextPageToken', [])
print(messages2,token2)
if __name__ == '__main__':
main()
Results of get_email_ids.py (shortened):
[{'id': '179ed5ae720de1f6', 'threadId': '179ed5ae720de1f6'}, ... {'id': '179ba226644a079a', 'threadId': '17972318184138fa'}] 09573475999783117733
[{'id': '179b9f8852d3b09d', 'threadId': '179b9f8852d3b09d'}, ... {'id': '1797fa390caa3454', 'threadId': '1797fa390caa3454'}] 07601624978802434502
I can't test it but I would use the same variables messages, token without 1,2,3 and results I would add to the same list with all messages. And I would run it in some loop.
Something like this
all_messages = []
token = ''
while True:
messages = service.users().messages().list(userId=user_id, pageToken=token).execute().get('messages', [])
token = service.users().messages().list(userId=user_id, pageToken=token).execute().get('nextPageToken', [])
print(messages, token)
if not messages:
break
#all_messages.extend(messages) # `extend` or `+=`, not `append`
all_messages += messages # `extend` or `+=`, not `append`
I only don't know how API informs that there is no more messages - maybe it returns empty list or maybe it gives empty token, or maybe it raise error.
EDIT:
Information for other users: as #emmalynnh mentioned in comment
When there are no more messages it gives an empty token
and the API will return a 400 error if you try to request.
A Improved version on #furas can be made.
all_messages = []
token = ''
while True:
service_messages = service.users().messages()
messages = service_messages.list(userId=user_id, pageToken=token).execute().get('messages', [])
token = service_messages.list(userId=user_id, pageToken=token).execute().get('nextPageToken', [])
if not messages:
break
all_messages += messages
print(all_messages)
I want to download them with as few API calls as possible. https://github.com/googleapis/google-api-python-client/tree/master/samples doesn't have Gmail.
Start by following Python quickstart it will give you an idea of how to get the Auth part working
from __future__ import print_function
import pickle
import os.path
from googleapiclient.discovery import build
from google_auth_oauthlib.flow import InstalledAppFlow
from google.auth.transport.requests import Request
# If modifying these scopes, delete the file token.pickle.
SCOPES = ['https://www.googleapis.com/auth/gmail.readonly']
def main():
"""Shows basic usage of the Gmail API.
Lists the user's Gmail labels.
"""
creds = None
# The file token.pickle stores the user's access and refresh tokens, and is
# created automatically when the authorization flow completes for the first
# time.
if os.path.exists('token.pickle'):
with open('token.pickle', 'rb') as token:
creds = pickle.load(token)
# If there are no (valid) credentials available, let the user log in.
if not creds or not creds.valid:
if creds and creds.expired and creds.refresh_token:
creds.refresh(Request())
else:
flow = InstalledAppFlow.from_client_secrets_file(
'credentials.json', SCOPES)
creds = flow.run_local_server(port=0)
# Save the credentials for the next run
with open('token.pickle', 'wb') as token:
pickle.dump(creds, token)
service = build('gmail', 'v1', credentials=creds)
# Call the Gmail API
results = service.users().labels().list(userId='me').execute()
labels = results.get('labels', [])
if not labels:
print('No labels found.')
else:
print('Labels:')
for label in labels:
print(label['name'])
if __name__ == '__main__':
main()
Once you understand what that is doing you should be able to consult user message list to get an idea of how to alter it for listing a messages.
I am using gmail api. I am getting the following warning:
new_request() takes at most 1 positional argument (2 given)
from this code:
message = GMAIL.users().messages().get(userId=user_id, id=m_id).execute() # fetch the message using API
Here is my full code (mostly taken from gmail API):
"""
Shows basic usage of the Gmail API.
Lists the user's Gmail labels.
"""
from __future__ import print_function
from apiclient.discovery import build
from httplib2 import Http
from oauth2client import file, client, tools
from apiclient.discovery import build
from oauth2client.file import Storage
from oauth2client.client import OAuth2WebServerFlow
from oauth2client.tools import run_flow, argparser
from oauth2client import tools
from colorama import Fore, Back, Style
from colorama import init
# use Colorama to make Termcolor work on Windows too
init()
# Setup the Gmail API
def get_credentials():
store = file.Storage('credentials.json')
creds = store.get()
flow = OAuth2WebServerFlow(
client_id='845-ehe.apps.googleusercontent.com',
client_secret='curo',
scope = 'https://www.googleapis.com/auth/gmail.modify',
user_agent='people_cal2sms')
if not creds or creds.invalid:
flags = tools.argparser.parse_args(args=[])
creds = tools.run_flow(flow, store, flags)
service = build('gmail', 'v1', http=creds.authorize(Http()))
# Importing required libraries
from apiclient import discovery
# Creating a storage.JSON file with authentication details
SCOPES = 'https://www.googleapis.com/auth/gmail.modify' # we are using modify and not readonly, as we will be marking the messages Read
store = file.Storage('storage.json')
creds = store.get()
if not creds or creds.invalid:
flags = tools.argparser.parse_args(args=[])
flow = client.flow_from_clientsecrets('client_secret.json', SCOPES)
creds = tools.run_flow(flow, store, flags)
GMAIL = discovery.build('gmail', 'v1', http=creds.authorize(Http()))
user_id = 'me'
label_id_one = 'INBOX'
# Getting all the unread messages from Inbox
# labelIds can be changed accordingly
unread_msgs = GMAIL.users().messages().list(userId='me',labelIds=[label_id_one], q="label:clinic_sms after:2018/9/14").execute()
# We get a dictonary. Now reading values for the key 'messages'
mssg_list = unread_msgs.get('messages', [])
print ("Total unread messages in inbox: ", str(len(mssg_list)))
final_message_dict_list = [ ]
def retrieve_phone_2_gmail_message_dict():
phone_2_gmail_message_dict = {}
for mssg in mssg_list:
message_dict = { }
m_id = mssg['id'] # get id of individual message
message = GMAIL.users().messages().get(userId=user_id, id=m_id).execute() # fetch the message using API