Cómo enviar un correo electrónico con boto y SES

Prácticamente todas las aplicaciones y sitios web basados ​​en el usuario deben enviar un correo electrónico al usuario en algún momento, por lo que eventualmente tendrá que lidiar con el alegre mundo del programa...

Introducción

Prácticamente todas las aplicaciones y sitios web basados ​​en el usuario necesitan enviar un correo electrónico al usuario en algún momento, por lo que eventualmente tendrá que lidiar con el alegre mundo de los correos electrónicos programáticos. Están surgiendo bastantes servicios para ayudarte con esto, pero como cada aplicación tiene sus propios requisitos únicos, pocos de estos servicios hacen el trabajo de manera adecuada.

Habiendo enfrentado el problema varias veces (y en algunos idiomas), decidí escribir esta breve publicación sobre cómo enviar correos electrónicos con bota y SSE. La biblioteca boto es un contenedor muy bueno para Python que lo ayuda a interactuar con la API de AWS. Para ver más de sus capacidades, consulte mi otro artículo de boto sobre cómo subir un archivo a s3.

Configuración

Antes de que realmente pueda hacer algo, necesitará una cuenta de AWS (obviamente) junto con la clave de acceso y la clave secreta de su cuenta, que se usarán para autenticarse con los servidores SES. Hay pocas formas diferentes puede usar las claves para autenticarse, pero aquí solo las pasaremos al método connect_to_region proporcionado por boto.

A continuación, deberá verificar con SES una dirección de correo electrónico (una dirección de Gmail funciona bien) o un dominio de su propiedad. Si solo está probando esta función, le sugiero que verifique solo una dirección de correo electrónico, ya que es un poco más rápido. Todo lo que necesita hacer es hacer clic en un enlace en el correo electrónico de verificación que le envían, en lugar de agregar registros TXT a su archivo de zona para verificar un dominio.

Si es la primera vez que usa SES y su aplicación deberá enviar un gran volumen de correos electrónicos, es posible que deba enviar una solicitud para aumentar su cuota de envío. Su cuenta SES se coloca inicialmente en un 'sandbox', lo que significa que solo puede enviar 200 correos electrónicos en un período de 24 horas. Una vez que haya solicitado con éxito aumentar sus límites de envío, debería poder enviar muchos más (me aprobaron 50,000 por día, que es mucho más de lo que necesito).

El Código

Una vez que haya realizado la configuración inicial que mencioné anteriormente, debería poder usar el código a continuación para enviar correos electrónicos.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
import boto.ses

AWS_ACCESS_KEY = 'YOUR-ACCESS-KEY-HERE'
AWS_SECRET_KEY = 'YOUR-SECRET-KEY-HERE'

class Email(object):
    def __init__(self, to, subject):
        self.to = to
        self.subject = subject
        self._html = None
        self._text = None
        self._format = 'html'

    def html(self, html):
        self._html = html

    def text(self, text):
        self._text = text

    def send(self, from_addr=None):
        body = self._html

        if isinstance(self.to, basestring):
            self.to = [self.to]
        if not from_addr:
            from_addr = '[correo electrónico protegido]'
        if not self._html and not self._text:
            raise Exception('You must provide a text or html body.')
        if not self._html:
            self._format = 'text'
            body = self._text

        connection = boto.ses.connect_to_region(
            'us-east-1',
            aws_access_key_id=AWS_ACCESS_KEY, 
            aws_secret_access_key=AWS_SECRET_KEY
        )

        return connection.send_email(
            from_addr,
            self.subject,
            None,
            self.to,
            format=self._format,
            text_body=self._text,
            html_body=self._html
        )

Para usar este código, todo lo que necesitas hacer es esto:

1
2
3
4
email = Email(to='[correo electrónico protegido]', subject='You are HTML Awesome')
email.text('This is a text body. Foo bar.')
email.html('<html><body>This is a text body. <strong>Foo bar.</strong></body></html>')  # Optional
email.send()

La llamada email.html() es opcional. Si incluye tanto texto como HTML en su correo electrónico, ambos se incluirán en la MÍMICA resultante y el cliente de correo electrónico mostrará el formato compatible o preferido por el usuario.

Uso de plantillas de correo electrónico

Si quiere ser realmente elegante, intente usar un motor de plantillas. En lugar de pasar la cadena del cuerpo del correo electrónico directamente, podemos cargarla desde una plantilla, como si renderizara una página HTML en un marco web como Django.

Aquí usamos el motor de plantillas Jinja2 para manejar la carga y el renderizado de plantillas:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
import boto.ses
from jinja2 import Environment, PackageLoader

# Loads templates from the yourapp.templates folder
env = Environment(loader=PackageLoader('yourapp', 'templates'))

AWS_ACCESS_KEY = 'YOUR-ACCESS-KEY-HERE'
AWS_SECRET_KEY = 'YOUR-SECRET-KEY-HERE'

class Email(object):
    def __init__(self, to, subject):
        self.to = to
        self.subject = subject
        self._html = None
        self._text = None

    def _render(self, filename, context):
        template = env.get_template(filename)
        return template.render(context)

    def html(self, filename, context):
        self._html = self._render(filename, context)

    def text(self, filename, context):
        self._text = self._render(filename, context)

    def send(self, from_addr=None):
        # Same as before...

Nota: Para el código de producción, en realidad no coloque sus claves de seguridad de AWS directamente en su código. Use algo como variables ambientales en su lugar.

El uso de este código es similar al anterior, pero en su lugar solo pasaremos el nombre de archivo de la plantilla y el contexto desde el cual se completará la plantilla:

1
2
3
4
5
email = Email(to='[correo electrónico protegido]', subject='OMG an Email!')
ctx = {'username': user.username}
email.text('email.txt', ctx)
email.html('email.html', ctx)  # Optional
email.send()

Ahora puede crear y procesar fácilmente correos electrónicos HTML como lo hace con las páginas web.

Conclusión

Espero que este breve tutorial te haya resultado útil. El código aquí debería ser bueno para la mayoría de los casos de uso, aunque puede avanzar aún más agregando Cc, Bcc, direcciones de respuesta, rutas de retorno o incluso archivos adjuntos.

Todas estas características adicionales que acabo de mencionar, excepto los archivos adjuntos, pueden ser manejadas por la función send_email. Para enviar archivos adjuntos, tendrá que usar la función send_raw_email de nivel inferior, que requiere que usted mismo construya el mensaje MIME. No se preocupe, eso no es demasiado difícil gracias al paquete Email de Python, pero lo guardaremos para otro artículo.

¿Te resultó útil? ¿Encontraste un error? ¡Házmelo saber en los comentarios!