Learn how to Automatically add an Attachment to a NetSuite Message Object

This article is relevant if you want to automatically add an attachment to a NetSuite email message object.


We are solving a number of client challenges with our Content Renderer Engine (CRE) which allows you to get much more data to a NetSuite Advanced PDF or HTML template. In many cases, because of the power of this tool, we are replacing the conventional Advanced PDF invoice and other standard transactional objects. Our CRE tool allows you to flexibly create file and email output. A client recently wanted to preserve the native NetSuite message object but they wanted all the goodness of CRE. In this case, they wanted a simple way to ensure that a file attachment was added to the native NetSuite message object so that users could have freedom to craft their own email yet ensure they have branded content as a file attachment.

SuiteScript 1.0 Pattern to Add Attachment to NetSuite Message

The following code pattern can be used as inspiration for any message object that needs a file attachment. At the same time, it illustrates how, with just a few lines of code , you can generate CRE profile based content. In addition, see the code pattern to turn off and hide NetSuite’s default message behavior which will add a transaction attachment.

//Function:		cre_EmailTemplate_BeforeLoad
//Record:		message
//Type:			BeforeLoad
//Description:			On the related transaction, generate the cre attachment and
//				add as attachments to current message
function cre_EmailTemplate_MsgBeforeLoad(type, form, request) {
    //check proper context
	if (type != 'create') return;
    var context = nlapiGetContext();
    if (context.getExecutionContext() != 'userinterface') return;
    if (!request) return;

    // get the query string parameters; this message example only works with transactions
	// ne is a custom function to return back a value if an expression returns back empty
    var recid = ne(request.getParameter("transaction"),'');
    if (recid.length == 0) return;

	//here, we have a custom script parameter holding a JSON structure binding transactions
	//to specific types of CRE profile templates.
    var rectype = nlapiLookupField('transaction', recid, 'type', false);

    var cre_trx_binding = JSON.parse(ne(context.getSetting('SCRIPT', 'custscript_cre_transaction_binding'),'{}'));
    var cre_profileid = cre_trx_binding[rectype];

    //only act on transactions that have a specific binding to CRE
	if (cre_profileid.length == 0) return;

	var error_list = [];

    //produce CRE output (effectively a PDF file)
        var creProfile = new CREProfile(cre_profileid);
		var str = "There was trouble generating the CRE file: " + recid + '-->' + cre_profileid; + '; error: ' + e.getCode();
		nlapiLogExecution("ERROR", 'could not create cre ouput', str);
		error_list.push("There was an error creating the CRE file. " + str);

	if (error_list.length > 0){

	//we should have file output
    var file_obj = null;
    var attachment_list = [];
    var foldername = cre_getFolderName(TEMPLATE_FOLDER_ID);

    if (creProfile.fields.DocumentName.translatedValue) {
          file_obj = nlapiLoadFile(foldername +'/' + creProfile.fields.DocumentName.translatedValue);
             var str = "There was trouble looking up CRE output file: " + creProfile.fields.DocumentName.Value + '-->' + creProfile.fields.DocumentName.translatedValue; + '; error: ' + e.getCode();
             nlapiLogExecution("ERROR", 'could not create document', str);
             //syntax template does not exist. Return this one.
             error_list.push("There was an error creating the CRE attachment. " + str);

	//get the file object and add it to the attachment list array
    if (file_obj){
        nlapiLogExecution('DEBUG', 'fetched file' + file_obj.getName() + '; id:' +  file_obj.getId() + '; type:' + file_obj.getType() );
    } else {
        nlapiLogExecution('DEBUG', 'Missing fetchd file; return');
        error_list.push("There was an error attaching the CRE file.");

	//add the attachment to the oject
    if (attachment_list.length > 0){
        for (var m=0; m<attachment_list.length; m++){
            nlapiSetCurrentLineItemValue('mediaitem', 'mediaitem', attachment_list[m]);
    } else {
        nlapiLogExecution('DEBUG', 'attachment_list is empty');
        error_list.push("Expected an attachment and found none.");

    // now enhance the default CRE message system to remove the default transaction checkbox so they don't send
    // netsuite's default message.
    var html = "";
    html += '<SCRIPT language="JavaScript" type="text/javascript">\r\n';
    html += "function bindEvent(element, type, handler) {if(element.addEventListener) {element.addEventListener(type, handler, false);} else {element.attachEvent('on'+type, handler);}} \r\n";
    html += "</SCRIPT>\r\n";
    html += '<SCRIPT language="JavaScript" type="text/javascript">\r\n';
    html += "function wload() \r\n{\r\n";
    html += "nlapiSetFieldValue('includetransaction', 'F');\r\n";
    html += "var fld = nlapiGetField('includetransaction');\r\n";
    html += "if (fld){fld.setDisplayType('hidden');};\r\n";
    html += "var fld = nlapiGetField('emailpreference');\r\n";
    html += "if (fld){fld.setDisplayType('hidden');};\r\n";
    if (error_list.length > 0){
        html += "alert('Warning: there appears to be an error fetching attachments. Please review the attachment list before sending.\\n\\n"+error_list.join('\\n')+"');\r\n";
        nlapiLogExecution('ERROR', 'Error fetching attachments', JSON.stringify(error_list));
    html += "}\r\n";
    html += "</SCRIPT>\r\n";
    html += '<SCRIPT language="JavaScript" type="text/javascript">\r\n';
    html += 'bindEvent(window, "load", wload);\r\n';
    html += "</SCRIPT>\r\n";
    var field0 = form.addField('custpage_client_html', 'inlinehtml', '',null, null);

Drive NetSuite To Fit Your Specific Requirements

NetSuite’s platform affords us many opportunities to streamline our day-to-day operational usage while increase our capacity to act quickly — this spells into lower cost and higher profits. If you have a unique requirement and wish to get more out the NetSuite platform, let’s have a conversation.

Be Sociable, Share!

Marty Zigman

Holding all three official certifications, Marty is Southern California's NetSuite expert and leads a team of senior professionals at Prolecto Resources, Inc. He is a former Deloitte & Touche CPA and has held CTO roles. For over 25 years, Marty has produced leadership in ERP, CRM and eCommerce business systems. Contact Marty to setup a conversation.

More Posts - Website - Twitter - Facebook - LinkedIn - Google Plus - YouTube

| Tags: , , , | Category: NetSuite, Technical | Leave a comment

Post a Comment

Your email is never published nor shared. Required fields are marked *


You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>