Sending email via gmail & python
Question: What is the recommended way of sending an email using gmail and python? There
are a lot of SO threads, but most of them are old and it seems smtp with
username & password is not working any more or the user has to downgrade the
security of their gmail (for example see
[here](http://stackoverflow.com/a/29354018/3769451)). Is OAuth the recommended
way? Or maybe there are some python libraries already there that work with
gmail (possibly with OAuth)?

It would be great if one can suggest/point to a working sample code. Also I
would like not to downgrade gmail security settings if at all possible.


Answer: With gmail API and OAuth there is no need to save the username and password in
the script. The first time the script opens a browser to authorize the script
and will store credentials locally (it will not store username and password).
So consequent runs won't need the browser and can send emails straight. With
this method you will not get errors like SMTPException below and there is no
need to allow Access for less secure apps:

    
    
    raise SMTPException("SMTP AUTH extension not supported by server.")  
    smtplib.SMTPException: SMTP AUTH extension not supported by server.
    

**Here are the steps to send email using gmail API:**

[![Turn on Gmail API
steps](http://i.stack.imgur.com/ICIXt.png)](http://i.stack.imgur.com/ICIXt.png)
(Wizard link [here](https://console.developers.google.com/start/api?id=gmail),
More info [here](https://developers.google.com/gmail/api/quickstart/python))

Step 2: Install the Google Client Library

    
    
    pip install --upgrade google-api-python-client
    

Step 3: Use the following script to send email(just change the variables in
main function)

    
    
    import httplib2
    import os
    import oauth2client
    from oauth2client import client, tools
    import base64
    from email.mime.multipart import MIMEMultipart
    from email.mime.text import MIMEText
    from apiclient import errors, discovery
    
    SCOPES = 'https://www.googleapis.com/auth/gmail.send'
    CLIENT_SECRET_FILE = 'client_secret.json'
    APPLICATION_NAME = 'Gmail API Python Send Email'
    
    def get_credentials():
        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-email-send.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
            credentials = tools.run_flow(flow, store)
            print 'Storing credentials to ' + credential_path
        return credentials
    
    def SendMessage(sender, to, subject, msgHtml, msgPlain):
        credentials = get_credentials()
        http = credentials.authorize(httplib2.Http())
        service = discovery.build('gmail', 'v1', http=http)
        message1 = CreateMessage(sender, to, subject, msgHtml, msgPlain)
        SendMessageInternal(service, "me", message1)
    
    def SendMessageInternal(service, user_id, 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, msgHtml, msgPlain):
        msg = MIMEMultipart('alternative')
        msg['Subject'] = subject
        msg['From'] = sender
        msg['To'] = to
        msg.attach(MIMEText(msgPlain, 'plain'))
        msg.attach(MIMEText(msgHtml, 'html'))
        return {'raw': base64.urlsafe_b64encode(msg.as_string())}
    
    def main():
        to = "to@address.com"
        sender = "from@address.com"
        subject = "subject"
        msgHtml = "Hi<br/>Html Email"
        msgPlain = "Hi\nPlain Email"
        SendMessage(sender, to, subject, msgHtml, msgPlain)
    
    if __name__ == '__main__':
        main()
    

