> 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 Please add documentation to git-send-email.txt > 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@xxxxxxxxx > 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@xxxxxxxxxxx > 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@xxxxxxxxxxxxxxx> > --- > 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") { Be careful to check that $smtp_auth is initialized to avoid warnings: Use of uninitialized value $smtp_auth in string eq at /home/matt/libexec/git-core/git-send-email line 1493. Use of uninitialized value $smtp_auth in string eq at /home/matt/libexec/git-core/git-send-email line 1493. > + # 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 => {