18

I want to use Oauth to connect to Gmail in Python. Right now I've got the xoauth.py script from Google (link), and generating a token works all fine, but how can I then use that in another script? It's going to be in Django.

Right now my script logs in like this:

m = imaplib.IMAP4_SSL("imap.gmail.com")
m.login("example@gmail.com", "password")

But I want something more secure.

imz -- Ivan Zakharyaschev
  • 4,921
  • 6
  • 53
  • 104
HankSmackHood
  • 4,673
  • 7
  • 29
  • 30

3 Answers3

16

Here's an example using the oauth2 module to authenticate using oauth, taken from the readme:

import oauth2 as oauth
import oauth2.clients.imap as imaplib

# Set up your Consumer and Token as per usual. Just like any other
# three-legged OAuth request.
consumer = oauth.Consumer('your_consumer_key', 'your_consumer_secret')
token = oauth.Token('your_users_3_legged_token', 
    'your_users_3_legged_token_secret')

# Setup the URL according to Google's XOAUTH implementation. Be sure
# to replace the email here with the appropriate email address that
# you wish to access.
url = "https://mail.google.com/mail/b/your_users_email@gmail.com/imap/"

conn = imaplib.IMAP4_SSL('imap.googlemail.com')
conn.debug = 4 

# This is the only thing in the API for impaplib.IMAP4_SSL that has 
# changed. You now authenticate with the URL, consumer, and token.
conn.authenticate(url, consumer, token)

# Once authenticated everything from the impalib.IMAP4_SSL class will 
# work as per usual without any modification to your code.
conn.select('INBOX')
print conn.list()

Quite a bit cleaner than using xoauth.

Acorn
  • 49,061
  • 27
  • 133
  • 172
  • Hi Acorn, I am new to oauth2 and imaplib, and I have some questions now, can you answer them at: http://stackoverflow.com/questions/17976626/oauth2-and-imap-connection-with-gmail – Cacheing Jul 31 '13 at 18:01
  • 5
    I don't get where "your_users_3_legged_token" and "your_users_3_legged_token_secret" come from :/ – daveoncode Oct 24 '16 at 12:18
7

Google has a good example code to do OAuth2 and IMAP. Also make sure that your scope is correct.

'scope': 'https://mail.google.com/'
'access_type': 'offline'

Below is from the code sample in google example

import base64
import imaplib

my_email = "xyz@gmail.com"
access_token = ""    #Oauth2 access token

auth_string = GenerateOAuth2String(my_email, access_token, base64_encode=False)
TestImapAuthentication(my_email, auth_string)


def TestImapAuthentication(user, auth_string):
  """Authenticates to IMAP with the given auth_string.

  Prints a debug trace of the attempted IMAP connection.

  Args:
    user: The Gmail username (full email address)
    auth_string: A valid OAuth2 string, as returned by GenerateOAuth2String.
        Must not be base64-encoded, since imaplib does its own base64-encoding.
  """
  print
  imap_conn = imaplib.IMAP4_SSL('imap.gmail.com')
  imap_conn.debug = 4
  imap_conn.authenticate('XOAUTH2', lambda x: auth_string)
  imap_conn.select('INBOX')


def GenerateOAuth2String(username, access_token, base64_encode=True):
  """Generates an IMAP OAuth2 authentication string.

  See https://developers.google.com/google-apps/gmail/oauth2_overview

  Args:
    username: the username (email address) of the account to authenticate
    access_token: An OAuth2 access token.
    base64_encode: Whether to base64-encode the output.

  Returns:
    The SASL argument for the OAuth2 mechanism.
  """
  auth_string = 'user=%s\1auth=Bearer %s\1\1' % (username, access_token)
  if base64_encode:
    auth_string = base64.b64encode(auth_string)
  return auth_string
Ben
  • 23
  • 6
David Dehghan
  • 22,159
  • 10
  • 107
  • 95
  • Google provide OAuth 1 & 2 examples. Their OAuth 1 API is depreciated and I can't get it working with django-social-auth. The above which is OAuth 2 works fine with django-social-auth. – Mark Horgan Aug 31 '13 at 19:11
3

Here is an example of connecting to IMAP using routines present in Google's xoauth.py. It'll output some debug information, so you'll probably want to switch to using the oauth package for a real application. At least this should get you started:

import imaplib
import random
import time

import xoauth

MY_EMAIL = 'xxx@gmail.com'
MY_TOKEN = # your token
MY_SECRET = # your secret

def connect():
    nonce = str(random.randrange(2**64 - 1))
    timestamp = str(int(time.time()))

    consumer = xoauth.OAuthEntity('anonymous', 'anonymous')
    access = xoauth.OAuthEntity(MY_TOKEN, MY_SECRET)
    token = xoauth.GenerateXOauthString(
        consumer, access, MY_EMAIL, 'imap', MY_EMAIL, nonce, timestamp)

    imap_conn = imaplib.IMAP4_SSL('imap.googlemail.com')
    imap_conn.authenticate('XOAUTH', lambda x: token)
    imap_conn.select('INBOX')

    return imap_conn

connect()
samplebias
  • 37,113
  • 6
  • 107
  • 103
  • This works indeed, thanks. How would I do it with the oauth package? – HankSmackHood Mar 04 '11 at 17:02
  • You could continue using xoauth as-is if you can tolerate the print statements, or just rip them out of your local copy. I haven't personally used oauth but I imagine the api is similar. There is an example in the oauth repository: [oauth client example](http://oauth.googlecode.com/svn/code/python/oauth/example/client.py) – samplebias Mar 04 '11 at 18:12