Published: 1. 6. 2017   Category: Programming

Sending emails with Python via Google's SMTP or Amazon SES server

Years ago, I was usually using my own SMTP server, but after some time my IP addresses were constantly on some spamming black-list or gray-list, because email was coming from an IP range of the provider with some dynamically allocated public IPs and a lot of other users has some viruses or spam bots, so I was almost constantly banned from sending emails.

The solution in this case is to use some 3rd party SMTP server which will not have problems described above. This example is mainly for sending emails with Python script, but you can also setup your own MTA (Mail Transfer Agent, e.g. postfix) to use those servers as relay host.

Warning: Google or Amazon usually has no problem with delivery, however you cannot set random From: field, only verified email addresses can be used!

Use Google

Setup Google is little bit faster because Amazon needs special permission to remove from sandbox. Limits are described here, it should be around 2000 emails a day.

To be able to use Google SMTP, you need to setup 2-step verification. Without it, it is not possible to use your credentials directly with SMTP. With 2-step verification you will have your original credentials for accessing your Google account and you will generate additional password just to access SMTP.

  1. Go to: https://myaccount.google.com/?utm_source=OGB&pli=1
  2. Select: Sign-in & security
  3. If you did not do previously: Turn on 2 Step Verification and provide your mobile phone number.
  4. Select: App password.
  5. Choose Select app: Mail and Select device: Other. You can save it as named profile.
  6. Google will display your password once.

Now you can use your account login and this password to access SMTP server.

Use Amazon SES

Amazon SES runs in sandbox mode and only verified emails can be use as sender and receiver. It can be useful when you need to send and receive some email notification just yourself, but to send email also to other "non-verified" address you need to remove your account from sandbox. Once removed from sandbox, they will give you about 50000 emails a day and 14 emails per second.

  1. Login to you account in AWS management console.
  2. Go to Amazon SES, and select desired availability zone. N. Virginia/us-east-1 is selected by default.
  3. Select SMTP Settings and Create my STMP credentials.
  4. Amazon will generate a new user with a random login/password, and it will set IAM automatically for this user. These credentials looks like the same format as API access keys but they are just for SMTP.

Removal from sandbox

  1. Login to AWS console and SES as described above.
  2. Select Sending Statistics and Request a Sending Limit Increase.
  3. It will open Service Support form to fill, you need also fill this:
    • My email-sending complies with the AWS Service Terms and AUP: Yes.
    • I only send to recipients who have specifically requested my mail: Yes.
    • I have a process to handle bounces and complaints: Yes.
  4. Use Case Description is also required, and the supports wants to hear how you will handle bounces and complains. If you do not provide these information they will contact you and request them. I wrote some nice story, that our company cares and will have email like support@ and abuse@ and we are preparing some automated tool to handle it. Luckily, it was enough they want to here.
  5. Once removed from sandbox, you can set any recipient, but from email must be verified (SES/Email addresses/Verify a New Email Address).

Python code snippet

You need to set credentials and SMTP server hostname and port and the rest is quite straightforward thanks to smtplib module:

#!/usr/bin/env python3
import sys
import smtplib

# Google:
USER='yourlogin@gmail.com'
PASS='google-will-provide-this'
SMTP='smtp.gmail.com'
SMTP_PORT=587

# Amazon SES
USER='AKIA................'
PASS='amazon-ses-will-generate-password-for-you'
SMTP_HOST='email-smtp.us-east-1.amazonaws.com'
SMTP_PORT=587

# Send email
sent_from = 'Only verified email here'
to = [ 'recipient@somedomain.com' ]
subject = 'Hello, test email'
body = "Thist is test!"
email_text = """From: %s  
To: %s  
Subject: %s

%s
""" % (sent_from, ", ".join(to), subject, body)

def main(argv):
    try:
        server = smtplib.SMTP(SMTP, SMTP_PORT)
        server.ehlo()
        server.starttls()
        server.login(USER, PASS)
        server.sendmail(sent_from, to, email_text)
        server.close()
        print('Email sent!')
    except Exception as e:
        print('Something with SMTP went wrong...')
        print(e)

if __name__ == "__main__":
    main(sys.argv)

Download source code.