Nylas Node.js SDK
Installation
Install the Nylas SDK:
npm install nylas
or yarn add nylas
API Overview
Every resource (i.e., messages, events, contacts) is accessed via an instance of Nylas
. Before making any requests, be sure to call config
and initialize the Nylas
instance with your appId
and appSecret
. Then, call with
and pass it your accessToken
. The accessToken
allows Nylas
to make requests for a given account's resources.
import Nylas from 'nylas';
Nylas.config({
appId: APP_ID,
appSecret: APP_SECRET,
});
const nylas = Nylas.with(ACCESS_TOKEN);
Every resource method accepts an optional callback as the last argument:
nylas.threads.list({}, (err, threads) => {
console.log(threads.length);
});
Additionally, every resource method returns a promise, so you don't have to use callbacks if your code is promise-friendly. Here's an example using promises:
nylas.threads.list({}).then(threads => {
console.log(threads.length);
});
And here's an example using async/await:
const getThreadCount = async nylas => {
const threads = await nylas.threads.list({});
return threads.length;
};
Authentication
The Nylas REST API uses server-side (three-legged) OAuth, and the Node.js bindings provide convenience methods that simplify the OAuth process. For more information about authenticating users with Nylas, visit the API docs.
urlForAuthentication()
takes in an options
object, which must have a redirectURI
property defined. Other supported, but optional, properties are:
loginHint
- The user's email address, if known.state
- An arbitrary string that will be returned back as a query param in your redirectURI
.scopes
- An array of which scopes you'd like to auth with. Possible items are 'email'
, 'calendar'
, and 'contacts'
. If omitted, defaults to all scopes.
Step 1: Redirect the user to Nylas
import Nylas from 'nylas';
Nylas.config({
appId: APP_ID,
appSecret: APP_SECRET,
});
router.get('/connect', (req, res, next) => {
options = {
redirectURI: 'http://localhost:3000/oauth/callback',
};
res.redirect(Nylas.urlForAuthentication(options));
});
Step 2: Handle the Authentication Response
router.get('/oauth/callback', (req, res, next) => {
if (req.query.code) {
Nylas.exchangeCodeForToken(req.query.code).then(token => {
});
} else if (req.query.error) {
res.render('error', {
message: req.query.reason,
error: {
status:
'Please try authenticating again or use a different email account.',
stack: '',
},
});
}
});
Fetching Messages, Events, Contacts, etc.
The Node.js SDK exposes API resources (threads, messages, folders, labels, files, events, contacts, etc.) as attributes of the nylas
object. You can query these resources in several ways. Available filters can be found in the API docs.
const nylas = Nylas.with(ACCESS_TOKEN);
nylas.threads.first({ from: EMAIL_ADDRESS }).then(thread => {
console.log(thread.subject);
console.log(thread.snippet);
});
nylas.threads.count({ in: 'inbox' }).then(count => {
console.log(`There are ${count} threads in your inbox.`);
});
nylas.threads
.find(THREAD_ID)
.then(thread => {
console.log(thread.subject);
})
.catch(err => {
console.log(`Thread not found! Error: ${err.toString()}`);
});
nylas.threads.find(THREAD_ID, (err, thread) => {
if (err) {
console.log(`Thread not found! Error: ${err.toString()}`);
return;
}
console.log(thread.subject);
});
nylas.threads.forEach(
{ unread: false, from: 'chaiskye@gmail.com' },
thread => console.log(thread.subject),
err => console.log('Finished iterating through threads.')
);
nylas.threads.list({ in: 'inbox' }).then(threads => {
console.log(threads);
});
Folders and Labels
The folders and labels API allows you to apply Gmail labels to whole threads or individual messages and, for providers other than Gmail, to move threads and messages between folders.
Note that folders and labels are identical from the standpoint of the SDK. The only difference is that a message can have many labels but only a single folder.
const nylas = Nylas.with(ACCESS_TOKEN);
nylas.labels.list({}).then(labels => {
for (const label of labels) {
console.log(label.displayName);
console.log(label.id);
}
});
nylas.folders.list({}).then(folders => {
for (const folder of folders) {
console.log(folder.displayName);
console.log(folder.id);
}
});
const fld = nylas.folders.build({ displayName: 'Reminders' });
fld.save();
let spamLabel = undefined;
nylas.labels.list({}).then(labels => {
for (const label of labels) {
if (label.displayName == 'Spam') {
spamLabel = label;
break;
}
}
nylas.threads.list({}, (err, threads) => {
const thread = threads[0];
thread.labels.push(spamLabel);
thread.save();
console.log(thread);
});
});
File Metadata
const nylas = Nylas.with(ACCESS_TOKEN);
const f = nylas.files.build({
id: fileId,
});
f.metadata((err, data) => {
console.log(data);
});
On success, the file metadata should look like:
{
"content_type": "application/msword",
"filename": "Reinstatement of Corporation.doc",
"id": "9tm2n206vdj29wrhcxfvmvo4o",
"message_ids": [
"93mtrpk4uo3wsvwcpb5yh57kp"
],
"account_id": "6aakaxzi4j5gn6f7kbb9e0fxs",
"object": "file",
"size": 100864
}
Uploading Files
Because of a bug in the library we use to issue HTTP requests, we can't pass a stream to the file upload function, which is why we read the file directly.
import fs from 'fs';
const nylas = Nylas.with(ACCESS_TOKEN);
fs.readFile(filePath, 'utf8', (err, data) => {
f = nylas.files.build({
filename: filePath,
data: data,
contentType: 'text/plain',
});
f.upload((err, file) => {
const draft = nylas.drafts.build({
subject: 'Ice Cream',
to: [{ email: 'helena@nylas.com' }],
body: 'Hey, find the file attached.',
});
draft.files = [file];
draft.send().then(message => {
console.log(`${message.id} was sent`);
});
});
});
Downloading Files
import fs from 'fs';
const nylas = Nylas.with(ACCESS_TOKEN);
const f = nylas.files.build({
id: fileId,
});
f.download((err, file) => {
fs.writeFile('/tmp/' + file.filename, file.body);
});
Creating and Sending Drafts
You can create, save, and send drafts. To send, first create a draft object with the correct fields (To/CC/BCC, subject, body, etc.), and then call send
. When the draft is sent, the Nylas API will return a Message
object.
If you want to send a reply, set replyMessageId
to the ID of the message to which you're replying. When that field is set, the Nylas API will set email headers to mark your message as a reply.
const nylas = Nylas.with(ACCESS_TOKEN);
const draft = nylas.drafts.build({
subject: 'My New Draft',
to: [{ email: 'ben@nylas.com' }],
replyToMessageId: MESSAGE_ID,
});
draft.send().then(message => {
console.log(`${message.id} was sent`);
});
draft.save().then(draft => {
console.log(`${draft.id} was saved`);
});
const savedId = '1234';
nylas.drafts
.find(savedId)
.then(draft => draft.send())
.then(message => {
console.log(`Sent ${message.subject}!`);
});
Searching Threads and Messages
You can run a full-text search on threads and messages using search
and passing a string to query. By default, the Nylas API returns 40 results, but you can pass a limit
and offset
to perform pagination.
const nylas = Nylas.with(ACCESS_TOKEN);
nylas.messages.search('Hey!').then(messages => console.log(messages));
Using the Delta Streaming API
const DELTA_EXCLUDE_TYPES = ['contact', 'calendar', 'event', 'file', 'tag'];
const nylas = Nylas.with(ACCESS_TOKEN);
nylas.deltas.latestCursor((error, cursor) => {
persistCursor(cursor);
const stream = nylas.deltas.startStream(cursor, DELTA_EXCLUDE_TYPES);
stream
.on('delta', delta => {
console.log('Received delta:', delta);
persistCursor(delta.cursor);
})
.on('error', err => {
console.error('Delta streaming error:', err);
});
stopButton.addEventListener('click', () => {
stream.close();
});
});
Interacting with Events
You can send calendar invites to events using the Nylas API. To send invites and updates to the event's participants, set notify_participants
to true
.
const nylas = Nylas.with(ACCESS_TOKEN);
const event = nylas.events.build({
title: 'Out of time',
calendarId: CALENDAR_ID,
when: { start_time: 1437500000, end_time: 1437501600 },
participants: [{ email: 'helena@nylas.com', name: 'Helena Handbasket' }],
});
event.save({ notify_participants: true }).then(event => {
console.log(event);
console.log('Sent an invite to the participants');
});
nylas.events
.find(EVENT_ID)
.then(event => event.rsvp('maybe', 'I may attend this event'))
.then(event => console.log('RSVP sent!'));
Sending and Retrieving Raw MIME
To send raw MIME, you can build a draft and, instead of providing the normal fields, pass the MIME in an object as rawMime
.
To retrieve the raw MIME for an account's message, call getRaw
on the message object, and the MIME will be returned in a promise.
const nylas = Nylas.with(ACCESS_TOKEN);
const draft = nylas.drafts.build({ rawMime });
draft.send().then(message => console.log(message));
nylas.messages
.first()
.then(message => message.getRaw())
.then(rawMessage => console.log(rawMessage));
Accounts
It's possible to get details about the account you're accessing by using the account
method:
const nylas = Nylas.with(ACCESS_TOKEN);
nylas.account.get().then(account => console.log(account));
You can access the billing status and cancel/reactivate an account for the accounts in your app by using the accounts
method:
Nylas.accounts.list().then(accounts => {
console.log(accounts.length);
for (const account of accounts) {
console.log(
account.id,
account.billingState,
account.syncState
);
}
});
Nylas.accounts
.first()
.then(account => account.downgrade())
.then(response => console.log(response));
Nylas.accounts
.first()
.then(account => account.upgrade())
.then(response => console.log(response));
Open-Source API
The Nylas Sync Engine is open-source, and you can also use the Node.js SDK with the open-source API. Since the open-source API provides no authentication or security, connecting to it is simple.
It requires us to "auth" to it by passing the account id as an auth token. Here's an example of fetching the messages of the first account after getting the account ID:
import Nylas from 'nylas';
Nylas.config({
appId: 'appId',
appSecret: 'appSecret',
apiServer: 'http://localhost:5555',
});
Nylas.accounts.first().then(account => {
const nylas = Nylas.with(account.id).messages.list(
{ limit: 20 },
(err, messages) => {
for (const message of messages) {
console.log(message.subject);
}
}
);
});
Example Apps
We have a few example Express apps in the example
directory that show examples for authentication and webhooks. You can run them to see how they're implemented:
npm install
or yarn
npm start
or yarn start
Note that you'll need to replace the Nylas app ID and app secret in app.js
or create a config.js
file with your application's credentials.
Contributing
We'd love your help making the Nylas Node.js SDK better. Come chat in the Nylas community Slack channel or email support@nylas.com.
Please sign the Contributor License Agreement before submitting pull requests. (It's similar to other projects, like NodeJS or Meteor.)
Tests can be run with:
npm test
or yarn test
Our linter can be run with:
npm run lint
or yarn lint
To use the package during local development, symlink the directory:
npm link
or yarn link
in the nylas-nodejs
directory
npm link nylas
or yarn link nylas
in the directory with your code that uses the package