Distributed James Server — Matchers
This documentation page lists and documents Matchers that can be used within the Distributed James Server MailetContainer in order to write your own mail processing logic with out-of-the-box components.
Supported matchers
AtLeastPriority
Numeric value. The priority of this mail should be at least the specified value to be matched.
Inclusive.
AtMost
Checks that a mail did at most X executions on a specific operation.
If no executions have been performed previously for Y attribute, it will be set up. In the mail, every time the check succeeds, its counter will be incremented by one. The check fails when the defined X limit is reached.
-
X - count of how many times a specific operation is performed
-
Y - name of attribute represented for specific operation executions, default value is: AT_MOST_EXECUTIONS
The example below will match a mail with at most 3 executions on the mailet with attribute name AT_MOST_EXECUTIONS
<mailet match="AtMost=AT_MOST_EXECUTIONS:3" class="<any-class>"> </mailet>
AtMostPriority
Numeric value. The priority of this mail should be at most the specified value to be matched.
Inclusive.
DLP
Enable evaluation of incoming emails against DLP rules (Data Leak Prevention) attached to the sender domains.
Example:
<mailet match="DLP" class="ToRepository"> <repositoryPath>/var/mail/quarantine</repositoryPath> </mailet>
Rules can be administered via webAdmin.
Only available on top of Memory and Cassandra storages.
Additionally a cache can be added to reduce queries done to the underlying database.
Example:
<mailet match="DLP=cache:60s" class="ToRepository"> <repositoryPath>/var/mail/quarantine</repositoryPath> </mailet>
Will query the DLP rules for a given domain only every 60 seconds.
Please note that querying DLP rules on top of Cassandra relies on Event sourcing, involves reading a potentially large event stream and involves some SERIAL reads (LightWeight transactions) for each processed emails.
Efficiency of the cache can be tracked with the following metrics:
-
dlp.cache.hitRate
-
dlp.cache.missCount
-
dlp.cache.hitCount
-
dlp.cache.size
FetchedFrom
Matches mail with a header set by Fetchpop X-fetched-from
fetchpop sets X-fetched-by to the "name" of the fetchpop fetch task.
This is used to match all mail fetched from a specific pop account.
Once the condition is met the header is stripped from the message to prevent looping if the mail is re-inserted into the spool.
HasException
This Matcher determines if the exception specified in the condition or the subclasses of it has occurred during the processing of the mail. If true, all recipients are returned, else null. This matcher presupposes that the exception has been captured as a Mail attribute org.apache.mailet.Mail#MAILET_ERROR_ATTRIBUTE_NAME in the process.
Sample configuration:
<mailet match="HasException=org.apache.james.managesieve.api.ManageSieveException" class="<any-class>">
HasHeader
use:
<mailet match="HasHeader={<header>[=value]}+" class="..." />
This matcher checks if the header is present in the message (global) and per recipient (specific). It complements the AddHeader mailet.
HasHeaderWithPrefix
Matches emails with headers having a given prefix.
If a header with the given prefix is found in the message (global) all recipients will be matched. If a header with the given prefix is found per recipient (specific), only these will be matched.
Otherwise, no recipient in returned.
use:
<mailet match="HasHeaderWithPrefix=PREFIX" class="..." />
HasMailAttribute
This Matcher determines if the mail contains the attribute specified in the condition, and returns all recipients if it is the case.
Sample configuration:
<mailet match="HasMailAttribute=whatever" class="<any-class>">
HasMailAttributeWithValue
This Matcher determines if the mail contains the attribute specified in the condition and if the value answered when the method toString() is invoked on the attribute is equal to the String value specified in the condition. If both tests are true, all recipients are returned, else null.
Notes:
The current matcher implementation expects a single String value to match on. This matcher requires two values, the attribute name and attribute value. This requires some implicit rules to govern how the single value supplied to the matcher is parsed into two values.
-
In the match condition, the split between the attribute name and the attribute value is made at the first comma. Attribute names that include a comma will parse incorrectly and therefore are not supported by this matcher.
-
Leading and trailing spaces are removed from both the attribute name and attribute value specified in the condition and the tested attribute value in the mail prior to matching. Therefore, "abc" , " abc", "abc " and " abc " are considered equivalent.
-
To test for an empty string, do not specify an attribute value after the comma.
Sample configuration:
<mailet match="HasMailAttributeWithValue=name, value" class="<any-class>">
HasMailAttributeWithValueRegex
This Matcher determines if the mail contains the attribute specified in the condition and that attribute matches the supplied regular expression, it returns all recipients if that is the case.
Sample configuration:
<mailet match="HasMailAttributeWithValueRegex=whatever,<regex>" class="<any-class>">
Note: as it is not possible to put arbitrary objects in the configuration, toString() is called on the attribute value, and that is the value matched against.
HasMimeType
This matcher checks if the content type matches.
This matcher does not walk down the mime tree and stops at the top level mime part.
use:
<mailet match="HasMimeType=text/plain,text/html" class="..." />
HasMimeTypeParameter
This matcher checks if the content type parameters matches.
use:
<mailet match="HasMimeTypeParameter=report-type=disposition-notification,report-type=other" class="..." />
HasPriority
Numeric value. The priority of this mail should be equal to the specified value to be matched.
IsMarkedAsSpam
Matches mails having a org.apache.james.spamassassin.status per recipient header with a Yes value.
As an example, here is a part of a mailet pipeline which can be used in your LocalDelivery processor:
<!-- SpamAssassing mailets pipeline --> <mailet match="RecipientIsLocal" class="SpamAssassin"> <spamdHost>spamassassin</spamdHost> <spamdPort>783</spamdPort> </mailet> <mailet match="IsMarkedAsSpam" class="WithStorageDirective"> <targetFolderName>Spam</targetFolderName> </mailet> <!-- End of SpamAssassing mailets pipeline -->
In order to use this with rspamd
, we need to declare a condition for the matcher
and drop the Rspamd jar (third-party/rspamd) in the James extensions-jars folder.
Eg: With the recipient header for Rspamd being org.apache.james.rspamd.status,
then the configuration would be:
<!-- Rspamd mailets pipeline --> <mailet match="IsMarkedAsSpam=org.apache.james.rspamd.status" class="WithStorageDirective"> <targetFolderName>Spam</targetFolderName> </mailet>
IsOverQuota
This matcher will check if the incoming email will make recipients exceed their quotas.
Here is a configuration example:
<mailet match="IsOverQuota" class="<any-class>"/>
IsRemoteDeliveryPermanentError
Checks if the mail has a permanent remote delivery failure attribute
Example:
<mailet match="IsRemoteDeliveryPermanentError" class="<any-class>"/>
IsRemoteDeliveryPermanentError
Checks if the mail has a temporary remote delivery failure attribute set to false (meaning it’s a temporary error)
Example:
<mailet match="IsRemoteDeliveryTemporaryError" class="<any-class>"/>
IsSenderInRRTLoop
This matcher allow you to know if the sender of an email is part of a RRT loop.
This is useful when bouncing upon RRT execution issues: we don’t want to create a bouncing loop (as the execution of that RRT loop will fail).
Example:
<mailet match="IsSenderInRRTLoop" class="<any-class>"/>
IsX509CertificateSubject
Checks if the subject of a X509Certificate contains the supplied string. The certificate is read from the specified mail attribute.
If the specified attribute contains more than one certificate the matcher matches if at least one of the certificates contains the given string.
Configuration string:
-
mailAttribute;string
RecipientDomainIs
This will return recipients matching a configured domain.
Sample configuration:
<mailet match="RecipientDomainIs=<domain.com>" class="<any-class>"/>
RecipientIs
This matcher matches a specific recipient (in the envelope of the mail), passed as a condition to this matcher.
The example below will match only the recipient user@domain
<mailet match="RecipientIs=user@domain" class="<any-class>"> </mailet>
RecipientIsRegex
Matches recipients whose address matches a regular expression.
Is equivalent to the SenderIsRegex matcher but matching on the recipient.
Configuration string: a regular expression.
<mailet match="RecipientIsRegex=<regular-expression>" class="<any-class>">
The example below will match any recipient in the format user@log.anything
<mailet match="RecipientIsRegex=(.*)@log\.(.*)" class="<any-class>"> </mailet>
RemoteAddrInNetwork
Checks the IP address of the sending server against a comma-delimited list of IP addresses, domain names or sub-nets.
See AbstractNetworkMatcher for details on how to specify entries.
RemoteAddrInNetwork
Checks the IP address of the sending server against a comma-delimited list of IP addresses, domain names or sub-nets.
See AbstractNetworkMatcher for details on how to specify entries.
SenderDomainIs
SenderDomainIs will look at the envelope sender’s domain. If equal to configured value, then all recipients will be returned. Otherwise an empty list will be returned.
Sample configuration:
<mailet match="SenderDomainIs=<domain.com>" class="<any-class>">
SenderHostIs
Checks the sender’s displayed domain name against a supplied list.
Sample configuration:
<mailet match="SenderHostIs=domain.com" class="ToProcessor"> <processor> spam </processor> </mailet>
SenderIs
This matcher matches a specific sender, passed as a condition to this matcher.
The example below will match mail with a sender being user@domain
<mailet match="SenderIs=user@domain" class="<any-class>"> </mailet>
SenderIsNull
Matches mails that are sent by a null sender.
<mailet match="SenderIsNull" class="<any-class>">
SenderIsRegex
Matches mails that are sent by a sender whose address matches a regular expression.
Is equivalent to the RecipientIsRegex matcher but matching on the sender.
Configuration string: a regular expression.
<mailet match="SenderIsRegex=<regular-expression>" class="<any-class>">
The example below will match any sender in the format user@log.anything
<mailet match="SenderIsRegex=(.*)@log\.(.*)" class="<any-class>"> </mailet>
Another example below will match any sender having some variations of the string mp3 inside the username part.
<mailet match="SenderIsRegex=(.*)(mp3|emmepitre)(.*)@" class="<any-class>"> </mailet>
SentByMailet
This matcher matches email sent automatically by mailets.
<mailet match="SentByMailetAny" class="<any-class>"/>
This matcher allows you, for instance, to enable/disable routing automatically generated emails out of your server.
SizeGreaterThan
Checks whether the message (entire message, not just content) is greater than a certain number of bytes. You can use 'k' and 'm' as optional postfixes.
In other words, "1m" is the same as writing "1024k", which is the same as "1048576".
SMTPAuthSuccessful
Matches mails that are sent by an SMTP authenticated user.
If the sender was not authenticated it will not match.
<mailet match="SMTPAuthSuccessful" class="<any-class>">
SMTPAuthUserIs
Matches mails that are sent by an SMTP authenticated user present in a supplied list.
If the sender was not authenticated it will not match.
Configuration string: a comma, tab or space separated list of James users.
<mailet match="SMTPAuthUserIs=<list-of-user-names>" class="<any-class>">
SMTPIsAuthNetwork
Matches mails that are sent by a client which is allowed to relay.
<mailet match="SMTPIsAuthNetwork" class="<any-class>">
Experimental matchers
AttachmentFileNameIs
Checks if at least one attachment has a file name which matches any element of a comma-separated or space-separated list of file name masks.
Syntax: match="AttachmentFileNameIs=[-d] [-z] masks"
The match is case insensitive.
File name masks may start with a wildcard '\*'.
Multiple file name masks can be specified, e.g.: '*.scr,\*.bat'.
If '-d' is coded, some debug info will be logged.
If '-z' is coded, the check will be non-recursively applied to the contents of any attached '*.zip' file.
CommandForListserv
Returns positive if the recipient is a command for a listserv. For example, if my listserv is james@list.working-dogs.com, this matcher will return true for james-on@list.working-dogs.com and james-off@list.working-dogs.com.
CommandListservMatcher
CommandListservMatcher is the matcher that pairs with the CommandListservManager It checks to see if the request is intended for the ListservManager, but doesn’t guarantee that it is a valid command.
To configure, insert this into the config.xml inside of the root processor block.
<mailet match="CommandListservMatcher=announce@localhost" class="CommandListservManager"> ... </mailet>
CompareNumericHeaderValue
Matches mails containing a header with a numeric value whose comparison with the specified value is true.
If the header is missing in the message, there will be no match
Configuration string: The headerName, a comparison operator and the numeric headerValue to compare with, space or tab delimited.
The comparison operators are: <, ⇐, ==, >=, >; another set of operators is: LT, LE, EQ, GE, GT.
Also the following operators are accepted: =<, =, ⇒.
Example:
<mailet match="CompareNumericHeaderValue=X-MessageIsSpamProbability > 0.9" class="ToProcessor"> <processor> spam </processor> </mailet>
InSpammerBlacklist
Checks the network IP address of the sending server against a blacklist of spammers. There are 3 lists that support this…
-
blackholes.mail-abuse.org: Rejected - see http://www.mail-abuse.org/rbl/
-
dialups.mail-abuse.org: Dialup - see http://www.mail-abuse.org/dul/
-
relays.mail-abuse.org: Open spam relay - see http://www.mail-abuse.org/rss/
Example:
<mailet match="InSpammerBlacklist=blackholes.mail-abuse.org." class="ToProcessor"> <processor>spam</processor> </mailet>
Composite matchers
It is possible to combine together matchers in order to create a composite matcher, thus simplifying your Mailet Container logic.
Here are the available logical operations:
-
And : This matcher performs And conjunction between the two matchers: recipients needs to match both matcher in order to match the composite matcher.
-
Or : This matcher performs Or conjunction between the two matchers: consider it to be a union of the results. It returns recipients from the Or composition results of the child matchers.
-
Not : It returns recipients from the negated composition of the child Matcher(s). Consider what wasn’t in the result set of each child matcher. Of course it is easier to understand if it only includes one matcher in the composition, the normal recommended use.
-
Xor : It returns Recipients from the Xor composition of the child matchers. Consider it to be the inequality operator for recipients. If any recipients match other matcher results then the result does not include that recipient.
Here is the syntax to adopt in mailetcontainer.xml:
<processor state="transport" enableJmx="true">
<matcher name="relay-allowed" match="org.apache.james.mailetcontainer.impl.matchers.Or">
<matcher match="SMTPAuthSuccessful"/>
<matcher match="SentByMailet"/>
<matcher match="org.apache.james.jmap.mailet.SentByJmap"/>
<matcher match="RemoteAddrInNetwork=127.0.0.1, 10.2.*, 193.50.151.*"/>
</matcher>
<!-- ... -->
<mailet match="relay-allowed" class="ToProcessor">
<processor>relay</processor>
</mailet>
</processor>