From: Dmitry Torokhov <dmitry.torokhov@gmail.com>
To: tools@kernel.org
Subject: [PATCH] b4: Implement --bcc and send-series-bcc config option
Date: Fri, 6 Mar 2026 17:27:45 -0800 [thread overview]
Message-ID: <20260307012748.1414702-1-dmitry.torokhov@gmail.com> (raw)
Allow using blind carbon copy when sending entire series (no per-patch
Bcc).
Handling is similar to "To" and "Cc" handling except that it ignores
"not-me-too" and other exclusion lists as the intent to send to the
address(es) specified in bcc is explicit.
Signed-off-by: Dmitry Torokhov <dmitry.torokhov@gmail.com>
---
docs/config.rst | 9 +++++++++
docs/contributor/send.rst | 11 ++++++++++-
src/b4/__init__.py | 19 +++++++++++++------
src/b4/command.py | 1 +
src/b4/ez.py | 23 ++++++++++++++++++++++-
5 files changed, 55 insertions(+), 8 deletions(-)
diff --git a/docs/config.rst b/docs/config.rst
index 8ffbf5e..9f508cf 100644
--- a/docs/config.rst
+++ b/docs/config.rst
@@ -591,6 +591,15 @@ Contributor-oriented settings
.. versionchanged:: v0.15
Added ``shallow`` config value.
+ :term:`b4.send-series-bcc`
+ A comma-separated list of addresses to always add to the "Bcc:" list.
+ Recipients in this list will always receive the series regardless of
+ any exclusion filters (such as the ``--not-me-too`` flag or the
+ :term:`b4.email-exclude` configuration setting).
+ See :ref:`prep_recipients`.
+
+ Default: ``None``
+
:term:`b4.send-series-cc`
A comma-separated list of addresses to always add to the "Cc:" header.
See :ref:`prep_recipients`.
diff --git a/docs/contributor/send.rst b/docs/contributor/send.rst
index ba18ef5..1314d48 100644
--- a/docs/contributor/send.rst
+++ b/docs/contributor/send.rst
@@ -320,8 +320,17 @@ Command line flags
configuration file using the :term:`b4.send-series-cc` option (see
:ref:`contributor_settings`).
+``--bcc``
+ Additional email addresses to include into the Bcc: list. Recipients
+ in this list will always receive the series regardless of any
+ exclusion filters (such as the ``--not-me-too`` flag or the
+ :term:`b4.email-exclude` configuration setting). Separate multiple
+ entries with a comma. You can also set this in the configuration
+ file using the :term:`b4.send-series-bcc` option (see
+ :ref:`contributor_settings`).
+
``--not-me-too``
- Removes your own email address from the recipients.
+ Removes your own email address from the To: or Cc: recipients.
``--no-sign``
Don't sign your patches with your configured attestation mechanism.
diff --git a/src/b4/__init__.py b/src/b4/__init__.py
index 9a5d25b..9ad68a4 100644
--- a/src/b4/__init__.py
+++ b/src/b4/__init__.py
@@ -4413,6 +4413,14 @@ def send_mail(smtp: Union[smtplib.SMTP, smtplib.SMTP_SSL, List[str], None], msgs
dryrun = True
for msg in msgs:
+ if not destaddrs:
+ alldests = email.utils.getaddresses([str(x) for x in msg.get_all('to', [])])
+ alldests += email.utils.getaddresses([str(x) for x in msg.get_all('cc', [])])
+ alldests += email.utils.getaddresses([str(x) for x in msg.get_all('bcc', [])])
+ myaddrs = {x[1] for x in alldests}
+ else:
+ myaddrs = set(destaddrs)
+
if not msg.get('X-Mailer'):
msg.add_header('X-Mailer', f'b4 {__VERSION__}')
msg.set_charset('utf-8')
@@ -4422,6 +4430,11 @@ def send_mail(smtp: Union[smtplib.SMTP, smtplib.SMTP_SSL, List[str], None], msgs
else:
nl = '\r\n'
+ # If we have a Bcc header, we must strip it from the message body
+ # before sending it out.
+ if msg['Bcc']:
+ del msg['Bcc']
+
bdata = LoreMessage.get_msg_as_bytes(msg, nl=nl, headers='encode')
subject = msg.get('Subject', '')
@@ -4450,12 +4463,6 @@ def send_mail(smtp: Union[smtplib.SMTP, smtplib.SMTP_SSL, List[str], None], msgs
logger.info(' | ' + bdata.decode().rstrip().replace('\n', '\n | '))
logger.info(' --- DRYRUN: message ends ---')
continue
- if not destaddrs:
- alldests = email.utils.getaddresses([str(x) for x in msg.get_all('to', [])])
- alldests += email.utils.getaddresses([str(x) for x in msg.get_all('cc', [])])
- myaddrs = {x[1] for x in alldests}
- else:
- myaddrs = set(destaddrs)
tosend.append((myaddrs, bdata, ls))
diff --git a/src/b4/command.py b/src/b4/command.py
index a49a8bc..d115765 100644
--- a/src/b4/command.py
+++ b/src/b4/command.py
@@ -425,6 +425,7 @@ def setup_parser() -> argparse.ArgumentParser:
help='Do not add any addresses found in the cover or patch trailers to To: or Cc:')
sp_send.add_argument('--to', nargs='+', metavar='ADDR', help='Addresses to add to the To: list')
sp_send.add_argument('--cc', nargs='+', metavar='ADDR', help='Addresses to add to the Cc: list')
+ sp_send.add_argument('--bcc', nargs='+', metavar='ADDR', help='Addresses to add to the Bcc: list')
sp_send.add_argument('--not-me-too', action='store_true', default=False,
help='Remove yourself from the To: or Cc: list')
sp_send.add_argument('--resend', metavar='vN', nargs='?', const='latest',
diff --git a/src/b4/ez.py b/src/b4/ez.py
index 52eb239..378d201 100644
--- a/src/b4/ez.py
+++ b/src/b4/ez.py
@@ -1968,6 +1968,8 @@ def cmd_send(cmdargs: argparse.Namespace) -> None:
excludes: Set[str] = set()
pccs: Dict[str, List[Tuple[str, str]]] = dict()
+ bccdests = list()
+
if cmdargs.preview_to or cmdargs.no_trailer_to_cc:
todests = list()
ccdests = list()
@@ -2006,6 +2008,7 @@ def cmd_send(cmdargs: argparse.Namespace) -> None:
tos = set()
ccs = set()
+ bccs = set()
if cmdargs.preview_to:
tos.update(cmdargs.preview_to)
else:
@@ -2017,6 +2020,13 @@ def cmd_send(cmdargs: argparse.Namespace) -> None:
ccs.update(cmdargs.cc)
if config.get('send-series-cc'):
ccs.add(config.get('send-series-cc'))
+ if cmdargs.bcc:
+ bccs.update(cmdargs.bcc)
+ if config.get('send-series-bcc'):
+ bccs.add(config.get('send-series-bcc'))
+ if bccs:
+ for pair in email.utils.getaddresses(list(bccs)):
+ bccdests.append(pair)
if ccs:
for pair in email.utils.getaddresses(list(ccs)):
if pair[1] in seen:
@@ -2032,6 +2042,7 @@ def cmd_send(cmdargs: argparse.Namespace) -> None:
allto = list()
allcc = list()
+ allbcc = list()
alldests = set()
if todests:
@@ -2042,6 +2053,10 @@ def cmd_send(cmdargs: argparse.Namespace) -> None:
allcc = b4.cleanup_email_addrs(ccdests, excludes, None)
logger.debug('allcc: %s', allcc)
alldests.update(set([x[1] for x in allcc]))
+ if bccdests:
+ allbcc = b4.cleanup_email_addrs(bccdests, set(), None)
+ logger.debug('allbcc: %s', allbcc)
+ alldests.update(set([x[1] for x in allbcc]))
logger.debug('alldests: %s', alldests)
@@ -2076,7 +2091,7 @@ def cmd_send(cmdargs: argparse.Namespace) -> None:
# Give the user the last opportunity to bail out
if not cmdargs.dryrun:
- if not len(alldests):
+ if not len(allto):
logger.critical('CRITICAL: Could not find any destination addresses')
logger.critical(' try b4 prep --auto-to-cc or b4 send --to addr')
sys.exit(1)
@@ -2135,6 +2150,7 @@ def cmd_send(cmdargs: argparse.Namespace) -> None:
logger.info('---')
b4.print_pretty_addrs(allto, 'To')
b4.print_pretty_addrs(allcc, 'Cc')
+ b4.print_pretty_addrs(allbcc, 'Bcc')
logger.info('---')
for commit, msg in patches:
if not msg:
@@ -2256,6 +2272,11 @@ def cmd_send(cmdargs: argparse.Namespace) -> None:
msg.replace_header('Cc', b4.format_addrs(pcc))
else:
msg.add_header('Cc', b4.format_addrs(pcc))
+ if allbcc:
+ if msg['Bcc']:
+ msg.replace_header('Bcc', b4.format_addrs(allbcc))
+ else:
+ msg.add_header('Bcc', b4.format_addrs(allbcc))
send_msgs.append(msg)
--
2.53.0.473.g4a7958ca14-goog
next reply other threads:[~2026-03-07 1:27 UTC|newest]
Thread overview: 2+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-03-07 1:27 Dmitry Torokhov [this message]
2026-03-07 4:49 ` [PATCH] b4: Implement --bcc and send-series-bcc config option Konstantin Ryabitsev
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20260307012748.1414702-1-dmitry.torokhov@gmail.com \
--to=dmitry.torokhov@gmail.com \
--cc=tools@kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox