Plain-Text and HTML Email

In the world of data integration alerts, Email is, many times, the preferred alerting method for integration outcomes showing unusable, should be corrected or critical conditions. Plain-text email is excellent in many of these situations, but what if you include tabular data? In this post, I’ll show you how to send HTML email, so tabular data is far more readable.

There is no magic to send email from Jitterbit in HTML format rather than plain-text. You need to prepend and append <html> and </html>> to your email body. Have a look at the Jitterbit Email message component below for some email best practices.

Notice how <html> and </html> wrap the email body. Simple, right?

You may also notice the heavy use of global variables. As stated in an earlier post, global variables are ideal for configuring Jitterbit components. Here, I’m using Jitterbit Project Variables for all the EMAIL.* variables and assigning values to the EVENT.* variables within the Operation that sends this email message. Below are some variable details in some fields.

From:

I’ll use the Jitterbit Project name as the sender’s human-readable descriptive name and include the required email address (that can be fake) in angle brackets.

Subject:

There are two variables here that provide me with a descriptive subject value.

  • [EVENT.env] I showed how one might assign this value in the post Capturing Events and Errors and there; the value is the Jitterbit Environment Name and an event severity level.

  • [Event.op] This global variable value is the Jitterbit Operation name that has identified an issue worthy of an email alert. The uppercase EVENT syntax is not used here as the value can be assigned inside any Operation that precedes the use of (in my case) SendEmailMessage(). As you read in Capturing Events and Errors, I centralize all event logging and alerting. This email may be sent by an On Failure Operation so, $Event.op is assigned in the Operation preceding the On Failure Operation.

Text:

The only difference between a plain-text email and an HTML email is the leading and trailing <html> tags.

  • [EVENT.msg.email] The global variable containing the email message with alert details.

  • [EVENT.bp] Finally — and this is a table example — I provide a boilerplate with details of the environment where the event occurred. A Jitterbit Script builds the table, and $EVENT.bp is assigned as follows. Note, this script uses the two custom scripts — “Build HTML table w/ array” and “Get HTML small style” shared further below.

$EVENT.bp = RunScript("<TAG>Scripts/Utilities/Build EVENT.bp</TAG>");

Build EVENT.bp

_title=IfEmpty(_1,"Integration Services Environment");
_table=IfEmpty(_2,RunScript("<TAG>Scripts/Utilities/Build HTML table w/ array</TAG>",
    "{{Attribute,Name,ID},"
    +"{Environment,"+IfEmpty($EVENT.env,GetEnvironmentName())+","+GetEnvironmentId()+"},"
    +"{Project,"+IfEmpty($jitterbit.operation.project_name,"UNAVAILABLE")+",N/A},"
    +"{Operation,"+IfEmpty($jitterbit.operation.name,"UNAVAILABLE")+","+$jitterbit.operation.guid+"},"
    +"{Organization,"+GetOrganizationName()+","+GetOrganizationId()+"},"
    +"{Agent Group,"+GetAgentGroupName()+","+GetAgentGroupId()+"},"
    +"{Agent Name,"+GetAgentName()+","+GetAgentId()+"},"
    +"{Agent Version,"+GetAgentVersionName()+","+GetAgentVersionId()+"}}"
  )
);
_beforeData = _3;
_afterData = _4+"<br><br>";
style=IfEmpty(_5,RunScript("<TAG>Scripts/Utilities/Get HTML small style</TAG>"));
"<head>"+ style +"<_title>"+ _title +"</_title></head><body>"
+"<br><b><font size=-2>"+ _title +"</font></b>"
// Powered-by Logo…
+"<img  src=\"data:image/png;base64,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\"/>"
+ _beforeData + _table + _afterData;

Build HTML table w/ array

Building an HTML table from a Jitterbit array can be done with the following Script. The ReadArrayString() function in line 2 below is faulty (for multi-dimensional arrays), so there are some workarounds identified below. This version is designed for my uses so, by default and using the CSS below, alternates the table row background color.

// String rep. of 1D JB array
_colsArray = ReadArrayString(IfEmpty(_1,"{UNKNOWN COL 1, UNKNOWN COL 2, ...}")); 
_oddClass=IfEmpty(_2,"oddrows");
_evenClass=IfEmpty(_3,"evenrows");
cn=Length(_colsArray[0]); rows=Null(); header = "<tr>";
i=0;While(i<cn, header += "<th>"+ToUpper(_colsArray[0][i])+"</th>"; i++); header+="</tr>";
rowType=_oddClass;
i=1;While(i<Length(_colsArray), row="<tr>";
  // workaround ReadArrayString() defect -- ignore the empty rows
  nullVal=Array(); k=0; While(k<cn,
    If(IsNull(_colsArray[i][k]),Set(nullVal,Null(),-1),Set(nullVal,true,-1));k++
  );
  If(Count(nullVal)==0,i++, // end w/a
    j=0;While(j<cn, 
      value = If(IsNull(_colsArray[i][j]),"<em>(null)</em>",_colsArray[i][j]);
      row += "<td class="+rowType+">"+ RTrim(value) +"</td>";j++
    );
    row += "</tr>"; rowType=If(rowType==_oddClass,_evenClass,_oddClass);i++;
    rows+=row;
  );
);
"<table border=2 cellpadding=2 cellspacing=1>"+header+rows+"</table>"

Get HTML small style

"<style type=\"text/css\">
BODY {
     font-family: Verdana;
     font-size: 5pt ; /*unique to JB small style */
     text-align: Left;
     background-color: #FFFFFF;
     color: black;
 }
TH {
     font-family: Verdana;
     font-size: 5pt ; /*unique to JB small style */
     font-weight: bold; 
     text-align: Center;
     background-color: #93D900;
     color: black; /*unique to JB small style */
 }
.oddrows {
     font-family: Verdana;
     font-size: 5pt ; /*unique to JB small style */
     text-align: Left;
     background-color: #FFFFFF;
     color: black;
 }
.evenrows {
     font-family: Verdana;
     font-size: 5pt ; /*unique to JB small style */
     text-align: Left;
     background-color: #D6D6D6;
     color: black;
 }

</style>";

Log Environment

I use this as the boilerplate value in text-only emails.

  "\nOrganization (Name /ID): "+GetOrganizationName()+" /"
    +GetOrganizationId()
  +"\n"+WriteToOperationLog("Environment (Name /ID): " +($EVENT.env=GetEnvironmentName())
    +" /"+GetEnvironmentId())
  +"\n"+WriteToOperationLog("Agent Group (Name /ID): " +($EVENT.group=GetAgentGroupName())
    +" /"+GetAgentGroupId())
  +"\n"+WriteToOperationLog("Agent (Name /ID: "        +($EVENT.agent=GetAgentName())
    +" /"+GetAgentId())
  +"\n"+WriteToOperationLog("Agent Version Name /ID): "+($EVENT.version=GetAgentVersionName())
    +" /"+GetAgentVersionId()+"\n");

Ultimately, here’s an example notification email in my inbox: