PROCMAILSC(5)
๐ PROCMAILSC ๐
okay bestie, this is procmailsc from the File Formats Manual, and it's literally the glow-up your recipes have been waiting for. it's the procmail weighted scoring technique โ and no, it's not boring, it's giving โจmathโจ and it slays.
๐ธ NAME ๐ธ
procmailsc โ the procmail weighted scoring technique. that's it, that's the name, and it's iconic.
โจ SYNOPSIS โจ
[*] w^x condition
๐ DESCRIPTION ๐
so like, you already know the classic true-or-false conditions you can put on a recipe, right? well, plot twist: you can also use a weighted scoring technique to decide whether a recipe matches or not. when weighted scoring is in play, the final score for that recipe has to be positive for it to match. no positive score, no match. periodt. ๐
a condition can chip in to the score if you give it a weight (w) and an exponent (x). you do that by sticking this right in front of the condition, on the same line:
w^x
and both w and x are real numbers from -2147483647.0 to 2147483647.0 inclusive. yes, inclusive. we love an inclusive queen. ๐
๐ฅ Weighted regular expression conditions ๐ฅ
the first time the regular expression is found, it adds w to the score. the second time it's found, w*x gets added. third time? w*x*x. fourth time, w*x*x*x. and so on and so on, forever, exponential queen behavior. ๐
here's the concise formula, look at her:
n
n k-1 x - 1
w * Sum x = w * -------
k=1 x - 1
that's the total added score for this condition if n matches are found. math ate, honestly.
and now the case distinctions, because these matter, no cap:
x=0โ only the first match contributeswto the score. any matches after that? ignored. not even looked at. bye. ๐x=1โ every match contributes the samewto the score. the score grows linearly with the number of matches found.0<x<1โ every match contributes less than the one before it. the score asymptotically approaches a certain value (go peek at the NOTES section below, it's all there).1<xโ every match contributes more than the one before it. the score grows exponentially. she's escalating. ๐ฅx<0โ can be utilised to favour an odd or even number of matches. yes, really.
and if the regular expression is negated (i.e., it matches when it isn't found), then n obviously can only ever be zero or one. simple as that. ๐ฆ
๐ Weighted program conditions ๐
if the program returns an exitcode of EXIT_SUCCESS (=0), then the total added score will be w. if it returns literally any other exitcode (which means failure), the total added score will be x.
and if the exitcode of the program is negated, then the exitcode gets treated as if it were a virtual number of matches. the calculation of the added score then proceeds exactly as if it had been a normal regular expression with n= exitcode matches. mind = blown. ๐ง
๐ Weighted length conditions ๐
if the length of the actual mail is M, then:
* w^x > L
will generate an additional score of:
x
/ M \
w * | --- |
\ L /
and:
* w^x < L
will generate an additional score of:
x
/ L \
w * | --- |
\ M /
in both cases, if L=M, this adds w to the score. but here's the tea: in the former case, larger mails get favoured. in the latter case, smaller mails get favoured. and even though you can vary x to fine-tune the steepness of the function, typical usage just sets x=1. keep it simple, bestie. ๐
๐ MISCELLANEOUS ๐
you can query the final score of all the conditions on a recipe from the environment variable $=. this variable gets set every single time, just after procmail has parsed all conditions on a recipe โ even if the recipe is not being executed. she's always reporting back to you, that's loyalty. ๐ซถ
โญ EXAMPLES โญ
okay this is the part you actually came for. let's go.
the following recipe will ditch all mails having more than 150 lines in the body. the first condition contains an empty regular expression which, because it always matches, is used to give our score a negative offset. the second condition then matches every line in the mail, and consumes up the previous negative offset we gave (one point per line). in the end, the score will only be positive if the mail contained more than 150 lines. chef's kiss. ๐ญ
:0 Bh
* -150^0
* 1^1 ^.*$
/dev/null
now suppose you have a priority folder which you always read first. the next recipe picks out the priority mail and files them in this special folder. the first condition is a regular one, i.e., it doesn't contribute to the score, but simply has to be satisfied. the other conditions describe things like: john and claire usually have something important to say, meetings are usually important, replies are favoured a bit, mails about Elvis (this is merely an example :-) are favoured (the more he is mentioned, the more the mail is favoured, but the maximum extra score due to Elvis will be 4000, no matter how often he is mentioned), lots of quoted lines are disliked, smileys are appreciated (the score for those will reach a maximum of 3500), those three people usually don't send interesting mails, the mails should preferably be small (e.g., 2000 bytes long mails will score -100, 4000 bytes long mails do -800). as you see, if some of the uninteresting people send mail, then the mail still has a chance of landing in the priority folder, e.g., if it is about a meeting, or if it contains at least two smileys. ๐
:0 HB
* !^Precedence:.*(junk|bulk)
* 2000^0 ^From:.*(john@home|claire@work)
* 2000^0 ^Subject:.*meeting
* 300^0 ^Subject:.*Re:
* 1000^.75 elvis|presley
* -100^1 ^>
* 350^.9 :-\)
* -500^0 ^From:.*(boss|jane|henry)@work
* -100^3 > 2000
priority_folder
and if you are subscribed to a mailinglist, and just would like to read the quality mails, then the following recipes could do the trick. first we make sure that the mail is coming from the mailinglist. then we check if it is from certain persons of whom we value the opinion, or about a subject we absolutely want to know everything about. if it is, file it. otherwise, check if the ratio of quoted lines to original lines is at most 1:2. if it exceeds that, ditch the mail. everything that survived the previous test, is filed. ๐ฆ
:0
^From mailinglist-request@some.where
{
:0:
* ^(From:.*(paula|bill)|Subject:.*skiing)
mailinglist
:0 Bh
* 20^1 ^>
* -10^1 ^[^>]
/dev/null
:0:
mailinglist
}
for further examples you should look in the procmailex(5) man page. go, read it, it's good for you. ๐
๐ CAVEATS ๐
listen, this part matters, don't skip it. because this speeds up the search by an order of magnitude, the procmail internal egrep will always search for the leftmost shortest match โ unless it is determining what to assign to MATCH, in which case it searches the leftmost longest match.
e.g., for the leftmost shortest match, by itself, the regular expression:
.*โ will always match a zero length string at the same spot..+โ will always match one character (except newlines of course).
bestie this trips everyone up. leftmost shortest is the default, leftmost longest is only for MATCH. memorize it. ๐ง
๐ SEE ALSO ๐
procmail(1), procmailrc(5), procmailex(5), sh(1), csh(1), egrep(1), grep(1),
๐ BUGS ๐
if, in a length condition, you specify an x that causes an overflow, procmail is at the mercy of the pow(3) function in your mathematical library. like, completely at its mercy. no backup plan. ๐ญ
also: floating point numbers in engineering format (e.g., 12e5) are not accepted. don't try it. she said no.
๐ MISCELLANEOUS (part two, the sequel) ๐
as soon as plus infinity (2147483647) is reached, any subsequent weighted conditions will simply be skipped.
as soon as minus infinity (-2147483647) is reached, the condition will be considered as no match and the recipe will terminate early.
so yeah, the score has limits, and hitting them changes everything. dramatic? maybe. correct? absolutely. ๐
๐ฎ NOTES ๐ฎ
if in a regular expression weighted formula 0<x<1, the total added score for this condition will asymptotically approach:
w
-------
1 - x
and in order to reach half the maximum value, you need:
- ln 2
n = --------
ln x
matches. there you go, now you can calculate exactly how much is too much. math bestie behavior. ๐งฎโจ
๐ AUTHORS ๐
Stephen R. van den Berg <srb@cuci.nl>
and that's the whole page, bestie! this one was written by BuGless and it's from the PROCMAILSC(5) manual. go forth and score your mail like the main character you are. ๐โจ๐๐ฆ๐ธ๐
๐ซถ
๐ฆ where this page comes from
- centos-stream 10: procmail 3.24-8.el10 ยท gpl-2.0-or-later
- fedora 43: procmail 3.24-9.fc43 ยท gpl-2.0-or-later
- fedora 44: procmail 3.24-10.fc44 ยท gpl-2.0-or-later
- nixos 26.05: procmail 3.24
- nixpkgs unstable: procmail 3.24
- opensuse-leap 16.0: procmail 3.24-160000.2.2 ยท Artistic-1.0 OR GPL-2.0-or-later
- opensuse-leap 16.0: procmail 3.24-160000.2.2 ยท Artistic-1.0 OR GPL-2.0-or-later
- opensuse-leap 16.0: procmail 3.24-160000.2.2 ยท Artistic-1.0 OR GPL-2.0-or-later
- ubuntu noble: procmail 3.24-1ubuntu2
- ubuntu questing: procmail 3.24-1ubuntu4
- ubuntu resolute: procmail 3.24-1ubuntu5
- ubuntu stonking: procmail 3.24-1ubuntu6
- ๐ girlified by deepseek-ai/DeepSeek-V4.1-Flash on : a language model's rewrite of the original, under its terms