0

I would like to send an email using Gmail OAuth protocol from Python. For some background, the general process of my program takes user input, creates an image, then sends an email. In theory the program could be sending hundreds of emails at some point. The issue that I ran into is when I tried to retrieve a token for OAuth, I received an Unauthorized redirect url error. The app has not been verified nor do I have a G Suite Admin account, but every tutorial I walk through make no mention of this. The only redirect urls I have enabled are https://developers.google.com/oauthplayground and http://localhost:8080/oauth2callback, which are both in the client_secret.json file I download from the credentials page on google developers.

Here is what I have:

import base64
import httplib2
from email.mime.text import MIMEText
from apiclient.discovery import build
from oauth2client.client import flow_from_clientsecrets
from oauth2client.file import Storage
from oauth2client.tools import run

# Path to the client_secret.json file downloaded from the Developer Console
CLIENT_SECRET_FILE = 'client_secret.json'

# Check https://developers.google.com/gmail/api/auth/scopes for all available scopes
OAUTH_SCOPE = 'https://www.googleapis.com/auth/gmail.compose'

# Location of the credentials storage file
STORAGE = Storage('gmail.storage')

# Start the OAuth flow to retrieve credentials
flow = flow_from_clientsecrets(CLIENT_SECRET_FILE, scope=OAUTH_SCOPE)
http = httplib2.Http()

# Try to retrieve credentials from storage or run the flow to generate them
# This is where it fails.
credentials = STORAGE.get()
if credentials is None or credentials.invalid:
  credentials = run(flow, STORAGE, http=http)

# Authorize the httplib2.Http object with our credentials
http = credentials.authorize(http)

# Build the Gmail service from discovery
gmail_service = build('gmail', 'v1', http=http)

# create a message to send
message = MIMEText("Message goes here.")
message['to'] = "[email protected]"
message['from'] = "[email protected]"
message['subject'] = "your subject goes here"
body = {'raw': base64.b64encode(message.as_string())}

# send it
try:
  message = (gmail_service.users().messages().send(userId="me", body=body).execute())
  print('Message Id: %s' % message['id'])
  print(message)
except Exception as error:
  print('An error occurred: %s' % error)
18
  • So what you would need to do is to add the redirect_uri in the OAuth consent screen and after that redownload the JSON file with the credentials. Try to do that and confirm if you still having trouble with this error. Commented May 26, 2020 at 8:05
  • Where is the OAuth consent screen? Because the instructions you laid out is what I did as my question states. Commented May 26, 2020 at 12:11
  • Does your client secret have a redirect_uri field? Try to add it in there and check if you can get past that error. There are some question around the same error too and maybe some already solve your issue 1 or 2 Commented May 28, 2020 at 7:25
  • Okay that worked, but now I get an Authorization Error about how the redirect url: localhost:8080 does not exist. Yet I provided localhost:8000/oauth2callback and 127.0.0.1:8887/oauth2callback as redirects. Commented Jun 2, 2020 at 15:44
  • You need to actually use the run_local_server to make that page exist. That would handle all the token interaction as stated in the documentation. Commented Jun 2, 2020 at 15:59

1 Answer 1

0

This has been discussed in greater details in the comments.

Basically when you create an app that interacts with google services the user needs to accepts the scopes that your app will have. This means you need to create a Oauth Consent Screen.

So you go to your project in Google Console Cloud, in there choose Api & Services > OAuth consent screen or go to this link. To create that OAuth Consent Screen you will be prompted with two options:

  • Internal: Only for G Suite accounts, your app will be only accessible by members of your organization
  • External: The only option for NON G Suite accounts, if you access "powerful" scopes the app will need to be verified, if not it will be tagged as unverified.

For your case (which seems personal use/development) just go ahead and deal with unverified app choose External.

OAuth Consent Screen creation

You can see that in fact google is pointing out that I need verification but on creation I get prompted with a screen explaining that my app is an unverified app

OAuth Screen

Use this only for personal use (it has a 100 users cap).

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.