User Guide

Python comes with the built-in smtplib module for sending emails using the Simple Mail Transfer Protocol (SMTP). smtplib uses the RFC 2821 protocol for SMTP. The email package is a library for managing email messages. It is specifically not designed to do any sending of email messages to SMTP (RFC 2821), NNTP, or other servers; those are functions of modules such as smtplib.

The auto-emailer library provides a nice, easy to use, wrapper around the two libraries.

Credentials

Credentials are the means of identifying a user to a authenticate a SMTP client and host. Auto credentials can be obtained in two different ways with the class emailer.Emailer: environment credentials and environment credentials file. Another way to authenticate is to manually pass configurations to the Credentials class and then initiate emailer with those credentials.

With the Credentials class, you do not need to set the port or host, though it is HIGHLY recommended that you do. The Credentials class will set the port to a default value of 587 if is not set and will attempt to guess the host from the sender email address if host is not set.

SMTP clients in which EMAILER_HOST and EMAILER_PORT will be auto configured. This means you only need to specify EMAILER_SENDER and EMAILER_PASSWORD.

Provider SMTP Server
Gmail smtp.gmail.com
Outlook/Hotmail smtp.office365.com
Yahoo Mail smtp.mail.yahoo.com

Auto Credentials

If you instantiate the emailer class with default configuration settings, it will perform the following credential configuration checks:

1. If the environment variable EMAILER_CREDS is set to the path of a valid JSON file, then the credentials are loaded and returned.

2. If explicit environment variables are set (they start with EMAILER_), then the environment variables are loaded and returned.

Initiating the emailer.Emailer will automatically determine the credentials from the environment if config argument is None.:

from auto_emailer import Emailer

# auto-configuration of credentials
my_emailer = Emailer(config=None, delay_login=False)
print(my_emailer.connected)

Environment Credentials File

The auto-emailer library will first look for the environment variable EMAILER_CREDS to create a Credentials instance from an authorized user json file. Set the EMAILER_CREDS environment variable to the full path to your credential file:

EMAILER_CREDS='/path/to/creds.json'

The json file needs to be in the specified format (order does not matter):

{
  "EMAILER_SENDER": "test@gmail.com",
  "EMAILER_PASSWORD": "mypassword",
  "EMAILER_HOST": "smtp.gmail.com",
  "EMAILER_PORT": 587
}

Environment Credentials Variables

The auto-emailer library will then look for these environment variables:

EMAILER_SENDER
Environment variable providing the value of auto-emailer’s config attribute EMAILER_SENDER.
EMAILER_PASSWORD
Environment variable providing the value of auto-emailer’s config attribute EMAILER_PASSWORD.
EMAILER_HOST
Environment variable providing the value of auto-emailer’s config attribute EMAILER_HOST.
EMAILER_PORT
Environment variable providing the value of auto-emailer’s config attribute EMAILER_PORT.

If it cannot find any credentials from environment file or explicit environment variables, then an error message will display asking you to either create your own configuration, or if you use auto configuration, then specify either credential file or explicit environment variables.

Warning

Credential files must be kept secret. If you expose your secret file it is recommended that you change your credentials from the email host you are using.

Manual Credentials

You manually configure your credentials but why would you do that since the hard work is already done for you with environment variables :) However, if you would like to it is recommended that you initiate Credentials from the class methods. Here is how you can with a file or python dictionary.

Use from_authorized_user_file():

from auto_emailer import Emailer
from auto_emailer.config import Credentials

# path to creds file
creds_path = '/path/to/creds.json'

# explicitly initiate credentials
email_creds = Credentials.from_authorized_user_file(creds_path)

# pass credential instance to Emailer
my_emailer = Emailer(config=email_creds, delay_login=False)
print(my_emailer.connected)

Use from_authorized_user_info():

import pickle
from auto_emailer import Emailer
from auto_emailer.config import Credentials

# load creds from pickle file
# must be type: dict
with open('creds_file.pickle', 'rb') as creds:
    creds_dict = pickle.load(creds)

# explicitly initiate credentials
email_creds = Credentials.from_authorized_user_info(creds_dict)

# pass credential instance to Emailer
my_emailer = Emailer(config=email_creds, delay_login=False)
print(my_emailer.connected)

Emailer

Emailer is the interface to the SMTP client. To send an email using auto-emailer, all you need to do is call the send_email function. If you’re send an email with the auto_emailer.emailer.Message, the to_addrs and from_addr arguments are optional. However, if you are sending a string email message, then you need to pass the arguments. Otherwise an error will raise if one or both are missing. At the moment, auto-emailer uses TLS encryption but there will be support for SSL encryption in future versions.

Sending Emails

Sending emails with the auto-emailer library is very easy. Once you have your email account setup and credentials configured, all you need to do is this:

from auto_emailer import Emailer, Message

# create emailer instance
my_emailer = Emailer()

# send email!
my_emailer.send_email('Hello, how are you doing today?',
                      'my_email@gmail.com',
                      ['my_friend_email@gmail.com'])

Or you can send an email with a Message object, like this:

# create a message object instance
my_email = Message('my_email@gmail.com',
                   ['my_friend@gmail.com'],
                   'Hello Friend!')
# draft a message
my_email = my_email.draft_message(text="Hi! Let's hang out 😁")

# send email message to friend!
mailer.send_email(my_email)

Notice that you do not need to pass in the arguments to_addrs and from_addr because they are optional if you send a Message object.

Message

Message is the wrapper for building email messages to send with Emailer. A Message object has headers and payloads. Headers and the body are the two main parts of an email. When you call the Message class, a message object is created automatically. However, it does not populate the message until you call the method draft_message. The method return the message object with headers and text.

The Message class handles the object representation of an email; it does not actually have the functionality to send emails (that functionality is in the Emailer module).

Message from Templates

To use the Message template functionality, you’ll need to create a text file.:

'/path/to/email_template.txt'

An example text file could look like this:

Hi,

How are you doing today?

Sincerely,
Your friend

After creating a text file template, pass the file path as an argument to the draft_message() function. The function will open the template text file, read the text and add it as the body of the Message:

from auto_emailer import Emailer, Message

# create emailer instance
my_emailer = Emailer()

# email template file path
my_template = '/path/to/email_template.txt'

# create a message
my_email = Message('my_email@test.com',
                   ['my_friend@gmail.com'],
                   'My Subject!')

# draft email message with template
my_email.draft_message(template_path=my_template)

# send email with template!
my_emailer.send_email(my_email)

Message from Templates with Dynamic Arguments

Using the example above, what if you wanted to have the template dynamically change depending on the destination of the email? For example, you can create a text file with {test_var} variables and change the variable values on some event

Create a text file with variables:

Hi {name},

How are you doing today?

Sincerely,
Your friend

After creating a text file template with keyword variables, pass the file path as an argument to the draft_message() function as well as the variable keyword values. The draft_message function will open the template text file, read the text, insert the variables values, and attach the text as the body of the email:

from auto_emailer import Emailer, Message

# create emailer instance
my_emailer = Emailer()

# email template file path
my_template = '/path/to/email_template.txt'

# create a message
my_email = Message('my_email@test.com',
                   ['my_friend@gmail.com'],
                   'My Subject!')

# draft email message with template
my_email.draft_message(template_path=my_template,
                       template_args=dict(name="joe")

# send email with template arguments!
my_emailer.send_email(my_email)

As you might have noticed, you don’t need to pass in the text argument, since the body of the email is populated by the template text.

Message with Attachments

In order to send binary files to an email server that is designed to work with textual data, they need to be encoded before transport. This is most commonly done using base64, which encodes binary data into printable ASCII characters. All of this is done in the attach method. At the moment text, json, csv, and other file formats are supported as attachments. As well as .png and .jpeg image formats. In future versions, the auto-emailer will have the ability to attach audio files.:

from auto_emailer import Emailer, Message

 # create emailer instance
 my_emailer = Emailer()

 # email template file path
 files = ['/path/to/attachment_1.csv',
          '/path/to/attachment_2.png']

 # create a message
 my_email = Message('my_email@test.com',
                    ['my_friend@gmail.com'],
                    'Hello Friend!')

 # draft email message
 my_email.draft_message(text="Please see attached.")

 # add attachments to message
 my_email.attach(attach_files=files)

 # send email with attachments!
 my_emailer.send_email(my_email)

Please note that each SMTP client has a limit on email size. If you are having trouble sending attachments, check your specific client’s allowed email size.