From 15a07f7de2dc716056c59a49bbef2b71ab209e7e Mon Sep 17 00:00:00 2001 From: Mathias Lang Date: Tue, 20 Aug 2024 13:03:22 +0200 Subject: [PATCH] Mail: Implement SMTP XOAUTH2 authentication A fairly simple implementation allowing to send emails to M365 / gmail. --- mail/vibe/mail/smtp.d | 23 ++++++++++++++++++++++- 1 file changed, 22 insertions(+), 1 deletion(-) diff --git a/mail/vibe/mail/smtp.d b/mail/vibe/mail/smtp.d index 6dc8ec4b37..63609c61b2 100644 --- a/mail/vibe/mail/smtp.d +++ b/mail/vibe/mail/smtp.d @@ -71,7 +71,15 @@ enum SMTPAuthType { none, plain, login, - cramMd5 + cramMd5, + /// Authenticate using XOAUTH2 protocol + /// + /// Works for GMail and Office 365 + /// + /// See_Also: + /// - https://developers.google.com/gmail/imap/xoauth2-protocol#using_oauth_20 + /// - https://learn.microsoft.com/en-us/exchange/client-developer/legacy-protocols/how-to-authenticate-an-imap-pop-smtp-application-by-using-oauth + xoauth2, } @@ -191,6 +199,19 @@ void sendMail(in SMTPClientSettings settings, Mail mail) conn.write(Base64.encode(cast(const(ubyte)[])settings.password) ~ "\r\n"); expectStatus(conn, 235, "login password"); break; + case SMTPAuthType.xoauth2: + // Ideally we should inspect the server's capabilities instead of + // making this decision, but since the RFC for OAuth requires TLS, + // be a bit conservative. + enforce(settings.connectionType != SMTPConnectionType.plain, + "Cannot use XOAUTH2 without TLS"); + conn.write("AUTH XOAUTH2\r\n"); + expectStatus(conn, SMTPStatus.serverAuthReady, "AUTH XOAUTH2"); + const authStr = "user=%s\1auth=Bearer %s\1\1".format( + settings.username, settings.password); + conn.write(Base64.encode(authStr.representation) ~ "\r\n"); + expectStatus(conn, 235, "XOAUTH2 authentication"); + break; case SMTPAuthType.cramMd5: assert(false, "TODO!"); }