Filter rules get applied to messages on sent or receive. Each filter has a match condition and a list of ordered actions that are automatically applied server-side when the condition is met. Condition expressions yield a boolean result and are written much like in a programming language, with operators, function calls, the logical connectors AND,OR,NOT. Typical actions consist of tagging the message, setting a priority, a status, redirecting or discarding it automatically.
The filter's direction can be Incoming mail to test the rule only against incoming messages (imported by manitou-mdx), Outgoing mail against messages that are written and sent with Manitou-Mail, Both for both incoming and outgoing, or None to disable the filter altogether.
The user interface has an editor for conditions and actions, launched by the menu command. Below is a screenshot with some sample rules defined:

Filter rule editor
Numbers must be positive integers in base 10. When a number is immediately followed by the letter K, it is multiplied by 1024 (for kilobytes). When it is immediately followed by the letter M, it is multiplied by 1024*1024 (for megabytes), and when followed by G, it is multiplied by 1024*1024*1024 (for gigabytes). The letter after the number can be uppercase or lowercase.
Strings must be enclosed between double quotes or single quotes.
If the first character is a single quote, double quotes can be used in the string as normal characters (example: 'Result of "command"'). Conversely, if the first character is a double quote, single quotes can be used normally inside the string (example: "Scarlett O'Hara")
A string may also contain the enclosing character itself. In this case, the entire string must be started by an backslash before the single or double quote, and the non-terminating occurrence of the enclosing character inside the string must be preceded by a backslash. In addition, to represent a backslash itself in such a string, the backslash character must be doubled.
For example, a regexp that matches single or double quotes could be written as:
\"[\"\']"
Table V.2. Operators for filter expressions
| Operator | Example | Description |
|---|---|---|
! | !condition("urgent") | Logical inverse of the operand. Equivalent to not. |
= | header("Precedence")="bulk" | Test the case insensitive equality of two strings. Equivalent to is |
is | header("Precedence") is "bulk" | Test the case insensitive equality of two strings. Equivalent to the equal sign. |
isnot | to isnot "me@example.com" | This is the logical inverse of the is operator. |
eq | header("Precedence") eq "bulk" | Test the exact equality of two strings (case sensitive). |
ne | header("Precedence") ne "bulk" | This is the logical inverse of the eq operator (case-sensitive equality of strings). |
containcontains | header("from") contains "@domain.net" | True if the left operand contains the right operand, case insensitive. |
!= | now("month")!=12 | Test the inequality of two numeric values. |
== | date("weekday")==1 | Test the equality of two numeric values. |
< | age("days")>=2 | Compare two numeric values, testing for lower, lower or equal, greater, greater or equal. |
=~ | header("subject") =~ "^\[URGENT\]" | True if the left operand matches the regular expression in the right operand, case insensitive. |
!~ | header("subject") !~ "^\[URGENT\]" | True if the left operand does not match the regular expression in the right operand, case insensitive. |
regmatches | header("subject") regmatches "^\[URGENT\]" | True is the left operand against the regular expression matches the right operand, case sensitive. |
and | from is "a@domain.com" AND to is "b@domain.com" | True if both the left operand and right operand evaluate to true. |
or | from is "a@domain.com" OR from is "b@domain.com" | True if either of the left operand or right operand evaluate to true. |
Arbitrarily complex expressions can be written by combining conditions and operators and nested parentheses. Example:
(pg_gen OR pg_interf) AND NOT (header("From") contains "@mydomain.tld")
All the expressions that have at least one action connected to them are evaluated, unless the "Stop filters" action gets triggered.
Expressions may call built-in functions that implicitly refer to the message being filtered. Functions provide information about the messages, the context and meta-data, but they're not allowed to modify anything. On the other hand, filter actions may modify some message properties, such as the priority or certain header fields. In this case, functions that are called subsequently work on the modified data. Another way of expressing this is that the effects of filters will cascade onto the filters.
Table V.3. Built-in filter functions
| Function name | Return type | Arguments | Description |
|---|---|---|---|
age | number |
A time unit as a string, which must be one of "minutes", "hours" or "days".
| Return the time elapsed since the date and time indicated in the Date field of the message, as a number of minutes, hours or days depending on the argument. If the date field cannot be parsed, the result is null. |
body | string | None | Return the entire body of the message. |
cc | string | None | Return a comma-separated list of addresses extracted from the Cc (carbon copy) field. If the Cc field is "John Doe" <john.doe@email.tld>, the cc function will return john.doe@email.tld (whereas header("Cc") would return the entire field). |
condition | boolean | Condition name | Evaluate the named condition and return its result. The name refers to another filter entry. |
date | boolean | Date field | Return the date and time of the message in the local time zone. The possible arguments are the same than for the now() function. |
date_utc | boolean | Date field | Identical to the date() function, except that the date and time is expressed in UTC time instead of the local time zone. |
from | string | None | Return the sender's address extracted from the From field. In the unlikely event that there are several addresses in this field, return a comma-separated list of these addresses. |
header | string | Field name | Return the decoded value of the header field. The line is unfolded and non US-ASCII characters encoded with the RFC-2047 rules have been decoded and converted to unicode. Use rawheader() to access the non-decoded version. |
headers | string | None | Return the decoded value of the entire message header as one big string with consecutive fields separated by a newline character. The lines are unfolded and non US-ASCII characters encoded with the RFC-2047 rules have been decoded and converted to unicode. This function should be used only in the rare cases where it's not adequate to target a specific field with the header() function. |
identity | string | none | Return the email address from our identities that is associated with the message. For an outgoing message, that would normally be the address of the From field. For an incoming message, it is the mail address that is associated with the spool directory from wich the mailfile has been picked up. These associations are declared in manitou-mdx configuration file. |
now | string | Date field | Return the current date and time in the local timezone. The possible arguments and corresponding return values are:
|
now_utc | string | Date field | This is identical to now(),except that it returns the date in UTC time instead of the local timezone. |
rawheader | string | Field name | Return the non-decoded value of the header field, possibly with quoted-printable and base64 contents according to RFC2047. The line is unfolded.Generally the headerfunction should be used instead. |
rawheaders | string | None | Return the non-decoded value of the entire message header as one big string with consecutive fields separated by a newline character, possibly with quoted-printable and base64 contents according to RFC2047. Generally the headersfunction should be used instead. |
The action panel refers to the currently selected condition. It is disabled when no condition is selected. To add an action, select (New action) in the actions list. To remove the currently selected action, use the Del key.
The actions that are currently supported are:
Assign tag: assign a tag to the matching messages. Child tags are expressed flattened as parent_tag->child_tag->grandchild_tag->...
Set status: the argument is a combination of letters: 'R' for read,'A' for archive, all separated by + signs.
Remove header: discard the specified header field. If the field is present multiple times, all its occurrences will be removed.
Set header: set a header field. If the field is already present, the new value will replace the old one in all occurrences of the field, otherwise the field will be added.
Set priority: assign a priority to the matching messages, either as an increment, with the +=X syntax or as an absolute value, with the =X syntax. The priority is an integer number ranging from -32768 to +32767.
Redirect: the argument is an email address to which the matching message is immediately resent.
Delete: dicard the message or put it into the trashcan. The latter is equivalent to having the trashed status.
Stop filters: this is a control-action that instructs the filtering the system that it shouldn't evaluate any more filter rule for the current message.
Set identity: assign a different identity to the message. Each incoming message is associated by manitou-mdx to an identity defined in Preferences/Identities, and each outgoing message is also associated to a sender's identity chosen in the mail composer. The purpose of this action is to override this identity. One practical use is that when replying to an incoming message with an updated identity, the new identity will automatically be pre-selected as the sender of the reply.
Consider alert e-mails sent by a Nagios monitoring system. If they're received outside of business hours, we want to transfer them to some other mail account, for example one that is routed to a mobile phone.
Condition name: alert
Expression: from is "nagios@domain.tld" AND subject contains "** PROBLEM Service Alert"
Actions: none
Condition name: business hours
Expression: (now("hour") >= 9) AND (now("hour") < 18)
Actions: none
Condition name: (not necessary)
Expression: condition("alert") AND (NOT condition("business hours"))
Actions: redirect to mobile's email
Condition name: (not necessary)
Expression: condition("alert") AND condition("business hours")
Actions: set priority to +10
Normally, the presence of a Reply-To field suggests that a reply should go only to the addresses designated by the field, there-by ignoring the From and Cc fields. But this feature is sometimes misused, either by mailing-lists software or by senders who set up their mail account with a Reply-To field always set.
The filtering system provides an action that removes a specific header field. That can be used against these undesirable Reply-To fields. Example:
Expression: from is "specific-email@domain.tld" AND header("reply-to") is "specific-email@domain.tld"
Actions: Remove header field Reply-To
The current day is the first day of the month: now("day")="01" or now("day")==1 (with implicit conversion to numeric).
The year is 2011: now("year")="2011".
The day is exactly the November 17, 2011: now("date")="2011-11-17"
The sender's date on the message is November 17, 2011: date("date")="2011-11-17"