#Email-HTML-String: Create SimpleNotice

Email-HTML String, Create SimpleNotice
Assembles HTML text for email from workflow data. The html text will consist of blocks of abstract, image, main sentence, link button, and sub-sentence. If the setting is blank, the block will not be displayed.
Configs
  • A1: Set Magazine Title (e.g. “SaaS News”) *#{EL}
  • A2: Set Magazine Color (e.g. “#009900”)#{EL}
  • A3: Set Magazine Font (e.g. “Arial”)#{EL}
  • A4: Set Magazine Logo Url (eg https://example.com/example.png )#{EL}
  • B1: Set Subject (eg. “Questetra v13 Automatic Start Enhanced”) *#{EL}
  • B2: Set Abstract (Line breaks are automatically converted to br)#{EL}
  • B3: Set Image Url (e.g. https://example.com/example.png )#{EL}
  • B4: Set Section1 (e.g. “About New Feature”)#{EL}
  • B5: Set Paragraph1#{EL}
  • B6: Set LinkButton Text#{EL}
  • B7: Set LinkButton URL#{EL}
  • B8: Set Section2 (e.g. “About Questetra”)#{EL}
  • B9: Set Paragraph2#{EL}
  • C1: Set Publisher Name (e.g. “Questetra, Inc.”) *#{EL}
  • C2: Set Publisher Url (e.g. https://example.com/ ) *#{EL}
  • C3: Set Publisher Statement#{EL}
  • D: Select STRING DATA that stores Email-HTML (update) *
Script (click to open)
// GraalJS Script (engine type: 2)

//////// START "main()" /////////////////////////////////////////////////////////////////
main();
function main(){ 

//// == Config Retrieving / 工程コンフィグの参照 ==
let   strMagazineTitle     = configs.get( "StrConfA1" );          /// REQUIRED
      strMagazineTitle     = encodeHTML( strMagazineTitle );
  if( strMagazineTitle   === "" ){
    throw new Error( "\n AutomatedTask ConfigError:" +
                     " Config {A1: MagazineTitle} is empty \n" );
  }
let   strMagazineColor     = configs.get( "StrConfA2" ).replace(/\"/g, ""); // NotRequired
  if( strMagazineColor   === "" ){
    engine.log( " AutomatedTask ConfigWarning: " +
                " {A2: MagazineColor} is empty (default '#009900' applied)" );
    strMagazineColor = "#009900";
  }
let   strMagazineFont      = configs.get( "StrConfA3" ).replace(/\"/g, "'"); // NotRequired
  if( strMagazineFont    === "" ){
    engine.log( " AutomatedTask ConfigWarning: " +
                " {A3: MagazineFont} is empty (default applied)" );
    strMagazineFont = "Arial, -apple-system, Meiryo, Helvetica, sans-serif";
  }
const strLogoUrl           = configs.get( "StrConfA4" );          // NotRequired
  if( strLogoUrl         === "" ){
    engine.log( " AutomatedTask ConfigWarning: " +
                " {A4: LogoUrl} is empty" );
  }
let   strSubject           = configs.get( "StrConfB1" );          /// REQUIRED
      strSubject           = encodeHTML( strSubject );
  if( strSubject         === "" ){
    throw new Error( "\n AutomatedTask ConfigError:" +
                     " Config {B1: Subject} is empty \n" );
  }
let   strAbstract          = configs.get( "StrConfB2" );          // NotRequired
  if( strAbstract        === "" ){
    engine.log( " AutomatedTask ConfigWarning: " +
                " {B2: Abstract} is empty" );
  }else{
      strAbstract          = encodeHTML( strAbstract ).replace(/\n/g, '<br>\n');
      strAbstract          = convertMultiSpaces( strAbstract );
  }
const strImageUrl          = configs.get( "StrConfB3" );          // NotRequired
  if( strImageUrl        === "" ){
    engine.log( " AutomatedTask ConfigWarning: " +
                " {B3: ImageUrl} is empty" );
  }
let   strSection1          = configs.get( "StrConfB4" );          // NotRequired
  if( strSection1        === "" ){
    engine.log( " AutomatedTask ConfigWarning: " +
                " {B4: Section1} is empty" );
  }else{
      strSection1          = encodeHTML( strSection1 );
  }
let   strParagraph1        = configs.get( "StrConfB5" );          // NotRequired
  if( strParagraph1      === "" ){
    engine.log( " AutomatedTask ConfigWarning: " +
                " {B5: Paragraph1} is empty" );
  }else{
      strParagraph1        = encodeHTML( strParagraph1 ).replace(/\n/g, '<br>\n');
      strParagraph1        = convertMultiSpaces( strParagraph1 );
  }
let   strLinkButtonText    = configs.get( "StrConfB6" );          // NotRequired
      strLinkButtonText    = encodeHTML( strLinkButtonText );
  if( strLinkButtonText  === "" ){
    engine.log( " AutomatedTask ConfigWarning: " +
                " {B6: LinkButtonText} is empty" );
  }
const strLinkButtonUrl     = configs.get( "StrConfB7" );          // NotRequired
  if( strLinkButtonUrl   === "" ){
    engine.log( " AutomatedTask ConfigWarning: " +
                " {B7: LinkButtonUrl} is empty" );
  }
if( strLinkButtonText === "" && strLinkButtonUrl !== "" ){
    strLinkButtonText      =    strLinkButtonUrl;
}
let   strSection2          = configs.get( "StrConfB8" );          // NotRequired
  if( strSection2        === "" ){
    engine.log( " AutomatedTask ConfigWarning: " +
                " {B4: Section2} is empty" );
  }else{
      strSection2          = encodeHTML( strSection2 );
  }
let   strParagraph2        = configs.get( "StrConfB9" );          // NotRequired
  if( strParagraph2      === "" ){
    engine.log( " AutomatedTask ConfigWarning: " +
                " {B5: Paragraph2} is empty" );
  }else{
      strParagraph2        = encodeHTML( strParagraph2 ).replace(/\n/g, '<br>\n');
      strParagraph2        = convertMultiSpaces( strParagraph2 );
  }
let   strPublisherName     = configs.get( "StrConfC1" );          /// REQUIRED
      strPublisherName     = encodeHTML( strPublisherName );
  if( strPublisherName   === "" ){
    throw new Error( "\n AutomatedTask ConfigError:" +
                     " Config {C1: PublisherName} is empty \n" );
  }
const strPublisherUrl      = configs.get( "StrConfC2" );          /// REQUIRED
  if( strPublisherUrl    === "" ){
    throw new Error( "\n AutomatedTask ConfigError:" +
                     " Config {C2: PublisherUrl} is empty \n" );
  }
let   strPublisherStatement   = configs.get( "StrConfC3" );         // NotRequired
  if( strPublisherStatement === "" ){
    engine.log( " AutomatedTask ConfigWarning: " +
                " {C3: PublisherStatement} is empty" );
  }else{
      strPublisherStatement   = encodeHTML( strPublisherStatement ).replace(/\n/g, '<br>\n');
      strPublisherStatement   = convertMultiSpaces( strPublisherStatement );
  }
const strPocketHtml           = configs.getObject( "SelectConfD" ); /// REQUIRED



//// == Data Retrieving / ワークフローデータの参照 ==
// (Nothing. Retrieved via Expression Language in Config Retrieving)


//// == Calculating / 演算 ==
// Build HTML String with Template_literals (ES6)
// ${strMagazineTitle}
// ${strMagazineColor}
// ${strMagazineFont}
// ${strLogoUrl}
// ${strSubject}
// ${strAbstract}
// ${strImageUrl}
// ${strSection1}
// ${strParagraph1}
// ${strLinkButtonText}
// ${strLinkButtonUrl}
// ${strSection2}
// ${strParagraph2}
// ${strPublisherName}
// ${strPublisherUrl}
// ${strPublisherStatement}

let strBlockHeader = `<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
  "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"><html><head>
  <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
  <meta http-equiv="Content-Style-Type" content="text/css">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>${strMagazineTitle}</title>
</head><body bgcolor="#ffffff"
  style="background-color:#ffffff; margin:0 auto; padding:0; width:100%; font-family:${strMagazineFont}">

<table width="640" border="0" align="center" cellpadding="0" cellspacing="0" bgcolor="#ffffff"
  style="width:100%; max-width:640px; border:none; margin:0 auto; padding:0; background-color:#ffffff">
`;

let strBlockLogo = `<tr><td height="8" style="height:0.5em"></td></tr>
<tr><td width="100%" style="width:100%; margin:0; padding:0">
  <img src="${strLogoUrl}" alt="Logo Image" style="max-width:100%; height:auto">
</td></tr>
<tr><td height="8" style="height:0.5em"></td></tr>
`;

let strBlockSubject = `<tr><td height="8" style="height:0.5em"></td></tr>
<tr><td style="font-family:${strMagazineFont}">
  ${strMagazineTitle}
</td></tr>
<tr><td>
  <h2 style="font-size:1.8em; color:${strMagazineColor}; font-family:${strMagazineFont}">
  ${strSubject}</h2>
</td></tr>
`;

let strBlockAbstract = `<tr><td style="font-family:${strMagazineFont}">
  ${strAbstract}
</td></tr>
`;

let strBlockImage = `<tr><td height="8" style="height:0.5em"></td></tr>
<tr><td
  width="100%" style="width:100%; margin:0; padding:0">
    <table width="100%" border="0" align="center" cellpadding="0" cellspacing="0" bgcolor="#ffffff"
    style="width:100%; border:none; margin:0 auto; padding:0; background-color:#ffffff">
    <tr><td width="5%"></td>
        <td width="90%">
          <img src="${strImageUrl}" alt="Featured Image" style="max-width:100%">
        </td>
        <td width="5%"></td></tr>
    </table>
</td></tr>
<tr><td height="8" style="height:0.5em"></td></tr>
`;

let strBlockSection1 = `<tr><td height="8" style="height:0.5em"></td></tr>
<tr><td>
  <h3 style="font-size:1.6em; font-family:${strMagazineFont}">
  ${strSection1}</h3>
</td></tr>
`;

let strBlockParagraph1 = `<tr><td style="font-family:${strMagazineFont}">
  ${strParagraph1}
</td></tr>
`;

let strBlockLinkButton = `<tr><td height="16" style="height:1.0em"></td></tr>
<tr><td
  width="100%" align="center"
  style="width:100%; margin:0px auto">
  <a href="${strLinkButtonUrl}"
  style="display:inline-block; font-weight:bold; border-radius:8px; padding:10px 20px;
  color:#ffffff; background:${strMagazineColor}; border:solid 4px ${strMagazineColor}">
  ${strLinkButtonText}</a>
</td></tr>
<tr><td height="16" style="height:1.0em"></td></tr>
`;

let strBlockSection2 = `<tr><td height="8" style="height:0.5em"></td></tr>
<tr><td>
  <h3 style="font-size:1.6em; font-family:${strMagazineFont}">
  ${strSection2}</h3>
</td></tr>
`;

let strBlockParagraph2 = `<tr><td style="font-family:${strMagazineFont}">
  ${strParagraph2}
</td></tr>
`;

let strBlockFooter = `<tr><td height="32" style="height:2.0em"></td></tr>
<tr><td height="24" bgcolor="#eeeeee" style="height:1.5em; background:#eeeeee"></td></tr>
<tr><td
  width="100%" align="center" bgcolor="#eeeeee"
  style="width:100%; text-align:center; background:#eeeeee; font-size:.8em">
  <a href="${strPublisherUrl}">${strPublisherName}</a>
</td></tr>
<tr><td
  width="100%" align="center" bgcolor="#eeeeee"
  style="width:100%; text-align:center; background:#eeeeee; font-size:.7em">
  ${strPublisherStatement}
</td></tr>
<tr><td height="24" bgcolor="#eeeeee" style="height:1.5em; background:#eeeeee"></td></tr>
<tr><td height="24" style="height:1.5em"></td></tr>

</table></body></html>
`;

let strHtml =  strBlockHeader;
  if( strLogoUrl !== "" ){
    strHtml += strBlockLogo;
  }
    strHtml += strBlockSubject;
  if( strAbstract !== "" ){
    strHtml += strBlockAbstract;
  }
  if( strImageUrl !== "" ){
    strHtml += strBlockImage;
  }
  if( strSection1 !== "" ){
    strHtml += strBlockSection1;
  }
  if( strParagraph1 !== "" ){
    strHtml += strBlockParagraph1;
  }
  if( strLinkButtonUrl !== "" ){
    strHtml += strBlockLinkButton;
  }
  if( strSection2 !== "" ){
    strHtml += strBlockSection2;
  }
  if( strParagraph2 !== "" ){
    strHtml += strBlockParagraph2;
  }
    strHtml += strBlockFooter;


//// == Data Updating / ワークフローデータへの代入 ==
engine.setData( strPocketHtml, strHtml );

} //////// END "main()" /////////////////////////////////////////////////////////////////


function encodeHTML( str ){
  return str.replace(/&/g, '&')
            .replace(/</g, '<')
            .replace(/>/g, '>')
            .replace(/"/g, '"')
            .replace(/'/g, ''');
}

// convert multiple consecutive spaces to "      .."
function convertMultiSpaces( strArg ){
  let re = /\ {2,}/g;
//  let re = /s{2,}/g;
  let strReturn = strArg.replace( re, function( strMatch ){
                    let strNbspSpRepeat = "";
                    for( let i = 0; i < strMatch.length; i++ ){
                      if( (i % 2) === 0 ){ // Even number
                        strNbspSpRepeat += " ";
                      }else{ // Odd number
                        strNbspSpRepeat += " ";
                      }
                    }
                    return strNbspSpRepeat;
                  });
  return strReturn;
}


/*
Notes:
- When a token reaches the automated step, the code for HTML mail is automatically generated.
    - The generated code can be set in "Message Sending Intermediate Event (Email)" (v13.1) as it is.
    - https://support.questetra.com/bpmn-icons/throwing-message-intermediate-event-email/
    - It is also effective to add a human step in downstream to add decorative tags such as strong and span.
- Special characters in workflow data are escaped as appropriate.
    - For example, "<" is automatically converted to "<".
    - Line feed codes in multi-line text are automatically converted to br tags.
- Multiple spaces (two or more spaces) in workflow data are replaced with " " every other character.
    - eg "A   B  C D" to "A   B  C D"
APPENDIX
- The generated HTML code is not guaranteed to be displayed properly in all mailers.
- The HTML code is built on the basis of 640px wide table tags.
    - Basically, the background color is white and the text color is black.
    - Subjects (titles) in the email body will be displayed in the color specified in MagazineColor.
    - The link button in the email will be displayed in the color specified in MagazineColor.
- MagazineLogo image is displayed in its original size.
    - Image with a width greater than 640px will be scaled down.
    - As a guide, the height should be between 20px and 50px.
    - The URL of the MagazineLogo image must be accessible to the recipient.
Notes-ja:
- 案件が自動処理工程に到達した際、HTMLメール用のコードが自動的に生成されます。
    - 生成されたコードは、そのまま『メッセージ送信中間イベント(メール)』(v13.1)にセットできます。
    - https://support.questetra.com/ja/bpmn-icons/throwing-message-intermediate-event-email/
    - 下流に "装飾タグを手動追加する工程"(strong や span など)を配置するのも効果的です。
- ワークフローデータ内の特殊文字は、適宜エスケープ処理されます。
    - たとえば、"<" は "<" に自動的に変換されます。
    - 複数行テキスト内の改行コードは、自動的に br タグに変換されます。
- ワークフローデータ内の連続スペース(2文字以上)は、一文字おきに " " に置換されます。
    - eg "A   B  C D" to "A   B  C D"
APPENDIX-ja
- 生成されるHTML コードは、全てのメーラで正常に表示されることが保証されている訳ではありません。
- HTML コードは、640px 幅の table タグがベースとなって組み立てられます。
    - 背景色は白、文字色は黒が基本となります。
    - メール内に再掲されるサブジェクト(タイトル)は、MagazineColor で指定した色で表示されます。
    - メール内に表示されるリンクボタンは、MagazineColor で指定した色で表示されます。
- Magazine Logo 画像は、そのままのサイズで表示されます。
    - 幅が 640px を超える画像は縮小表示されます。
    - 高さが 20px から 50px が目安となります。
    - Magazine Logo 画像の URL は、受信者がアクセスできるURLでなければなりません。
*/


Download

2021-06-20 (C) Questetra, Inc. (MIT License)
https://support.questetra.com/addons/email-html-string-create-simplenotice-2021/
The Addon-import feature is available with Professional edition.

Notes

  • When a token reaches the automated step, the code for HTML mail is automatically generated.
  • Special characters in workflow data are escaped as appropriate.
    • For example, “<” is automatically converted to “&lt;“.
    • Line feed codes in multi-line text are automatically converted to br tags.
  • Multiple spaces (two or more spaces) in workflow data are replaced with “&nbsp;” every other character.
    • eg “A   B  C D” to “A&nbsp; &nbsp;B&nbsp; C D

Capture

Assembles HTML text for email from workflow data. The html text will consist of blocks of abstract, image, main sentence, link button, and sub-sentence. If the setting is blank, the block will not be displayed.
Assembles HTML text for email from workflow data. The html text will consist of blocks of abstract, image, main sentence, link button, and sub-sentence. If the setting is blank, the block will not be displayed.

Appendix

  • The generated HTML code is not guaranteed to be displayed properly in all mailers.
  • The HTML code is built on the basis of 640px wide table tags.
    • Basically, the background color is white and the text color is black.
    • Subjects (titles) in the email body will be displayed in the color specified in MagazineColor.
    • The link button in the email will be displayed in the color specified in MagazineColor.
  • MagazineLogo image is displayed in its original size.
    • Image with a width greater than 640px will be scaled down.
    • As a guide, the height should be between 20px and 50px.
    • The URL of the MagazineLogo image must be accessible to the recipient.

See also

Discover more from Questetra Support

Subscribe now to keep reading and get access to the full archive.

Continue reading