pmx-policy - Interface to the PureMessage policy engine
pmx-policy <command> [options]
The pmx-policy command provides an interface to the PureMessage policy engine.
Note: As of PureMessage 5.2.1, the policy.siv file supports UTF-8 characters beyond the Latin1 range. As a result, certain areas of the policy now accept Japanese characters. See the PureMessage 5.2.1 release notes for details.
The following subcommands are recognized by the pmx-policy
script:
Messages are delivered or quarantined as if they are regular 'live'
messages received by the PureMessage milter (unless the --dry-run option
is specified). If the delivery action of a policy rule is pmx_tempfail
,
discard
or reject
, the message is discarded. When complete,
a report is generated that describes the actions taken for each message.
If the --dry-run option is specified, messages are processed according to the policy script, but is not delivered, discarded or quarantined.
Messages are not deleted from the quarantine unless the --delete option is specified, which causes messages to be moved to the trash after being injected. The --delete option is useful for re-processing quarantined messages with a newly modified policy script; messages are deleted from the quarantine, but are re-quarantined if they trigger that action in the policy script.
The --where option is used to specify the messages in the quarantine that should be processed. Alternatively, the quarantine database ids can be listed explicitly. The syntax of the --where condition can be found in PureMessage::MessageStore.
The following options are recognized:
quarantine_dir
option in the pmx.conf
configuration file.
--dry-run
option is specified. The --no-index
option has no effect unless the --dry-run
option is specified as well.
This option is mainly useful for profiling the filtering engine.
The policy script is executed for each message that is processed. The policy script can test various characteristics of the message, and perform a variety of actions based on the results of those tests. The default policy script is policy.siv and is located in the /opt/pmx/etc directory.
The PureMessage policy script is expressed in Sieve, a mail-filtering language defined by RFC 3028. Sieve is a command-based language; its syntax somewhat resembles C or Perl, but it has no variables or looping constructs. And, like those languages, Sieve is case sensitive. Sieve commands can be either tests, actions or controls. Tests check whether some condition is met. Actions modify the routing or content of the message. Controls modify the control flow in the script.
Commands can have three different kinds of arguments: positional, optional and tagged. Tagged arguments begin with a colon and can appear in any order after a command. Tagged arguments can have zero or more parameters that appear after them.
Positional arguments must appear in order, and must appear after any tagged arguments. Optional arguments are exactly like tagged arguments except that they are optional.
Here is an example policy script:
# Filter out badly formatted mail # and mail from unwanted senders. if anyof (not exists ["From", "Date"], header :contains "From" "unwanted@foo.com") { discard; stop; }
Things to note about this example:
anyof
, not
, exists
and
header
.
discard
.
if
, and stop
.
anyof
and not
tests take other tests as arguments.
The if
control only takes one test as its condition; to
make compound tests you need to use the special allof
and anyof
tests.
exists
test takes a list of strings as an argument.
String-lists are contained in square brackets and delimited by commas.
header
test takes a tagged argument of :contains
,
followed by two string arguments.
The following tags are used by many of the tests and actions described in this document.
ADDRESS-PART
tag specifies the portion
of the address to match against.
user+box1@example.com
is processed as
user@example.com
. You can override this default behavior by specifying the
<:detail
> option. This option can be used in conjunction with <:localpart
>.
:comparator <comparator-name: string>
Where comparator name can be one of:
The <key-list: string-list> parameter, which matches data, is interpreted
differently, depending on the MATCH_TYPE
specified.
There are five possible match types:
The :re match is a PureMessage specific Sieve extension.
:over
and :under
can be combined with the not
test to compare 'at-least' and 'at-most'
the given number, respectively.
if <test1: test> <block1: block>
elsif <test2: test> <block2: block>
else <block>
Description:
The semantics are similar to other languages that use these control commands. When the interpreter sees an 'if', it evaluates the test associated with it. If the test is true, it executes the block associated with it.
If the test of the 'if' is false, it evaluates the test of the first ``elsif'' (if any). If the test of 'elsif' is true, it runs the 'elsif''s block. An 'elsif' may be followed by additional 'elsif' statements, in which case, the interpreter repeats this process until each 'elsif' has been evaluated.
When the interpreter runs out of 'elsif's, there may be an 'else' case. If there is, and none of the 'if' or 'elsif' tests were true, the interpreter runs the 'else' case.
require <capabilities: string-list>
The 'require' control states that a script makes use of a certain extension. It must be stated before anything other than a 'require' can be used. An error occurs if a 'require' is used after a command other than 'require'.
Example:
require ["extension1", "extension2"];
Example:
require "extension1"; require "extension2";
To use any PureMessage specific extension tests or actions (which are prefixed with 'pmx_') in the script, the script must start with:
require "PureMessage";
PureMessage also provides the standard extensions 'reject' and 'envelope' as specified in RFC 3028.
Note that if you 'require ``PureMessage''', you don't need to require 'reject' or 'envelope': they are included implicitly with the ``PureMessage'' extension.
stop
Description: Stop processing the message. When a message hits a stop command, it immediately stops processing and its 'delivery action' is executed. If no delivery action has been set on the message, the default action is 'keep'. If a message reaches the end of a policy script, the 'stop' command is implied.
Parameters: none
Sieve has special tests that are used as logical operators.
allof <test-list>
Description: Returns true if all the tests in test-list return true.
anyof <test-list>
Description: Returns true if any the tests in test-list
return true.
Returns immediately once a true test is found, evaluating left-to-right
(known as 'short-circuit' operation).
false
Description: Always returns false.
not <test>
Description: Returns false if test returns true, and vice-versa.
true
Description: Always returns true.
address [ADDRESS-PART] [COMPARATOR] [MATCH-TYPE] <header-list: string-list> <key-list: string-list>
Description: Returns true if any email address in the 'To','From','Cc' or 'Bcc' headers matches.
Parameters:
<header-list: string-list> - list of headers to match against. Can be any of ('To', 'From', 'Cc', 'Bcc').
<key-list: string-list> - match data, which will be interpreted
differently depending on the MATCH_TYPE
.
envelope [COMPARATOR] [ADDRESS-PART] [MATCH-TYPE] <envelope-part: string-list> <key-list: string-list>
Description: Returns true if any either the envelope sender or any envelope recipients' addresses match.
Parameters:
<envelope-part: string-list> - list of envelope parts to match against.
Possible values:
'to' - match the envelope recipient
Note: When using this test in conjunction with email addresses that
have been associated as part of a Recipient aliases map, you must ensure that the
'to' value specified here matches the ``Map To'' portion of the address map.
For example, if service@example.com
has been mapped to joe@example.com
,
then the 'to' address is joe@example.com
. For more information, see
'Address Maps' in the Policy Rules section of the Administrator's Reference.
'from' - match the envelope sender
'group' - pick up the sender or recipient(s)
group(s)
based on message's
direction and match them against the provided key-list
<key-list: string-list> - match data, which will be interpreted
differently depending on the MATCH_TYPE
.
Description: Returns true if any header in header-names
exists within the message.
Parameters:
<header-names: string-list> - headers to look for
header [COMPARATOR] [MATCH-TYPE] <header-names: string-list> <key-list: string-list>
Description: Returns true if the value of any header in header-names
matches.
Parameters:
<header-names: string-list> - headers to match against
[MATCH-TYPE] <key-list: string-list> - see MATCH-TYPE
section
pmx_relay [:fur] [MATCH_TYPE] <key-list: string-list>
Description: Returns true if IP or hostname of the connecting MTA/MUA matches.
Parameters:
:fur - If present, modifies the test to use first untrusted relay detection.
[MATCH-TYPE] <key-list: string-list> - see MATCH-TYPE
section
Description: Returns true if the proportion of 8bit (non-ASCII) characters in a message is over or under a certain number. This can be used to check whether a message is 7bit-clean (pure ASCII).
Parameters:
[NUMERIC-COMP] <limit:number> - see NUMERIC-COMP
section. limit
must be
an integer between 0 and 100.
pmx_attachment_name [:tft] [MATCH-TYPE] <key-list: string-list>
Description: Returns true if an attachment name matches a value in key-list
.
Searches the Content-Type and Content-Disposition headers as well as the files
themselves for the filename(s)
you have specified.
Archives are automatically expanded, so that files within other files can be tested. PureMessage will search as many levels as necessary (up to a configured maximum) to find specified file types. The maximum recursion depth is set in /opt/pmx/etc/tft.conf.
Can be used to do attachment-specific filtering. Expands the %%ATTACHMENT_NAMES%%
template variable.
Note: Because this test also returns true whenever PureMessage is unable to scan
a message, you should use the pmx_cantscan
test within pmx_attachment_name
to specify how unscannable messages are handled.
Parameters:
:tft - if present, modifies the test to use true file type detection. The file itself is examined in addition to the filename shown in the Content-Type and Content-Disposition headers.
Tests for document types should use the application-specific file extension (such as .doc or .xls). To view a list of extensions that PureMessage supports, run:
pmx-list-true-filetypes --verbose
The following example uses pmx_attachment_name to detect Microsoft Excel documents:
if pmx_attachment_name :tft :matches "*.xls" { pmx_mark1 "MSExcel"; }
[MATCH-TYPE] <key-list: string-list> - see MATCH-TYPE
section
pmx_attachment_size [NUMERIC-COMP] <limit: number>
Description: Returns true if the size of any attachment (including
text/plain and text/html message body parts) is over or under limit
.
Can be used to do attachment-specific filtering. If no size unit is
specified, the default is bytes. To specify an alternate size unit,
append 'K' (kilobytes), 'M' (megabytes) or 'G' (gigabytes) to the
number. Expands the %%ATTACHMENT_NAMES%%
template variable.
Parameters:
[NUMERIC-COMP] <limit: number> - see NUMERIC-COMP
section
pmx_attachment_true_filetype [MATCH-TYPE] <key-list: string-list>
Description: Returns true if file attachments match a file type specified in
key-list
. The advantage of using this test over similar tests
(pmx_attachment_type
and pmx_attachment_name
) is that the action is not
performed on a message unless the file type is a true match for one that is
specified in this test.
For example, the pmx_attachment_type
test will perform the action if there is
a file type match in the message's Content-Type header, even if that does not
represent the true identity of the file. So, it could be that a message appears
to contain a Microsoft Word attachment, but the file extension has been
falsified, and the message actually contains a .jpeg file instead.
Important: This test can be used to detect specific file types or groups of
file types. Run pmx-list-true-filetypes
to display a list of true filetype
groupings. Run pmx-list-true-filetypes --verbose
to also display the
individual file extensions included in each group. When using this test, you
should specify the appropriate true filetype definition (as displayed in the list
of groupings) in the :contains
argument.
For example, you could create a rule that applies to all Microsoft Word document files, ranging from Word 95 to the most recent Word document extensions:
if pmx_attachment_true_filetype :contains "Document/Microsoft Word" { pmx_mark1 "MS Word Document"; stop; }
To create a rule that detects only Word 2007 documents:
if pmx_attachment_true_filetype :contains "Document/Microsoft Word-OPC" { pmx_mark1 "MS Word Document"; stop; }
To create a rule that quarantines any message with an attached image:
if pmx_attachment_true_filetype :contains "Image/" { pmx_mark1 "Image"; pmx_quarantine "Image"; stop; }
You can use pmx_attachment_true_filetype
to target file types that PureMessage
was not able to identify. This is done by specifying the ``Data/Binary'' group, as
shown below:
if pmx_attachment_true_filetype :contains "Data/Binary" { pmx_mark1 "UnknownFileType"; pmx_quarantine "UnknownFileType"; stop; }
Note: Because this test also returns true whenever PureMessage is unable to
scan a the message, you should use the pmx_cantscan
test within
pmx_attachment_true_filetype
to specify how unscannable messages are handled.
Expands the %%ATTACHMENT_NAMES%%
template variable.
Parameters:
[MATCH-TYPE] - <key-list: string-list> - see MATCH-TYPE
section
pmx_attachment_type [:tft] [MATCH-TYPE] <key-list: string-list>
Description: Returns true if an attachment Content-Type header or the contents
of a file itself match a value in key-list
. Archives are automatically
expanded, so that files within other files can be tested. PureMessage will
search as many levels as necessary (up to a configured maximum) to find
specified file types. The maximum recursion depth is set in
/opt/pmx/etc/tft.conf.
Can be used to do attachment-specific filtering. Expands the
%%ATTACHMENT_NAMES%%
template variable.
Note: Because this test also returns true whenever PureMessage is unable to
scan a message, you should use the pmx_cantscan
test within pmx_attachment_type
to specify how unscannable messages are handled.
Parameters:
:tft - if present, modifies the test to use true file type detection. The file itself is examined in addition to the Content-Type header.
Tests for attachment types should use the Mime file type. For a complete list of the Mime types that PureMessage supports, run:
pmx-list-true-filetypes --verbose
To create a rule, for example, that detects Excel attachments:
if pmx_attachment_type :tft :matches "application/ms-excel" { pmx_mark1 "MSExcel"; }
[MATCH-TYPE] <key-list: string-list> - see C<MATCH-TYPE> section
pmx_body_size [NUMERIC-COMP] <limit: number>
Description: Returns true if the size of the body is over or under the number given. If no size unit is specified, the default is bytes. To specify an alternate size unit, append 'K' (kilobytes), 'M' (megabytes) or 'G' (gigabytes) to the number.
Parameters:
[NUMERIC-COMP] <limit: number> - see NUMERIC-COMP
section
pmx_cantscan
Description: Returns true if a message could not be scanned. Must
be called after pmx_attachment_name
, pmx_attachment_true_filetype
,
pmx_attachment_type
, pmx_credit_card
, pmx_phrase
, or
pmx_suspect_attachment
to be effective.
This test is mainly used to differentiate between messages that cannot be scanned for some reason (e.g., an unrecognized file type), and messages that contain undesired content, since both will cause the various content tests to return true.
The kinds of unscannable content that PureMessage should allow or deny can be
customized by editing the files in /opt/pmx/etc/scanlimit.d/. To configure
unscannable content options for the pmx_phrase
and pmx_credit_card
tests,
use /opt/pmx/etc/scanlimit.d/phrase.conf. For the attachment tests, use
/opt/pmx/etc/scanlimit.d/tft.conf. See the tft.conf and phrase.conf man
pages for more information.
Parameters:
None
pmx_credit_card [:attachments] [:scanall]
Description: Returns true if the message contains any numeric sequences that are common to major credit cards. This test is based on the Luhn algorithm, a checksum formula that performs the validation. Supported credit cards are American Express, MasterCard, Visa, Visa Electron, Discover Card, Diners Club, and China Union Pay.
The creditcard_number_limit
setting in /opt/pmx/etc/creditcard.conf
determines how many numeric sections PureMessage will scan in a given message.
By default, PureMessage scans nine separate sections of numbers that might
contain credit card numbers before proceeding to the next stage of processing.
You can configure the scan failure actions for this test in /opt/pmx/etc/scanlimit.d/phrase.conf.
Note: Because this test also returns true whenever PureMessage is unable to
scan a message, you should use the pmx_cantscan
test within pmx_credit_card
to specify how unscannable messages are handled.
Parameters:
:attachments - If specified, pmx_credit_card
also matches inside of
attachments, including attachments contained in .tgz and .zip files. For
example, it can detect a phrase that appears in an .xls file, which is embedded
in a .doc file that is inside a .zip file.
:scanall - When specified together with the :attachments parameter, this test scans all attachments regardless of whether a match is found. If you only specify the :attachments parameter, the associated action is performed as soon as the first match is found, so any remaining attachments are not scanned. This is a concern if you are combining the pmx_credit_card test with actions such as pmx_drop_attachment because only the attachment in which the first match occurred would be dropped; the remainder would be delivered, regardless of their contents.
pmx_dkim_verify [MATCH-TYPE] pass none fail invalid
DomainKeys Identified Mail (DKIM) is an authentication framework used to sign and validate a message, based on the domain of the sender. This test performs the validation by verifying the origin of the sending address. To configure PureMessage to add a DKIM signature to some or all outgoing messages, see pmx_dkim_sign.
DKIM verification depends on access to public keys stored on an available DNS server. This must also be configured for this test to take affect. For general information, see www.dkim.org.
Important: To ensure the effectiveness of this test, it is recommended that you insert it ahead of spam tests in the policy. It is particularly crucial that this test be run before tests that modify message headers because such modifications could corrupt or remove the DKIM signature.
Description: When specified, PureMessage can verify the origin of messages that bear a DomainKeys Identified Mail (DKIM) signature. This test returns true if the message matches the value specified.
Create multiple tests to allow for the four possibilities described in the values below.
Configurable Values:
pass - A signature is detected and verified.
none - there is no DKIM signature.
fail - A DKIM signature is present but cannot be verified.
invalid - The message cannot be verified for some reason. For example, a DNS timeout or an invalid DNS hostname.
To create a rules for all of these values you could, for example, edit your policy as follows:
# attr NAME=DKIM verified as "pass" if pmx_dkim_verify :is "pass" { } # attr NAME=DKIM verified as "none" elsif pmx_dkim_verify :is "none" { } # attr NAME=DKIM verified as "fail" elsif pmx_dkim_verify :is "fail" { pmx_quarantine "DKIM failed"; } # attr NAME=DKIM verified as "invalid" else { pmx_quarantine "DKIM invalid"; }
If you plan to quarantine messages based on certain test results, you may want to create a quarantine digest informing end users that messages have been quarantined for this reason. For more information, see the pmx-qdigest.conf manpage or 'Managing Quarantine Digest Rules' in the Quarantine Tab section of the Manager Reference.
Parameters:
[MATCH-TYPE] pass, none, fail, or invalid
pmx_header_size [NUMERIC-COMP] <limit: number>
Description: Returns true if the size of the header is over or under the number given. If no size unit is specified, the default is bytes. To specify an alternate size unit, append 'K' (kilobytes), 'M' (megabytes) or 'G' (gigabytes) to the number.
Parameters:
[NUMERIC-COMP] <limit: number> - see NUMERIC-COMP
section
pmx_number_of_attachments [NUMERIC-COMP] <limit: number>
Description: Returns true if the number of parts a message has is over or under the number given.
Parameters:
[NUMERIC-COMP] <limit: number> - see NUMERIC-COMP
section
pmx_number_of_recipients [NUMERIC-COMP] <limit: number>
Description: Returns true if the number of recipients for message is over, under or equal to the number specified.
Parameters:
[NUMERIC-COMP] <limit: number> - see NUMERIC-COMP
section
pmx_offensive_word
Description: Returns true if the message contains a word or phrase listed in the ``offensive-words'' list. This test will decode base64/quoted-printable encoded text and will strip out HTML markup before looking for a match.
Parameters: none
pmx_phrase [:attachments] [:scanall] [MATCH-TYPE] <key-list: string-list>
Description: Returns true if the body, subject, or attachments match a value in
key-list
. This test will decode base64/quoted-printable encoded text and will
strip out HTML markup before looking for a match. This test supports both ASCII
and Latin 1 UTF-8 encodings.
Note: Because this test also returns true whenever PureMessage is unable to
scan a message, you should use the pmx_cantscan
test within pmx_phrase
to
specify how unscannable messages are handled.
Parameters:
:attachments - If specified, pmx_phrase also matches inside of attachments, including attachments contained in .tgz and .zip files. For example, it can detect a phrase that appears in an .xls file, which is embedded in a .doc file that is inside a .zip file.
:scanall - When specified together with the :attachments parameter, this test scans all attachments regardless of whether a match is found. If you only specify the :attachments parameter, the associated action is performed as soon as the first match is found, so any remaining attachments are not scanned. This is a concern if you are combining the pmx_phrase test with actions such as pmx_drop_attachment because only the attachment in which the first match occurred would be dropped; the remainder would be delivered, regardless of their contents.
Two variables are available for this test: %%MATCHED_TEXT%% and %%MATCHED_FILE%%. See Contextual Variables for more information.
You can set the maximum attachment size and the maximum time per message scanned in /opt/pmx/etc/phrase.conf.
[MATCH-TYPE] <key-list: string-list> - see MATCH-TYPE
section
Of the the available match-types, only the contains
and re
match-types are recommended for this test. The is
and matches
tests
will compare against the entire text of the message or attachment, which is
usually not desirable when looking for a particular phrase.
pmx_spam_hit [MATCH-TYPE] <key-list: string-list>
Description: Returns true if the name of a spam rule matches the given value. Examples of spam hits are 'RCVD_IN_RFCI', and 'SUSPICIOUS_RECIPS'.
Parameters:
[MATCH-TYPE] <key-list: string-list>
pmx_spam_prob [NUMERIC-COMP] <limit:number>
Description: Returns true if the probability of the message being spam is over
or under the given number. Even if a message passes through several
pmx_spam_prob
tests, the message is only scanned once, and its spam
probability value is saved from the first test. This makes it possible to have
different actions based on different spam probability ranges without having to
scan the message multiple times.
Parameters:
[NUMERIC-COMP] <limit:number> - see the NUMERIC-COMP
section
pmx_suspect_attachment [:tft] [:inspect_archives]
Description: Returns true if the message contains an attachment whose filename matches the ``suspect-attachment-names'' list, or whose content-type matches the ``suspect-attachment-types'' list.
This test searches the attachment itself as well as the Content-Type and Content-Disposition headers for filenames.
The suspect attachment test can be used with the standard delivery actions (reject, discard, pmx_quarantine, etc.), to quarantine, reject or silently discard messages containing suspicious attachments.
Parameters:
:tft - if present, modifies the test to use true file type detection. The file itself is examined as well as the filename and file type as shown in the Content-Type and Content-Disposition headers. Archives (and archives within archives) are automatically inspected by this option.
Note: If the :tft parameter has been specified, the :inspect_archives parameter described below is not required.
:inspect_archives [deprecated] - if present, this test will attempt to inspect attached archives for filenames that match the suspect-attachment-names list. Only ZIP (plain and encrypted) archives are supported. Also, just the top-level archive is inspected - if the archive itself contains an archive, the contained archive is not inspected.
Note: Because this test also returns true whenever PureMessage is unable to
scan a message, you should use the pmx_cantscan
test within
pmx_suspect_attachment
to specify how unscannable messages are handled.
pmx_virus
Description: Returns true if a virus engine detects a virus.
Parameters: none
pmx_virus_id [MATCH-TYPE] <key-list: string-list>
Description: Returns true if the ID of one of the viruses in the message matches a given value.
Parameters:
[MATCH_TYPE] <key-list: string-list> - see the MATCH-TYPE
section
pmx_virus_cantscan
Description: Returns true if virus scanning failed for a message. Must
be called after pmx_virus
to be effective. This test is mainly used
to differentiate between messages that cannot be scanned for some reason
(e.g. encryption), and messages that contain viruses, since both will
cause pmx_virus
to return true. The kinds of unscannable content
that PureMessage should allow or deny can be customized by editing the
etc/virus.d/cantscan.conf file.
Type man cantscan.conf
for more information about cantscan.conf.
Parameters:
None
size [NUMERIC-COMP] <limit: number>
Description: Returns true if the size of the message is over or under the number given. If no size unit is specified, the default is bytes. To specify an alternate size unit, append 'K' (kilobytes), 'M' (megabytes) or 'G' (gigabytes) to the number.
Parameters:
[NUMERIC-COMP] <limit: number> - see NUMERIC-COMP
section
Description: Returns true if the IP address of the sender is listed in the Blocklist data package from SophosLabs. pmx_blocklist traverses the message's ``Received'' headers looking for a match, skipping hosts listed in trusted-relays or internal-hosts. IP addresses in ip-blocking-exceptions are explicitly exempted.
Example:
if pmx_blocklist { discard; }
The pmx_blocklist
test is a policy-level implementation of the MTA-level
IP blocking provided by pmx-blocker. It allows more
flexibility in handling messages from blocked IP addresses and can
provide more information about those messages in the logs. By using the
IP addresses in the ``Received'' headers rather than just the connecting
IP address, pmx_blocklist
is effective even if the PureMessage server
is one or more hops behind the network gateway.
These actions pertain to the routing of a message. Some actions affect the
final destination of a message (deliver
, discard
, reject
),
some trigger another message to be delivered (pmx_notify
, pmx_forward
),
and some alter the recipients of a message (pmx_add_recipient
,
pmx_map_recipients
).
The most common routing actions tell PureMessage what 'delivery action' to take on the message. These are:
When a message encounters one of these actions, its delivery action is set
and cannot be changed, but the message still progresses through the
policy script until it reaches the end of the script or a stop
command.
When the message stops processing, PureMessage analyzes the delivery action
of the message and determines how it should be handled.
discard
Description: Silently throw away the message.
Parameters: none
keep
Description: Deliver the message to its envelope recipients.
Parameters: None
pmx_add_recipient <address: string-list>
Description: Add one or more recipients to the message envelope (as opposed to
redirect
, which replaces the envelope recipients).
Parameters:
<address: string-list> - addresses to add to the message envelope
pmx_deliver_for [:except] [MATCH-TYPE] <key-list: string-list>
Description: Queue messages to specified recipients for delivery, skipping subsequent policy rules. For example:
pmx_deliver_for :memberof ["anti-spam-optouts"];
This rule exempts messages to recipients in the anti-spam-optouts
list from further policy processing and queues them for delivery.
If a message has matching and non-matching SMTP envelope recipients, a copy of the message for the matching recipients is queued for delivery, and another copy for the remaining (non-matching) recipients continues through subsequent policy rules.
Note: Queued messages are not delivered until the pmx-qindex
and
pmx-queue run
scheduled jobs are executed.
Parameters:
[:except] - inverts the match. When present, the non-matching recipients are queued for delivery.
[MATCH-TYPE] <key-list: string-list> - see [MATCH-TYPE] section
pmx_file <reason: string>
Description: File a copy of the message in the quarantine. pmx_file
does not
actually affect the delivery of the message. If called multiple times,
multiple copies of the message are filed in the quarantine. The copy filed
in the quarantine will incorporate any changes made to the message up to that
point by previous actions. Quarantine reasons should be a single word or
identifier; any whitespace is collapsed to single underscores (_).
Parameters:
<reason: string> - reason for filing the message
pmx_forward <address: string-list>
Description: Forward message to the specified addresses. pmx_forward
does not affect the delivery of the message (like pmx_add_recipient
does);
instead, it writes a copy of the message to the outgoing queue, which is
then delivered by pmx-queue
.
Calling pmx_forward
multiple times will cause multiple copies of the message
to be written to the outgoing queue and delivered. pmx_forward
is like a
Bcc or ``blind carbon copy'' in that the original recipients of the message will
not see that the message was forwarded. Note: queued messages are not delivered
until pmx-qindex
and pmx-queue run
are executed.
Parameters:
<address: string-list> - recipient(s)
to forward to.
pmx_map_recipients <map-name: string>
Description: Maps the envelope recipients using a named list lookup. The envelope recipients are looked up in the list, and, if they match, they are replaced with the looked-up value.
Parameters:
<map-name: string> - name of the recipient map, which must be declared in etc/lists.conf.
pmx_notify <":sender" / ":recipients"> [:map <map-name: string>] <":data" / ":file"> <data: string>
Description: Queue a notification email for delivery to the sender or recipients
of a message. Any template variables in the data are expanded. Any lines
up to the first blank line are interpreted as headers. Note: queued messages
are not delivered until pmx-qindex
and pmx-queue run
are executed.
Parameters:
:sender - send a notification to the mail sender
:recipients - send a notification to the recipients (default)
:data - indicates that 'data' should be used verbatim as the email
:file - indicates that 'data' should be interpreted as a filename, and the email text read from the specified file.
[:map <map-name: string>] - optional map specification. The tag :map
followed by the name of a map that applies to the addresses where the
notification is sent.
pmx_quarantine <reason: string>
Description: File a copy of the message in the quarantine and discard the
original. pmx_quarantine
is the equivalent of pmx_file
, followed by
discard
. Quarantine reasons should be a single word or identifier; any
whitespace is collapsed to single underscores (_).
Parameters:
<reason: string> - reason for quarantining the message
pmx_rename_attachment <data: string>
Description: Rename an attachment. The replacement string can use the
%%ATTACHMENT_NAME%%
template variable to provide the original
filename in the replacement name. For example:
if pmx_attachment_name :tft :matches "*.scr" { pmx_rename_attachment "%%ATTACHMENT_NAME%%.warning" }
Parameters:
<data: string> - see DATA-TYPE section
pmx_route [<server: string-list>] [:copy] [:nobounce] <key-list: string-list>
Description: Route the message to a specified server or to multiple servers, usually
for the purpose of archiving or encrypting. Enter the IP address(es)
or fully qualified
hostname(s)
of the server(s)
to which the message should be routed. For example,
you could route all internal mail originating from a company's legal department
to an encryption server, which would then deliver the message.
# attr NAME=Encrypt all mail from Legal if envelope :comparator "i;ascii-casemap" :all :memberof ["from"] ["Legal"] { pmx_route ["EncryptionServer.example.com"]; }
Note: When using pmx_route
, make sure that the relay you specify here is
not also a mail server that is delivering mail via the same server that performed
the routing action. This would cause PureMessage to route mail in a
continuous loop instead of delivering it.
Parameters:
:copy - In addition to processing the message and sending it to its intended destination, PureMessage also sends a copy of the message to the specified server(s). If this option is not used, the message will be routed to the specified server instead of the intended recipient(s).
:nobounce - If the specified routing server is not available, do not bounce the
message. By default, the message is bounced to the original sender. The original
sender receives a notification that is defined in the template
/opt/pmx/etc/templates/Language_Dir
/bounce-on-failure.tmpl.
Note: If, when upgrading to the latest version of PureMessage, an error
message is displayed regarding the smtp_generic_maps
setting in
/opt/pmx/postfix/etc/main.cf, complete the following steps:
smtp_generic_maps
setting is of the type pcre
. For example:
smtp_generic_maps=pcre:PathToMapFile
/(.*)%(.*)@.*/ $1@$2
make
.
These steps may also be necessary if you are using an external Postfix installation. Follow the same instructions, making adjustments for the different file locations.
pmx_tempfail
Description: Signal the MTA to return SMTP error code 421 - service not available.
Parameters: none.
redirect <addresses: string-list>
Description: Redirect the message. The original envelope recipients are replaced.
Parameters:
<addresses: string-list> - the addresses of the new recipients
reject [:rcode <rcode:number> :xcode <xcode: string>] <reason: string>
Description: Reject the message.
Parameters:
<reason: string> - reason for rejecting. The message will be given to the connecting MTA and the sender will see this when the message 'bounces' back to them.
:rcode - optional SMTP rcode
parameter for MTA response. Default is 550.
:xcode - optional SMTP xcode
parameter for MTA response.
pmx_add_banner [:body] [:top] [:charset <charset:rx>] [:header <header-name: string>] [:groupfile <group multifile: string] [:recode] [:ignore <content-type: string>] [:use_html_pre] [DATA-TYPE] <data: string>
Description: Add a custom banner to the body or headers of a message.
If the body
tag is specified, the banner is added to the end of a
message (if the message contains a text part). For HTML parts, the
banner is inserted just before the </BODY> tag. If there is no
</BODY> tag, the banner is inserted just before the
</HTML> tag.
If the top
tag is specified, the banner is prepended to the beginning
of a message. For HTML parts, the banner is inserted immediately after
the <BODY> tag. If there is no <BODY> tag, the banner
is inserted immediately after the <HTML> tag.
If the groupfile
tag is specified, the banner is fetched based on the
group(s)
to which the message belongs and uses the default one assigned
by data
or file
, if there is no group-specific banner(s).
If the message contains both an HTML and a plain text part, the banner
is added to both (unless the ignore
tag is used to ignore one of
these types). If the message contains multiple text parts, the banner
is added to the first one. If the message is multipart, and no
text/plain or text/html part exists, the banner is added in a new
text/plain part at the end of the message.
Banners can include Template Variables. Some template variables are only expanded after particular tests or within rules containing particular tests or actions.
Parameters:
[:body] - Add the banner to the end of the message body.
[:top] - Prepend the banner to the top of the message body.
Note: Choose either :body
or :top
, not both.
[:charset] - specify the character set of the banner so it is only added
to matching message parts. This field can be a string or a regular
expression that matches several aliases of a particular character set.
The test is not case sensitive. For example, Big[_-]5.*
would match
and add a banner to message parts declared as big5
, Big-5
, and
BIG5-HKSCS
. If a character set is not specified, the banner text is added to
all message parts. If the specified character set does not match any message
parts, then no banner is added.
[:groupfile] - specify the group-specific multifile name.
[:header <header-name: string>] - add the banner to the message header
[:recode] - If a header contains encoded words, re-encode it when adding
the banner. This option should be used if pmx_add_banner
garbles the
original encoded header when prepending text.
[:ignore <content-type: string>] - ignore a content-type. For example, to add banners to text/plain parts only, specify ':ignore ``text/html'''.
[:use_html_pre] - when adding the banner to an HTML part, put the banner in HTML <PRE> tags. This preserves text formatting (e.g. newlines and indentation) that would otherwise be lost in the rendered HTML.
[DATA-TYPE] <data: string> - see DATA-TYPE section
Note: When adding a banner by way of a file (:file
), specify the full path
and filename. The contents of the file must be text. The file must be of the
same charset specified in the policy action.
If the banner is specified as 'verbatim' and charset is used, it will only be added successfully if:
Conversion from UTF-8 to iso-2022 does not work correctly for older versions of iconv
(including
versions shipped with Solaris 2.6). To work around this limitation, use an iso-2022-jp file for adding the
banner.
pmx_add_header <key: string> <value: string>
Description: Add a header 'key' with value 'value'. Note: the sendmail specification does not state where (prepended, appended, etc.) the new header will be added.
Parameters:
<key: string> - the header name
<value: string> - the header value
pmx_archive [:original] [:mstore] <filename: string>
Description: Archive the message. By default, a copy of the message is stored
in 'mbox' format (compatible with many mail readers) in the specified directory
and filename. If the :mstore option is specified, messages are stored using
the PureMessage 'message store' directory and file architecture. The :mstore
option is preferable on high-volume systems because archiving to a single file
requires locking, which may slow down message processing.
Parameters:
:original
- If specified, PureMessage archives the original,
unmodified message, prior to any modifications made by the policy script.
Otherwise, the archived message includes modifications made to the message by the
policy script up to the current point in processing.
:mstore
- If specified, the message is saved using the PureMessage message store
directory and file architecture. The 'filename' argument should be a quarantine
identifier in the following format:
dir:/opt/pmx/var/myarchive
The message store directory is created if it does not already exist. Messages within a message store can be manipulated using the message store tools (the pmx-store-expire manpage, the pmx-store-import manpage, etc).
<filename: string> - The path to the archive. When storing a message in mbox format, any text that appears following the final forward slash (/) is interpreted as the filename; if the file already exists, it is overwritten. The directory must be writable by the PureMessage user. If an absolute path is not specified, the path is interpreted as relative to the home directory of the PureMessage user (/opt/pmx/home).
pmx_delete_header [:all / :index <n: number>] <key: string>
Description: Delete header 'key'. The optional :all
parameter deletes all
repeated headers for the given key
and the optional :index
parameter can be
used to specify which header to delete if the header is repeated. The header
indices are zero-based, meaning that the first header is referred to by index 0,
the second by index 1, etc. For example, the third 'Received' header can be
deleted by the command:
pmx_delete_header :index 2 "Received"
Parameters:
<key: string> - the header name
[:all] - the all matched headers
[:index <n:number>] - the header index
pmx_attachment_log
Description: Writes an entry to the message_log that includes the attachment type, attachment size and number of attachments. PureMessage uses this data to generate the Attachment Sizes and Attachment Types reports.
pmx_dkim_sign
Description: DomainKeys Identified Mail (DKIM) is a an authentication framework used to sign and validate a message, based on the domain of its sender. This action signs outgoing messages with a unique DKIM signature. To configure PureMessage to detect and verify DKIM signatures for incoming messages, see pmx_dkim_verify.
In order for this action to take effect, you must configure /opt/pmx/etc/dkim.conf. This configuration file contains the required signing options, and the location of the private key that is used to create the DKIM signature. If you want multiple PureMessage servers in the same domain to share one signature for delivered mail, you must also add the location of the private key to the DomainKeys-Identified-Mail publication, and distribute it to the servers in that domain. See the dkim.conf manpage for more information.
DKIM signatures depend on access to a private key. This must also be configured in order for this action to take effect. For general information, www.dkim.org.
The action appends a signature to messages, and, therefore, should only be applied to rules in the 'Mail from internal hosts' section of the PureMessage policy.
Parameters: none
pmx_drop_attachment
Description: Drop an attachment. Must be used in the same rule as an attachment test, or it has no effect. See Attachment-Specific Filtering and Template Variables.
Parameters: none
pmx_virus_clean <filename: string>
Description: Clean the message of any viruses. pmx_virus_clean
will use all
installed engines capable of cleaning to attempt to clean viruses from the
message. After cleaning, the message is rescanned to ensure that the clean
was successful. If the virus engines are not able to clean the message,
the part containing the virus is replaced by data from a template file.
The name of the template file is specified in the ``filename'' parameter, and
must reside in the folder /opt/pmx/etc/virus.d. The default template
included with PureMessage is called cantclean.tmpl.
Parameters:
<filename: string> - name of the template file to use if cleaning fails
pmx_replace_header [:all / :index <n:number>] <key: string> <value: string>
Description: Replace the header named key
with value
. The optional :all
parameter replaces all repeated headers for the given key
and the optional
:index
parameter can be used to specify which header to replace if the header
is repeated (see pmx_delete_header
for an example). If the header is not
found in the message, the new header is added in a way similar to
pmx_add_header
. Like with pmx_delete_header
, the header indices are
zero-based.
Parameters:
<key: string> - the header name
<value: string> - the new header value
[:all] - the all matched headers
[:index <n:number>] - the header index
pmx_replace_body [:content_type <ct: string>] [:transfer_encoding <te: string>] [DATA_TYPE] <data: string>
Description: Replace an attachment, or the whole body of the message, with
custom text or a file. If used in the same rule as an attachment-test, the
matching attachment(s)
are replaced. If it is used outside of this context,
the entire body of the message is replaced.
Expands the %%ATTACHMENT_NAME%%
, %%ATTACHMENT_TYPE%%
, and
%%ATTACHMENT_SIZE%%
template variables. Can use the
%%ATTACHMENT_NAMES%%
template variable within rules using
pmx_attachment_name
, pmx_attachment_size
, or
pmx_attachment_type
tests.
Parameters:
:content_type <ct: string> - content-type to use in the replaced part. Default is ``text/plain''.
:transfer_encoding <te:string> - transfer encoding to use in the replaced part. Default is ``7bit''. Supported transfer encodings: UTF-8, 7bit, 8bit, base64, quoted-printable, binary.
[DATA-TYPE] <data:string> - see DATA-TYPE
section.
pmx_custom_mark <key: string> <value: string>
Description: Mark the message with a key-value pair. This action should only
be used for custom policy reports. For more information, see
'Admimistrative Groups > Viewing and Managing Reports'. The
message will accumulate marks as it is processed that are written to the
message log (as specified in the <milter> section of the pmx.conf
configuration file) when the message stops processing. These marks can be used
to generate custom statistical reports.
Parameters:
<key: string> - mark key - can consist of alphanumeric characters and underscores.
<value: string> - mark value - arbitrary character string
:overwrite - If present, PureMessage adds a single mark to the message log per message, for any given key. Regardless of the number of actions associated with the key, only one mark is logged.
Important: The :overwrite
parameter should be applied to all
pmx_custom_mark
actions for a specific key, or not at all. Inconsistent use
will affect the accuracy of the custom report.
pmx_log <priority: string> <message: string>
Description: Log a message to the PureMessage log destination
(specified by the 'log_to' parameter in pmx.conf
. The
priority string is one of the following::
"DEBUG" "INFO" "NOTICE" "WARNING" "ERROR" (can also be spelled "ERR") "CRIT" "ALERT" "EMERG"
Parameters:
<priority: string> - the priority string
<message: string> - the message to be logged
pmx_mark <key: string> <value: string>
Description: Mark the message with a key-value pair. The message will
accumulate 'marks' as it is processed that are written to the message log (as
specified in the <milter> section of the pmx.conf
configuration
file) when the message stops processing. If the policy includes pmx_mark
entries with duplicate keys, only the last one that is processed will be
recorded. These marks can be used to generate report data.
Parameters:
<key: string> - mark key - can consist of alphanumeric characters and underscores.
<value: string> - mark value - arbitrary character string
pmx_mark1 <key: string>
Description: Mark the message with given key. The message will
accumulate 'marks' as it is processed that are written to the message log (as
specified in the <milter> section of the pmx.conf configuration
file) when the message stops processing. If the policy includes duplicate
pmx_mark1
keys, only the last one that is processed will be recorded. These
marks can be used to generate report data.
Parameters:
<key: string> - mark key - can consist of alphanumeric characters and underscores, up to a maximum of 64 characters.
pmx_test_mark
Description: Forwards test IDs to the message log (as specified in the
<milter> section of the pmx.conf
configuration file) so that the
pmx-test
script can recognize the messages it injects.
pmx_set_var <template: string> <command: string>
Description: Initialize a template variable with a shell command.
pmx_set_var
will execute the command string, and put the output in a
template variable that can be used in subsequent tests and actions.
Use the %%MESSAGE_FILE%%
template in the command string to determine
the filename of a file containing a message.
Parameters:
<template: string> - a template variable name. Must consist of uppercase alphanumeric characters and underscores.
<command: string> - the shell command to run.
Template variables are used to access information specific to the message that is being processed. Template variables can be used inside any string value in the policy script. They have the form '%%WORD%%'. When the message is being processed, the variable value is substituted for the variables.
Example:
if size :over 10M { pmx_log "INFO" "Found a big message - %%MESSAGE_SIZE%% bytes!"; }
In this example, messages over 10 megabytes will trigger a log entry, and the
%%MESSAGE_SIZE%%
template variable will be converted to the size of the
message, in bytes.
The following template variables are always available:
hostname
command.
Useful in multi-server deployments for identifying which server
processed a given message.
The following variables are available after the pmx_spam_prob
test
has been run on a message:
pmx_spam_prob
.
MY_CUSTOM_RULE+ 4, OVERRIDDEN_RULE! 2, DEFAULT_RULE 1.1
MY_CUSTOM_RULE+ 4.000 Site rule OVERRIDDEN_RULE! 2.000 Default rule description DEFAULT_RULE 1.100 Default rule description
The following variables are available after pmx_blocklist
and
pmx_virus
respectively.
reason
string as determined by pmx_blocklist
(taken from
PureMessage::Blocklist::Data
). It is the same as the reply
string
seen in the SMTP session. Available after a pmx_blocklist
test.
pmx_virus
test.
The following variables are available inside rules containing specific tests or actions:
pmx_rename_attachment
and pmx_replace_body
actions.
pmx_attachment_name
, pmx_attachment_size
, pmx_attachment_type
, or
pmx_attachment_true_filetype
tests or the pmx_rename_attachment
action.
pmx_replace_body
action.
pmx_replace_body
action.
pmx_phrase
test.
pmx_phrase
test.
The pmx_attachment_size
, pmx_attachment_name
and pmx_attachment_type
tests make it possible to filter on specific attachments in a message. Most
tests return immediately after finding a ``match'', but these will scan the whole
message for all attachments that meet the test criteria and save them. If any
matching attachments are found, the test returns true, and the matching
attachments can be acted upon within that rule (i.e. within the following ``if''
block). A simple example of this is:
if pmx_attachment_size :over 10M { pmx_drop_attachment; }
Which will drop (delete) any attachment over 10 megabytes. For more complex filtering, rules should be nested:
if pmx_attachment_size :over 10M { if pmx_attachment_name :matches "*.exe" { pmx_replace_body :data "No large executables allowed, sorry!"; } }
This outermost block will match any attachments over 10 megabytes, and the inner block will match any attachments that are over 10 megabytes AND have an ``.exe'' extension. And so the test in the inner block matches only on the attachments that were matched by the outer block.
It is recommended that the attachment-specific tests are not combined using allof
or anyof
, as these may produce unexpected results. If the test is preceded by
a not
command, the attachments that don't match the test condition are selected.
If a message has attachments, the main part (not the body) is returned as a matching part or a non-matching part according to your test. That means a test as below:
if pmx_attachment_type ["text/plain"] { ... }
on a message like this:
Content-Type: multipart/mixed; boundary="foo" ...
--foo Content-Type: text/plain ...
--foo Content-Type: text/plain ...
--foo--
always returns false for the existence of the main part's content-type.
So, the definition of 'attachment' in pmx_attachment_size
, pmx_attachment_name
and
pmx_attachment_type
commands includes the message's top level as well as any
body parts that are not attachments.
The envelope test can be used to selectively execute parts of the script, based on the recipient of the message. If the message has multiple recipients, PureMessage will split the message into copies and operate on those copies independently, to simulate one-recipient-per-message behavior. Here is an example of opting out of a header being added:
if not envelope :is ["alice@example.com", "bob@example.com", "carol@example.com"] { pmx_add_header "X-Hello" "There"; }
In this example, messages sent to anyone except Alice, Bob, and Carol will have an X-Hello header added.
Multidimensional lists (or multilists) can be used to make tests work on a per-recipient basis. They can be used in place of regular lists in any PureMessage policy test that accepts a :memberof tag for matching against lists. If a multilist is used in one of these tests, PureMessage will use a list belonging to the recipient of the message, rather than using a single ``global'' list for all recipients. Here is an example of using a multilist to implement a per-recipient sender whitelist:
if envelope :memberof "from" "whitelisted-senders-per-user" { pmx_mark1 "Whitelisted"; keep; stop; }
If the envelope sender's address belongs to the recipient's whitelist, this rule will cause the message to be delivered with no further checking.
The policy repository contains Sieve code, both complete scripts and special purpose snippets that can be used to implement your mail policy.
The available commands are:
Copyright (C) 2000-2009 Sophos Group. All rights reserved. Sophos and PureMessage are trademarks of Sophos Plc and Sophos Group.
the pmx manpage, PureMessage::List, PureMessage::MessageStore, perlretut