* [PATCH b4 0/2] Add support for oauth2 SMTP authentication
@ 2026-01-29 9:10 Tomas Melin
2026-01-29 9:10 ` [PATCH b4 1/2] ez: add SMTP authentication method to printed information Tomas Melin
` (2 more replies)
0 siblings, 3 replies; 13+ messages in thread
From: Tomas Melin @ 2026-01-29 9:10 UTC (permalink / raw)
To: Kernel.org Tools; +Cc: Konstantin Ryabitsev, Tomas Melin
Add support for oauth2 authentication with SMTP server, integrating
with git credential helpers for retrieving tokens. With this approach,
the same configuration as is needed for git send-email can be used
to send patches using oauth2 with b4.
Signed-off-by: Tomas Melin <tomas.melin@vaisala.com>
---
Tomas Melin (2):
ez: add SMTP authentication method to printed information
b4: add support for oauth2 SMTP authentication
src/b4/__init__.py | 25 +++++++++++++++++++++++++
src/b4/ez.py | 2 +-
2 files changed, 26 insertions(+), 1 deletion(-)
---
base-commit: 477734000555ffc24bf873952e40367deee26f17
change-id: 20260123-smtp-oauth2-outlook-f09d40b65f18
Best regards,
--
Tomas Melin <tomas.melin@vaisala.com>
^ permalink raw reply [flat|nested] 13+ messages in thread* [PATCH b4 1/2] ez: add SMTP authentication method to printed information 2026-01-29 9:10 [PATCH b4 0/2] Add support for oauth2 SMTP authentication Tomas Melin @ 2026-01-29 9:10 ` Tomas Melin 2026-02-01 5:37 ` Konstantin Ryabitsev 2026-01-29 9:10 ` [PATCH b4 2/2] b4: add support for oauth2 SMTP authentication Tomas Melin 2026-02-01 5:37 ` [PATCH b4 0/2] Add " Konstantin Ryabitsev 2 siblings, 1 reply; 13+ messages in thread From: Tomas Melin @ 2026-01-29 9:10 UTC (permalink / raw) To: Kernel.org Tools; +Cc: Konstantin Ryabitsev, Tomas Melin In many situations it is valuable information what authentication method is being attempted when autenticating with SMTP server. Signed-off-by: Tomas Melin <tomas.melin@vaisala.com> --- src/b4/ez.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/b4/ez.py b/src/b4/ez.py index 298e382227eb..581d51357de1 100644 --- a/src/b4/ez.py +++ b/src/b4/ez.py @@ -2193,7 +2193,7 @@ def cmd_send(cmdargs: argparse.Namespace) -> None: sys.exit(1) else: - logger.info(' - via SMTP server %s', smtpserver) + logger.info(' - via SMTP server %s using %s auth', smtpserver, sconfig.get('smtpauth', 'basic')) if not (cmdargs.reflect or cmdargs.resend or cmdargs.preview_to): logger.info(' - tag and reroll the series to the next revision') -- 2.52.0 ^ permalink raw reply related [flat|nested] 13+ messages in thread
* Re: [PATCH b4 1/2] ez: add SMTP authentication method to printed information 2026-01-29 9:10 ` [PATCH b4 1/2] ez: add SMTP authentication method to printed information Tomas Melin @ 2026-02-01 5:37 ` Konstantin Ryabitsev 2026-02-02 14:31 ` Tomas Melin 0 siblings, 1 reply; 13+ messages in thread From: Konstantin Ryabitsev @ 2026-02-01 5:37 UTC (permalink / raw) To: Kernel.org Tools; +Cc: Konstantin Ryabitsev, Tomas Melin On Thu, 29 Jan 2026 11:10:29 +0200, Tomas Melin <tomas.melin@vaisala.com> wrote: > diff --git a/src/b4/ez.py b/src/b4/ez.py > index 298e382..581d513 100644 > --- a/src/b4/ez.py > +++ b/src/b4/ez.py > @@ -2193,7 +2193,7 @@ def cmd_send(cmdargs: argparse.Namespace) -> None: > sys.exit(1) > > else: > - logger.info(' - via SMTP server %s', smtpserver) > + logger.info(' - via SMTP server %s using %s auth', smtpserver, sconfig.get('smtpauth', 'basic')) > This is a nit, but the default value 'basic' is displayed when smtpauth is not configured, but the actual auth mechanism used by get_smtp() is login-based (smtp.login()), not "basic". Consider 'login' as a more accurate default label, or only display the auth method when smtpauth is explicitly set. > if not (cmdargs.reflect or cmdargs.resend or cmdargs.preview_to): > logger.info(' - tag and reroll the series to the next revision') -- Konstantin Ryabitsev <konstantin@linuxfoundation.org> ^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [PATCH b4 1/2] ez: add SMTP authentication method to printed information 2026-02-01 5:37 ` Konstantin Ryabitsev @ 2026-02-02 14:31 ` Tomas Melin 0 siblings, 0 replies; 13+ messages in thread From: Tomas Melin @ 2026-02-02 14:31 UTC (permalink / raw) To: Konstantin Ryabitsev, Kernel.org Tools Hi, On 01/02/2026 07:37, Konstantin Ryabitsev wrote: > On Thu, 29 Jan 2026 11:10:29 +0200, Tomas Melin <tomas.melin@vaisala.com> wrote: >> diff --git a/src/b4/ez.py b/src/b4/ez.py >> index 298e382..581d513 100644 >> --- a/src/b4/ez.py >> +++ b/src/b4/ez.py >> @@ -2193,7 +2193,7 @@ def cmd_send(cmdargs: argparse.Namespace) -> None: >> sys.exit(1) >> >> else: >> - logger.info(' - via SMTP server %s', smtpserver) >> + logger.info(' - via SMTP server %s using %s auth', smtpserver, sconfig.get('smtpauth', 'basic')) >> > > This is a nit, but the default value 'basic' is displayed when smtpauth is not > configured, but the actual auth mechanism used by get_smtp() is login-based > (smtp.login()), not "basic". Consider 'login' as a more accurate default label, > or only display the auth method when smtpauth is explicitly set. AFAIS, login() and basic auth are in this context the same. Basic in contrast to oauth2. But, indeed to avoid any confusion, it can be best to print the auth value only when smtpauth has been set. Thanks, Tomas > >> if not (cmdargs.reflect or cmdargs.resend or cmdargs.preview_to): >> logger.info(' - tag and reroll the series to the next revision') > ^ permalink raw reply [flat|nested] 13+ messages in thread
* [PATCH b4 2/2] b4: add support for oauth2 SMTP authentication 2026-01-29 9:10 [PATCH b4 0/2] Add support for oauth2 SMTP authentication Tomas Melin 2026-01-29 9:10 ` [PATCH b4 1/2] ez: add SMTP authentication method to printed information Tomas Melin @ 2026-01-29 9:10 ` Tomas Melin 2026-01-30 12:09 ` Tomas Melin 2026-02-01 5:37 ` Konstantin Ryabitsev 2026-02-01 5:37 ` [PATCH b4 0/2] Add " Konstantin Ryabitsev 2 siblings, 2 replies; 13+ messages in thread From: Tomas Melin @ 2026-01-29 9:10 UTC (permalink / raw) To: Kernel.org Tools; +Cc: Konstantin Ryabitsev, Tomas Melin Add support for oauth2 authentication with SMTP server. This will transparently call a configured git credential-helper for retrieving the required token. The helper needs to be configured in advance and will pass the token from the keyring or other backing store. Functionality was tested using git-credential-email [1] and in particular the git credential-outlook helper. It works seamlessly with mentioned helper but other oauth2 compatible tools are also expected to work, possibly with some needs for tweaking. Helpers listed in [2] are expected to be compatible. To take this feature into use (replace outlook with the helper required) 1) authenticate once $git-credential-outlook --authenticate 2) configure .gitconfig [sendemail] smtpauth = XOAUTH2 ... [credential "smtp://smtp.office365.com:587"] helper = outlook [1] https://github.com/AdityaGarg8/git-credential-email [2] https://git-scm.com/docs/git-send-email Signed-off-by: Tomas Melin <tomas.melin@vaisala.com> --- src/b4/__init__.py | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/src/b4/__init__.py b/src/b4/__init__.py index 3d774f70c026..0adf5ca4e435 100644 --- a/src/b4/__init__.py +++ b/src/b4/__init__.py @@ -30,6 +30,7 @@ import shutil import mailbox import pwd import io +import base64 import requests @@ -2922,6 +2923,16 @@ def git_credential_fill(gitdir: Optional[str], protocol: str, host: str, usernam return None +def git_credential_helper(name: str) -> str: + if not name: + raise ValueError("credential helper name cannot be empty") + name = 'credential-' + name + ecode, out = git_run_command(None, args=[name]) + if ecode == 0: + return out.strip() + return '' + + def git_get_command_lines(gitdir: Optional[str], args: List[str]) -> List[str]: ecode, out = git_run_command(gitdir, args) lines = list() @@ -4050,6 +4061,15 @@ def get_sendemail_config() -> Dict[str, Optional[Union[str, List[str]]]]: return SENDEMAIL_CONFIG +def get_oauth2_token(server: str, smtpuser: str) -> str: + creds = get_config_from_git(rf'credential.*{server}*') + access_token = git_credential_helper(creds.get('helper', '')) + if not access_token: + raise smtplib.SMTPException(f'Unable to get access token from git credential helper for server {server}') + auth_string = f'user={smtpuser}\x01auth=Bearer {access_token}\x01\x01' + return base64.b64encode(auth_string.encode()).decode() + + def get_smtp(dryrun: bool = False) -> Tuple[Union[smtplib.SMTP, smtplib.SMTP_SSL, List[str], None], str]: sconfig = get_sendemail_config() # Limited support for smtp settings to begin with, but should cover the vast majority of cases @@ -4118,6 +4138,11 @@ def get_smtp(dryrun: bool = False) -> Tuple[Union[smtplib.SMTP, smtplib.SMTP_SSL if smtpauth.lower() == 'none': return smtp, fromaddr + if (sconfig.get('smtpauth').lower() == 'xoauth2'): + logger.debug('Authenticating to SMTP server using oauth2') + auth_b64 = get_oauth2_token(server, sconfig.get('smtpuser')) + smtp.docmd('AUTH', 'XOAUTH2 ' + auth_b64) + auser = str(sconfig.get('smtpuser', '')) apass = str(sconfig.get('smtppass', '')) if auser and not apass: -- 2.52.0 ^ permalink raw reply related [flat|nested] 13+ messages in thread
* Re: [PATCH b4 2/2] b4: add support for oauth2 SMTP authentication 2026-01-29 9:10 ` [PATCH b4 2/2] b4: add support for oauth2 SMTP authentication Tomas Melin @ 2026-01-30 12:09 ` Tomas Melin 2026-02-01 5:37 ` Konstantin Ryabitsev 1 sibling, 0 replies; 13+ messages in thread From: Tomas Melin @ 2026-01-30 12:09 UTC (permalink / raw) To: Kernel.org Tools; +Cc: Konstantin Ryabitsev Hi, On 29/01/2026 11:10, Tomas Melin wrote: > > diff --git a/src/b4/__init__.py b/src/b4/__init__.py > index 3d774f70c026..0adf5ca4e435 100644 > --- a/src/b4/__init__.py > +++ b/src/b4/__init__.py > @@ -30,6 +30,7 @@ import shutil > import mailbox > import pwd > import io > +import base64 > > import requests > > @@ -2922,6 +2923,16 @@ def git_credential_fill(gitdir: Optional[str], protocol: str, host: str, usernam > return None > > > +def git_credential_helper(name: str) -> str: > + if not name: > + raise ValueError("credential helper name cannot be empty") > + name = 'credential-' + name > + ecode, out = git_run_command(None, args=[name]) > + if ecode == 0: > + return out.strip() > + return '' For V2 I will expand this function to work for general case with custom command syntax, as is the case with git credentials. (https://git-scm.com/docs/gitcredentials) Before preparing V2 I would also appreciate any other feedback. Thanks, Tomas > + > + > def git_get_command_lines(gitdir: Optional[str], args: List[str]) -> List[str]: > ecode, out = git_run_command(gitdir, args) > lines = list() > @@ -4050,6 +4061,15 @@ def get_sendemail_config() -> Dict[str, Optional[Union[str, List[str]]]]: > return SENDEMAIL_CONFIG > > > +def get_oauth2_token(server: str, smtpuser: str) -> str: > + creds = get_config_from_git(rf'credential.*{server}*') > + access_token = git_credential_helper(creds.get('helper', '')) > + if not access_token: > + raise smtplib.SMTPException(f'Unable to get access token from git credential helper for server {server}') > + auth_string = f'user={smtpuser}\x01auth=Bearer {access_token}\x01\x01' > + return base64.b64encode(auth_string.encode()).decode() > + > + > def get_smtp(dryrun: bool = False) -> Tuple[Union[smtplib.SMTP, smtplib.SMTP_SSL, List[str], None], str]: > sconfig = get_sendemail_config() > # Limited support for smtp settings to begin with, but should cover the vast majority of cases > @@ -4118,6 +4138,11 @@ def get_smtp(dryrun: bool = False) -> Tuple[Union[smtplib.SMTP, smtplib.SMTP_SSL > if smtpauth.lower() == 'none': > return smtp, fromaddr > > + if (sconfig.get('smtpauth').lower() == 'xoauth2'): > + logger.debug('Authenticating to SMTP server using oauth2') > + auth_b64 = get_oauth2_token(server, sconfig.get('smtpuser')) > + smtp.docmd('AUTH', 'XOAUTH2 ' + auth_b64) > + > auser = str(sconfig.get('smtpuser', '')) > apass = str(sconfig.get('smtppass', '')) > if auser and not apass: > ^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [PATCH b4 2/2] b4: add support for oauth2 SMTP authentication 2026-01-29 9:10 ` [PATCH b4 2/2] b4: add support for oauth2 SMTP authentication Tomas Melin 2026-01-30 12:09 ` Tomas Melin @ 2026-02-01 5:37 ` Konstantin Ryabitsev 2026-02-02 14:08 ` Tomas Melin 2026-02-02 16:49 ` Tomas Melin 1 sibling, 2 replies; 13+ messages in thread From: Konstantin Ryabitsev @ 2026-02-01 5:37 UTC (permalink / raw) To: Kernel.org Tools; +Cc: Konstantin Ryabitsev, Tomas Melin On Thu, 29 Jan 2026 11:10:30 +0200, Tomas Melin <tomas.melin@vaisala.com> wrote: > diff --git a/src/b4/__init__.py b/src/b4/__init__.py > index 3d774f7..0adf5ca 100644 > --- a/src/b4/__init__.py > +++ b/src/b4/__init__.py > @@ -2922,6 +2923,16 @@ def git_credential_fill(gitdir: Optional[str], protocol: str, host: str, usernam > return None > > > +def git_credential_helper(name: str) -> str: > + if not name: > + raise ValueError("credential helper name cannot be empty") > + name = 'credential-' + name > + ecode, out = git_run_command(None, args=[name]) > + if ecode == 0: Any reason we're not making use of git_credential_fill() here? I'm not sure we can expect correct return here, because credential helpers expect input on stdin like: protocol=smtp host=<server> username=<user> The existing git_credential_fill() function should already handle this correctly, unless I'm mistaken or you have other reasons not to use it. > + return out.strip() > + return '' > + > + > def git_get_command_lines(gitdir: Optional[str], args: List[str]) -> List[str]: > ecode, out = git_run_command(gitdir, args) > lines = list() > @@ -4050,6 +4061,15 @@ def get_sendemail_config() -> Dict[str, Optional[Union[str, List[str]]]]: > return SENDEMAIL_CONFIG > > > +def get_oauth2_token(server: str, smtpuser: str) -> str: > + creds = get_config_from_git(rf'credential.*{server}*') > + access_token = git_credential_helper(creds.get('helper', '')) The regex does not look correct here. You probably want to do: rf'credential\.{re.escape(server)}\.*' or something like that. > + if not access_token: > + raise smtplib.SMTPException(f'Unable to get access token from git credential helper for server {server}') > + auth_string = f'user={smtpuser}\x01auth=Bearer {access_token}\x01\x01' > + return base64.b64encode(auth_string.encode()).decode() > + > + > def get_smtp(dryrun: bool = False) -> Tuple[Union[smtplib.SMTP, smtplib.SMTP_SSL, List[str], None], str]: > sconfig = get_sendemail_config() > # Limited support for smtp settings to begin with, but should cover the vast majority of cases > @@ -4118,6 +4138,11 @@ def get_smtp(dryrun: bool = False) -> Tuple[Union[smtplib.SMTP, smtplib.SMTP_SSL > if smtpauth.lower() == 'none': > return smtp, fromaddr > > + if (sconfig.get('smtpauth').lower() == 'xoauth2'): > + logger.debug('Authenticating to SMTP server using oauth2') Two issues here: 1. sconfig.get('smtpauth') has no default value. If smtpauth is not set in the config, this returns None and .lower() raises AttributeError. Two lines above, the same key is fetched with a default: smtpauth = str(sconfig.get('smtpauth', '')) You should use the existing `smtpauth` variable instead of re-fetching. 2. The parentheses around the condition are unnecessary (minor Python style issue). > + auth_b64 = get_oauth2_token(server, sconfig.get('smtpuser')) > + smtp.docmd('AUTH', 'XOAUTH2 ' + auth_b64) > + > auser = str(sconfig.get('smtpuser', '')) > apass = str(sconfig.get('smtppass', '')) This is going to not do the right thing. After successful XOAUTH2 authentication, there is no return statement. Execution falls through to the basic auth block below, which will call smtp.login(auser, apass). This will either fail (no password configured) or attempt a second, unwanted authentication. Add `return smtp, fromaddr` after smtp.docmd() to prevent fall-through. Also: smtp.docmd() returns a (code, message) tuple. The response code should be checked -- XOAUTH2 authentication can fail (e.g. expired token), and silently ignoring the response means the caller will not know authentication failed. > if auser and not apass: -- Konstantin Ryabitsev <konstantin@linuxfoundation.org> ^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [PATCH b4 2/2] b4: add support for oauth2 SMTP authentication 2026-02-01 5:37 ` Konstantin Ryabitsev @ 2026-02-02 14:08 ` Tomas Melin 2026-02-02 16:49 ` Tomas Melin 1 sibling, 0 replies; 13+ messages in thread From: Tomas Melin @ 2026-02-02 14:08 UTC (permalink / raw) To: Konstantin Ryabitsev, Kernel.org Tools Hi, On 01/02/2026 07:37, Konstantin Ryabitsev wrote: > On Thu, 29 Jan 2026 11:10:30 +0200, Tomas Melin <tomas.melin@vaisala.com> wrote: >> diff --git a/src/b4/__init__.py b/src/b4/__init__.py >> index 3d774f7..0adf5ca 100644 >> --- a/src/b4/__init__.py >> +++ b/src/b4/__init__.py >> @@ -2922,6 +2923,16 @@ def git_credential_fill(gitdir: Optional[str], protocol: str, host: str, usernam >> return None >> >> >> +def git_credential_helper(name: str) -> str: >> + if not name: >> + raise ValueError("credential helper name cannot be empty") >> + name = 'credential-' + name >> + ecode, out = git_run_command(None, args=[name]) >> + if ecode == 0: > > Any reason we're not making use of git_credential_fill() here? I'm not sure we > can expect correct return here, because credential helpers expect input on > stdin like: > > protocol=smtp > host=<server> > username=<user> > > The existing git_credential_fill() function should already handle this > correctly, unless I'm mistaken or you have other reasons not to use it. AFAIU basically they are kindof related but with slightly different usage. git-credential-outlook will call out the helper and get the token. Using 'git-credential-something' follows directly from the documented usage for the git-credential helper https://github.com/AdityaGarg8/git-credential-email?tab=readme-ov-file#usage That way, the integration is seamless with git-send-email oauth2 and b4 oauth usage. > >> + return out.strip() >> + return '' >> + >> + >> def git_get_command_lines(gitdir: Optional[str], args: List[str]) -> List[str]: >> ecode, out = git_run_command(gitdir, args) >> lines = list() >> @@ -4050,6 +4061,15 @@ def get_sendemail_config() -> Dict[str, Optional[Union[str, List[str]]]]: >> return SENDEMAIL_CONFIG >> >> >> +def get_oauth2_token(server: str, smtpuser: str) -> str: >> + creds = get_config_from_git(rf'credential.*{server}*') >> + access_token = git_credential_helper(creds.get('helper', '')) > > The regex does not look correct here. You probably want to do: > > rf'credential\.{re.escape(server)}\.*' > > or something like that. I've tested e.g. with server name smtp://smtp.office365.com:587. Escaping does sound like correct this to do, need to test it out some more.. > >> + if not access_token: >> + raise smtplib.SMTPException(f'Unable to get access token from git credential helper for server {server}') >> + auth_string = f'user={smtpuser}\x01auth=Bearer {access_token}\x01\x01' >> + return base64.b64encode(auth_string.encode()).decode() >> + >> + >> def get_smtp(dryrun: bool = False) -> Tuple[Union[smtplib.SMTP, smtplib.SMTP_SSL, List[str], None], str]: >> sconfig = get_sendemail_config() >> # Limited support for smtp settings to begin with, but should cover the vast majority of cases >> @@ -4118,6 +4138,11 @@ def get_smtp(dryrun: bool = False) -> Tuple[Union[smtplib.SMTP, smtplib.SMTP_SSL >> if smtpauth.lower() == 'none': >> return smtp, fromaddr >> >> + if (sconfig.get('smtpauth').lower() == 'xoauth2'): >> + logger.debug('Authenticating to SMTP server using oauth2') > > Two issues here: > > 1. sconfig.get('smtpauth') has no default value. If smtpauth is not set > in the config, this returns None and .lower() raises AttributeError. > Two lines above, the same key is fetched with a default: > smtpauth = str(sconfig.get('smtpauth', '')) > You should use the existing `smtpauth` variable instead of re-fetching. > > 2. The parentheses around the condition are unnecessary (minor Python style > issue). > >> + auth_b64 = get_oauth2_token(server, sconfig.get('smtpuser')) >> + smtp.docmd('AUTH', 'XOAUTH2 ' + auth_b64) >> + >> auser = str(sconfig.get('smtpuser', '')) >> apass = str(sconfig.get('smtppass', '')) > > This is going to not do the right thing. > > After successful XOAUTH2 authentication, there is no return statement. > Execution falls through to the basic auth block below, which will call > smtp.login(auser, apass). This will either fail (no password configured) > or attempt a second, unwanted authentication. Indeed here the basic auth is a fallback operation. Certainly I can change it to be exclusive so that it will not attempt basic auth. But with oauth2 it currently works, if the basic credentials are available they are autofilled and it proceeds. > > Add `return smtp, fromaddr` after smtp.docmd() to prevent fall-through. Yes, will add. > > Also: smtp.docmd() returns a (code, message) tuple. The response code > should be checked -- XOAUTH2 authentication can fail (e.g. expired > token), and silently ignoring the response means the caller will not > know authentication failed. Absolutely, thanks for pointing out. Adding return value check here. Thanks, Tomas > >> if auser and not apass: > ^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [PATCH b4 2/2] b4: add support for oauth2 SMTP authentication 2026-02-01 5:37 ` Konstantin Ryabitsev 2026-02-02 14:08 ` Tomas Melin @ 2026-02-02 16:49 ` Tomas Melin 2026-02-03 3:31 ` Konstantin Ryabitsev 1 sibling, 1 reply; 13+ messages in thread From: Tomas Melin @ 2026-02-02 16:49 UTC (permalink / raw) To: Konstantin Ryabitsev, Kernel.org Tools On 01/02/2026 07:37, Konstantin Ryabitsev wrote: > On Thu, 29 Jan 2026 11:10:30 +0200, Tomas Melin <tomas.melin@vaisala.com> wrote: >> diff --git a/src/b4/__init__.py b/src/b4/__init__.py >> index 3d774f7..0adf5ca 100644 >> --- a/src/b4/__init__.py >> +++ b/src/b4/__init__.py >> @@ -2922,6 +2923,16 @@ def git_credential_fill(gitdir: Optional[str], protocol: str, host: str, usernam >> return None >> >> >> +def git_credential_helper(name: str) -> str: >> + if not name: >> + raise ValueError("credential helper name cannot be empty") >> + name = 'credential-' + name >> + ecode, out = git_run_command(None, args=[name]) >> + if ecode == 0: > > Any reason we're not making use of git_credential_fill() here? I'm not sure we > can expect correct return here, because credential helpers expect input on > stdin like: > > protocol=smtp > host=<server> > username=<user> > > The existing git_credential_fill() function should already handle this > correctly, unless I'm mistaken or you have other reasons not to use it. Adding to my previous reply, this integration aligns with https://git-scm.com/docs/gitcredentials and in particular https://git-scm.com/docs/gitcredentials#_custom_helpers And in identical manner as git-send-email this uses external helpers like listed here https://git-scm.com/docs/git-send-email#_sending_patches So I don't see that git_credential_fill would be a match for it. thanks, Tomas > >> + return out.strip() >> + return '' >> + >> + >> def git_get_command_lines(gitdir: Optional[str], args: List[str]) -> List[str]: >> ecode, out = git_run_command(gitdir, args) >> lines = list() >> @@ -4050,6 +4061,15 @@ def get_sendemail_config() -> Dict[str, Optional[Union[str, List[str]]]]: >> return SENDEMAIL_CONFIG >> >> >> +def get_oauth2_token(server: str, smtpuser: str) -> str: >> + creds = get_config_from_git(rf'credential.*{server}*') >> + access_token = git_credential_helper(creds.get('helper', '')) > > The regex does not look correct here. You probably want to do: > > rf'credential\.{re.escape(server)}\.*' > > or something like that. > >> + if not access_token: >> + raise smtplib.SMTPException(f'Unable to get access token from git credential helper for server {server}') >> + auth_string = f'user={smtpuser}\x01auth=Bearer {access_token}\x01\x01' >> + return base64.b64encode(auth_string.encode()).decode() >> + >> + >> def get_smtp(dryrun: bool = False) -> Tuple[Union[smtplib.SMTP, smtplib.SMTP_SSL, List[str], None], str]: >> sconfig = get_sendemail_config() >> # Limited support for smtp settings to begin with, but should cover the vast majority of cases >> @@ -4118,6 +4138,11 @@ def get_smtp(dryrun: bool = False) -> Tuple[Union[smtplib.SMTP, smtplib.SMTP_SSL >> if smtpauth.lower() == 'none': >> return smtp, fromaddr >> >> + if (sconfig.get('smtpauth').lower() == 'xoauth2'): >> + logger.debug('Authenticating to SMTP server using oauth2') > > Two issues here: > > 1. sconfig.get('smtpauth') has no default value. If smtpauth is not set > in the config, this returns None and .lower() raises AttributeError. > Two lines above, the same key is fetched with a default: > smtpauth = str(sconfig.get('smtpauth', '')) > You should use the existing `smtpauth` variable instead of re-fetching. > > 2. The parentheses around the condition are unnecessary (minor Python style > issue). > >> + auth_b64 = get_oauth2_token(server, sconfig.get('smtpuser')) >> + smtp.docmd('AUTH', 'XOAUTH2 ' + auth_b64) >> + >> auser = str(sconfig.get('smtpuser', '')) >> apass = str(sconfig.get('smtppass', '')) > > This is going to not do the right thing. > > After successful XOAUTH2 authentication, there is no return statement. > Execution falls through to the basic auth block below, which will call > smtp.login(auser, apass). This will either fail (no password configured) > or attempt a second, unwanted authentication. > > Add `return smtp, fromaddr` after smtp.docmd() to prevent fall-through. > > Also: smtp.docmd() returns a (code, message) tuple. The response code > should be checked -- XOAUTH2 authentication can fail (e.g. expired > token), and silently ignoring the response means the caller will not > know authentication failed. > >> if auser and not apass: > ^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [PATCH b4 2/2] b4: add support for oauth2 SMTP authentication 2026-02-02 16:49 ` Tomas Melin @ 2026-02-03 3:31 ` Konstantin Ryabitsev 0 siblings, 0 replies; 13+ messages in thread From: Konstantin Ryabitsev @ 2026-02-03 3:31 UTC (permalink / raw) To: Tomas Melin; +Cc: Kernel.org Tools On Mon, Feb 02, 2026 at 06:49:09PM +0200, Tomas Melin wrote: > > Any reason we're not making use of git_credential_fill() here? I'm not sure we > > can expect correct return here, because credential helpers expect input on > > stdin like: > > > > protocol=smtp > > host=<server> > > username=<user> > > > > The existing git_credential_fill() function should already handle this > > correctly, unless I'm mistaken or you have other reasons not to use it. > > Adding to my previous reply, this integration aligns with > https://git-scm.com/docs/gitcredentials and in particular > https://git-scm.com/docs/gitcredentials#_custom_helpers > > And in identical manner as git-send-email this uses external helpers > like listed here https://git-scm.com/docs/git-send-email#_sending_patches > > So I don't see that git_credential_fill would be a match for it. Sounds good to me, thank you for doing the extra legwork. I will be happy to review v2 once you send it in with the other fixes. -K ^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [PATCH b4 0/2] Add support for oauth2 SMTP authentication 2026-01-29 9:10 [PATCH b4 0/2] Add support for oauth2 SMTP authentication Tomas Melin 2026-01-29 9:10 ` [PATCH b4 1/2] ez: add SMTP authentication method to printed information Tomas Melin 2026-01-29 9:10 ` [PATCH b4 2/2] b4: add support for oauth2 SMTP authentication Tomas Melin @ 2026-02-01 5:37 ` Konstantin Ryabitsev 2026-02-01 5:52 ` Konstantin Ryabitsev 2 siblings, 1 reply; 13+ messages in thread From: Konstantin Ryabitsev @ 2026-02-01 5:37 UTC (permalink / raw) To: Kernel.org Tools; +Cc: Konstantin Ryabitsev, Tomas Melin On Thu, 29 Jan 2026 11:10:28 +0200, Tomas Melin <tomas.melin@vaisala.com> wrote: > Add support for oauth2 authentication with SMTP server, integrating > with git credential helpers for retrieving tokens. With this approach, > the same configuration as is needed for git send-email can be used > to send patches using oauth2 with b4. Thank you for sending this in! I'm using this series as a guinea pig for the "b4 review" functionality, using agent-assisted reviews. I know it's not everyone's cup of tea, but there is enough interest in it to at least support it. I'm sending per-patch followups with the problems the agent has identified (combed by myself -- I'm not just blindly relying on the agent here). I am also screencasting this whole process, so hopefully this will be educational as well. :) -- Konstantin Ryabitsev <konstantin@linuxfoundation.org> ^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [PATCH b4 0/2] Add support for oauth2 SMTP authentication 2026-02-01 5:37 ` [PATCH b4 0/2] Add " Konstantin Ryabitsev @ 2026-02-01 5:52 ` Konstantin Ryabitsev 2026-02-05 9:18 ` Tomas Melin 0 siblings, 1 reply; 13+ messages in thread From: Konstantin Ryabitsev @ 2026-02-01 5:52 UTC (permalink / raw) To: Kernel.org Tools; +Cc: Tomas Melin On Sun, Feb 01, 2026 at 12:37:34AM -0500, Konstantin Ryabitsev wrote: > On Thu, 29 Jan 2026 11:10:28 +0200, Tomas Melin <tomas.melin@vaisala.com> wrote: > > Add support for oauth2 authentication with SMTP server, integrating > > with git credential helpers for retrieving tokens. With this approach, > > the same configuration as is needed for git send-email can be used > > to send patches using oauth2 with b4. > > Thank you for sending this in! I'm using this series as a guinea pig for > the "b4 review" functionality, using agent-assisted reviews. I know it's > not everyone's cup of tea, but there is enough interest in it to at > least support it. > > I'm sending per-patch followups with the problems the agent has > identified (combed by myself -- I'm not just blindly relying on the > agent here). > > I am also screencasting this whole process, so hopefully this will be > educational as well. :) This is the screencast: https://asciinema.org/a/777545 There are still lots of improvements to "b4 review" to consider it useful and remotely maintainer-ready, but it's at least doing useful things already. Cheers, -K ^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [PATCH b4 0/2] Add support for oauth2 SMTP authentication 2026-02-01 5:52 ` Konstantin Ryabitsev @ 2026-02-05 9:18 ` Tomas Melin 0 siblings, 0 replies; 13+ messages in thread From: Tomas Melin @ 2026-02-05 9:18 UTC (permalink / raw) To: Konstantin Ryabitsev, Kernel.org Tools Hi, On 01/02/2026 07:52, Konstantin Ryabitsev wrote: > On Sun, Feb 01, 2026 at 12:37:34AM -0500, Konstantin Ryabitsev wrote: >> On Thu, 29 Jan 2026 11:10:28 +0200, Tomas Melin <tomas.melin@vaisala.com> wrote: >>> Add support for oauth2 authentication with SMTP server, integrating >>> with git credential helpers for retrieving tokens. With this approach, >>> the same configuration as is needed for git send-email can be used >>> to send patches using oauth2 with b4. >> >> Thank you for sending this in! I'm using this series as a guinea pig for >> the "b4 review" functionality, using agent-assisted reviews. I know it's >> not everyone's cup of tea, but there is enough interest in it to at >> least support it. >> >> I'm sending per-patch followups with the problems the agent has >> identified (combed by myself -- I'm not just blindly relying on the >> agent here). >> >> I am also screencasting this whole process, so hopefully this will be >> educational as well. :) > > This is the screencast: > https://asciinema.org/a/777545 > Thanks for sharing! Interesting stuff and looks promising. FYI for upcoming v2 I have also reviewed the patches with an agent, so let's see if they agree about possible findings :) thanks, Tomas > There are still lots of improvements to "b4 review" to consider it useful and > remotely maintainer-ready, but it's at least doing useful things already. > > Cheers, > -K ^ permalink raw reply [flat|nested] 13+ messages in thread
end of thread, other threads:[~2026-02-05 9:19 UTC | newest] Thread overview: 13+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2026-01-29 9:10 [PATCH b4 0/2] Add support for oauth2 SMTP authentication Tomas Melin 2026-01-29 9:10 ` [PATCH b4 1/2] ez: add SMTP authentication method to printed information Tomas Melin 2026-02-01 5:37 ` Konstantin Ryabitsev 2026-02-02 14:31 ` Tomas Melin 2026-01-29 9:10 ` [PATCH b4 2/2] b4: add support for oauth2 SMTP authentication Tomas Melin 2026-01-30 12:09 ` Tomas Melin 2026-02-01 5:37 ` Konstantin Ryabitsev 2026-02-02 14:08 ` Tomas Melin 2026-02-02 16:49 ` Tomas Melin 2026-02-03 3:31 ` Konstantin Ryabitsev 2026-02-01 5:37 ` [PATCH b4 0/2] Add " Konstantin Ryabitsev 2026-02-01 5:52 ` Konstantin Ryabitsev 2026-02-05 9:18 ` Tomas Melin
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox