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

Re: [PATCH] send-email: implement SMTP bearer authentication

From
SQShengyu Qu <wiagn233@outlook.com>
Date
Oct 11, 2024, 17:48 UTC
Message-ID
<TYCPR01MB843751F88AF98DFDB606B0BE98792@TYCPR01MB8437.jpnprd01.prod.outlook.com>
In-Reply-To
<20240225103413.9845-1-julian@swagemakers.org>
Hello,

Sorry to bother but what had happened to this patch? It is more useful now since outlook also switched to oauth2 only mode.

Best regards, Shengyu

在 2024/2/25 18:34, Julian Swagemakers 写道:
Show 125 quoted lines
> 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
>
> Signed-off-by: Julian Swagemakers <julian@swagemakers.org>
> ---
>   git-send-email.perl | 65 +++++++++++++++++++++++++++++++++++++++++++--
>   1 file changed, 63 insertions(+), 2 deletions(-)
>
> diff --git a/git-send-email.perl b/git-send-email.perl
> index 821b2b3a13..72d378f6fd 100755
> --- a/git-send-email.perl
> +++ b/git-send-email.perl
> @@ -1359,6 +1359,63 @@ 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 will
> +		# be enforced at this point.
> +		#
> +		# https://datatracker.ietf.org/doc/html/rfc7628#section-3
> +		die __("For $smtp_auth TLS is required.")
> +	}
> +	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;
> +	}
> +}
> +
>   # Returns 1 if authentication succeeded or was not necessary
>   # (smtp_user was not specified), and 0 otherwise.
>   
> @@ -1392,8 +1449,12 @@ sub smtp_auth_maybe {
>   		'password' => $smtp_authpass
>   	}, sub {
>   		my $cred = shift;
> -
> -		if ($smtp_auth) {
> +		if ($smtp_auth eq "OAUTHBEARER" or $smtp_auth eq "XOAUTH2") {
> +			# Since Authen:SASL does not support XOAUTH2 nor OAUTHBEARER we will
> +			# manuall authenticate for tese types. The password field should
> +			# contain the auth token at this point.
> +			return smtp_bearer_auth($cred->{'username'}, $cred->{'password'});
> +		} elsif ($smtp_auth) {
>   			my $sasl = Authen::SASL->new(
>   				mechanism => $smtp_auth,
>   				callback => {
Previous: M HickfordNext: Junio C Hamano
Message 3 of 7 in “send-email: implement SMTP bearer authentication”
  1. send-email: implement SMTP bearer authenticationJulian Swagemakers, Feb 25, 2024
  2. M HickfordFeb 28, 2024
  3. Shengyu QuOct 11, 2024
  4. Junio C HamanoOct 11, 2024
  5. Shengyu QuOct 11, 2024
  6. Julian SwagemakersOct 12, 2024
  7. send-email: implement SMTP bearer authenticationJulian Swagemakers, Jan 25, 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.