Special Sending Rules
- Table of Contents
- Overview
- Special Sending Rules: Usage & Interface
- System and Organization Configuration
- Campaign Preview Emails
- Special Sending Rules: Development
- Definition of Data In and Out of Special Sending Rules
- Special Sending Rule Function Interface
- Examples
Overview
Special Sending Rules provide a way to programmatically customize the sending
attributes or the content of a message before it is sent.
When a Special Sending Rule is configured for an email campaign a function is
called to customize each message. This function is given data about what will be
sent and can return data to override the sending attributes or content of the
message.
Special Sending Rule code is called once per message.
Special Sending Rules: Usage & Interface
Notes
- Only System Admin users may create or update Special Sending Rules.
- Special Sending Rules may be applied to mailing lists as a campaign default.
 New campaigns will use that SSR as a default.
- Special Sending Rules may be applied to campaigns.
- If a special sending rule returns a Virtual MTA,Bounce Email, orURL Domain
 that does not exist (by name, not ID) in SendSage Engine, it will cause
 the campaign to fail.
- In PHP, the timezone is set to “US/Central” by default. To change this, see
 date_default_timezone_set.
Attributes of a Special Sending Rule
Name — This is the identifier that you’ll use within SendSage Studio to select this SSR.
Number of Workers — This value determines how many processes will be run to execute this SSR. If
the SSR is simple with low CPU usage, this can safely be set to the default (2).
If you have an SSR that is complex or slow, this can be increased to improve
overall performance. The maximum value for this field is determined by the Max system configuration.
SSR Workers
Language — The programming language that the SSR will be evaluated as. Currently Perl and
PHP are the supported SSR languages.
Code — This is the computer code that will be executed to determine this SSR’s functionality.
Managing Special Sending Rules
Viewing the List of Special Sending Rules
In the Admin top navigation, click on the SSRs sub-navigation link.
Creating a New Special Sending Rule
- In the Admintop navigation, click on theSSRssub-navigation link.
- Click Create a special sending rule.
- Fill in this form with the correct details. See the documentation below to
 know how to declare the SSR function.
- Click Create this special sending rule.
Previewing a Special Sending Rule
To see what effect an SSR will have on a campaign, navigate to the SSR’s show
page and do the following.
- Click the Preview this special sending rulebutton.
- Select an organization, campaign, and subscriber details to use.
- Click the View previewbutton.
The resulting page will detail what the SSR did. If there is an error or
exception thrown by the code, it will be shown on this page.
If the selected campaign has a split-test, the preview will run for the first
defined content.
Special Sending Rules in Campaign Preview Emails
If a campaign is configured to use a special sending rule, that rule will be
applied to campaign preview emails as well.
The special sending rule evaluation and preview email will have the following details:
- The recipient’s email address will be the address specified when creating the preview.
- The recipient’s custom fields will be the mailing list’s Preview and Seed Custom Field Values.
- If no segment is set for the campaign, nullvalues will be
 passed to the special sending rule for segment fields.
- Other delivery details will be pulled from the campaign. If no delivery
 details are set, then the systemCampaign Preview Defaultsvalues will be used.
- The preview delivery default Virtual MTA will always be used, regardless of
 if the campaign or special sending rule overrides it.
- Any errors in the special sending rule will be presented when creating the preview email.
System and Organization Configuration
Setting the Max SSR Workers Value
In order to prevent individual SSRs from being configured to use too many
processes, in the System Configuration screen you may set a Max SSR Workers
value. This is the maximum number of workers that any individual SSR may allocate.
Organization Permissions
Special Sending Rules are disabled by default for all organizations other than
the System Organization. System administrators may navigate to an
organization’s individual page to grant or revoke access to SSRs, with
the following caveats.
- This is an “all or nothing” option – turning on special sending rules for an
 organization grants them access to all of them
- If you remove access to SSRs for an organization which has any autoresponders,
 not-yet-started campaigns or mailing lists that use a Special Sending Rule,
 then the Special Sending Rule setting for those campaigns or
 autoresponders will be cleared.- This can change the email that will be sent by these autoresponders,
 campaigns, and/or mailing lists, so a confirmation message will be shown on
 the organization edit page confirming the change.
- When an autoresponder or campaign is updated in this way, a note is added
 to their history about the update.
 
- This can change the email that will be sent by these autoresponders,
- Campaigns that start sending with an SSR and do not have permissions to an
 SSR (e.g. campaign was setup with SSR permissions, started sending with SSR
 permissions, then was paused after permissions were revoked, and later
 resumed) are failed with a note in the campaign history log
- If an autoresponder or campaign has an SSR and the organization doesn’t have
 SSR permissions, still show it in the campaign’s view page with the
 (invalid)suffix
- If an autoresponder or campaign has an SSR and the organization doesn’t have
 SSR permissions, still show it in the edit page for that object, but they may
 only selectNone– show the current SSR with the(invalid)suffix
Campaign Preview Emails
If a campaign is configured to use a Special Sending Rule at the time a preview
email is requested, the SSR will be evaluated on that preview email.
Special Sending Rules: Development
Conventions in this Document
This document describes methods in multiple computer languages which use
different terms for similar things. Here is how the concepts are translated.
| In this document | Perl | PHP | 
|---|---|---|
| Hash | Hash reference | Array | 
| Undefined | undef | null | 
Details and Limitations
For Special Sending Rules used in campaigns:
- A Special Sending Rule may run for a maximum of 60seconds before being
 terminated, potentially causing the campaign to fail.
- Special Sending Rules will be attempted three times before causing processing
 the subscriber to fail.
- The first retry will be 10seconds later, with the second retry60
 seconds after that.
- Depending on the configuration of the Special Sending Rule, either:
- A single error processing a subscriber will cause the campaign to be stopped
- An error threshold must be exceeded for the campaign to be stopped
 (For example, greater than 10% of subscribers with errors in the last 2 minutes.)
 
- The Number of Workersfield in Special Sending Rules defines the
 parallelism of the SSR. Every campaign that is using this SSR will run that
 many instances of the evaluator process.
- Each Special Sending Rule process will handle multiple messages – but will
 occasionally be restarted in order to reduce the danger of memory leaks in
 custom code. For this reason, you may use global variables in order to
 optimize for speed (for example, fetching a resource from an HTTP request and
 storing it in a global); but you should not assume that an SSR is only
 started once per campaign. A Special Sending Rule might be loaded many times
 over the course of a campaign.
For Special Sending Rules used in autoresponders and web-forms:
- A Special Sending Rule may run for a maximum of 60seconds before being
 terminated, potentially causing the message to be skipped.
- An error will not cause a retry.
- Errors are logged to the autoresponder or web-form history page.
- Currently, each Special Sending Rule process will handle a single message. This may
 change in the future to allow one process to handle multiple messages.
- Because there is little parallelism in SSR evaluation and the error handling is not
 as robust as campaigns, it is strongly recommended to not access any external
 resources or do any time-intensive processing.
Definition of Data In and Out of Special Sending Rules
Data Provided to the Special Sending Rule
Campaign Information Hash
The Campaign Information Hash ($campaign_information_hash) contains data about the campaign. This does not change per recipient:
| Key | Description | 
|---|---|
| entity_type | The type of message that is being delivered. May be campaign,autoresponder, orweb_form. | 
| is_preview | If this is a campaign preview, then 1. Otherwise0. | 
| seed_list_id | Deprecated: The ID of the first seed list assigned to the Campaign, ordered by ID. Use seed_listsinstead. (Undefined if no seed list selected.) | 
| seed_list_name | Deprecated: The name of the first seed list, ordered by ID. (Undefined if no seed list selected.) | 
| seed_lists | An array of seed lists used for the campaign. Each entry will be a hash with idandnamekeys. | 
| speed | Speed of the campaign in messages per hour or zero if unlimited. | 
| from_name | Fromaddress name. | 
| from_email | Fromemail address. | 
| sender_email | Senderemail address. (Undefinedif not specified.) | 
| reply_to | Reply-Toemail address (Undefinedif not specified.) | 
| virtual_mta_name | Name of VirtualMTA used for sending. (If this option is hidden from the user, then this will be set to the actual value used for sending.) | 
| virtual_mta_id | Primary key of the VirtualMTA. | 
| url_domain_name | Domain name for click and open tracking URLs. (If this option is hidden from the user, then this will be set to the actual value used for sending.) | 
| url_domain_id | Primary key of the URL Domain. | 
| track_opens | If tracking opens, then 1. Otherwise0. | 
| track_links | If tracking links, then 1. Otherwise0. | 
| bounce_email | Bounce handling email address. (If this option is hidden from the user, then this will be set to the actual value used for sending.) | 
| mailing_list_name | Name of mailing list. | 
| mailing_list_id | Primary key of mailing list. | 
| segmentation_criteria_name | The name of the segment used for this campaign. | 
| segmentation_criteria_id | The idof the segment used for this campaign. | 
| segmentation_criteria_json | The JSON blob that defines the segment used for this campaign (applies to Standard Mailing Lists). | 
| segmentation_criteria_sql | The SQL query used to retrieve the recipient list for this campaign (applies to Remote Lists). | 
Note on segmentation_criteria_json: The format of this field is undocumented.
It exists as an input for users that need it, but its fields should be
discovered through experimentation. (If a campaign does not yet have a segment
defined, then these values will be null. This can happen when a SSR is applied
to a campaign preview where the campaign does not have a segment defined.)
For campaigns, the following extra keys will be present.
| Key | Description | 
|---|---|
| campaign_name | Name of campaign. | 
| campaign_id | Primary key of campaign. | 
For autoresponders, the following extra keys will be present.
| Key | Descriptioni | 
|---|---|
| autoresponder_name | Name of autoresponder. | 
| autoresponder_id | Primary key of autoresponder. | 
For web forms, the following extra keys will be present.
| Key | Description | 
|---|---|
| web_form_name | Name of web form. | 
| web_form_id | Primary key of web form. | 
Recipient Information Hash
The Recipient Information Hash ($multiple_recipients_information_hash) contains two hashes:
| Key | Description | 
|---|---|
| subscriber | Information about the recipient of the email message. (Defined below.) | 
| content | Information about the content to be sent. This is not part of the campaign information hash, because with split A/B testing a campaign can send different content versions to different subscribers. (Defined below.) | 
subscriber Hash
| subscriber hash 
 | |||||||||||||||||||||||||||
The date values are returned in YYYY-MM-DDThh:mm:ss.s format, using UTC as the time zone. For example, 2014-10-30 13:08:18.936708.
For Remote Lists, the meaning of the fields will be the following:
- These fields will always be NULL- created_at
- created_at_epoch
- created_at_epoch_utc
- status
- subscribe_time
- subscribe_time_epoch
- subscribe_time_epoch_utc
- subscribe_ip
 
- These keys will never be present:
- confirmed(remote lists can not have a confirmed field)
- email_format(remote lists can not have a format field)
 
- The idfield will be the recipient’s sequence number during delivery.
- If the recipient has a distinct id, it will be in thecustom_fields["distinct_id"]value.
- The emailfield will be recipient’s email address.
- The field names in custom_fieldswill be lowercased.
content Hash
| Key | Description | 
|---|---|
| id | The internal ID of this content object | 
| format | Format of email message to send: both,html, ortext | 
| html | HTML content before custom field replacement, click tracking, and open tracking. (If this is a text-only message, then this will be undefined.) | 
| text | Text content before custom field replacement, click tracking, and open tracking. (If this is a html-only message, then this will be undefined.) | 
| subject | Subjectof email before custom field replacement. | 
Data Returned From the Special Sending Rule
Override Hash
Setting a key in the Override Hash (the return value of the Special Sending Rule) overrides the
default value for a particular delivery.
| html string | message_information_hash.content.htmlNew HTML content. If this is set to  | 
| text string | message_information_hash.content.textNew text content. If this is set to  | 
| subject string | message_information_hash.content.subjectNew  | 
| from_name string | campaign_information_hash.from_nameNew  | 
| from_email string | campaign_information_hash.from_emailNew  | 
| sender_email string | campaign_information_hash.sender_emailNew  | 
| reply_to string | campaign_information_hash.reply_toNew  | 
| virtual_mta_name string | campaign_information_hash.virtual_mta_nameNew VirtualMTA. Set to the name of the VirtualMTA. Specify only one of this or  | 
| virtual_mta_id string | campaign_information_hash.virtual_mta_idNew VirtualMTA. Set to the ID of the VirtualMTA. Specify only one of this or  | 
| url_domain_name string | campaign_information_hash.url_domain_nameNew URL Domain. Set to the URL Domain domain name. Specify only one of this or  | 
| url_domain_id string | campaign_information_hash.url_domain_idNew URL Domain. Set to the ID of the URL Domain. Specify only one of this or  | 
| bounce_email string | campaign_information_hash.bounce_emailNew Bounce email address. Specify only one of this or  | 
| bounce_email_id string | New Bounce email address. Specify only one of this or bounce_email. | 
| skip string | A return value of true, 1, or a number greater than zero in this field will cause this recipient to be skipped in delivery. | 
| skip_message string | If provided, this message will be set on the skipevent and presented in statistics screen. | 
| attachments string | An array of attachment hashes, as defined below. | 
| custom_headers string | A string of email headers that will be added to the message (e.g. X-Data: User 123).These header names must begin with  Multiple headers may be specified by putting a newline between them (e.g.  If no trailing newline is included, one will be added. CRLF ( | 
- If the SSR’s override hash includes htmlortextkeys, this may cause
 the email format to change. For example, if a campaign was originallytext,
 but the SSR returns non-blank values for bothhtmlandtext, a
 multipart/alternativeemail will be sent instead oftext/plain.
- If the SSR returns blank values for both htmlandtext, this will cause
 the delivery to fail because no content is available to send. Note that this
 only comes up if the override has defined those keys, removing the original
 content.
- If a SSR returns a blank value for texton a text-only campaign, this will
 cause the delivery to fail because no content is available to send.
Attachment Hash
Each hash in the attachments array of the Override Hash must have the following keys:
| Key | Description | 
|---|---|
| filename | The string that will be used as the filename in the attachment. Must not be blank. | 
| content_type | The string that will be used as the MIME type for the attached file. | 
| content | The string that will be used as the content of the attachment. | 
- Filenames may contain the characters A–Z,a–z,0–9,_,-,.
 and spaces, must be at least one character long, must contain at least one
 non-whitespace character, and may be at most 100 characters long.
- If content_typeis blank, it will default toapplication/octet-stream.
Here are some of the most common MIME Types used in email attachments.
See the Wikipedia page on MIME Types
for an expanded list of types.
| MIME Type | File Extension | Description | 
|---|---|---|
| text/plain | .txt | Plain Text | 
| text/html | .html | HTML | 
| application/pdf | .pdf | Adobe Acrobat Portable Document Format | 
| application/msword | .doc | Microsoft Word | 
| application/vnd.ms-excel | .xls | Microsoft Excel | 
Special Sending Rule Function Interface
General Structure
Your Special Sending Rule contains code that will be run as part of a function by SendSage
Studio. You don’t provide the syntax that defines the function/subroutine itself (such as
function example ($arg) { statements... }), but rather just provide the source code lines
(statements) that will be run.
Input values will be provided in variables already defined in the local context.
Data is returned by calling the return command. Not calling the return command will result in
an error.
Input Variables
The following variables will be defined in local context:
| Variable | Description | 
|---|---|
| $campaign_information_hash | Campaign Information Hash | 
| $multiple_recipients_information_hash | Multiple Recipients Information Hash | 
Campaign Information Hash
This is the Campaign Information Hash as defined above.
Multiple Recipients Information Hash
This is a hash that contains information on one or more recipients for the Special Sending Rule
to process.
- Key– The id of the subscriber (the numeric primary key).
- Value– The- recipient information hash(as defined above) with information on this subscriber
 and their email.
See examples below.
Expected Return Value
The Special Sending Rule returns a hash with override information for the current subscriber.
- Key– The subscriber id (numeric primary key) of the subscriber to have overrides performed
 on their email. This subscriber id must have been provided as part of the- Multiple Recipientsthat was passed to this invocation of the Special Sending Rule.
 Information Hash
- Value– The- override hash(as defined above) with the settings to override.
See examples below.
Examples
We’ve created a practical set of examples for reference
Perl
Example Input to SSR
$campaign_information_hash = {
    seed_list_name    => 'SendSage Monitor',
    seed_list_id      => 12,
    seed_lists        => [ { id => 12, name => 'SendSage Monitor' } ],
    speed             => 0,
    from_name         => 'DRH Internet',
    from_email        => 'newsletter@example.drh.net',
    sender_email      => undef,
    reply_to          => undef,
    virtual_mta_name  => 'smtp1-2',
    virtual_mta_id    => 3,
    url_domain_name   => 'http://newsletter.example.drh.net/',
    track_opens       => 1,
    track_links       => 1,
    bounce_email      => 'return@newsletter.example.drh.net',
    campaign_name     => 'December newsletter',
    campaign_id       => 76,
    mailing_list_name => 'Newsletter subscribers',
    mailing_list_id   => 3,
};
$multiple_recipients_information_hash = {
    182634 => {
        subscriber => {
            id                       => 182634,
            email                    => 'fred@example.com',
            created_at               => '2014-12-03T08:39:53+12:00',
            created_at_epoch         => 1417595993,
            created_at_epoch_utc     => 1417552793,
            confirmed                => 1,
            email_format             => 'html',
            status                   => 'active'
            subscribe_time           => '2014-12-03T08:39:53+12:00',
            subscribe_time_epoch     => 1417595993,
            subscribe_time_epoch_utc => 1417552793,
            subscribe_ip             => '10.0.0.3',
            custom_fields            => {
                "First Name" => {
                    name  => "First Name",
                    type  => "text",
                    value => "Bob",
                },
                "Favorite Color" => {
                    name  => "Favorite Color",
                    type  => "select_single_dropdown",
                    value => "Red",
                },
            },
        },
        content => {
            format  => 'both',
            html    => '<html><body><p>Hello world</p><p><a href="%%unsubscribe_link%%">Unsubscribe me</a></p>/body></html>',
            text    => "Hello world\n\nUnsubscribe me: %%unsubscribe_link%%\n",
            subject => 'Hello',
        },
    },
};
Example Return Value
$return_value = {
    182634 => {
        html              => '<html><body><p>Hi there</p><p><a href="%%unsubscribe_link%%">Unsubscribe me</a></p>/body></html>',
        text              => "Hi there\n\nUnsubscribe me: %%unsubscribe_link%%\n",
        subject           => 'Hi',
        from_name         => 'DRH Internet Newsletter',
        from_email        => 'the-newsletter@example.drh.net',
    },
};
Example Special Sending Rule that Passes Through the Values it Receives
## Available variables:
##
## $campaign_information_hash
## $multiple_recipients_information_hash
##
## NOTE: The example code below returns all potential values. For best
## performance, it's best to trim the return value down to just the fields
## you need to override.
my %result = map {
  my $recipient_id = $_;
  my $recipient    = $multiple_recipients_information_hash->{ $recipient_id };
  $recipient_id => {
    html              => $recipient->{content}{html},
    text              => $recipient->{content}{text},
    subject           => $recipient->{content}{subject},
    from_name         => $campaign_information_hash->{from_name},
    from_email        => $campaign_information_hash->{from_email},
    sender_email      => $campaign_information_hash->{sender_email},
    reply_to          => $campaign_information_hash->{reply_to},
    virtual_mta_name  => $campaign_information_hash->{virtual_mta_name},
    url_domain_name   => $campaign_information_hash->{url_domain_name},
    bounce_email      => $campaign_information_hash->{bounce_email},
  }
} keys(%$multiple_recipients_information_hash);
return \%result;
Example Special Sending Rule that Issues an HTTP GET to Replace the Text Content
use LWP::Simple;
my %result = map {
  my $recipient_id = $_;
  my $recipient    = $multiple_recipients_information_hash->{ $recipient_id };
  my $new_content = get("http://drh.net/robots.txt");
  $recipient_id => {
    text => $new_content,
  }
} keys(%$multiple_recipients_information_hash);
return \%result;
Example Special Sending Rule that Sends Using Different Virtual MTAs for Even and Odd Subscriber IDs
my %result = map {
  my $recipient_id = $_;
  my $recipient    = $multiple_recipients_information_hash->{ $recipient_id };
  my $override_hash = {};
  if ( $recipient_id % 2 == 0 ) {
    $override_hash->{virtual_mta_name} = "smtp-even";
  } else {
    $override_hash->{virtual_mta_name} = "smtp-odd";
  }
  $recipient_id => $override_hash;
} keys(%$multiple_recipients_information_hash);
return \%result;
PHP
Example Special Sending Rule that Passes Through the Values it Receives
## Available variables:
##
## $campaign_information_hash
## $multiple_recipients_information_hash
##
## NOTE: The example code below returns all potential values. For best
## performance, it's best to trim the return value down to just the fields
## you need to override.
return array_map((function ($recipient) use ($campaign_information_hash) {
  return array(
    'html'              => $recipient->content->html,
    'text'              => $recipient->content->text,
    'subject'           => $recipient->content->subject,
    'from_name'         => $campaign_information_hash->from_name,
    'from_email'        => $campaign_information_hash->from_email,
    'sender_email'      => $campaign_information_hash->sender_email,
    'reply_to'          => $campaign_information_hash->reply_to,
    'virtual_mta_name'  => $campaign_information_hash->virtual_mta_name,
    'url_domain_name'   => $campaign_information_hash->url_domain_name,
    'bounce_email'      => $campaign_information_hash->bounce_email,
  );
}), $multiple_recipients_information_hash);
Example Special Sending Rule that Issues an HTTP GET to Replace the Text Content
return array_map((function ($recipient) use ($campaign_information_hash) {
  $new_content = file_get_contents("http://drh.net/robots.txt");
  return array(
    'text' => $new_content,
  );
}), $multiple_recipients_information_hash);
Example Special Sending Rule that Sends Using Different Virtual MTAs for Even and Odd Subscriber IDs
return array_map((function ($recipient) use ($campaign_information_hash) {
  $override_hash = array();
  if ( $recipient->subscriber->id % 2 === 0 )
    $override_hash["virtual_mta_name"] = "smtp-even";
  else
    $override_hash["virtual_mta_name"] = "smtp-odd";
  return $override_hash;
}), $multiple_recipients_information_hash);
