procmail

最後更新: 2020-12-09

介紹

HomePage: http://www.procmail.org/

原理

[A] invoked automatically over the .forward (sendmail)

[B] invoked from within the mailer immediately (postfix - mailbox_command)

目錄

  • Installation
  • Postfix Configure
    [方式 1] By Postfix 's mailbox_command
    [方式 2] By Postfix 's transport_maps
  • rcfile
  • Rule Syntax
  • Procmail Flags
  • Sending to Dovecot
  • Example
  • Work with spamassassin

 


Installation

 

# Centos 6

yum install procmail

# Check Version

procmail -v

procmail v3.22 2001/09/10

 


Postfix Configure

 

[方式 1] By Postfix 's mailbox_command

[方式 2] By Postfix ' s transport_maps

 

[方式 1] By Postfix 's mailbox_command

vi /etc/postfix/main.cf

mailbox_command = /usr/bin/procmail

service postfix restart

 

[方式 2] By Postfix 's transport_maps

Postfix Setting

main.cf

procmail_destination_recipient_limit = 1

transport_maps =
 hash:/etc/postfix/cf/transport_maps_user,
 ...

master.cf

procmail unix - n n - - pipe
 flags=RO user=vmail argv=/usr/bin/procmail -t -m
 USER=${user}
 DOMAIN=${domain}
 EXTENSION=${extension}
 /etc/postfix/procmailrc/${recipient}

${extension} # postfix variable

This macro expands to the extension part of a recipient address.

For example, with an address user+foo@domain the extension is foo.

${mailbox} # postfix variable

This macro expands to the complete local part of a recipient address.

For example, with an address user+foo@domain the mailbox is user+foo.

${user}

user+foo@domain => user

Remark

A command-line argument that contains ${extension} / ${mailbox}

expands into as many command-line arguments as there are recipients.

This information is modified by the u flag for case folding.

h             # postfix pipe flag

Fold the command-line $original_recipient and $recipient address domain part to lower case

u             # postfix pipe flag

Fold the command-line $original_recipient and  $recipient address localpart to lower case.

q             # postfix pipe flag

Quote white space and other special characters in the command-line $sender,

$original_recipient and $recipient address localparts

The q flag affects only entire addresses, not the partial address information from the $user,

$extension or $mailbox command-line macros.

-a argument                  # procmail Opts

This will set $1 to be equal to argument.  

Each succeeding -a argument will set the next number variable  ($2, $3, etc).

-t                                # procmail Opts

Make procmail fail softly

i.e.

if procmail cannot deliver the mail to any of the destinations you gave,

the mail will not bounce, but will return to the  mailqueue.

-m                               # procmail Opts

Turns procmail into a general purpose mail filter.

In this mode one rcfile must be specified on the command line.

transport_maps_user

U@D       procmail

procmailrc.common

# comment ...
ORGMAIL=${HOME}/$DOMAIN/$USER/
DEFAULT=${ORGMAIL}
VERBOSE=off
LOGFILE=${ORGMAIL}/procmail.log
LOG="`date`
"
MAILDIR=${ORGMAIL}

U@D

INCLUDERC=/etc/postfix/procmailrc/procmailrc.common
VERBOSE=off

# deliver to folder test and stop
:0 w:
.test/

Postfix Log

... postfix/virtual[22163]: 654C33219C5:
 to=<U@D>, relay=virtual, delay=0.07, delays=0.01/0/0/0.06,
 dsn=2.0.0, status=sent (delivered to maildir)

變成

... postfix/pipe[23771]: 2AE9D3219EC: 
  to=<U@D>, relay=procmail, delay=1104, delays=1103/0.02/0/0.02,
  dsn=2.0.0, status=sent (delivered via procmail service)

Help

man 5 procmailrc         # procmail rcfile

man 5 procmailex        # procmail rcfile examples

 


rcfile

 

Procmail Configuration

The Procmail configuration file contains important environmental variables.

These variables specify things such as which messages to sort and what to do with the messages that do not match any recipes.

<env-variable>=<value>

支援

  • ${VAR:-value}
  • ${VAR:+value}

Default rcfile: $HOME/.procmailrc          # Environment variable

VERBOSE=on
LOGFILE=$HOME/procmail.log
LOG="
"

procmail.log

procmail: Match on "^From.*tim@mydomain.*"
procmail: Assigning "LASTFOLDER=mydomain"
procmail: Opening "mydomain"
procmail: Acquiring kernel-lock
procmail: Notified comsat: "tim@0:/home/tim/mydomain"
From tim@mydomain  Fri Apr  1 13:04:38 2016
 Subject: test msg
  Folder: test_folder    2519

LOG

Assigning something to this variable writes out the assigned value to the LOGFILE.

Often, you want to include a final newline <- 用來間開每次的 log

LOG="
"

INCLUDERC

Specifies additional rc files containing more recipes for messages to be checked against.

INCLUDERC=$MAILDIR/spam.rc

DEFAULT

Sets the default mailbox where messages that do not match any recipes are placed.

If procmail can not deliver to the DEFAULT location,

the mail ends up in the location specified in the ORGMAIL variable

ORGMAIL

ORGMAIL=${HOME}/Maildir/

Thus, a better '/etc/procmailrc' that copes with this fact would be:

ORGMAIL=${HOME}/Maildir/
DEFAULT=${ORGMAIL}

MAILDIR

Sets the current working directory for Procmail

If set, all other Procmail paths are relative to this directory.

ie.

MAILDIR=$HOME/vmail/$DOMAIN/$USER/Maildir

 


Rule Syntax

 

Syntax

:0 [flags] [ : [locallockfile] ]
* <zero or more conditions (one per line)>
[special-action-character]
<exactly one action line>

Basic Example

:0
* case-insensitive-egrep-regex-1
* case-insensitive-egrep-regex-2
folder_name

:0
* another-case-insensitive-egrep-regex
folder_name

說明

行1: A line starting with ':' marks the beginning of a recipe.

行2: Conditions start with a leading '*',

       everything after that character is passed on to the internal egrep literally

行3: Conditions are ANDed; if there are no conditions the result will be true by default.

Locking

# No locking

:0 flags

# Let Procmail figure out lock file to use.

# use a locallockfile (for this recipe only)

# procmail will use the destination filename

:0 flags:

應用: 沒有加 flag

:0:

# Name a lock file to use.

:0 flags:lockfile

Log

rcfile

# deliver to folder test and stop
:0:
.test/

log

procmail: Assigning "MAILDIR=/home/vmail/MyDomain/MyUser/"
procmail: Locking ".test/.lock"
procmail: Assigning "LASTFOLDER=.test/new/1607486477.20033_1.mail.MyDomain"
procmail: Unlocking ".test/.lock"
 Subject: test@1201
  Folder: .test/new/1607486477.20033_1.mail.MyDomain                1062

special-action-character

  • < — Checks if the message is under a specified number of bytes
  • > — Checks if the message is over a specified number of bytes
  • | — Starts a specified program to process the message
  • ! — In the action line, this character tells Procmail to forward the message to the specified email addresses
  • { and } — Constructs a nesting block, used to contain additional recipes to apply to matching messages

egrep regular expressions

  • !                      # In the condition line, this character inverts the condition.
  • ^                     # matches the beginning of the line
  • $                     # matches the end of the line
  • .                      # Matches any single character
  • (character)*     # match arbitrarily many occurences of (character)
  • (character)?     # Match 0 or 1 instance of (character)
  • [abcdef]          # Match any character enclosed in []
  • expression1|    # expression2     Matches expression1 or expression 2.

 


Procmail Flags

 

* case-sensitive

D — Makes the egrep comparison case-sensitive

Default: case-insensitive

* 連 spamassassin 使用

H — Parses the header of the message and looks for matching conditions. This is the default behavior.

w — Tells Procmail to wait for the specified filter or program to finish,
       and reports whether or not it was successful before considering the message filtered.

* Generate a carbon copy of this mail

Flag: c

* Ignore any write errors on this recipe

Flag: i

* Parses the body

Flag: B

* Wait

w

Wait for the program in the action line to finish before continuing.

Otherwise, Procmail will spawn off the program and leave it executing on its own.

W

Like w, but additionally suppresses any "program failure" messages from the action pipeline.

* # Clone message and execute the action(s) in a subprocess if the conditions match.

Flag: c

 


Sending to Dovecot

 

rcfile

DELIVER="/usr/lib/dovecot/deliver -d $LOGNAME"
DEFAULT="$HOME/Maildir/"
MAILDIR="$HOME/Maildir/"

-d <username>: Destination username.

If given, the user information is looked up from dovecot-auth.

i.e.

# deliver spam to spam folder
:0 w
* ^X-Spam-Status: Yes
| $DELIVER -m Spam

# deliver to INBOX and stop
:0 w
| $DELIVER

 


More Example

 

# 1: Drop Unwanted Sources

:0
* ^From: .*@domain.com
/dev/null

# 2: Forwarding Mail

:0
* ^Subject: .*something-or-other
! [email protected]

# 3: from a particular sender places it in a specified folder (Maildir)

a)

DEFAULT=$HOME/Maildir/
MAILDIR=$HOME/Maildir/

:0
* ^From: @MYDOMAIN
.MYDOMAIN/

b)

DEFAULT=$HOME/Maildir/
MAILDIR=$HOME/Maildir/

:0:
* ^X-Spam-Status: Yes
.Junk/

# 4: {...}

1. Have the word "AAA" in the subject

2. Have the word "BBB" in the text

3. Do not have the words "CCC" or "DDD" in the text

:0
* ^Subject:.*AAA.*                 # subject condition
* !^X-Loop: [email protected]  # prevent mail loops
{
   :0 c B     # c: make sure you still receive the mail, B: check body instead of header
   * BBB      # body conditions
   * !CCC
   * !DDD
   | (formail -r -A"X-Loop: [email protected]" ; echo "This is my reply") | $SENDMAIL -t
}

 


Work with spamassassin

 

~/.procmailrc

INCLUDERC=/etc/mail/spamassassin/spamassassin-default.rc   # By spamc
INCLUDERC=/etc/mail/spamassassin/spamassassin-spamc.rc     # By spamd

將 spam mail 放到某 spam 資料夾

:0 Hw
* ^X-Spam-Status: Yes
spam

 


 

 

Creative Commons license icon Creative Commons license icon