¿Quieres implementar envío y recepción de emails en tus aplicaciones?

El email es una herramienta muy potente, si bien lo habitual es utilizarlo en persona, hay muchos servicios y aplicaciones que lo utilizan de forma automática para enviar y recibir notificaciones de estado.

En esta primera entrada de gmail desde Python, vamos a ver como acceder a una cuenta GMAIL, consultar la bandeja de entrada y descargar los mensajes.

Antes de nada es necesario configurar la cuenta GMAIL para permitir el acceso a otras aplicaciones. Si ya lo has hecho puedes saltarte este paso.

El código

Vamos a trabajar con los módulos email e imaplib.

#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
Created on Tue Aug 14 10:38:51 2018

@author: altaruru
"""

import imaplib
import email

def get_body(tmsg):    
    body = ""
    if tmsg.is_multipart():        
        for part in tmsg.walk():
            ctype = part.get_content_type()
            cdispo = str(part.get('Content-Disposition'))    
            # skip any text/plain (txt) attachments
            if ctype == 'text/plain' and 'attachment' not in cdispo:
                body = str(part.get_payload(decode=True))  # decode
                body=body.replace("\\r\\n","\n")                
                break
    # not multipart - i.e. plain text, no attachments, keeping fingers crossed
    else:
        body = str(tmsg.get_payload(decode=True))
    return body

def get_emailinfo(id, data, bshowbody=False):
    for contenido in data:
        # comprueba que 'contenido' sea una tupla, si es así continua
        if isinstance(contenido, tuple):                    
            # recuperamos información del email:                    
            msg = email.message_from_string(contenido[1].decode())
            # mostramos resultados:   
            print ("%d - *** %s ***" % (id, msg['subject'].upper()))
            print ("enviado por %s" % msg['from'])
            print ("para %s" % msg['to'])
            if(bshowbody):
                print ("---                                                   ---")
                print(get_body(msg))
                print ("--------------------------------------------------------")
            return True
    # si no hay info
    return False

def get_emails(gmailsmtpsvr, gmailusr, gmailpwd, bshowbody):
    try:
        # Conectamos a nuestro servidor, gmail necesita un ssl socket (encriptado) por lo que utilizamos 
        # la subclase IMAP4_SSL
        # Parámetros: host='', port=IMAP4_SSL_PORT, keyfile=None, certfile=None, ssl_context=None
        # El puerto por defecto IMAP4_SSL_PORT es el 993, en el caso de gmail lo dejamos como está, el resto de 
        # parámetros tampoco son necesarios en este caso.
        # Únicamente es necesario pasar como parámetro el servidor stmp de gmail 
        mail = imaplib.IMAP4_SSL(gmailsmtpsvr)
        # logamos:
        mail.login(gmailusr, gmailpwd)
        # seleccionamos bandeja de entrada 'inbox'
        mail.select("inbox")
        # recuperamos lista de emails, es posible filtrar la consulta
        # ALL devuelve todos los emails
        # Ejemplo de filtro: '(FROM "altaruru" SUBJECT "ejemplo python")'        
        result, data = mail.search(None, 'ALL')
        strids = data[0] # coge lista de ids encontrados
        lstids = strids.split()
        # recuperamos valores para bucle
        firstid = int(lstids[0])
        lastid = int(lstids[-1])
        countid = 0
        # mostramos datos de los ids encontrados
        print("primer id: %d\nultimo id: %d\n..." % (firstid, lastid))
        # recorremos lista de mayor a menor (mas recientes primero)
        for id in range(lastid, firstid-1, -1):            
            typ, data = mail.fetch(str(id), '(RFC822)' ) # el parámetro id esperado es tipo cadena
            if (get_emailinfo(id, data, bshowbody)):
                countid+=1
        # fin, si llegamos aqui todo es correcto
        print("emails listados %d" % countid)
    except Exception as e:
        print("Error: %s" % (e))
        return ""
    except:
        print("Error desconocido")
        return ""
  • Resumen de los pasos a seguir:
    • creamos objeto «mail«
    • conectamos al servidor mail.login
    • seleccionamos bandeja de entrada mail.select(«inbox»)
    • recuperamos lista de emails: result, data = mail.search(None, ‘ALL’)
    • recorremos cada elemento obteniendo detalle del mensaje con get_emailinfo

 

Para hacer la magia, usar la función get_emails():

def test():    
    get_emails("smtp.gmail.com", "micuenta@gmail.com", "contraseña", False);

test()

La salida será similar a…

abriendo bandeja entrada de gmail...
primer id: 1
ultimo id: 5
...
5 - *** SECURITY ALERT ***
enviado por Google <no-reply@accounts.google.com>
para micuenta@gmail.com
4 - *** HELP US PROTECT YOU: SECURITY ADVICE FROM GOOGLE ***
enviado por Google <no-reply@accounts.google.com>
para micuenta@gmail.com
3 - *** SECURITY ALERT ***
enviado por Google <no-reply@accounts.google.com>
para micuenta@gmail.com
2 - *** ACCESS FOR LESS SECURE APPS HAS BEEN TURNED ON ***
enviado por Google <no-reply@accounts.google.com>
para micuenta@gmail.com
1 - *** MICUENTA, WELCOME TO YOUR NEW GOOGLE ACCOUNT  ***
enviado por Google Community Team <googlecommunityteam-noreply@google.com>
para micuenta@gmail.com
emails listados 5

Poniendo a True el último parámetro de la función get_emails recuperamos también el cuerpo del mensaje.

get_emails("smtp.gmail.com", "micuenta@gmail.com", "contraseña", True);

En este caso, la salida es…

abriendo bandeja entrada de gmail...
primer id: 1
ultimo id: 5
...
5 - *** SECURITY ALERT ***
enviado por Google <no-reply@accounts.google.com>
para micuenta@gmail.com
---                                                   ---
b"Dan Esco

New device signed in to
micuenta@gmail.com
Your Google Account was just signed in to from a new Linux device. You're
getting this email to make sure it was you.

Check activity
<https://accounts.google.com/AccountChooser?Email=micuenta@gmail.com&continue=https://myaccount.google.com/alert/nt/1537795369000?rfn%3D31%26rfnc%3D1%26eid%3D6185417258682954020%26et%3D0%26asae%3D2%26anexp%3Dgivab-fa--hsc-control_a>
<https://accounts.google.com/AccountChooser?Email=micuenta@gmail.com&continue=https://myaccount.google.com/alert/nt/1537795369000?rfn%3D31%26rfnc%3D1%26eid%3D6185417258682954020%26et%3D0%26asae%3D2%26anexp%3Dgivab-fa--hsc-control_a>

You received this email to let you know about important changes to your
Google Account and services.
\xc2\xa9 2018 Google LLC,1600 Amphitheatre Parkway, Mountain View, CA 94043, USA
1537795369000000
"
--------------------------------------------------------
4 - *** HELP US PROTECT YOU: SECURITY ADVICE FROM GOOGLE ***
enviado por Google <no-reply@accounts.google.com>
para micuenta@gmail.com
---                                                   ---
b'Dan Esco

Turn off less secure access
micuenta@gmail.com

Your personal information is vulnerable because you allow apps & devices to
access your account in a less secure way.
Turn off this type of access and see other personalized security
recommendations in the Security Ch...
...

Eso es todo, para cualquier duda dejad vuestros comentarios y responderé encantado.

¿Quieres enviar emails? aprende como en gmail desde Python, enviando emails

Altaruru!

 

 

 

5 comentarios sobre «GMAIL desde Python, accediendo a la bandeja de entrada»

  1. Anónimo

    hola disculpa para leer el mensaje del servicor de correo de zimbra seria igual

    1. admin

      Hola! este ejemplo es específico para gmail.
      Si necesitas acceder a Zimbra te recomiendo eches un vistazo a https://github.com/Zimbra-Community/python-zimbra

      Un saludo!

  2. Luis Bayó

    He intentado ejecutar el programa y obtengo error, tanto en un Ubuntu 18.04 como en una Raspberry Pi3 B+

    Error: [Errno 101] Network is unreachable

    Alguna sugerencia ?

    1. admin

      Hola Luis,
      parece un problema de configuracion de red.
      ¿el equipo tiene salida a internet?

  3. Luis Bayó

    Tenia un problema de configuracion del POSTFIX:
    Resuelto, Gracias

Deja tu comentario