* [PATCH] b4: allow using xoauth2/bearer token to authenticate to SMTP servers
@ 2026-03-06 16:20 Dmitry Torokhov
2026-03-06 17:18 ` Konstantin Ryabitsev
2026-03-13 2:05 ` Konstantin Ryabitsev
0 siblings, 2 replies; 11+ messages in thread
From: Dmitry Torokhov @ 2026-03-06 16:20 UTC (permalink / raw)
To: tools; +Cc: Dmitry Torokhov
Allow using XOAUTH2 as an authentication protocol and assume that when
XOAUTH2 is specified the password is actually a bearer token (typically
not stored in the config but rather returned via "git credentials".
Recognize "oauth", "oauth2" as aliases for "xoauth2".
Signed-off-by: Dmitry Torokhov <dmitry.torokhov@gmail.com>
---
src/b4/__init__.py | 10 +++++++---
1 file changed, 7 insertions(+), 3 deletions(-)
diff --git a/src/b4/__init__.py b/src/b4/__init__.py
index eab290b..9a5d25b 100644
--- a/src/b4/__init__.py
+++ b/src/b4/__init__.py
@@ -4312,8 +4312,8 @@ def get_smtp(dryrun: bool = False) -> Tuple[Union[smtplib.SMTP, smtplib.SMTP_SSL
# If we got to this point, we should do authentication,
# unless smtpauth is set to a special "none" value
- smtpauth = str(sconfig.get('smtpauth', ''))
- if smtpauth.lower() == 'none':
+ smtpauth = str(sconfig.get('smtpauth', '')).lower()
+ if smtpauth == 'none':
return smtp, fromaddr
auser = str(sconfig.get('smtpuser', ''))
@@ -4331,7 +4331,11 @@ def get_smtp(dryrun: bool = False) -> Tuple[Union[smtplib.SMTP, smtplib.SMTP_SSL
raise smtplib.SMTPException('No password specified for connecting to %s', server)
if auser and apass:
# Let any exceptions bubble up
- smtp.login(auser, apass)
+ if smtpauth in ('oauth', 'oauth2', 'xoauth2'):
+ auth_str = f'user={auser}\x01auth=Bearer {apass}\x01\x01'
+ smtp.auth('XOAUTH2', lambda: auth_str)
+ else:
+ smtp.login(auser, apass)
else:
# We assume you know what you're doing if you don't need encryption
smtp = smtplib.SMTP(server, port)
--
2.53.0.473.g4a7958ca14-goog
^ permalink raw reply related [flat|nested] 11+ messages in thread
* Re: [PATCH] b4: allow using xoauth2/bearer token to authenticate to SMTP servers
2026-03-06 16:20 [PATCH] b4: allow using xoauth2/bearer token to authenticate to SMTP servers Dmitry Torokhov
@ 2026-03-06 17:18 ` Konstantin Ryabitsev
2026-03-06 17:35 ` Dmitry Torokhov
2026-03-13 2:05 ` Konstantin Ryabitsev
1 sibling, 1 reply; 11+ messages in thread
From: Konstantin Ryabitsev @ 2026-03-06 17:18 UTC (permalink / raw)
To: tools; +Cc: Dmitry Torokhov, Tomas Melin
On Fri, 06 Mar 2026 08:20:18 -0800, Dmitry Torokhov <dmitry.torokhov@gmail.com> wrote:
> Allow using XOAUTH2 as an authentication protocol and assume that when
> XOAUTH2 is specified the password is actually a bearer token (typically
> not stored in the config but rather returned via "git credentials".
>
> Recognize "oauth", "oauth2" as aliases for "xoauth2".
Hmm... we do have another series already for XOAUTH2 support:
https://lore.kernel.org/tools/20260205-smtp-oauth2-outlook-v2-2-6a5eb233b285@vaisala.com/
However, it's outstanding with a few requests. I wonder if we can take
this one as a first patch and then build the other series on top of
this.
Cc'ing Tomas on this.
> diff --git a/src/b4/__init__.py b/src/b4/__init__.py
> index eab290b..9a5d25b 100644
> --- a/src/b4/__init__.py
> +++ b/src/b4/__init__.py
> @@ -4331,7 +4331,11 @@ def get_smtp(dryrun: bool = False) -> Tuple[Union[smtplib.SMTP, smtplib.SMTP_SSL
> raise smtplib.SMTPException('No password specified for connecting to %s', server)
> if auser and apass:
> # Let any exceptions bubble up
> - smtp.login(auser, apass)
> + if smtpauth in ('oauth', 'oauth2', 'xoauth2'):
> + auth_str = f'user={auser}\x01auth=Bearer {apass}\x01\x01'
> + smtp.auth('XOAUTH2', lambda: auth_str)
This is what the agent tells me about this, and it seems valid.
smtplib.SMTP.auth() calls authobject(challenge) with a positional
bytes argument when the server replies 334 (the XOAUTH2 error-detail
challenge). Because this lambda accepts no arguments, that call
raises TypeError, masking the real authentication error.
Suggest:
smtp.auth('XOAUTH2', lambda x=None: auth_str if x is None else '')
This way the initial response (no args) returns the auth string, and
a 334 challenge returns an empty string so the server sends its real
error code.
I'm happy to take this with this fix, but I'm also going to wait on
Tomas's thoughts.
Thanks!
--
KR
^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: [PATCH] b4: allow using xoauth2/bearer token to authenticate to SMTP servers
2026-03-06 17:18 ` Konstantin Ryabitsev
@ 2026-03-06 17:35 ` Dmitry Torokhov
2026-03-09 7:28 ` Tomas Melin
0 siblings, 1 reply; 11+ messages in thread
From: Dmitry Torokhov @ 2026-03-06 17:35 UTC (permalink / raw)
To: Konstantin Ryabitsev; +Cc: tools, Tomas Melin
On Fri, Mar 06, 2026 at 12:18:45PM -0500, Konstantin Ryabitsev wrote:
> On Fri, 06 Mar 2026 08:20:18 -0800, Dmitry Torokhov <dmitry.torokhov@gmail.com> wrote:
> > Allow using XOAUTH2 as an authentication protocol and assume that when
> > XOAUTH2 is specified the password is actually a bearer token (typically
> > not stored in the config but rather returned via "git credentials".
> >
> > Recognize "oauth", "oauth2" as aliases for "xoauth2".
>
> Hmm... we do have another series already for XOAUTH2 support:
> https://lore.kernel.org/tools/20260205-smtp-oauth2-outlook-v2-2-6a5eb233b285@vaisala.com/
>
> However, it's outstanding with a few requests. I wonder if we can take
> this one as a first patch and then build the other series on top of
> this.
>
> Cc'ing Tomas on this.
>
> > diff --git a/src/b4/__init__.py b/src/b4/__init__.py
> > index eab290b..9a5d25b 100644
> > --- a/src/b4/__init__.py
> > +++ b/src/b4/__init__.py
> > @@ -4331,7 +4331,11 @@ def get_smtp(dryrun: bool = False) -> Tuple[Union[smtplib.SMTP, smtplib.SMTP_SSL
> > raise smtplib.SMTPException('No password specified for connecting to %s', server)
> > if auser and apass:
> > # Let any exceptions bubble up
> > - smtp.login(auser, apass)
> > + if smtpauth in ('oauth', 'oauth2', 'xoauth2'):
> > + auth_str = f'user={auser}\x01auth=Bearer {apass}\x01\x01'
> > + smtp.auth('XOAUTH2', lambda: auth_str)
>
> This is what the agent tells me about this, and it seems valid.
>
> smtplib.SMTP.auth() calls authobject(challenge) with a positional
> bytes argument when the server replies 334 (the XOAUTH2 error-detail
> challenge). Because this lambda accepts no arguments, that call
> raises TypeError, masking the real authentication error.
Right, I guess because of implicit initial_response_ok argument to
smtp.auth() when I tested it the lambda was called without arguments and
the authentication went through (with gmail).
>
> Suggest:
> smtp.auth('XOAUTH2', lambda x=None: auth_str if x is None else '')
>
> This way the initial response (no args) returns the auth string, and
> a 334 challenge returns an empty string so the server sends its real
> error code.
>
> I'm happy to take this with this fix, but I'm also going to wait on
> Tomas's thoughts.
Totally fine with me.
Thanks.
--
Dmitry
^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: [PATCH] b4: allow using xoauth2/bearer token to authenticate to SMTP servers
2026-03-06 17:35 ` Dmitry Torokhov
@ 2026-03-09 7:28 ` Tomas Melin
2026-03-09 7:49 ` Dmitry Torokhov
0 siblings, 1 reply; 11+ messages in thread
From: Tomas Melin @ 2026-03-09 7:28 UTC (permalink / raw)
To: Dmitry Torokhov, Konstantin Ryabitsev; +Cc: tools
Hi,
On 06/03/2026 19:35, Dmitry Torokhov wrote:
> On Fri, Mar 06, 2026 at 12:18:45PM -0500, Konstantin Ryabitsev wrote:
>> On Fri, 06 Mar 2026 08:20:18 -0800, Dmitry Torokhov <dmitry.torokhov@gmail.com> wrote:
>>> Allow using XOAUTH2 as an authentication protocol and assume that when
>>> XOAUTH2 is specified the password is actually a bearer token (typically
>>> not stored in the config but rather returned via "git credentials".
>>>
>>> Recognize "oauth", "oauth2" as aliases for "xoauth2".
>> Hmm... we do have another series already for XOAUTH2 support:
>> https://lore.kernel.org/tools/20260205-smtp-oauth2-outlook-v2-2-6a5eb233b285@vaisala.com/
>>
>> However, it's outstanding with a few requests. I wonder if we can take
>> this one as a first patch and then build the other series on top of
>> this.
>>
>> Cc'ing Tomas on this.
Perhaps I'm missing something but this approach looks to me more like a
workaround. I'm not seeing how it handles the oauth2 lifecycle
expiration which is typically within hours. The other series handles
that with a helper that will update the token transparently as needed.
I will return shortly with updates to my original series.
Thanks,
Tomas
>>
>>> diff --git a/src/b4/__init__.py b/src/b4/__init__.py
>>> index eab290b..9a5d25b 100644
>>> --- a/src/b4/__init__.py
>>> +++ b/src/b4/__init__.py
>>> @@ -4331,7 +4331,11 @@ def get_smtp(dryrun: bool = False) -> Tuple[Union[smtplib.SMTP, smtplib.SMTP_SSL
>>> raise smtplib.SMTPException('No password specified for connecting to %s', server)
>>> if auser and apass:
>>> # Let any exceptions bubble up
>>> - smtp.login(auser, apass)
>>> + if smtpauth in ('oauth', 'oauth2', 'xoauth2'):
>>> + auth_str = f'user={auser}\x01auth=Bearer {apass}\x01\x01'
>>> + smtp.auth('XOAUTH2', lambda: auth_str)
>> This is what the agent tells me about this, and it seems valid.
>>
>> smtplib.SMTP.auth() calls authobject(challenge) with a positional
>> bytes argument when the server replies 334 (the XOAUTH2 error-detail
>> challenge). Because this lambda accepts no arguments, that call
>> raises TypeError, masking the real authentication error.
> Right, I guess because of implicit initial_response_ok argument to
> smtp.auth() when I tested it the lambda was called without arguments and
> the authentication went through (with gmail).
>
>> Suggest:
>> smtp.auth('XOAUTH2', lambda x=None: auth_str if x is None else '')
>>
>> This way the initial response (no args) returns the auth string, and
>> a 334 challenge returns an empty string so the server sends its real
>> error code.
>>
>> I'm happy to take this with this fix, but I'm also going to wait on
>> Tomas's thoughts.
> Totally fine with me.
>
> Thanks.
>
^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: [PATCH] b4: allow using xoauth2/bearer token to authenticate to SMTP servers
2026-03-09 7:28 ` Tomas Melin
@ 2026-03-09 7:49 ` Dmitry Torokhov
2026-03-09 9:50 ` Tomas Melin
0 siblings, 1 reply; 11+ messages in thread
From: Dmitry Torokhov @ 2026-03-09 7:49 UTC (permalink / raw)
To: Tomas Melin; +Cc: Konstantin Ryabitsev, tools
Hi Tomas,
On Mon, Mar 09, 2026 at 09:28:30AM +0200, Tomas Melin wrote:
> Hi,
>
> On 06/03/2026 19:35, Dmitry Torokhov wrote:
> > On Fri, Mar 06, 2026 at 12:18:45PM -0500, Konstantin Ryabitsev wrote:
> > > On Fri, 06 Mar 2026 08:20:18 -0800, Dmitry Torokhov <dmitry.torokhov@gmail.com> wrote:
> > > > Allow using XOAUTH2 as an authentication protocol and assume that when
> > > > XOAUTH2 is specified the password is actually a bearer token (typically
> > > > not stored in the config but rather returned via "git credentials".
> > > >
> > > > Recognize "oauth", "oauth2" as aliases for "xoauth2".
> > > Hmm... we do have another series already for XOAUTH2 support:
> > > https://lore.kernel.org/tools/20260205-smtp-oauth2-outlook-v2-2-6a5eb233b285@vaisala.com/
> > >
> > > However, it's outstanding with a few requests. I wonder if we can take
> > > this one as a first patch and then build the other series on top of
> > > this.
> > >
> > > Cc'ing Tomas on this.
>
> Perhaps I'm missing something but this approach looks to me more like a
> workaround. I'm not seeing how it handles the oauth2 lifecycle expiration
> which is typically within hours. The other series handles that with a helper
> that will update the token transparently as needed.
In my setup "git credential" returns bearer token that should last
enough for this b4 run. Next time b4 runs "git credential" will request
a new bearer token if previous one expired. It is not expected that the
token is stored in the configuration file. It looks like
git-credential-email behavior should also be compatible with this use.
However looking at your patch I do not understand why you want to parse
configuration and run the helpers directly instead of having "git
credential" return the data for you and rely on it to figure out what
helper to use and how. It gets protocol, username, and host and should
be able to figure out what should be returned. It is not b4's role to
interact directly with git helpers.
I also do not see any traces of handling lifetime expiration in your
patch either... Not that it is needed IMO.
Thanks.
--
Dmitry
^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: [PATCH] b4: allow using xoauth2/bearer token to authenticate to SMTP servers
2026-03-09 7:49 ` Dmitry Torokhov
@ 2026-03-09 9:50 ` Tomas Melin
2026-03-09 17:13 ` Dmitry Torokhov
0 siblings, 1 reply; 11+ messages in thread
From: Tomas Melin @ 2026-03-09 9:50 UTC (permalink / raw)
To: Dmitry Torokhov; +Cc: Konstantin Ryabitsev, tools
Hi,
On 09/03/2026 09:49, Dmitry Torokhov wrote:
> Hi Tomas,
>
> On Mon, Mar 09, 2026 at 09:28:30AM +0200, Tomas Melin wrote:
>> Hi,
>>
>> On 06/03/2026 19:35, Dmitry Torokhov wrote:
>>> On Fri, Mar 06, 2026 at 12:18:45PM -0500, Konstantin Ryabitsev wrote:
>>>> On Fri, 06 Mar 2026 08:20:18 -0800, Dmitry Torokhov <dmitry.torokhov@gmail.com> wrote:
>>>>> Allow using XOAUTH2 as an authentication protocol and assume that when
>>>>> XOAUTH2 is specified the password is actually a bearer token (typically
>>>>> not stored in the config but rather returned via "git credentials".
>>>>>
>>>>> Recognize "oauth", "oauth2" as aliases for "xoauth2".
>>>> Hmm... we do have another series already for XOAUTH2 support:
>>>> https://lore.kernel.org/tools/20260205-smtp-oauth2-outlook-v2-2-6a5eb233b285@vaisala.com/
>>>>
>>>> However, it's outstanding with a few requests. I wonder if we can take
>>>> this one as a first patch and then build the other series on top of
>>>> this.
>>>>
>>>> Cc'ing Tomas on this.
>> Perhaps I'm missing something but this approach looks to me more like a
>> workaround. I'm not seeing how it handles the oauth2 lifecycle expiration
>> which is typically within hours. The other series handles that with a helper
>> that will update the token transparently as needed.
> In my setup "git credential" returns bearer token that should last
> enough for this b4 run. Next time b4 runs "git credential" will request
> a new bearer token if previous one expired. It is not expected that the
> token is stored in the configuration file. It looks like
> git-credential-email behavior should also be compatible with this use.
In your case, how do you provide the new token to git credential?
How does you .gitconfig for this look like?
> However looking at your patch I do not understand why you want to parse
> configuration and run the helpers directly instead of having "git
> credential" return the data for you and rely on it to figure out what
> helper to use and how. It gets protocol, username, and host and should
> be able to figure out what should be returned. It is not b4's role to
> interact directly with git helpers.
git-send-email also requires similar integration with external helpers
https://git-scm.com/docs/git-send-email#_sending_patches
thanks,
Tomas
>
> I also do not see any traces of handling lifetime expiration in your
> patch either... Not that it is needed IMO.
>
> Thanks.
>
^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: [PATCH] b4: allow using xoauth2/bearer token to authenticate to SMTP servers
2026-03-09 9:50 ` Tomas Melin
@ 2026-03-09 17:13 ` Dmitry Torokhov
2026-03-10 6:48 ` Tomas Melin
0 siblings, 1 reply; 11+ messages in thread
From: Dmitry Torokhov @ 2026-03-09 17:13 UTC (permalink / raw)
To: Tomas Melin; +Cc: Konstantin Ryabitsev, tools
On Mon, Mar 09, 2026 at 11:50:40AM +0200, Tomas Melin wrote:
> Hi,
>
> On 09/03/2026 09:49, Dmitry Torokhov wrote:
> > Hi Tomas,
> >
> > On Mon, Mar 09, 2026 at 09:28:30AM +0200, Tomas Melin wrote:
> > > Hi,
> > >
> > > On 06/03/2026 19:35, Dmitry Torokhov wrote:
> > > > On Fri, Mar 06, 2026 at 12:18:45PM -0500, Konstantin Ryabitsev wrote:
> > > > > On Fri, 06 Mar 2026 08:20:18 -0800, Dmitry Torokhov <dmitry.torokhov@gmail.com> wrote:
> > > > > > Allow using XOAUTH2 as an authentication protocol and assume that when
> > > > > > XOAUTH2 is specified the password is actually a bearer token (typically
> > > > > > not stored in the config but rather returned via "git credentials".
> > > > > >
> > > > > > Recognize "oauth", "oauth2" as aliases for "xoauth2".
> > > > > Hmm... we do have another series already for XOAUTH2 support:
> > > > > https://lore.kernel.org/tools/20260205-smtp-oauth2-outlook-v2-2-6a5eb233b285@vaisala.com/
> > > > >
> > > > > However, it's outstanding with a few requests. I wonder if we can take
> > > > > this one as a first patch and then build the other series on top of
> > > > > this.
> > > > >
> > > > > Cc'ing Tomas on this.
> > > Perhaps I'm missing something but this approach looks to me more like a
> > > workaround. I'm not seeing how it handles the oauth2 lifecycle expiration
> > > which is typically within hours. The other series handles that with a helper
> > > that will update the token transparently as needed.
> > In my setup "git credential" returns bearer token that should last
> > enough for this b4 run. Next time b4 runs "git credential" will request
> > a new bearer token if previous one expired. It is not expected that the
> > token is stored in the configuration file. It looks like
> > git-credential-email behavior should also be compatible with this use.
>
> In your case, how do you provide the new token to git credential?
git credential itself calls into configured helpers and the helper does
this. You do not need to replicate this logic in other places.
>
> How does you .gitconfig for this look like?
global sendemail.smtpserver smtp.gmail.com
global sendemail.smtpserverport 587
global sendemail.smtpencryption tls
global sendemail.smtpuser dmitry.torokhov@gmail.com
global sendemail.thread true
global sendemail.bcc dmitry.torokhov@gmail.com
global sendemail.suppresscc self
global credential.helper cache --timeout=3000
global credential.helper local-helper
local sendemail.smtpuser dmitry.torokhov@gmail.com
local sendemail.smtpauth XOAUTH2
local sendemail.bcc dmitry.torokhov@gmail.com
The local-helper is a custom python script that behaves similarly to the
gmail credential helper, but the difference that it supports different
credential stores - either based on secret storage API or GPG-based so I
can move my configuration between a headless workstation, a VM, or my
laptop easily.
The beauty of credential helpers is that if they do not know how to
handle the request they simply skip it so that the next one might be
able to resolve it.
>
> > However looking at your patch I do not understand why you want to parse
> > configuration and run the helpers directly instead of having "git
> > credential" return the data for you and rely on it to figure out what
> > helper to use and how. It gets protocol, username, and host and should
> > be able to figure out what should be returned. It is not b4's role to
> > interact directly with git helpers.
>
> git-send-email also requires similar integration with external helpers
> https://git-scm.com/docs/git-send-email#_sending_patches
No, it says that git-send-email makes use of "git credential", it does
not say that it calls out directly to any helpers. In fact, this is
git-send-email code:
$auth = Git::credential({
'protocol' => 'smtp',
'host' => smtp_host_string(),
'username' => $smtp_authuser,
# if there's no password, "git credential fill" will
# give us one, otherwise it'll just pass this one.
'password' => $smtp_authpass
}, sub {
my $cred = shift;
my $result;
my $error;
# catch all SMTP auth error in a unified eval block
eval {
if ($smtp_auth) {
my $sasl = Authen::SASL->new(
mechanism => $smtp_auth,
callback => {
user => $cred->{'username'},
pass => $cred->{'password'},
authname => $cred->{'username'},
}
);
$result = $smtp->auth($sasl);
} else {
$result = $smtp->auth($cred->{'username'}, $cred->{'password'});
}
1; # ensure true value is returned if no exception is thrown
} or do {
$error = $@ || 'Unknown error';
};
return ($error
? handle_smtp_error($error)
: ($result ? 1 : 0));
});
As you can see it does exactly what my patch does: it calls to "git
credential" and expects something resolving a secret (password) in
return. Then XOAUTH2.pm SASL module takes that secret and produces
that "user=$username\001auth=Bearer $token\001\001" string that is
needed to authenticate.
BTW, I am not sure why you are using smtp.docmd() and not smtp.auth()...
Thanks.
--
Dmitry
^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: [PATCH] b4: allow using xoauth2/bearer token to authenticate to SMTP servers
2026-03-09 17:13 ` Dmitry Torokhov
@ 2026-03-10 6:48 ` Tomas Melin
2026-03-10 7:10 ` Dmitry Torokhov
2026-03-11 15:41 ` Konstantin Ryabitsev
0 siblings, 2 replies; 11+ messages in thread
From: Tomas Melin @ 2026-03-10 6:48 UTC (permalink / raw)
To: Dmitry Torokhov; +Cc: Konstantin Ryabitsev, tools
Hi,
On 09/03/2026 19:13, Dmitry Torokhov wrote:
> On Mon, Mar 09, 2026 at 11:50:40AM +0200, Tomas Melin wrote:
>> Hi,
>>
>> On 09/03/2026 09:49, Dmitry Torokhov wrote:
>>>
>> In your case, how do you provide the new token to git credential?
> git credential itself calls into configured helpers and the helper does
> this. You do not need to replicate this logic in other places.
>
>> How does you .gitconfig for this look like?
> global sendemail.smtpserver smtp.gmail.com
> global sendemail.smtpserverport 587
> global sendemail.smtpencryption tls
> global sendemail.smtpuser dmitry.torokhov@gmail.com
> global sendemail.thread true
> global sendemail.bcc dmitry.torokhov@gmail.com
> global sendemail.suppresscc self
> global credential.helper cache --timeout=3000
> global credential.helper local-helper
> local sendemail.smtpuser dmitry.torokhov@gmail.com
> local sendemail.smtpauth XOAUTH2
> local sendemail.bcc dmitry.torokhov@gmail.com
>
> The local-helper is a custom python script that behaves similarly to the
> gmail credential helper, but the difference that it supports different
> credential stores - either based on secret storage API or GPG-based so I
> can move my configuration between a headless workstation, a VM, or my
> laptop easily.
>
> The beauty of credential helpers is that if they do not know how to
> handle the request they simply skip it so that the next one might be
> able to resolve it.
Yes, indeed then this looks like a cleaner solution to the
authentication process and
the approach proposed in your patch should be taken instead of my
initial attempt.
FWIW I tested this out, but for some reason I was occasionally not
getting the
token back, instead it falls back to password authentication prompt
(which then fails).
Thanks,
Tomas
>
>>> However looking at your patch I do not understand why you want to parse
>>> configuration and run the helpers directly instead of having "git
>>> credential" return the data for you and rely on it to figure out what
>>> helper to use and how. It gets protocol, username, and host and should
>>> be able to figure out what should be returned. It is not b4's role to
>>> interact directly with git helpers.
>> git-send-email also requires similar integration with external helpers
>> https://git-scm.com/docs/git-send-email#_sending_patches
> No, it says that git-send-email makes use of "git credential", it does
> not say that it calls out directly to any helpers. In fact, this is
> git-send-email code:
>
> $auth = Git::credential({
> 'protocol' => 'smtp',
> 'host' => smtp_host_string(),
> 'username' => $smtp_authuser,
> # if there's no password, "git credential fill" will
> # give us one, otherwise it'll just pass this one.
> 'password' => $smtp_authpass
> }, sub {
> my $cred = shift;
> my $result;
> my $error;
>
> # catch all SMTP auth error in a unified eval block
> eval {
> if ($smtp_auth) {
> my $sasl = Authen::SASL->new(
> mechanism => $smtp_auth,
> callback => {
> user => $cred->{'username'},
> pass => $cred->{'password'},
> authname => $cred->{'username'},
> }
> );
> $result = $smtp->auth($sasl);
> } else {
> $result = $smtp->auth($cred->{'username'}, $cred->{'password'});
> }
> 1; # ensure true value is returned if no exception is thrown
> } or do {
> $error = $@ || 'Unknown error';
> };
>
> return ($error
> ? handle_smtp_error($error)
> : ($result ? 1 : 0));
> });
>
> As you can see it does exactly what my patch does: it calls to "git
> credential" and expects something resolving a secret (password) in
> return. Then XOAUTH2.pm SASL module takes that secret and produces
> that "user=$username\001auth=Bearer $token\001\001" string that is
> needed to authenticate.
>
> BTW, I am not sure why you are using smtp.docmd() and not smtp.auth()...
>
> Thanks.
>
^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: [PATCH] b4: allow using xoauth2/bearer token to authenticate to SMTP servers
2026-03-10 6:48 ` Tomas Melin
@ 2026-03-10 7:10 ` Dmitry Torokhov
2026-03-11 15:41 ` Konstantin Ryabitsev
1 sibling, 0 replies; 11+ messages in thread
From: Dmitry Torokhov @ 2026-03-10 7:10 UTC (permalink / raw)
To: Tomas Melin; +Cc: Konstantin Ryabitsev, tools
Hi Tomas,
On Tue, Mar 10, 2026 at 08:48:55AM +0200, Tomas Melin wrote:
> Hi,
>
> On 09/03/2026 19:13, Dmitry Torokhov wrote:
> > On Mon, Mar 09, 2026 at 11:50:40AM +0200, Tomas Melin wrote:
> > > Hi,
> > >
> > > On 09/03/2026 09:49, Dmitry Torokhov wrote:
> > > >
> > > In your case, how do you provide the new token to git credential?
> > git credential itself calls into configured helpers and the helper does
> > this. You do not need to replicate this logic in other places.
> >
> > > How does you .gitconfig for this look like?
> > global sendemail.smtpserver smtp.gmail.com
> > global sendemail.smtpserverport 587
> > global sendemail.smtpencryption tls
> > global sendemail.smtpuser dmitry.torokhov@gmail.com
> > global sendemail.thread true
> > global sendemail.bcc dmitry.torokhov@gmail.com
> > global sendemail.suppresscc self
> > global credential.helper cache --timeout=3000
> > global credential.helper local-helper
> > local sendemail.smtpuser dmitry.torokhov@gmail.com
> > local sendemail.smtpauth XOAUTH2
> > local sendemail.bcc dmitry.torokhov@gmail.com
> >
> > The local-helper is a custom python script that behaves similarly to the
> > gmail credential helper, but the difference that it supports different
> > credential stores - either based on secret storage API or GPG-based so I
> > can move my configuration between a headless workstation, a VM, or my
> > laptop easily.
> >
> > The beauty of credential helpers is that if they do not know how to
> > handle the request they simply skip it so that the next one might be
> > able to resolve it.
>
> Yes, indeed then this looks like a cleaner solution to the authentication
> process and
>
> the approach proposed in your patch should be taken instead of my initial
> attempt.
>
> FWIW I tested this out, but for some reason I was occasionally not getting
> the
>
> token back, instead it falls back to password authentication prompt (which
> then fails).
Hmm, this is weird. I've had the setup with the "git credential", my
credential helper, and "git send-email" for the last few years and I did
not observe this issue... Maybe one of the helpers is flaky? You can
call "git credential" from a script like this to test:
#!/bin/bash
#
git credential fill << ENDOFDATA | sed -n 's/^password=\(.*\)/\1/ p'
protocol=smtp
host=gmail.com
username=${1}
ENDOFDATA
to see how reliable it is. Obviously adjust host and other details as
needed.
Thanks.
--
Dmitry
^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: [PATCH] b4: allow using xoauth2/bearer token to authenticate to SMTP servers
2026-03-10 6:48 ` Tomas Melin
2026-03-10 7:10 ` Dmitry Torokhov
@ 2026-03-11 15:41 ` Konstantin Ryabitsev
1 sibling, 0 replies; 11+ messages in thread
From: Konstantin Ryabitsev @ 2026-03-11 15:41 UTC (permalink / raw)
To: Tomas Melin; +Cc: Dmitry Torokhov, Konstantin Ryabitsev, tools
On 2026-03-10 08:48 +0200, Tomas Melin wrote:
> > The beauty of credential helpers is that if they do not know how to
> > handle the request they simply skip it so that the next one might be
> > able to resolve it.
>
> Yes, indeed then this looks like a cleaner solution to the
> authentication process and the approach proposed in your patch should
> be taken instead of my initial attempt.
OK, I will take Dmitry's patch, then. Thanks!
-K
^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: [PATCH] b4: allow using xoauth2/bearer token to authenticate to SMTP servers
2026-03-06 16:20 [PATCH] b4: allow using xoauth2/bearer token to authenticate to SMTP servers Dmitry Torokhov
2026-03-06 17:18 ` Konstantin Ryabitsev
@ 2026-03-13 2:05 ` Konstantin Ryabitsev
1 sibling, 0 replies; 11+ messages in thread
From: Konstantin Ryabitsev @ 2026-03-13 2:05 UTC (permalink / raw)
To: tools, Dmitry Torokhov
On Fri, 06 Mar 2026 08:20:18 -0800, Dmitry Torokhov wrote:
> b4: allow using xoauth2/bearer token to authenticate to SMTP servers
Applied, thanks!
[1/1] b4: allow using xoauth2/bearer token to authenticate to SMTP servers
https://git.kernel.org/pub/scm/utils/b4/b4.git/commit/?id=7ccea87a5f68
Note: I will fix the small issue I've identified earlier in a fixup commit.
Best regards,
--
KR
^ permalink raw reply [flat|nested] 11+ messages in thread
end of thread, other threads:[~2026-03-13 3:12 UTC | newest]
Thread overview: 11+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-03-06 16:20 [PATCH] b4: allow using xoauth2/bearer token to authenticate to SMTP servers Dmitry Torokhov
2026-03-06 17:18 ` Konstantin Ryabitsev
2026-03-06 17:35 ` Dmitry Torokhov
2026-03-09 7:28 ` Tomas Melin
2026-03-09 7:49 ` Dmitry Torokhov
2026-03-09 9:50 ` Tomas Melin
2026-03-09 17:13 ` Dmitry Torokhov
2026-03-10 6:48 ` Tomas Melin
2026-03-10 7:10 ` Dmitry Torokhov
2026-03-11 15:41 ` Konstantin Ryabitsev
2026-03-13 2:05 ` Konstantin Ryabitsev
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox