Send email

Video

The email service creates a service that can send email via SMTP. Here is a sample configuration for GMail:

email:
  gramex-guide-gmail:
    type: gmail # Type of email used is GMail
    email: gramex.guide@gmail.com # Generic email ID used to test e-mails
    password: tlpmupxnhucitpte # App-specific password created for Gramex guide

In the type: section of gramex.yaml email configuration, the following types are supported. You need to add your email: and password:.

You can also connect to any SMTP or SMTPS mail server using type: smtp or type: smtps. This includes:

For example:

email:
  amazon-ses:
    type: smtps
    host: email-smtp.eu-west-1.amazonaws.com # AWS SES SMTP server for your region
    email: "***" # IAM access ID
    password: "***" # IAM password
  client-email:
    type: smtp # Use type: smtps for SMTPS servers
    host: 10.20.30.40 # Host name or IP address of the SMTP server
    # Optional parameters
    email: user@domain.com # Username or email to log into SMTP server
    password: "***" # Password for SMTP server
    port: 587 # For non-standard SMTP port. Default: SMTPS=587, SMTP=25

Send email

This creates an SMTPMailer instance that can be used as follows:

from  gramex import service     # Available only if Gramex is running
mailer = service.email['gramex-guide-gmail']
# Or, to construct the SMTPMailer when using Gramex as a library, use:
# from gramex.services import SMTPMailer
# mailer = SMTPMailer(type='gmail', email='gramex.guide@gmail.com', password='...')
mailer.mail(
    to='person@example.com',
    subject='Subject',
    html='<strong>Bold text</strong>. <img src="cid:logo">'
    body='This plain text is shown if the client cannot render HTML',
    attachments=['1.pdf', '2.txt'],
    images={'logo': '/path/to/logo.png'})

The mail() method accepts the following arguments:

You can also pass any standard email header. Use small letters, replacing - with _. Here are some commonly used ones:

See the source in the example below to understand how to use it.

Try a sample email

HTML email

Emails can have HTML content, text content, or both. HTML-friendly browsers like Outlook, GMail, etc display HTML content where available, and fall back to the text content.

The html= argument provides the HTML content. The body= argument provides the text content.

Writing HTML for email is quite different than for browsers. Here are some guides to read:

Email attachments

Attachments can be specified as filenames or as a dictionary with the body and content_type or filename keys. For example:

      attachments=['file.pdf']
      attachments=[{'filename': 'file.pdf', 'body': open('file.pdf', 'rb').read()}]
      attachments=[{'content_type': 'application/pdf', 'body': open('file.pdf', 'rb').read()}]

The attachment dict format is consistent with the handler.request.files structure that holds uploaded files.

Command-line emails

Gramex can be used as a standalone library to send emails as well. Here is a sample Python application:

from gramex.services import SMTPMailer

mailer = SMTPMailer(
    type='gmail',
    email='gramex.guide@gmail.com',       # Replace with your email ID
    password='tlpmupxnhucitpte',          # Replace with your passsword
)
mailer.mail(
    to='person@example.com',
    subject='Subject',
    html='<strong>This is bold text</strong> and <em>this is in italics</em>.',
    body='This plain text is shown if the client cannot render HTML',
    attachments=['1.pdf', '2.txt'])

The same parameters used in the gramex.yaml file may be used here.

Automated email alerts

Combined with schedule, you can automate email alerts. For example, this configuration sets up a schedule every weekday at 8am, and an email service.

schedule:
  email-alert:
    function: project.email_alert() # Run this function
    hours: 8 # at 8am on the system
    weekdays: mon,tue,wed,thu,fri # every weekday

email:
  email-alert: # Define the email service to use
    type: smtp # Connect via SMTP
    host: mailserver.example.org # to the mail server
    email: user@example.org # with a login ID
    password: $MAIL_PASSWORD # password stored in environment variable MAIL_PASSWORD

The project.email_alert() method can use this service to check if there are any unusual events, and send a templatized email if so. Here is a sample workflow for this:

def email_alert():
    data = gramex.cache.open(data_file, 'xlsx')                   # Open the data source
    analysis = find_unusual_events(data)                          # Apply some analysis
    if 'unusual' in analysis:                                     # If something is unusual
        tmpl = gramex.cache.open(template_file, 'template')       #   open a template
        service.email['email-alert'].mail(                        #   and send the email
            to='recipients@example.org',                          #   to the recipients
            subject='Alert: {unusual}'.format(**analysis),        #   with a clear subject
            html=tmpl.generate(data=data, analysis=analysis),     #   and render the template.
            attachments=[data_file],                              #   Maybe attach the data
        )

Test email service

To test an email service without sending an email, add stub: log to the configuration. For example:

email:
  email-test:
    type: gmail
    email: gramex.guide@gmail.com
    password: tlpmupxnhucitpte
    stub: log # Don't send emails. Just print them to the console

When an email is sent via the email-test service above, it will not actually be sent. The email contents will be printed on the console.