7.5. DATA

The DATA context is executed once for every recipient when the message is fully received (but not yet accepted). If multiple types of actions are performed, the response message (sent back to the client) will be choosen in the order of Reject, Defer, Quarantine, Delete, Deliver.

7.5.1. Pre-defined variables

These are the read-only pre-defined variables available for each recipient (on a message).

Variable Type Example Description
$messageid string “18c190a3-93f-47d7-bd...” ID of the message
$senderip string “192.168.1.11” IP address of the connected client
$senderport number 41666 TCP port of connected client
$serverip string “10.0.0.1” IP address of the mailserver
$serverport number 25 TCP port of the mailserver
$serverid string “mailserver:1” ID of the mailserver profile
$senderhelo string “mail.example.com” HELO message of sender
$tlsstarted boolean false Whether or not the SMTP session is using TLS
$saslusername string “mailuser” SASL username
$saslauthed boolean true Whether or not the SMTP session is authenticated (SASL)
$senderdomain string “example.org” Domain part of sender’s address (envelope)
$sender string “test@example.org” E-mail address of sender (envelope)
$senderparams array [“SIZE” => “2048”, ... ] Sender parameters to the envelope address
$recipientdomain string “example.com” Domain part of recipient’s address (envelope)
$recipient string “test@example.com” E-mail address of recipient (envelope)
$recipientdomains array [“example.com”, ...] List of all domain part of all recipient addresses (envelope)
$recipients array [“test@example.com”, ...] List of all recipient addresses (envelope), in order of scanning
$transportid string “mailtransport:1” ID of the transport profile to be used
$actionid number 1 ID; incremented per message action/recipient (Deliver, Quarantine, etc.)

These are the writable pre-defined variables available.

Variable Type Description
$context any Connection-bound variable

7.5.2. Functions

7.5.2.1. Misc

data.GetAddressList(value)

Extract addresses from a header value, often used with From, To and CC headers.

Parameters:value (string) – value to extract e-mail addresses from
Returns:e-addresses
Return type:array
$headerSender = GetAddressList(GetHeader("From"))[0]; // first e-mail address in From header
data.GetMailQueueMetric(options)

Return metric information about the mail queue, it can be used to enforce quotas.

Parameters:options (array) – options array

The following options are available in the options array.

  • metric (string) Metric to be returned; count or bytes. The default is count.
  • filter (array) Any of the available filters, see below. The default is no filters.

The following filters are available in the filters array.

Type Example
senderip $senderip
saslusername $saslusername
sender $sender
senderdomain $senderdomain
recipient $recipient
recipientdomain $recipientdomain
transportid $transportid
retry 1
$queuesize = GetMailQueueMetric(
        [
                "metric" => "bytes",
                "filter" => [
                        "senderdomain" => ["example.com" , "example.net"],
                        "transportid" => "mailtransport:2"
                ]
        ]
) / 1024 / 1024;
if ($queuesize > 500) {
        Defer("Current queue for mailtransport:2 exceeds 500 MiB");
}

Note

If multiple filters of the same type are given using array notation, any of them may match.

7.5.2.2. Routing

data.SetSender(sender)

Change the sender of the message.

Parameters:sender (string) – an e-mail address
Returns:sender if successful
Return type:string or none
Updates:$sender and $senderdomain

Warning

This function changes the sender for all recipients. To change sender per recipient use SetSender() in the Pre-delivery context.

data.SetRecipient(recipient)

Changes the recipient.

Parameters:recipient (string) – an e-mail address
Returns:recipient if successful
Return type:string or none
Updates:$recipient and $recipientdomain
data.SetMailTransport(transportid)

Changes the transport profile.

Parameters:transportid (string) – the transportid to be used
Return type:none
Updates:$transportid
data.SetDelayedDeliver(delay)

If the message is queued, the first delivery attempt is delayed.

Parameters:delay (number) – delay in seconds
Return type:none
data.SetMetaData(array)

Set the metadata for the next recipient(s). The metadata must be an array with both string keys and values.

Parameters:metadata (array) – metadata to set
Return type:none
SetMetaData(["foo" => "bar", "foo2" => json_encode(["array", 123.45, false]));

Note

To work-around the data type limitation of the metadata; data can be encoded using json_encode().

data.SetSenderIP(ip)

Change the senders IP of the message.

Parameters:ip (string) – an IP address
Returns:ip if successful
Return type:string or none
Updates:$senderip

Note

This function changes the $senderip for all recipients.

data.SetSenderHELO(hostname)

Change the senders HELO hostname of the message.

Parameters:hostname (string) – a hostname
Returns:hostname if successful
Return type:string or none
Updates:$senderhelo

Note

This function changes the $senderhelo for all recipients.

7.5.2.3. Headers

data.GetHeader(name[, decode = true])

Return the value of a header (if multiple headers with the same name exists, the first will be returned). The name is not case sensitive.

Parameters:
  • name (string) – name of the header
  • decode (boolean) – if false, the header will not be decoded
Returns:

header value

Return type:

string

data.GetHeaders(name[, decode = true])

Return the value of all headers with the name. If name is boolean true, all headers will be returned. The name is not case sensitive.

Parameters:
  • name (string) – name of the header
  • decode (boolean) – if false, the header will not be decoded
Returns:

headers’ values

Return type:

array

data.AddHeader(name, value[, refold = true])

Add a new header (at the top of the message).

Parameters:
  • name (string) – name of the header
  • value (string) – value of the header
  • refold (boolean) – refold header to 80 characters per line
Return type:

none

data.SetHeader(name, value[, refold = true])

Overwrite existing header(s) or create a new header. The name is not case sensitive.

Parameters:
  • name (string) – name of the header
  • value (string) – value of the header
  • refold (boolean) – refold header to 80 characters per line
Returns:

number of headers changed

Return type:

number

data.PrependHeader(name, value[, refold = true])

Prepend to existing header(s) or create a new header. The name is not case sensitive.

Parameters:
  • name (string) – name of the header
  • value (string) – value of the header
  • refold (boolean) – refold header to 80 characters per line
Returns:

number of headers changed

Return type:

number

data.AppendHeader(name, value[, refold = true])

Append to existing header(s) or create a new header. The name is not case sensitive.

Parameters:
  • name (string) – name of the header
  • value (string) – value of the header
  • refold (boolean) – refold header to 80 characters per line
Returns:

number of headers changed

Return type:

number

data.DelHeader(name)

Delete all headers by the name. The name is not case sensitive.

Parameters:name (string) – name of the header
Returns:number of headers deleted
Return type:number
data.GetRoute([extended_result = false])
Parameters:extended_result (boolean) – include more information
Returns:the message’s Received header(s) parsed in a usable format
Return type:array
data.GetDSN()

Parse a DSN message.

Returns:information about a DSN message
Return type:array or false
data.GetDSNHeader(name[, skip_decode = false])

Same as GetHeader except it works on attached DSN messages. The name is not case sensitive.

Parameters:
  • name (string) – the header
  • skip_decode (boolean) – if decoding should be skipped (return raw)
Returns:

the header value

Return type:

string

7.5.2.4. Actions

data.Deliver([options])

Deliver the message.

Parameters:options (array) – an options array
Returns:doesn’t return, script is terminated
Updates:$actionid

The following options are available in the options array.

  • recipient (string) set the recipient. The default is $recipient.
  • transportid (string) set the transportid. The default is $transportid.
  • metadata (array) add additional metadata to the message (KVP). same as SetMetaData().
  • delay (number) same as SetDelayedDeliver(). The default is 0 seconds.
  • done (boolean) if the function should terminate the script. Same as calling Done(). The default is true.
  • queue (boolean) deliver the message using the delivery queue. The default is true.
  • disconnect (boolean) disconnect the client. The default is false.
data.Reject([reason[, options]])

Reject (550) a message. If reason is an array or contains \n it will be split into a multiline response.

Parameters:
  • reason (string or array) – reject message with reason
  • options (array) – an options array
Returns:

doesn’t return, script is terminated

Updates:

$actionid

The following options are available in the options array.

  • disconnect (boolean) disconnect the client. The default is false.
data.Defer([reason[, options]])

Defer (421) a message. If reason is an array or contains \n it will be split into a multiline response.

Parameters:
  • reason (string or array) – reject message with reason
  • options (array) – an options array
Returns:

doesn’t return, script is terminated

Updates:

$actionid

The following options are available in the options array.

  • disconnect (boolean) disconnect the client. The default is false.
data.Delete()

Delete the message (and return 250).

Returns:doesn’t return, script is terminated
Updates:$actionid
data.Quarantine(quarantineid[, options])

Quarantine or archive a message.

Parameters:
  • quarantineid (string) – the quarantine profile
  • options (array) – an options array
Returns:

doesn’t return, script is terminated

Updates:

$actionid

The following options are available in the options array.

  • recipient (string) set the recipient. The default is $recipient.
  • transportid (string) set the transportid. The default is $transportid.
  • metadata (array) add additional metadata to the message (KVP). same as SetMetaData().
  • done (boolean) if the function should terminate the script. Same as calling Done(). The default is true.
  • reject (boolean) if the function should return an 500 error. The default is true.
  • reason (string) the reason to report. The default is a system generated message.
data.DiscardMailDataChanges()

Discard any content changes to the message.

Returns:number of changes discarded
Return type:number
data.Done()

Finishes the execution of the current recipient without doing an additional action. If a message is scanned without any action, it will be deferred.

Returns:doesn’t return, script is terminated

7.5.2.5. Anti-spam and anti-virus

data.ScanRPD([options])

Scan the message using CYREN RPD.

Parameters:options (array) – options array
Returns:score or refid
Return type:number or string

The following options are available in the options array.

  • refid (boolean) Return RefID (used to report FN and FP). The default is false.
Score Description
0 Unknown
10 Suspect
40 Valid bulk
50 Bulk
100 Spam
data.ScanRPDAV()

Scan the message using CYREN RPD’s outbreak anti-virus.

Returns:score
Return type:number
Score Description
0 Unknown
50 Medium probability
100 High probability
data.ScanSA([options])

Scan the message using SpamAssassin.

Parameters:options (array) – options array
Returns:score or rules
Return type:number or array

The following options are available in the options array.

  • rules (boolean) Return rules in an associative array with scores. The default is false.
Builtin rules Score Description
NOT_SCANNED_TOO_BIG 0 Message was to big too big to be scanned
NOT_SCANNED_QUEUE_TOO_LONG 0 Queue was too long to SpamAssassin

A score of 5 or higher is what most people accept to be considered spam.

data.ScanKAV()

Scan the message using the commercial anti-virus.

Returns:any viruses found
Return type:array
data.ScanCLAM()

Scan the message using CLAM anti-virus.

Returns:any viruses found
Return type:array
data.ScanDLP([patterns[, options]])

Scan a message using the builtin DLP engine.

Parameters:
  • patterns (array) – array of pre-configured rules or an array of custom rules
  • options (array) – options array
Returns:

all patterns found (may include ERR_ rules even if not explicitly given in the patterns argument)

Return type:

array

The following options are available in the options array.

  • stop_on_match (boolean) processing the mail when one match (of the requested type) is found. The default is false.
  • timeout (number) set an approximate timeout time in seconds. The default in no timeout.
  • recursion_limit (number) how deep to dig through MIME trees, archive files (such as ZIP), etc. The default is 9.
  • partid (boolean) return a data structure with the partid where the pattern is found. The default is false.

The patterns array may either be an array of pre-configured rules by name.

["RULE1", "RULE2", ...]

Or a custom rule with the patterns provided. A custom rule may contain multiple types (eg. filename, sha1hash etc.) with multiple patterns each. The available types may be extracted from the DLP configuration.

["RULE1" => ["filename" => ["\\.exe$", "\\.zip$"], "sha1hash" => ["..."]], ...]

Warning

Do not allow untrusted users to add custom regular expression, since not all regular expressions are safe. All user data should be escaped using pcre_quote() before compiled into a regular expression.

There are some builtin rules which may occur.

Builtin rules Description
ERR_UNKNOWN_ERROR An unknown error occurred (more details may be available in the log)
ERR_PASSWORD_PROTECTED The archive is password protected
ERR_RECURSION_LIMIT The archive is too nested

7.5.2.6. DKIM

data.ScanDMARC()

Returns the DMARC policy to apply to the message for the From-address. It will return an associative array containing the domain as result. If the domain cannot be properly extracted or missing an error message will be returned.

Returns:associative array containing the domain and result or an error.
Return type:array or string
data.DKIMSign(selector, domain, key[, options])

Sign the message using DKIM.

Parameters:
  • selector (string) – selector to use when signing
  • domain (string) – domain to use when signing
  • key (string) – private key to use, either pki:X or a private RSA key in PEM format.
  • options (array) – options array
Returns:

true if the message could be signed

Return type:

boolean

The following options are available in the options array.

  • canonicalization_header (string) body canonicalization (simple or relaxed). The default is simple.
  • canonicalization_body (string) body canonicalization (simple or relaxed). The default is simple.
  • algorithm (string) algorithm to hash the message with (sha1 or sha256). The default is sha256.
  • additional_headers (array) additional headers to sign in addition to those recommended by the RFC.
  • headers (array) headers to sign. The default is to sign all headers recommended by the RFC.
  • discard_changes (boolean) Discard any changes to the original message before signing. The default is false.
  • return_header (boolean) Return the DKIM signature as a string, instead of adding it to the message. The default is false.

Note

If return_header is used, you need to add the header yourself without refolding.

$dkimsig = DKIMSign("selector", "example.com", $key, ["return_header" => true]);
AddHeader("DKIM-Signature", $dkimsig, false); // without refolding
data.DKIMSDID([explicitdomains[, options]])

Returns the SDID (Signing Domain IDentifier) status from the DKIM header of the message.

Parameters:
  • explicitdomains (array) – array of explicit domains to check, empty array for all
  • options (array) – options array
Returns:

associative array containing the domain and result.

Return type:

array

The following options are available in the options array.

  • signature_limit (number) signatures to verify. The default is 5.
data.DKIMADSP()

Returns the ADSP (Author Domain Signing Practices) policy from the DKIM header of the message.

Returns:associative array containing the domain and result.
Return type:array
Result Description
none No DKIM Author Domain Signing Practices (ADSP) record was published.
pass This message had an Author Domain Signature that was validated. (An ADSP check is not strictly required to be performed for this result since a valid Author Domain Signature satisfies all possible ADSP policies.)
unknown No valid Author Domain Signature was found on the message and the published ADSP was “unknown”.
fail No valid Author Domain Signature was found on the message and the published ADSP was “all”.
discard No valid Author Domain Signature was found on the message and the published ADSP was “discardable”.
nxdomain Evaluating the ADSP for the Author’s DNS domain indicated that the Author’s DNS domain does not exist.
temperror An ADSP record could not be retrieved due to some error that is likely transient in nature, such as a temporary DNS error. A later attempt may produce a final result.
permerror An ADSP record could not be retrieved due to some error that is likely not transient in nature, such as a permanent DNS error. A later attempt is unlikely to produce a final result.

As defined in RFC5617.

7.5.2.7. MIME and attachments

data.GetMailFile()

Return a File class to the current mail file.

Returns:A File class to the current mail file.
Return type:File

Note

The file is returned in an unmodified state as received (only with a Recieived header applied).

class data.MIME(partid)
Parameters:partid (string) – the part id

Working with MIME parts is done using MIME objects. To instantiate a reference to the root MIME part object call the MIME function with the string literal “0” (zero) as the argument.

Warning

If you call the MIME function without arguments (partid), the standard library’s MIME object will be created instead.

MIME("0")->appendPart(
        MIME()
                ->setType("multipart/alternative")
                ->appendPart(
                        MIME()
                                ->setType("text/plain")
                                ->setBody("This is a custom footer")
                        )
                ->appendPart(
                        MIME()
                                ->setType("multipart/related")
                                ->appendPart(
                                        MIME()
                                                ->setType("text/html")
                                                ->setBody("This is a custom footer with an image <img src='cid:logo.png'>")
                                )
                                ->appendPart(
                                        MIME()
                                                ->setType("image/png")
                                                ->addHeader("Content-ID", "logo.png")
                                                ->setBody(
                                                        cache [ "ttl" => 3600 * 24 * 7 ]
                                                                http("https://pbs.twimg.com/profile_images/656816032930119680/52m1eugJ.jpg")
                                                )
                                )
                        )
);

Note

Changes done to any MIME object will not be reflected on consecutive calls to “get” functions, however they will be applied to the message upon delivery.

getID()

Return the MIME part’s ID. This ID can be used to instantiate a new MIME object.

Returns:part id
Return type:string
mime.getsize()

return the mime part’s size in bytes.

Returns:size in bytes
Return type:number
getFileName()

Return the MIME part’s file name (if it has one).

Returns:file name
Return type:string (or none)
getType()

Return the MIME part’s Content-Type‘s type field (eg. text/plain).

Returns:content type
Return type:string (or none)
getHeader(name[, options])

Return the value of a header (if multiple headers with the same name exists, the first will be returned). If no header is found, the type none is returned. The name is not case sensitive.

Parameters:
  • name (string) – name of the header
  • options (array) – an options array
Returns:

header value

Return type:

string (or none)

The following options are available in the options array.

  • index (number) The index of the header, from the top, starting at zero.
if (is_string($contentid = $part->getHeader("Content-ID")))
      echo "Content-ID is $contentid";
getHeaders(name)

Return a list of header values. If no header is found, an empty list is returned. The name is not case sensitive.

Parameters:name (string) – name of the header
Returns:header values
Return type:array of string
echo "Received headers: ".count(MIME("0")->getHeaders("Received"));
getHeaderNames()

Return a list of all header names, from the top. The names are in lower case.

Returns:header names
Return type:array of string
setHeader(name, value[, options])

Overwrite existing header(s) or create a new header. The name is not case sensitive.

Parameters:
  • name (string) – name of the header
  • value (string) – value of the header
  • options (array) – an options array
Returns:

number of headers changed

Return type:

number

The following options are available in the options array.

  • index (number) The index of the header, from the top, starting at zero.
addHeader(name, value)

Add a new header (at the top of the message).

Parameters:
  • name (string) – name of the header
  • value (string) – value of the header
Return type:

none

delHeader(name[, options])

Delete all headers by the name. The name is not case sensitive.

Parameters:
  • name (string) – name of the header
  • options (array) – an options array
Returns:

number of headers deleted

Return type:

number

The following options are available in the options array.

  • index (number) The index of the header, from the top, starting at zero.
remove()

Remove this MIME part.

Return type:none
getBody()

Get the body (content) of a MIME part. The content will be decoded according to the Content-Transfer-Encoding header. If the body size is bigger than 1 MiB, the type none is returned.

Returns:the body content
Return type:string (or none)
setBody(data)

Set the body (content) of a MIME part. If the body argument is bigger than 1 MiB (or an another error occured), the type none is returned. The MIME parts encoding (Content-Transfer-Encoding) will be changed to base64 as the data will encoded as such.

Parameters:data (string) – the body content
Returns:this
Return type:MIME (or none)
prependPart(part)

Add a MIME part before this part.

Parameters:part (MIME) – a MIME part
Returns:this
Return type:MIME
appendPart(part)

Add a MIME part after this part.

Parameters:part (MIME) – a MIME part
Returns:this
Return type:MIME
replacePart(part)

Replace the current MIME part.

Parameters:part (MIME) – a MIME part
Return type:none
findByType(type)

Find descendant parts (on any depth) based on their Content-Type.

Parameters:type (string) – type as regex
Returns:parts
Return type:array of MIME objects
findByFileName(filename)

Find descendant parts (on any depth) based on their file name.

Parameters:filename (string) – filename as regex
Returns:parts
Return type:array of MIME objects
getParts()

Return child parts.

Returns:parts
Return type:array of MIME objects

7.5.3. On script error

On script error Defer() is called.

7.5.4. On implicit termination

If not explicitly terminated then Deliver() is called.