Introducción

Python ofrece la posibilidad de automatizar envíos de correos. Esto nos sirve a la hora de mandar correos iguales a multiples contactos o clientes.

Para poder hacerlo, antes hay que seguir unos pasos de autenticación. Se pueden ver en este link.

De esta autenticación debemos quedarnos con la contraseña de la app (no la del mail, sino una generada en el proceso de seguridad). La utilizaremos a lo largo del código.

Funcionamiento básico para un solo mail

Importar librerias

In [6]:
import pandas as pd
import numpy as np

#Librerias para correos
import smtplib
import ssl
from email.message import EmailMessage

Indicamos remitente, destinatario, y clave de app

In [2]:
email_sender = 'completar' #Tu mail. Debe ser el mail en el que estés corriendo este colab.
email_password = 'completar' #La contraseña que salio de la autenticación
email_receiver = 'completar' #Dirección a la que quieras enviar el correo

Creamos mensaje y enviamos

In [8]:
em = EmailMessage()
subject = 'Prueba singular'
body = """
Hola, que tal?
"""
em['From'] = email_sender
em['To'] = email_receiver
em['Subject'] = subject
#em['reply-to'] = "denistrosman@gmail.com" # por si queremos que la opción de responder vaya hacia un correo distinto al nuestro
em.set_content(body)

context = ssl.create_default_context()

with smtplib.SMTP_SSL('smtp.gmail.com', 465, context=context) as smtp:
    smtp.login(email_sender, email_password)
    smtp.sendmail(email_sender, email_receiver, em.as_string())

Multiples mails

Creamos funcion con lo hecho previamente e iteramos por las direcciones que marquemos

In [9]:
def mandar_mail(sender, lista_mails, contrasena):
  
  subject = 'Prueba múltiple'
  body = """
  Hola, que tal?
  """

  em = EmailMessage()
  em['From'] = sender
  em['Subject'] = subject
  em.set_content(body)
  context = ssl.create_default_context()

  #Loop
  
  for direccion in lista_mails:
    em['To'] = direccion
    with smtplib.SMTP_SSL('smtp.gmail.com', 465, context=context) as smtp:
        smtp.login(sender, contrasena)
        smtp.sendmail(sender, direccion, em.as_string())
    del em['To']

Ejecutamos

In [10]:
mails = ['mail1','mail2'] #Completar con direcciones a enviar
contraseña = 'completar' #completar con contraseña que sale de la autenticación
sender = 'completar' #mail desde donde estas corriendo este colab

mandar_mail(sender,mails,contraseña)

Mails con archivos adjuntos

Importamos librerias

In [11]:
from email.mime.multipart import MIMEMultipart
from email.mime.text import MIMEText
from email.mime.base import MIMEBase
from email import encoders

Creo archivo adjunto

In [13]:
from numpy import random

df = pd.DataFrame(random.randint(100,size=10),columns=['numero']) #Creo data frame randomizado
writer = pd.ExcelWriter('/content/sample_data/df_prueba.xlsx') #Descargamos excel en nuestro repositorio temporal de colab 
df.to_excel(writer,float_format="%.2f")
writer.save()

Un solo correo

In [14]:
def mail_adjunto(sender, receiver, contrasena, adjunto):

  #Defino asunto y cuerpo del mail

  subject = 'Prueba con archivo adjunto - singular'
  body = """
  Envío el excel solicitado
  """

  #Asigno remitente y destinatario

  em = MIMEMultipart() 
  em['From'] = sender
  em['Subject'] = subject
  em['To'] = receiver
  context = ssl.create_default_context()

  #Creo mail y adjunto
  em.attach(MIMEText(body, 'plain'))
  attach_file = open(adjunto, 'rb') # Abrir archivo como binario
  payload = MIMEBase('application', 'octate-stream')
  payload.set_payload(open(adjunto, "rb").read())
  encoders.encode_base64(payload) #Encodear el adjunto
  payload.add_header('Content-Disposition', 'attachment; filename="archivo.xlsx"')
  em.attach(payload)

  #Envio mail

  with smtplib.SMTP_SSL('smtp.gmail.com', 465, context=context) as smtp:
          smtp.login(sender, contrasena)
          smtp.sendmail(sender, receiver, em.as_string())
In [16]:
receiver = 'Completar' #mails a enviar
contraseña = 'completar' #completar con contraseña que sale de la autenticación
sender = 'completar' #mail desde donde estas corriendo este colab
adjunto = '/content/sample_data/df_prueba.xlsx' #path del archivo adjunto guardado

mail_adjunto(sender, receiver, contraseña,adjunto) #Ejecutamos

Multiples correos adjuntos

In [18]:
def mails_adjuntos(sender, lista_mails, contrasena,adjunto):

  #Defino asunto y cuerpo del mail

  subject = 'Prueba con archivo adjunto - Múltiple'
  body = """
  Envío el excel solicitado
  """

  #Asigno remitente y destinatario

  em = MIMEMultipart() 
  em['From'] = sender
  em['Subject'] = subject
  context = ssl.create_default_context()

  #Creo mail y adjunto
  em.attach(MIMEText(body, 'plain'))
  attach_file = open(adjunto, 'rb') # Abrimos en formato binario
  payload = MIMEBase('application', 'octate-stream')
  payload.set_payload(open(adjunto, "rb").read())
  encoders.encode_base64(payload) #Encodeamos el adjunto
  payload.add_header('Content-Disposition', 'attachment; filename="archivo.xlsx"')
  em.attach(payload)

  #Envio mail
  for mail in lista_mails:
    em['To'] = mail
    with smtplib.SMTP_SSL('smtp.gmail.com', 465, context=context) as smtp:
            smtp.login(sender, contrasena)
            smtp.sendmail(sender, mail, em.as_string())
    del em['To']
In [20]:
mails = ['completar mail1','completar mail2'] #listado de mails
contraseña = '' #completar
sender = '' #mail desde donde estas corriendo este colab
adjunto = '/content/sample_data/df_prueba.xlsx' #path del archivo adjunto guardado

mails_adjuntos(sender, lista_mails = mails, contrasena  = contraseña, adjunto = adjunto) #Ejecutamos

Integracion a excel

La idea original de esta tarea era poder integrar la automatizacion de envios de correos a un excel que contenga:

  • Columna con direcciones de mails
  • Columnas con condiciones True y False (ticks de google sheets) para saber si hay que enviar el mail o no, y que tipo de mail hay que enviar.

Para esto, vamos a leer un archivo desde nuestro drive y generar un ejemplo de la automatizacion. En este ejemplo, tenemos una base de datos de compras con dos condiciones:

  1. Listo para retirar (pick-up)
  2. Producto enviado

Buscaremos enviar un mail cuando se cumpla alguna o ambas condiciones

Nuestro archivo lucirá de esta manera:

image.png

Librerias y lectura de archivo

Librerias generales

In [21]:
import pandas as pd
import numpy as np

Librerias y autorizaciones drive

In [22]:
from pydrive.auth import GoogleAuth
from pydrive.drive import GoogleDrive
from google.colab import auth
from oauth2client.client import GoogleCredentials

#Se va a abrir una ventana, darle permitir. Solo estarás permitiendole a tu Colab utilizar los archivos drive

auth.authenticate_user()
gauth = GoogleAuth()
gauth.credentials = GoogleCredentials.get_application_default()
drive = GoogleDrive(gauth)

from google.colab import auth
import gspread
from google.auth import default
creds, _ = default()

gc = gspread.authorize(creds)

Leo y formateo archivo.

In [33]:
#Indicamos nombre y traemos archivo

file_name = 'mails' #indicar nombre del archivo drive. No importa en que carpeta este, solo el nombre es suficiente
archivo =gc.open(file_name).get_worksheet(1) #Indicar numero de hoja, arrancando en 0
archivo = archivo.get_all_values()

#Creamos DataFrame 

df = pd.DataFrame(archivo)
df.columns = df.iloc[0]
df.drop(df.index[0],inplace=True)

#Visualizar

df
Out[33]:
nombre mail pickup enviado
1 Mail1 Mail1@gmail.com TRUE FALSE
2 Mail2 Mail2@gmail.com FALSE FALSE
3 Mail3 Mail3@gmail.com FALSE TRUE
4 Mail4 Mail4@gmail.com FALSE FALSE
5 Mail5 Mail5@gmail.com TRUE TRUE

Función para automatizar envíos según condiciones y direcciones plasmadas en un archivo excel

In [37]:
def mandar_mail(sender, contrasena):
  
  #Asunto y cuerpo segun correo a mandar 

  subject = 'Novedades de su compra'
  body_sent = """
  Su compra ha sido enviada!
  """
  body_pickup = """
  Su compra esta lista para retirar!
  """

  #Creo mensaje

  em = EmailMessage()
  em['From'] = sender
  em['Subject'] = subject
  context = ssl.create_default_context()

 #Loop para envios
    
  for mail_envio in [mail for mail,enviar in zip(df.mail,df.enviado) if enviar == 'TRUE' ]:
    em.set_content(body_sent)
    em['To'] = mail_envio
    with smtplib.SMTP_SSL('smtp.gmail.com', 465, context=context) as smtp:
        smtp.login(sender, contrasena)
        smtp.sendmail(sender, mail_envio, em.as_string())
    del em['To'] 
    print(f'Aviso de compra enviada para {mail_envio}')

  #Loop para pickups

  for mail_pickup in [mail for mail,pickup in zip(df.mail,df.pickup) if pickup == 'TRUE' ]:
    em.set_content(body_pickup)
    em['To'] = mail_pickup
    with smtplib.SMTP_SSL('smtp.gmail.com', 465, context=context) as smtp:
        smtp.login(sender, contrasena)
        smtp.sendmail(sender, mail_pickup, em.as_string())
    del em['To']
    print(f'Aviso de compra lista para retirar para {mail_pickup}')
In [38]:
contraseña = '' #completar
sender = 'completar' #mail propio desde donde estas corriendo este colab

mandar_mail(sender=sender, contrasena=contraseña)
Aviso de compra enviada para Mail3@gmail.com
Aviso de compra enviada para Mail5@gmail.com
Aviso de compra lista para retirar para Mail1@gmail.com
Aviso de compra lista para retirar para Mail5@gmail.com