Acceso con PHP a Exchange/Office 365

Anunciado durante mucho tiempo , ahora realidad : Microsoft ha desactivado la autenticación por contraseña para ciertos protocolos en Exchange Online desde septiembre de 2022 a favor de oAuth2. Los problemas de GitHub de muchas bibliotecas y scripts de respaldo dejan en claro que el cambio tomó por sorpresa a muchos administradores. A continuación, mostramos una forma de cómo puede continuar accediendo al contenido de su buzón de Exchange con la ayuda de oAuth2 a través de PHP a través de IMAP.


Desde el punto de vista de la seguridad, la jugada de Microsoft es muy correcta, pero la complejidad del acceso programático a sus correos electrónicos ha aumentado bastante. Por ejemplo, si utiliza la biblioteca barbushin/php-imap ampliamente utilizada, el acceso solía ser el siguiente:

734a82898010e2fcb02c72c3cd9702c2

Simplemente ya no funciona. Para establecer una conexión a través de oAuth2, la primera dificultad es conseguir el token de acceso. Y para ello hay que enfrentarse a dos obstáculos.

Directorio activo de Azure

Los siguientes pasos registran una nueva aplicación en Azure Active Directory:

Iniciar sesión en https://portal.azure.com
Abra el "Directorio activo de Azure"
Seleccione "Registros de aplicaciones" y "Nuevo registro".
Copie "ID de aplicación (cliente)" (= ID de cliente) y "ID de directorio (inquilino)" (= ID de inquilino).
"Permisos de API" y "Agregar permiso"
"API utilizadas por mi organización" y "Office 365 Exchange Online"
"Permisos de la aplicación" y "IMAP.AccessAsApp"
Otorgar consentimiento de administrador
"Certificados y secretos" y "Secretos del cliente" y "Secreto del nuevo cliente"
Elija la descripción y establezca la validez
Copie "Secret ID" (Client Secret) al portapapeles
Aplicaciones empresariales abiertas
Copie "ID de objeto".

Potencia Shell

Ahora activamos la aplicación en el Microsoft PowerShell (modo Administrador) y asigne permisos a los buzones individuales (<TENANTID>, <CLIENTID>, <OBJECTID>, <EMAIL> debe ser reemplazado en cada caso):

Install-Module -Name ExchangeOnlineManagement
Import-Module ExchangeOnlineManagement
Connect-ExchangeOnline -Organization <TENANTID>

New-ServicePrincipal -AppId <CLIENTID> -ServiceId <OBJECTID>
Add-MailboxPermission -Identity "<EMAIL>" -User <OBJECTID> -AccessRights FullAccess
...

Una vez que haya hecho eso, el resto no es ciencia espacial. Dado que barbushin/php-imap no es compatible con oAuth2, puede conectarse con la biblioteca alternativa Webklex/php-imap (que también tiene la ventaja de no requerir el módulo PHP IMAP ).:

734a82898010e2fcb02c72c3cd9702c2

Sin embargo, las bibliotecas que no admiten oficialmente oAuth2 también se pueden usar con un proxy como simonrob/email-oauth2-proxy hacerlo viable. Después de este Descargar y la instalación a través de python -m pip install -r requirements-no-gui.txt (Python ≥3.6 requerido) editas el archivo emailproxy.config por ejemplo, de la siguiente manera (reemplazando esta vez <TENANTID>, <CLIENTID>, <CLIENTSECRET> y <EMAIL>):

[Server setup]

[IMAP-1993]
local_address = localhost
server_address = outlook.office365.com
server_port = 993

[Account setup]

[<EMAIL>]
token_url = https://login.microsoftonline.com/<TENANTID>/oauth2/v2.0/token
oauth2_scope = https://outlook.office365.com/.default
redirect_uri = http://localhost:8080
client_id = <CLIENTID>
client_secret = <CLIENTSECRET>

Luego inicias el proxy con python emailproxy.py --no-gui y ahora puede ir a la IP sin cifrar localhost en el puerto 1993 conéctese a través de la autenticación básica normal (y cualquier contraseña establecida). Si desea iniciar el proxy como un servicio en segundo plano cuando inicia el sistema, puede usar, por ejemplo sistemad:

sudo systemctl edit --force --full emailproxy.service

[Unit]
Description=Email OAuth 2.0 Proxy
[Service]
ExecStart=/usr/bin/python /path/to/emailproxy.py --no-gui
Restart=always
[Install]
WantedBy=multi-user.target

sudo systemctl enable emailproxy.service --now
sudo systemctl status emailproxy.service
sudo systemctl start emailproxy.service

Si se requiere una conexión encriptada, esto también es posible; para esto, primero debe crear una clave privada y un certificado autofirmado.:

openssl genrsa -out key.pem 3072
openssl req -new -x509 -key key.pem -out cert.pem -days 360

Luego se hace referencia en el emailproxy.config estos dos archivos:

local_key_path = /path/to/key.pem
local_certificate_path = /path/to/cert.pem
Atrás