From: Johannes Thyssen Tishman Subject: smtpd: fix using modifiers with partial expansion in format specifiers To: tech@openbsd.org Date: Thu, 2 Apr 2026 16:24:45 +0000 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 \&: .