Automatizando nuestro Outlook con Python

Introducción

Nuestras aplicaciones de email y mensajería son como el sistema nervioso de nuestro equipo, ya que son uno de los principales mecanismos de transmisión de información interna.

Nuestro email sigue siendo tan importante que si queremos que el uso de LLMs tenga un impacto importante en nuestro día a día y nos ayuden a automatizar tareas, tenemos que utilizarlos para leer y procesar nuestro email.

Nos gustaría tener un script de Python que lea nuestro email, seleccione aquellos donde alguien nos presenta una oportunidad de inversión y extraer la información clave. Pero nuestro email está en Microsoft Outlook y para acceder a Outlook desde Python primero hay que dar unos pasos previos. En este post explicamos estos pasos.

Acceder a nuestro email en Microsoft Outlook

Para acceder a nuestro email desde Python tenemos que utilizar los siguientes servicios y recursos de Microsoft:

  1. Microsoft Graph, que es la API de Microsoft que permite acceder a todos nuestros datos almacenados en todas las aplicaciones de Microsoft 365, como Outlook o OneDrive.
  2. Microsoft Entra ID, la plataforma de IAM de Microsoft Azure, es decir, es la herramienta de gestión de identidades y accesos.

Microsoft Outlook es un cliente de email: una aplicación para leer y escribir emails; pero estos emails en realidad están en Microsoft Exchange, que es el servidor de email de Microsoft. Microsoft Exchange a su vez utiliza Microsoft Azure como infraestructura de almacenamiento.

Para Azure, nuestro script de Python es una aplicación que quiere acceder a determinados recursos (nuestro servidor de email) para los que necesita permisos.

Cuando Azure recibe una API call para acceder a nuestro email, Azure tiene que poder identificar quién hace la API call para saber si debe permitir o no el acceso.

Para darle permisos a nuestra aplicación, primero tenemos que registrarla en Azure Platform. A continuación resumimos los pasos que hemos seguido:

  1. Registramos nuestro script como una aplicación en la sección de App Registrations
  2. Será una Single Tenant application, ya que sólo queremos que personas de nuestro dominio (athos-cap.com) puedan acceder a los recursos de email.
  3. Una vez registrada la aplicación, nos copiamos los códigos de identificación que utilizaremos más adelante en nuestro script de Python: Application (client) ID, Directory (tenant) ID
  4. Generamos una secret key para la aplicación en la sección Manage -> Certificates & secrets. Tendremos que copiar el valor de esta secret key en el momento de generarlo, porque lo necesitaremos en nuestro script y más tarde ya no podremos ver su valor porque queda encriptado.
  5. Damos permisos a la aplicación (en la sección API Permissions); en concreto, daremos el permiso Mail.Read.
  6. Adicionalmente, en la sección Manage > Authentication, tenemos que indicar que se trata de una Web application en lugar de una single-page application o una mobile app. Además, hay que especificar que la URI de redirección es: https://login.microsoftonline.com/common/oauth2/nativeclient.

Una vez hechos estos pasos, nuestro script ya podrá acceder a nuestro email.

Script para leer nuestro email en Microsoft Outlook

En lo que sigue vamos a explicar las distintas partes del script que utilizamos para leer nuestro email.

Para acceder al email necesitamos tres códigos que obtenemos cuando registramos nuestro script en Azure. También tenemos que especificar la dirección de email a la que queremos acceder:

CLIENT_ID = "#ID de nuestra app"   
CLIENT_SECRET = "#Secret key de nuestra app"  
TENANT_ID = "#ID de nuestra organización"
user_email = "dirección email"   

La primera parte del script es conectarnos a Microsoft Graph. Para esto usamos la librería MSAL, que es la herramienta oficial de Microsoft para autenticarnos:

app = msal.ConfidentialClientApplication(
    CLIENT_ID,
    authority=f"<https://login.microsoftonline.com/{TENANT_ID}>",
    client_credential=CLIENT_SECRET
)

result = app.acquire_token_for_client(
    scopes=['<https://graph.microsoft.com/.default>']
)

access_token = result['access_token']

Cuando ejecutamos este código, MSAL se conecta a Azure y nos da un token de acceso. Es como un pase temporal que nos permite acceder a nuestro email.

Con el token ya podemos acceder a nuestros emails. Lo hacemos así:

GRAPH_API_ENDPOINT = '<https://graph.microsoft.com/v1.0>'

headers = {
    'Authorization': f'Bearer {access_token}',
    'Content-Type': 'application/json'
}

response = requests.get(
    f'{GRAPH_API_ENDPOINT}/users/{user_email}/messages?$top=100&$orderby=receivedDateTime desc',
    headers=headers
)

emails = response.json()['value']

Este código hace dos cosas importantes:

  1. Usa el token como una llave para abrir nuestro buzón
  2. Pide los últimos 100 emails, ordenados del más reciente al más antiguo

Para cada email que recibimos, extraemos la información que nos interesa:


filtered_emails = []

for email in emails:
    email_dict = {
        'subject': email.get('subject', 'No subject'),
        'from': email['from']['emailAddress']['address'],
        'received': email.get('receivedDateTime', 'No date')
    }

    # Obtener el cuerpo del email en una llamada separada
    body_response = requests.get(
        f"{GRAPH_API_ENDPOINT}/users/{user_email}/messages/{email['id']}?$select=body",
        headers=headers
    )
    
    
		# El cuerpo del email viene en formato HTML, 
		# Usamos la librería BeautifulSoup para limpiarlo y quedarnos solo con el texto
    
    raw_body = body_response.json()['body']['content']
		soup = BeautifulSoup(raw_body, 'html.parser')
		# Quitamos etiquetas meta y estilos
		for tag in soup(['meta', 'style']):
	    tag.decompose()
		email_dict['body'] = soup.get_text()

		filtered_emails.append(email_dict)

En los fragmentos anteriores hemos omitido algunas partes de código que nos sirven para detectar mejor errores pero que no son esenciales.

Finalmente, guardamos todos los emails procesados en un archivo:

with open('filtered_emails.txt', 'w') as file:
    json.dump(filtered_emails, file, indent=4)

En el archivo’filtered_emails.txt’ hemos guardado los últimos 100 emails.

Conclusión

En este post hemos explicado los pasos necesarios para poder acceder a nuestro email en Outlook desde un script de Python. El script hace varias cosas importantes:

  • Se conecta a nuestro email de forma segura usando las credenciales de Azure.
  • Extrae los emails más recientes con toda su información.
  • Limpia el contenido para que sea fácil de procesar.
  • Guarda todo en un archivo que podremos usar después.

La parte más tediosa es la configuración en Azure y la autenticación, pero una vez hecho el script funciona.

Este script es una parte de un proyecto más amplio, un script de Python que puede:

  1. Acceder y leer nuestro email en Microsoft Outlook.
  2. Con la API de Anthropic, identificar aquellos emails donde alguien nos introduce una oportunidad de inversión y extraer la información clave.
  3. Enviar la información de las oportunidades filtradas a nuestro repositorio en Airtable.

Siguiendo el esquema anterior, partimos este proyecto en 3 bloques en función de las APIs que utilizamos.

Queremos organizar el código en módulos independientes, para que sea fácil hacer cambios o mejoras en el futuro. Un ejemplo sería añadir más fuentes de oportunidades aparte de Outlook para enriquecer nuestro CRM o poder cambiar el CRM al que enviamos la información.

En otro post explicaremos los pasos para implementar este proyecto.

Keep reading