git/list[1] front-page[2] threads[3] people[4] search[5] about
 

[PATCH v5 1/3] send-email: implement SMTP bearer authentication

From
Aditya Garg <gargaditya08@live.com>
Date
Apr 24, 2025, 07:53 UTC
Message-ID
<PN0PR01MB95880D1DC65D0356F93B0C55B8852@PN0PR01MB9588.INDPRD01.PROD.OUTLOOK.COM>
In-Reply-To
<PN0PR01MB95884F106749628745FDFBB7B8852@PN0PR01MB9588.INDPRD01.PROD.OUTLOOK.COM>
From: Julian Swagemakers <julian@swagemakers.org>

Manually send SMTP AUTH command for auth type OAUTHBEARER and XOAUTH2. This is necessary since they are currently not supported by the Perls Authen::SASL module.

The bearer token needs to be passed in as the password. This can be done with git-credential-oauth[0] after minor modifications[1]. Which will allow using git send-email with Gmail and oauth2 authentication:

    [credential]
        helper = cache --timeout 7200    # two hours
        helper = oauth
    [sendemail]
        smtpEncryption = tls
        smtpServer = smtp.gmail.com
        smtpUser = example@gmail.com
        smtpServerPort = 587
        smtpauth = OAUTHBEARER
As well as Office 365 accounts:
    [credential]
        helper = cache --timeout 7200   # two hours
        helper = oauth
    [sendemail]
        smtpEncryption = tls
        smtpServer = smtp.office365.com
        smtpUser = example@example.com
        smtpServerPort = 587
        smtpauth = XOAUTH2

[0] https://github.com/hickford/git-credential-oauth [1] https://github.com/hickford/git-credential-oauth/issues/48

Tested-by: M Hickford <mirth.hickford@gmail.com>
Signed-off-by: Julian Swagemakers <julian@swagemakers.org>
Signed-off-by: Aditya Garg <gargaditya08@live.com>
---
 Documentation/git-send-email.adoc |  5 ++-
 git-send-email.perl               | 71 ++++++++++++++++++++++++++++++-
 2 files changed, 74 insertions(+), 2 deletions(-)
diff --git a/Documentation/git-send-email.adoc b/Documentation/git-send-email.adoc
index 7f223db42d..1bf75c060d 100644
--- a/Documentation/git-send-email.adoc
+++ b/Documentation/git-send-email.adoc
@@ -213,7 +213,10 @@ SMTP server and if it is supported by the utilized SASL library, the mechanism
 is used for authentication. If neither 'sendemail.smtpAuth' nor `--smtp-auth`
 is specified, all mechanisms supported by the SASL library can be used. The
 special value 'none' maybe specified to completely disable authentication
-independently of `--smtp-user`
+independently of `--smtp-user`. Specifying `OAUTHBEARER` or `XOAUTH2` will
+bypass SASL negotiation and force bearer authentication. In this case the
+bearer token must be provided with `--smtp-pass` or using a credential helper
+and `--smtp-encryption=tls` must be set.
 
 --smtp-pass[=<password>]::
 	Password for SMTP-AUTH. The argument is optional: If no
diff --git a/git-send-email.perl b/git-send-email.perl
index 1f613fa979..9ba47a6f38 100755
--- a/git-send-email.perl
+++ b/git-send-email.perl
@@ -1398,6 +1398,70 @@ sub smtp_host_string {
 	}
 }
 
+sub generate_oauthbearer_string {
+	# This will generate the oauthbearer string used for authentication.
+	#
+	# "n,a=" {User} ",^Ahost=" {Host} "^Aport=" {Port} "^Aauth=Bearer " {Access Token} "^A^A
+	#
+	# The first part `n,a=" {User} ",` is the gs2 header described in RFC5801.
+	# * gs2-cb-flag `n` -> client does not support CB
+	# * gs2-authzid `a=" {User} "`
+	#
+	# The second part are key value pairs containing host, port and auth as
+	# described in RFC7628.
+	#
+	# https://datatracker.ietf.org/doc/html/rfc5801
+	# https://datatracker.ietf.org/doc/html/rfc7628
+	my $username = shift;
+	my $token = shift;
+	return "n,a=$username,\001port=$smtp_server_port\001auth=Bearer $token\001\001";
+}
+
+sub generate_xoauth2_string {
+	# "user=" {User} "^Aauth=Bearer " {Access Token} "^A^A"
+	# https://developers.google.com/gmail/imap/xoauth2-protocol#initial_client_response
+	my $username = shift;
+	my $token = shift;
+	return "user=$username\001auth=Bearer $token\001\001";
+}
+
+sub smtp_bearer_auth {
+	my $username = shift;
+	my $token = shift;
+	my $auth_string;
+	if ($smtp_encryption ne "tls") {
+		# As described in RFC7628 TLS is required and will be enforced
+		# at this point.
+		#
+		# https://datatracker.ietf.org/doc/html/rfc7628#section-3
+		die sprintf(__("For %s TLS is required."), $smtp_auth);
+	}
+	if ($smtp_auth eq "OAUTHBEARER") {
+		$auth_string = generate_oauthbearer_string($username, $token);
+	} elsif ($smtp_auth eq "XOAUTH2") {
+		$auth_string = generate_xoauth2_string($username, $token);
+	}
+	my $encoded_auth_string = MIME::Base64::encode($auth_string, "");
+	$smtp->command("AUTH $smtp_auth $encoded_auth_string\r\n");
+	use Net::Cmd qw(CMD_OK);
+	if ($smtp->response() == CMD_OK){
+		return 1;
+	} else {
+		# Send dummy request on authentication failure according to rfc7628.
+		# https://datatracker.ietf.org/doc/html/rfc7628#section-3.2.3
+		$smtp->command(MIME::Base64::encode("\001"));
+		$smtp->response();
+		return 0;
+	}
+}
+
+# Check if we are using OAuth2.0 tokens
+
+sub is_smtp_bearer_auth {
+	my ($auth_method) = @_;
+	return ($auth_method eq "OAUTHBEARER" || $auth_method eq "XOAUTH2");
+}
+
 # Returns 1 if authentication succeeded or was not necessary
 # (smtp_user was not specified), and 0 otherwise.
 
@@ -1436,7 +1500,12 @@ sub smtp_auth_maybe {
 
 		# catch all SMTP auth error in a unified eval block
 		eval {
-			if ($smtp_auth) {
+			if (defined $smtp_auth && (is_smtp_bearer_auth($smtp_auth))) {
+				# Since Authen:SASL does not support XOAUTH2 nor OAUTHBEARER we
+				# will manually authenticate for these types. The password field
+				# should contain the auth token at this point.
+				$result = smtp_bearer_auth($cred->{'username'}, $cred->{'password'});
+			} elsif ($smtp_auth) {
 				my $sasl = Authen::SASL->new(
 					mechanism => $smtp_auth,
 					callback => {
-- 
2.49.0
Previous: Aditya GargNext: Julian Swagemakers
Message 18 of 63 in “send-email: add oauth2 support and fix outlook breaking threads”
  1. 0/3 send-email: add oauth2 support and fix outlook breaking threadsAditya Garg, Apr 23, 2025
  2. 1/3 send-email: implement SMTP bearer authenticationAditya Garg, Apr 23, 2025
  3. Junio C HamanoApr 23, 2025
  4. Aditya GargApr 23, 2025
  5. Greg Kroah-HartmanApr 24, 2025
  6. Aditya GargApr 24, 2025
  7. 2/3 send-email: retrieve Message-ID from outlook SMTP serverAditya Garg, Apr 23, 2025
  8. Junio C HamanoApr 23, 2025
  9. brian m. carlsonApr 23, 2025
  10. Aditya GargApr 24, 2025
  11. 3/3 send-email: add option to generate passswords like OAuth2 tokensAditya Garg, Apr 23, 2025
  12. Junio C HamanoApr 23, 2025
  13. Aditya GargApr 24, 2025
  14. Junio C HamanoApr 24, 2025
  15. M HickfordApr 23, 2025
  16. Aditya GargApr 24, 2025
  17. 0/3 send-email: add oauth2 support and fix outlook breaking threadsAditya Garg, Apr 24, 2025
  18. 1/3 send-email: implement SMTP bearer authenticationAditya Garg, Apr 24, 2025
  19. Julian SwagemakersApr 24, 2025
  20. 2/3 send-email: retrieve Message-ID from outlook SMTP serverAditya Garg, Apr 24, 2025
  21. Greg Kroah-HartmanApr 24, 2025
  22. Yao ZiApr 26, 2025
  23. Aditya GargApr 27, 2025
  24. Yao ZiApr 28, 2025
  25. Aditya GargApr 27, 2025
  26. 3/3 send-email: add option to generate passswords like OAuth2 tokensAditya Garg, Apr 24, 2025
  27. Julian SwagemakersApr 24, 2025
  28. Aditya GargApr 24, 2025
  29. Junio C HamanoApr 24, 2025
  30. Aditya GargApr 24, 2025
  31. Junio C HamanoApr 24, 2025
  32. 0/1 send-email: add oauth2 support and fix outlook breaking threadsAditya Garg, Apr 25, 2025
  33. 1/1 send-email: retrieve Message-ID from outlook SMTP serverAditya Garg, Apr 25, 2025
  34. Aditya GargApr 25, 2025
  35. Erik HuelsmannApr 25, 2025
  36. Junio C HamanoApr 25, 2025
  37. Erik HuelsmannApr 25, 2025
  38. Aditya GargApr 25, 2025
  39. Junio C HamanoApr 25, 2025
  40. Aditya GargApr 25, 2025
  41. Aditya GargApr 26, 2025
  42. Eric SunshineApr 26, 2025
  43. Aditya GargApr 26, 2025
  44. Junio C HamanoApr 28, 2025
  45. send-email: add --smtp-outlook-id-tweak optionAditya Garg, Apr 28, 2025
  46. send-email: add --smtp-outlook-id-tweak optionAditya Garg, Apr 28, 2025
  47. Junio C HamanoApr 28, 2025
  48. Aditya GargApr 29, 2025
  49. send-email: add --[no-]outlook-id-fix optionAditya Garg, Apr 29, 2025
  50. Aditya GargApr 29, 2025
  51. Junio C HamanoApr 29, 2025
  52. Junio C HamanoApr 29, 2025
  53. Aditya GargApr 29, 2025
  54. send-email: add --[no-]outlook-id-fix optionAditya Garg, Apr 29, 2025
  55. Junio C HamanoApr 29, 2025
  56. Aditya GargApr 30, 2025
  57. Aditya GargApr 24, 2025
  58. Erik HuelsmannApr 24, 2025
  59. Julian SwagemakersApr 25, 2025
  60. Aditya GargApr 25, 2025
  61. Aditya GargApr 25, 2025
  62. Erik HulsmannApr 25, 2025
  63. Aditya GargApr 24, 2025

Read the whole thread, see it on lore, or plain text.

$ cat FOOTERMessages come from the public archive at lore.kernel.org/git, fetched every hour. The front page is chosen and written each morning by an AI editor and can be wrong; the threads themselves are the record. About and API. For agents: an MCP server at https://gitlist.dev/mcp, and any thread, story or person page as Markdown by adding .md to its URL (or sending Accept: text/markdown). Details in /llms.txt.