Micropython: Usando SMTP para enviar e-mails

Dentro del mundo del Internet de las cosas (IOT) tenemos a nuestra disposición distintas formas de enviar información desde o hacia un dispositivo, los que llamamos protocolos. El protocolo SMTP que se usa comunmente para enviar e-mails o correos electrónicos es bastante antiguo y tiene algunas limitaciones, pero puede ser una opción interesante para algunas aplicaciones. En este artículo veremos como enviar información con este protocolo desde un ESP32 o un ESP8266.

El protocolo SMTP

El protocolo SMTP (Simple Mail Transfer Protocolo) fue creado por los años 80 para enviar mensajes de texto entre dos o mas computadoras. Con el paso de los años se lo fue actualizando para aceptar otros formatos de datos y si bien hace algunos años era el método mas común para el envío de mensajes, en la actualidad ha sido desplazado por otros protocolos y otras aplicaciones que ofrecen mas posibilidades. Sin embargo, es un protocolo sencillo y fácil de implementar en microcontroladores, que se puede aprovechar en aplicaciones sencillas en las que no queremos emplear servidores web para almacenar datos o apps específicas. Empleando SMTP podemos enviar notificaciones a una PC o teléfono cuando se produce un evento o reportar valores de sensores u otra información de manera periódica.

SMTP

El protocolo SMTP sirve solo para enviar información en un e-mail, los protocolos empleados para recibir información en el mismo formato son IMAP y POP3 que no se analizan en este artículo

Usando SMTP

El envío de datos empleando el protocolo SMTP se realiza entre un cliente SMTP (la placa ESP) y un servidor SMTP. Podemos usar un servidor propio o uno de los múltiples prestadores de servicios, como Google u Outlook. Para poder acceder al servidor, debemos conocer su dirección, el puerto donde “escucha” los pedidos y las credenciales de usuario: nombre de usuario y contraseña. Los puertos empleados por SMTP son el  25, 465 y 587, siendo el último el mas empleado en la actualidad. La seguridad de los datos enviados empleando SMTP se puede lograr usando SSL (Secure Socket Layer) o la mas actualizada TLS (Transport Layer Security). Según el método que usemos será el puerto al que debamos acceder.

En este artículo voy a utilizar el servidor de Google, cuyos datos son:

  • Dirección: smtp.gmail.com
  • Puerto TLS: 587
  • Puerto SSL: 465

Para que Gmail no rechace las conexiones, debemos configurar la cuenta para que permita el acceso de Aplicaciones menos seguras. Para no abrir una brecha de seguridad en nuestra cuenta habitual o principal, sugiero crear una cuenta nueva con esta configuración y utilizarla exclusivamente para hacer las pruebas o para la aplicación que tengamos en mente.

Una vez creada esa cuenta, debemos acceder a la administración y a la opción Seguridad y Acceso de apps menos seguras, habilitándola.

Habilitar el acceso de Apps menos seguras en Google

El módulo uMail

Micropython no cuenta con un módulo estándar para el protocolo SMTP, pero afortunadamente podemos contar con uno de código libre que podemos descargar del siguiente repositorio y es muy fácil de utilizar.

Antes de poder incluirlo en nuestro programa debemos descargarlo del repositorio y guardarlo en nuestra placa, tal como expliqué en este artículo anterior.

El módulo en el sistema de archivos de la placa

El módulo uMail contiene la clase SMTP que es la que vamos a utilizar, así que lo primero que debemos hacer es importar esa clase en nuestro código:

from umail import SMTP

Una vez hecho esto ya podemos crear o instanciar un objeto de esa clase para que funcione como cliente SMTP. El constructor tiene el siguiente formato:

SMTP (dirección_servidor, puerto, [ssl=True, username='usuario', password='contraseña'])

Los campos ssl, username y password son opcionales.

Ejemplo:

smtp = SMTP('smtp.gmail.com', 587, username='usuario@gmail.com', password='contraseña')

(reemplazar el usuario y la contraseña de la cuenta de Gmail configurada para el acceso de Apps menos seguras)

Importante

El objeto de la clase SMTP debe ser creado luego de que se realice la conexión a una red, de lo contrario devuelve error

El objeto de la clase SMTP así creado tiene los siguientes métodos:

SMTP.login(usuario, contraseña): Se identifica en el servidor con el nombre de usuario y contraseña. Es necesario solamente si no se especifico el usuario y contraseña en el constructor.

SMTP.to(dirección_destino, mail_from=’dirección_origen’): Dirección a la cual va destinado el e-mail. Opcionalmente también se puede especificar la dirección de origen (mail_from) que a veces es requerida por algunos servicios de correo electrónico.

SMTP.write(contenido): Envía el contenido al servidor. Este método es útil cuando se quiere enviar un mail en varios fragmentos. Si esa funcionalidad no es necesaria, utilizar directamente send.

SMTP.send([contenido]): Indica al servidor que se envíe el mail. Opcionalmente puede especificarse un contenido.

SMTP.quit(): Termina la conexión con el servidor.

El siguiente ejemplo usa la función que vimos en otro artículo para conectar a una red Wifi y luego envía un mail con el contenido “Hola Mundo!” a la dirección profetolocka@gmail.com

#Test SMTP

from umail import SMTP
import network, time

def conectaWifi (red, password):
      global miRed
      miRed = network.WLAN(network.STA_IF)     
      if not miRed.isconnected():              #Si no está conectado…
          miRed.active(True)                   #activa la interface
          miRed.connect(red, password)         #Intenta conectar con la red
          print('Conectando a la red', red +"…")
          timeout = time.time ()
          while not miRed.isconnected():           #Mientras no se conecte..
              if (time.ticks_diff (time.time (), timeout) > 10):
                  return False
      return True

if conectaWifi ("red", "contraseña"):
      print ("Conexión exitosa!")
      print('Datos de la red (IP/netmask/gw/DNS):', miRed.ifconfig())
      
      smtp = SMTP('smtp.gmail.com', 587, username='usuario@gmail.com', password='contraseña')
      smtp.to('profetolocka@gmail.com')
      smtp.send("Hola mundo!")  
      smtp.quit()  
      miRed.active (False)

 else:
      print ("Imposible conectar")

Como vimos, la seguridad de la información enviada a través del protocolo SMTP puede lograrse de dos maneras: usando SSL o TLS. El módulo uMail soporta ambos métodos. Si queremos emplear SSL, debemos especificar ssl=True en el constructor del objeto y luego conectarnos al puerto 465 del servidor. Si no lo hacemos, la seguridad dependerá del servidor. En el caso de Gmail, si nos conectamos al puerto 587, el servidor solicita que el cliente utilice seguridad TLS para continuar, lo que uMail realiza de manera transparente.

En este otro ejemplo no se especifican el usuario y contraseña de la cuenta de mail en el constructor sino que se lo hace con el método login (el resultado es el mismo), se usa SSL para la seguridad y por lo tanto el puerto es el 465 y el texto del mail se envía en dos partes, con dos métodos write, terminando con send:

from umail import SMTP

import network, time
def conectaWifi (red, password):
      global miRed
      miRed = network.WLAN(network.STA_IF)     
      if not miRed.isconnected():              #Si no está conectado…
          miRed.active(True)                   #activa la interface
          miRed.connect(red, password)         #Intenta conectar con la red
          print('Conectando a la red', red +"…")
          timeout = time.time ()
          while not miRed.isconnected():           #Mientras no se conecte..
              if (time.ticks_diff (time.time (), timeout) > 10):
                  return False
      return True

if conectaWifi ("red", "contraseña"):
      print ("Conexión exitosa!")
      print('Datos de la red (IP/netmask/gw/DNS):', miRed.ifconfig())
  
      smtp = SMTP('smtp.gmail.com', 465, ssl=True)
    
      smtp.login('usuario@gmail.com', 'contraseña')
      smtp.to('profetolocka@gmail.com')
      smtp.write ("Línea 1\n")
      smtp.write ("Línea 2\n")
      smtp.send ()
      smtp.quit()
      miRed.active (False)

 else:
      print ("Imposible conectar")

Conclusión

En este artículo vimos como enviar emails desde nuestras placas ESP usando Micropython, lo cual abre una gran cantidad de posibilidades para reportar distintos tipos de eventos. En próximos artículos veremos algunas aplicaciones concretas. Cualquier duda o sugerencia, pueden dejarla en la sección de comentarios.

2 comentarios en «Micropython: Usando SMTP para enviar e-mails»

  1. Hola Ernesto veo que tienes amplia experiencia, utilizando micropython. Excelente el tutorial para enviar correos electrónicos mediante la librería uMail. Pero hay alguna manera de adjuntar un archivo para ser enviado via mail, desde una tarjeta esp32 y micropython. Actualmente lo hago utilizando la red celular con un sim800L. me encantaría poder enviar datos e un sensor para abrirlos como un archivo csv en excel.

    Responder

Deja un comentario

Este sitio usa Akismet para reducir el spam. Aprende cómo se procesan los datos de tus comentarios.

Habilitar notificaciones OK No, gracias