I'm trying to understand the procmailrc syntax. From documentation that I've read, I can set my own variables using VARNAME=value and then use them elsewhere by refering to $VARNAME

I also understand that recipes filter mail input to different actions (dispositions)

I have a procmailrc with a single recipe and 2 variables, as follows:

SUBJECT='formail -xSubject:'
FROM='formail -rt -xTo:'

* !^From:.gmail\.com
| (formail) | $SENDMAIL -t -oi

Am I right in saying that the variables SUBJECT and FROM in this case are irrelevant as they are not used anywhere else in the file?

Also, I'm pretty bad at regular expressions, but from what I've read from documentations (both procmail and regex), am I right in saying that the recipe filters mail that does NOT have the "From:Xgmail.com", where X is any character? i.e. if the email has "mail from:", it will not be filtered by this recipe, but if the email has "mail from:, then it will be filtered?

Also, in the 2nd last line, if formail doesn't have any arguments, then where is it sending the response mail to, and with what content? Is there any default?

Lastly, does the last line mean that a copy of the mail is placed in the "archive" file in the mail directory?


  • This is rather broad; perhaps in the future try to isolate individual questions into separate posts, but of course, probably also don't ask too many questions in rapid succession, and show us what you have done yourself to troubleshoot. – tripleee Jun 26 '18 at 15:34

First off, your example contains a syntax error. A recipe can contain exactly one action. In fact, your recipe will effectively be parsed as

* !^From:.gmail\.com
| (formail) | $SENDMAIL -t -oi


You will also get an "extraneous locallockfile ignored" because Procmail cannot figure out a lockfile for the piping action.

If you want two actions for a recipe, use braces:

* !^From:.gmail\.com
  | (formail) | $SENDMAIL -t -oi

The c flag on the first recipe inside the braces says "this is not the final delivery`; by default, Procmail will stop processing a message when it is considered delivered.

Notice also the difference between single quotes and backticks. Your assignments create variables which contain the text between the quotes. Presumably you really mean

SUBJECT=`formail -xSubject:`  # not SUBJECT='formail -xSubject:'
FROM=`formail -rt -xTo:`  # not FROM='formail -rt -xTo:'

And indeed, if you never use these variables for anything, assigning them is pointless (though there are other variables which are special to Procmail, so assigning e.g. LOGFILE or LOCKFILE or SENDMAIL will have effects on Procmail's operation).

formail with no arguments simply passes standard input to standard output, with some normalization of headers. I don't think it performs any useful function here. The parentheses around the command cause it to be run in a separate shell, which is also pointless and inefficient.

Sending the message again with sendmail -t will create a mail loop, so you probably don't want to perform this action at all if the messages you process are not specifically guaranteed to be Bcc:ed to the current address, for example (in which case the message will be sent to the visible recipients in the headers, but not to you again; so, no mail loop).

The ^ in the regex anchors the search to beginning of line, so there can be no other text before From:, and the unescaped dot matches any character except newline, exactly like you explain; a better regex would probably be ^From:(.*\<)?gmail\.com which at least requires there to be a non-word character before gmail.com (but this is not a valid email address, so perhaps I am not able to correctly guess what you are hoping to accomplish). Finally, like you already figured out, the exclamation mark negates the regex, so the recipe triggers when the regex doesn't match.

Perhaps you already found http://www.iki.fi/era/procmail/quickref.html and http://www.iki.fi/era/mail/procmail-debug.html - though these are dated, they should hopefully help sort out some of your questions going forward.

  • Thanks! That's great help! I'm actually trying to figure out what the above procfilerc filter does, and how I can send a mail to either get filtered, or not. It seems like the recipe filters only based on the From field. Does this mean that if I send the SMTP command MAIL From:<xgmail.com>, it will not get filtered (assuming the < is not a character in the From field), but if I send MAIL From:<me@gmail.com>, it will get filtered? – user1118764 Jun 26 '18 at 16:15
  • The SMTP envelope recipient is completely separate. Procmail only examines the actual headers, not the envelope (so only what goes after DATA in the SMTP transaction) though some MTAs will sometimes "helpfully" populate some required headers if they are missing, perhaps with information from the envelope. The envelope sender is often exposed in a Return-Path: header which is inserted by the receiving MTA, but this is not required behavior. – tripleee Jun 26 '18 at 17:10
  • If the RFC822 headers contain From:<xgmail.com> (a) this is an invalid header and (b) indeed the string <x does not match the regex . because it only matches a single character, and the string is two characters long. If you have only < or only x then either of those are "any character except newline" and thus matches the regex . – tripleee Jun 26 '18 at 17:14
  • <me@ also is not a single character, so doesn't match either. From: gmail.com@example.net is an example of a valid, well-formed header which would match (the space is a single character); From:xgmail.com@example.net also matches, though it's atypical in practice, because the single x is one character. – tripleee Jun 27 '18 at 3:06
  • Actually formail will insert a From_ line so it's not just useless, it's harmful here. – tripleee Jun 27 '18 at 3:09

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.