Index | Thread | Search

From:
Johannes Thyssen Tishman <jtt@openbsd.org>
Subject:
smtpd: fix using modifiers with partial expansion in format specifiers
To:
tech@openbsd.org
Date:
Thu, 2 Apr 2026 16:24:45 +0000

Download raw body.

Thread
As described in smtpd.conf(5), format specifiers, e.g. '%{sender.user}',
support partial expansion using bracket notation (%{sender.user[n:m]}),
as well as modifiers (%{sender.user:strip}). However using both at the
same time (%{sender.user[n:m]:strip}) gives the following error:

  "smtpd: mda command line could not be expanded"

This occurs because the leading colon from the modifier is not stripped,
resulting in a "modifier not found" error. The diff below fixes this. I
also added a comment to smtpd.conf(5) to clarify that modifiers and
partial expansion *can* be used together and that, when used together,
modifiers are applied before partial expansion.

For those interested, a good example of how this can be used is sorting
emails from OpenBSD mailing lists into their own maildirs, e.g.:

  action "obsd_sort" maildir "~/mail/.OpenBSD.%{sender.user[6:]:strip}"
  match from mail-from regex "^owner-[^@]*@example\.org$" \
          for local action "obsd_sort"

diff /usr/src
path + /usr/src
commit - b47f74b4221666678dbec685b662de7d14a8b253
blob - 0542f95de3337ec47fd0b7573178885eed868bec
file + usr.sbin/smtpd/mda_variables.c
--- usr.sbin/smtpd/mda_variables.c
+++ usr.sbin/smtpd/mda_variables.c
@@ -94,7 +94,8 @@ mda_expand_token(char *dest, size_t len, const char *t
 			return -1;
 
 		/* token:mod_1,mod_2,mod_n -> extract modifiers */
-		mods = strchr(rbracket + 1, ':');
+		if ((mods = strchr(rbracket + 1, ':')) != NULL)
+			*mods++ = '\0';
 	} else {
 		if ((mods = strchr(rtoken, ':')) != NULL)
 			*mods++ = '\0';
commit - b47f74b4221666678dbec685b662de7d14a8b253
blob - 1cdaf067c5585ca69bb19baf72014d29adfe6747
file + usr.sbin/smtpd/smtpd.conf.5
--- usr.sbin/smtpd/smtpd.conf.5
+++ usr.sbin/smtpd/smtpd.conf.5
@@ -1144,6 +1144,13 @@ For example, with recipient
 .It %{rcpt:lowercase|strip} Ta expands to Dq user@example.org
 .El
 .Pp
+Modifiers and partial expansion can be used together. In such cases, the
+modifiers are applied before the partial expansion. For example, with sender
+.Dq owner-tech+M123456@openbsd.org :
+.Bl -column %{sender.user[6:]:strip} -offset indent
+.It %{sender.user[6:]:strip} Ta expands to Dq tech
+.El
+.Pp
 For security concerns, expanded values are sanitized and potentially
 dangerous characters are replaced with
 .Sq \&: .