If you’ve built anything in NetSuite beyond basic automation, you’ve almost certainly needed to send an email from a script. Whether it’s notifying a manager when an order hits a certain threshold, alerting a customer when their shipment ships, or letting your team know a scheduled job failed β email is one of the most practical tools in SuiteScript. The N/email module makes all of that straightforward once you understand how it works.
This guide covers everything you need to know about sending emails in SuiteScript 2.x β from basic setup to attachments, templated emails, and real-world patterns you’ll actually use.
What Is the N/email Module?
The N/email module is a built-in SuiteScript 2.x module that lets you send emails programmatically from inside NetSuite. You can send plain text or HTML emails, include attachments from the File Cabinet, send to multiple recipients, and even use NetSuite’s built-in email templates.
To use it, you load it like any other SuiteScript module:
/**
* @NApiVersion 2.1
* @NScriptType UserEventScript
*/
define(['N/email'], (email) => {
// your code here
});
Sending a Basic Email
The core method is email.send(). At minimum, you need an author (a NetSuite internal employee ID), at least one recipient, a subject, and a body.
email.send({
author: 5, // Internal ID of the sending employee
recipients: 'john.smith@example.com',
subject: 'Order Confirmed',
body: 'Your order has been received and is being processed.'
});
A few things to note here:
- The
authormust be a valid NetSuite employee internal ID. This determines the “From” address. - The
recipientsfield accepts a string (single email), an array of strings, or an array of NetSuite entity internal IDs. - The
bodycan be plain text or HTML β NetSuite will handle it accordingly.
Sending HTML Emails
For formatted emails, just pass HTML into the body field:
email.send({
author: 5,
recipients: ['john.smith@example.com', 'jane.doe@example.com'],
cc: 'manager@example.com',
subject: 'Invoice #1042 Ready for Review',
body: '<h2>Invoice Ready</h2><p>Hi John, your invoice <strong>#1042</strong> is ready. Please review and approve it.</p>'
});
You can also use cc and bcc fields just like you’d expect. Both accept the same format as recipients β a string, array of strings, or array of entity IDs.
Sending Emails with Attachments
Adding File Cabinet attachments is simple. Load the N/file module and pass file objects to the attachments field:
define(['N/email', 'N/file'], (email, file) => {
const exports = {};
exports.afterSubmit = (context) => {
const attachment = file.load({ id: '/SuiteScripts/reports/monthly_summary.pdf' });
email.send({
author: 5,
recipients: 'cfo@example.com',
subject: 'Monthly Summary Report',
body: '<p>Please find the monthly summary attached.</p>',
attachments: [attachment]
});
};
return exports;
});
The attachments field takes an array of File objects. You can attach multiple files at once.
Using NetSuite Email Templates
If you’ve set up email templates in NetSuite (under Setup > Company > Email Templates), you can trigger them from SuiteScript using email.sendBulk() or the templateId option. This is useful when you want consistent, admin-managed email content that doesn’t require a code deployment every time the copy changes.
email.send({
author: 5,
recipients: context.newRecord.getValue('custbody_contact_email'),
subject: 'Order Shipped',
templateId: 123, // Internal ID of the email template
relatedRecords: {
transactionId: context.newRecord.id
}
});
The relatedRecords field lets the template pull values from a specific transaction, customer, or other record type. This is how you get dynamic merge fields (like order numbers, customer names, etc.) to populate automatically.
Sending to NetSuite Entity IDs
Instead of hardcoding email addresses, you can pass NetSuite internal IDs for employees, contacts, customers, or vendors. NetSuite will look up the email address automatically:
email.send({
author: 5,
recipients: [101, 102], // Internal IDs of NetSuite contacts or employees
subject: 'Task Assigned',
body: 'You have been assigned a new task. Please log in to review it.'
});
This approach is cleaner for internal notifications since you’re not hardcoding addresses that might change.
Real-World Example: Notify on Sales Order Approval
Here’s a practical User Event script that sends a confirmation email to the sales rep when a sales order moves to “Approved” status:
/**
* @NApiVersion 2.1
* @NScriptType UserEventScript
*/
define(['N/email', 'N/runtime'], (email, runtime) => {
const exports = {};
exports.afterSubmit = (context) => {
if (context.type !== context.UserEventType.EDIT) return;
const newRecord = context.newRecord;
const oldRecord = context.oldRecord;
const newStatus = newRecord.getValue('orderstatus');
const oldStatus = oldRecord.getValue('orderstatus');
// Only fire when status changes to Approved (B)
if (newStatus !== 'B' || oldStatus === 'B') return;
const salesRepId = newRecord.getValue('salesrep');
const orderNumber = newRecord.getValue('tranid');
const customerName = newRecord.getValue('entity');
if (!salesRepId) return;
email.send({
author: runtime.getCurrentUser().id,
recipients: [salesRepId],
subject: `Sales Order ${orderNumber} Approved`,
body: `<p>Hi,</p><p>Sales Order <strong>${orderNumber}</strong> for <strong>${customerName}</strong> has been approved and is ready to fulfill.</p><p>Log in to NetSuite to review it.</p>`
});
};
return exports;
});
A few things worth highlighting here:
- We use
runtime.getCurrentUser().idas the author so the email appears to come from the person who approved the order β more natural than a hardcoded ID. - We check both the old and new status to avoid firing the email on every save.
- The
salesrepfield returns an internal ID, which we pass directly torecipients.
Common Pitfalls
A few things that can catch you out when first using N/email:
- Invalid author ID β if the employee ID you pass as
authordoesn’t exist or is inactive, the script will throw an error. Always validate the ID or useruntime.getCurrentUser().id. - Governance limits β
email.send()counts against your script’s governance. In Map/Reduce or Scheduled Scripts processing large datasets, be careful about sending an email per record. Batch your sends or use a Summary stage. - HTML encoding β when building HTML bodies dynamically, make sure you encode special characters properly. Unescaped characters in customer names or order fields can break your email formatting.
- Empty recipients β if your recipients field ends up empty (e.g., a customer with no email on file), the script will fail. Always check before calling
email.send().
Key Parameters Reference
Here’s a quick reference for the email.send() options:
- author (number, required) β Internal ID of the NetSuite employee sending the email.
- recipients (string | number | array, required) β Email address(es) or NetSuite entity IDs.
- cc (string | number | array, optional) β Carbon copy recipients.
- bcc (string | number | array, optional) β Blind carbon copy recipients.
- subject (string, required) β Email subject line.
- body (string, required unless using templateId) β Plain text or HTML body.
- attachments (array of File objects, optional) β Files from the File Cabinet to attach.
- templateId (number, optional) β Internal ID of a NetSuite email template.
- relatedRecords (object, optional) β Links to NetSuite records for template merge field population.
- isInternalOnly (boolean, optional) β If true, email is saved in NetSuite but not actually sent externally. Useful for testing.
Wrapping Up
The N/email module is one of those SuiteScript tools you’ll reach for constantly. Once you’ve used it a few times, the pattern becomes second nature β load the module, build your recipient list, pass in your subject and body, and send. The trickier parts are usually around getting your author ID right, handling empty email fields gracefully, and being mindful of governance when sending from batch scripts.
If you’re sending high-volume emails or need templated content that non-developers can update, look into email templates combined with relatedRecords β it keeps your business logic in code and your email copy in the hands of whoever owns it.
Discover more from The NetSuite Pro
Subscribe to get the latest posts sent to your email.
Leave a Reply