Contenedor Docker para enviar emails con archivos adjuntos (ejemplo de enviar SQL adjunto por email)

Tiempo de lectura: 2 minutos

Hola, hoy vamos a ver como crear un contenedor Docker para enviar emails que tienen archivos adjuntos usando Python. En este caso lo utilizaremos para enviar nuestras copias de SQL por email.

Lo primero que vamos a hacer es crear este docker-compose.yml

python_email_backup:
    build:
      context: ./Dockerfile
      dockerfile: python
    restart: unless-stopped
    container_name: python_email_backup
    env_file:
      - .env
    volumes:
      - ./app_email:/app
      - ./config/backups:/backups
    networks:
      - docker-network

En este caso lo primero que hacemos es crear un Dockerfile para python, en un archivo llamado python en una carpeta Dockerfile.

Para ello creamos la carpeta y archivo Dockerfile/python

# syntax=docker/dockerfile:1
FROM python:3.11.3

WORKDIR /app

RUN apt-get update && apt-get install -y \
    python3-dev \
    python3-pip \
    python3-setuptools \
    python3-wheel \
    && rm -rf /var/lib/apt/lists/*


CMD ["tail", "-f", "/dev/null"]

Hemos instalado el entorno de python 3.11.3 y dejamos el contenedor siempre en ejecución.

Ahora tenemos la línea de:

env_file:
  - .env

Aquí indicamos que tenemos una serie de parámetros en un archivo llamado .env lo creamos esta vez en raíz y de la siguiente forma:

SMTP_SERVER=SMTP.server.com
SMTP_PORT=587
EMAIL_USERNAME=username
EMAIL_PASSWORD=my_pass
EMAIL_FROM=my_email@server.com
EMAIL_TO=email_backups@server.com

Este archivo nos crea distintas variables de entorno que utilizaremos después.

Ahora montamos dos volúmenes:

  volumes:
      - ./app_email:/app
      - ./config/backups:/backups

En este caso vamos a crear la carpeta app_email y dentro vamos a crear un archivo llamado app.py

import sys
import smtplib
from email.mime.text import MIMEText
from email.mime.multipart import MIMEMultipart
from email.mime.application import MIMEApplication

def send_email(smtp_server, smtp_port, email_username, email_password, email_from, email_to, subject, body, attachment_path=None):
    try:
        # Configuración del servidor SMTP
        server = smtplib.SMTP(smtp_server, smtp_port)
        server.starttls()
        server.login(email_username, email_password)

        # Creación del correo electrónico
        msg = MIMEMultipart()
        msg['From'] = email_from
        msg['To'] = email_to
        msg['Subject'] = subject

        # Agregar el cuerpo del mensaje
        msg.attach(MIMEText(body, 'plain'))

        # Agregar el archivo adjunto si se proporciona la ruta
        if attachment_path:
            nombre_archivo = attachment_path.split('/')[-1]
            with open(attachment_path, 'rb') as attachment:
                part = MIMEApplication(attachment.read(), Name=nombre_archivo)
                part['Content-Disposition'] = f'attachment; filename="{nombre_archivo}"'
                msg.attach(part)

        # Envío del correo electrónico
        server.sendmail(email_from, email_to, msg.as_string())

        # Cerrar la conexión con el servidor SMTP
        server.quit()
        print("Correo electrónico enviado con éxito")
    except Exception as e:
        print(f"Error al enviar el correo electrónico: {e}")

if __name__ == "__main__":
    import os

    # Obtener las variables de entorno proporcionadas por Docker Compose
    smtp_server = os.environ['SMTP_SERVER']
    smtp_port = int(os.environ['SMTP_PORT'])
    email_username = os.environ['EMAIL_USERNAME']
    email_password = os.environ['EMAIL_PASSWORD']
    email_from = os.environ['EMAIL_FROM']
    email_to = os.environ['EMAIL_TO']

    # Obtener los argumentos de línea de comandos para el asunto, cuerpo y archivo adjunto
    args = sys.argv
    if len(args) < 4:
        print("Usage: python app.py <subject> <body> <attachment_path>")
        sys.exit(1)

    subject = args[1]
    body = args[2]
    attachment_path = args[3]

    # Enviar el correo electrónico
    send_email(smtp_server, smtp_port, email_username, email_password, email_from, email_to, subject, body, attachment_path)

En este archivo python, utiliza las variables de entorno para configurar el email y enviar un archivo adjunto.

Para usarlo: Usage: python app.py <subject> <body> <attachmen_path>

El otro volumen que creamos es para añadir los archivos que queremos enviar adjuntos, en este caso son copias de SQL que hemos generado con el post anterior: https://devcodelight.com/?p=5795&preview=true

Ahora ya podemos lanzar el contenedor:

docker compose up -d

Y si queremos enviar un email tenemos que poner este comando:

python app.py 'Backup SQL' 'Archivo adjunto' ../backups/backup_prueba.sql

*Con este comando se ejecuta desde dentro de docker.

Si queremos ejecutarlo desde fuera de Docker:

docker run python_email_backup python app.py 'Backup SQL' 'Archivo adjunto' ../backups/backup_prueba.sql

Deja un comentario