Spam Filter Rules: ForEach

Statement ForEach
Version 2.1.7+
Purpose Causes a loop to be run through for all values within specified criteria

The ForEach statement requires either two or three parameters (depending on the type of loop that is being conducted), in the format

ForEach <loop type> <data> <loop variable name>

On each pass through the loop, the loop variable will contain the current value of the data found.

All ForEach statements must be followed by an EndFor statement

Type Description Data Version
Addr Finds each address contained in the specified header line of the message Header name 2.1.11+
Bag Finds each value in a particular bag, in the order they were added to the bag Bag name 2.2.1+
Header Finds each header line in the message N/A 2.2.1+
MimeSection Finds details of each MIME section in the message. The MIME section details are presented as
<section number>:<IMAP4 section ID>:<MIME type>:<section size>:<number of lines>:<attachment name>
2.1.11+
Recipient Finds each recipient in the recipient list for the message 2.1.7+
Tag Finds each HTML tag contained in the message 2.1.9+
URL Finds each URL contained in the message 2.1.7+

Examples

The following example loops through each URL found in the message, and puts it into the '${FoundURLs}' variable. This is then sent to the log file.

ForEach URL FoundURLs
 Log "${FoundURLs}"
EndFor
#There should be a separate entry in the log file for each URL

The following example loops through each email address found in the 'Reply-To' header field of the message, and puts it into the '${ReplyAddr}' variable. This is then checked against the sender's whitelist.

ForEach Addr Reply-To ReplyAddr
 IfMatch WhiteList ${ReplyAddr}
  ${Score} += 100 [whitelist]
  Break
 EndIf
EndFor

The following example loops through all of the header lines of the message, and look for the 'Received:' header lines

ForEach Header HeaderLine
 IfMatch ${HeaderLine} /^Received:/
# Statements
 EndIf
EndFor

The following example loops through all of the recipients of any locally sent message, and adds the recipient to the spam whitelist

IfMatch SenderIP "local"
 IfMatch Protocol "SMTP"
  ForEach Recipient LoopRcpt
   AddWhiteList ${LoopRcpt}
  EndFor
 EndIf
EndIf

A MIME section result might be

2:1.2:text/plain:3253:20:

This would be the second message body section (section number 0 is the message header). The IMAP4 section ID shows any nesting of the section within any MIME multipart sections. The section MIME type is 'text/plain', the size is 3253 bytes and there are 20 lines in this section. There is no filename associated with this section.

You can use the ForEach MimeSection loop with the GetDecodedSection statement as in the following example, which loops through the MIME sections of a message looking for a non-empty section. The first IfMatch splits out the various parts of the section details. The next If statement checks that the header is not tested (the IMAP4 section ID of the message header is blank). Then, it tests if the section is a text type. If it is, it gets the section contents into the ${SectionText} variable. This is then tested to see if it contains any non-space characters, and if it does, then the ${HasContents} variable is set to 1 and the loop is exited using the Break statement.

ForEach MimeSection SectionInfo
 IfMatch ${SectionInfo} "/^(\d+):([\d\. ]*):(.*?):(\d+):(\d+):(.*)$/"
  ${SectionId} = ${1}
  If ${2} != ""
   IfMatch ${SectionType} "/^text\//i"
    GetDecodedSection ${SectionId} SectionText
    IfMatch ${SectionText} /\S/
     ${HasContents} = 1
     Break
    EndIf
   EndIf
  EndIf
 EndIf
EndFor