Linux Email Server – Procmail Variables and Recipe Syntax

emailemail-serverlinuxprocmail

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:'

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

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:<gmail.com>, it will not be filtered by this recipe, but if the email has mail from:<me@gmail.com>, 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?

Best Answer

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

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

archive=''

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:

:0
* !^From:.gmail\.com
{
  :0c
  | (formail) | $SENDMAIL -t -oi
  :0:
  archive
}

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.

Related Topic