A Node.js library to send all kinds of transactional notifications.
Features
-
Easy channel integration — Want to start sending
emails
|SMS
|pushes
|webpushes
|slack
? Do so in no time! -
Unique documentation — Don't look everywhere for the parameters you need to pass, just do it once. Switching provider becomes a no-brainer.
-
Multiple providers strategies — Want to use more than one provider? Use
fallback
andround-robin
strategies out of the box. -
Tools for local testing — Run a catcher locally to intercept all your notifications and display them in a web interface.
-
MIT license — Use it like you want.
Getting Started
$ yarn add notifme-sdk
import NotifmeSdk from 'notifme-sdk'
const notifmeSdk = new NotifmeSdk({}) // empty config = all providers are set to console.log
notifmeSdk
.send({sms: {from: '+15000000000', to: '+15000000001', text: 'Hello, how are you?'}})
.then(console.log)
✨ Congratulations, you should see the following lines in your console:
[Recommended] Setup Notification Catcher for your local tests
Notification Catcher is a web interface for viewing and testing notifications during development.
$ yarn add --dev notification-catcher
$ yarn run notification-catcher
import NotifmeSdk from 'notifme-sdk'
const notifmeSdk = new NotifmeSdk({
useNotificationCatcher: true // <= this sends all your notifications to the catcher running on port 1025
})
notifmeSdk
.send({sms: {from: '+15000000000', to: '+15000000001', text: 'Hello, how are you?'}})
.then(console.log)
😻 Open http://localhost:1080 on your favorite browser, you should see the notification:
How to use
1. General options
new NotifmeSdk({
channels: ..., // Object
useNotificationCatcher: ... // boolean
})
Option name | Required | Type | Description |
---|---|---|---|
channels |
false |
Object |
Define providers (Array ) and multiProviderStrategy (string ) for each channel (email, sms, push, webpush, slack).See all details below: 2. Providers. |
useNotificationCatcher |
false |
boolean |
If true, all your notifications are sent to the catcher running on localhost:1025 (channels option will be completely ignored!) |
Complete examples
// Env: development
new NotifmeSdk({
useNotificationCatcher: true
})
// Env: production
new NotifmeSdk({
channels: {
email: {
// If "Provider1" fails, use "Provider2"
multiProviderStrategy: 'fallback',
providers: [{
type: 'Provider1',
// ...credentials
}, {
type: 'Provider2',
// ...credentials
}]
},
sms: {
// Use "Provider1" and "Provider2" in turns (and fallback if error)
multiProviderStrategy: 'roundrobin',
providers: [{
type: 'Provider1',
// ...credentials
}, {
type: 'Provider2',
// ...credentials
}]
}
}
})
HTTP proxy option
If you want to use a HTTP proxy, set an environment variable NOTIFME_HTTP_PROXY
.
$ # Example
$ NOTIFME_HTTP_PROXY=http://127.0.0.1:8580 node your-script-using-notifme.js
2. Providers
Email providers
Logger (for development)
new NotifmeSdk({
channels: {
email: {
providers: [{
type: 'logger'
}]
}
}
})
SMTP (can be used for almost all providers)
new NotifmeSdk({
channels: {
email: {
providers: [{
type: 'smtp',
host: 'smtp.example.com',
port: 465,
secure: true,
auth: {
user: 'xxxxx',
pass: 'xxxxx'
}
}]
}
}
})
Sendmail
new NotifmeSdk({
channels: {
email: {
providers: [{
type: 'sendmail',
sendmail: true,
newline: 'unix',
path: '/usr/sbin/sendmail'
}]
}
}
})
Mailgun
new NotifmeSdk({
channels: {
email: {
providers: [{
type: 'mailgun',
apiKey: 'xxxxx',
domainName: 'example.com'
}]
}
}
})
Sendgrid
new NotifmeSdk({
channels: {
email: {
providers: [{
type: 'sendgrid',
apiKey: 'xxxxx'
}]
}
}
})
SES
new NotifmeSdk({
channels: {
email: {
providers: [{
type: 'ses',
region: 'xxxxx',
accessKeyId: 'xxxxx',
secretAccessKey: 'xxxxx',
sessionToken: 'xxxxx' // optional
}]
}
}
})
SparkPost
new NotifmeSdk({
channels: {
email: {
providers: [{
type: 'sparkpost',
apiKey: 'xxxxx'
}]
}
}
})
Custom (define your own)
new NotifmeSdk({
channels: {
email: {
providers: [{
type: 'custom',
id: 'my-custom-email-provider...',
send: async (request) => {
// Send email
return 'id...'
}
}]
}
}
})
request
being of the following type.
See all options: Email provider options
SMS providers
Logger (for development)
new NotifmeSdk({
channels: {
sms: {
providers: [{
type: 'logger'
}]
}
}
})
46elks
new NotifmeSdk({
channels: {
sms: {
providers: [{
type: '46elks',
apiUsername: 'xxxxx',
apiPassword: 'xxxxx'
}]
}
}
})
Callr
new NotifmeSdk({
channels: {
sms: {
providers: [{
type: 'callr',
login: 'xxxxx',
password: 'xxxxx'
}]
}
}
})
Clickatell
new NotifmeSdk({
channels: {
sms: {
providers: [{
type: 'clickatell',
apiKey: 'xxxxx' // One-way integration API key
}]
}
}
})
Infobip
new NotifmeSdk({
channels: {
sms: {
providers: [{
type: 'infobip',
username: 'xxxxx',
password: 'xxxxx'
}]
}
}
})
Nexmo
new NotifmeSdk({
channels: {
sms: {
providers: [{
type: 'nexmo',
apiKey: 'xxxxx',
apiSecret: 'xxxxx'
}]
}
}
})
OVH
new NotifmeSdk({
channels: {
sms: {
providers: [{
type: 'ovh',
appKey: 'xxxxx',
appSecret: 'xxxxx',
consumerKey: 'xxxxx',
account: 'xxxxx',
host: 'xxxxx' // https://github.com/ovh/node-ovh/blob/master/lib/endpoints.js
}]
}
}
})
Plivo
new NotifmeSdk({
channels: {
sms: {
providers: [{
type: 'plivo',
authId: 'xxxxx',
authToken: 'xxxxx'
}]
}
}
})
Twilio
new NotifmeSdk({
channels: {
sms: {
providers: [{
type: 'twilio',
accountSid: 'xxxxx',
authToken: 'xxxxx'
}]
}
}
})
Custom (define your own)
new NotifmeSdk({
channels: {
sms: {
providers: [{
type: 'custom',
id: 'my-custom-sms-provider...',
send: async (request) => {
// Send SMS
return 'id...'
}
}]
}
}
})
request
being of the following type.
See all options: SMS provider options
Push providers
Logger (for development)
new NotifmeSdk({
channels: {
push: {
providers: [{
type: 'logger'
}]
}
}
})
APN (Apple Push Notification)
new NotifmeSdk({
channels: {
push: {
providers: [{
type: 'apn',
token: {
key: './certs/key.p8',
keyId: 'xxxxx',
teamId: 'xxxxx'
}
}]
}
}
})
FCM (Firebase Cloud Messaging, previously called GCM, Google Cloud Messaging)
new NotifmeSdk({
channels: {
push: {
providers: [{
type: 'fcm',
id: 'xxxxx'
}]
}
}
})
WNS (Windows Push Notification)
new NotifmeSdk({
channels: {
push: {
providers: [{
type: 'wns',
clientId: 'xxxxx',
clientSecret: 'xxxxx',
notificationMethod: 'sendTileSquareBlock'
}]
}
}
})
ADM (Amazon Device Messaging)
new NotifmeSdk({
channels: {
push: {
providers: [{
type: 'adm',
clientId: 'xxxxx',
clientSecret: 'xxxxx'
}]
}
}
})
Custom (define your own)
new NotifmeSdk({
channels: {
push: {
providers: [{
type: 'custom',
id: 'my-custom-push-provider...',
send: async (request) => {
// Send push
return 'id...'
}
}]
}
}
})
request
being of the following type.
See all options: Push provider options
Webpush providers
Logger (for development)
new NotifmeSdk({
channels: {
webpush: {
providers: [{
type: 'logger'
}]
}
}
})
GCM (Google Cloud Messaging) - uses W3C endpoints if possible
new NotifmeSdk({
channels: {
webpush: {
providers: [{
type: 'gcm',
gcmAPIKey: 'xxxxx',
vapidDetails: {
subject: 'mailto: [email protected]',
publicKey: 'xxxxx',
privateKey: 'xxxxx'
}
}]
}
}
})
Custom (define your own)
new NotifmeSdk({
channels: {
webpush: {
providers: [{
type: 'custom',
id: 'my-custom-webpush-provider...',
send: async (request) => {
// Send webpush
return 'id...'
}
}]
}
}
})
request
being of the following type.
See all options: Webpush provider options
Slack providers
Logger (for development)
new NotifmeSdk({
channels: {
slack: {
providers: [{
type: 'logger'
}]
}
}
})
Slack
new NotifmeSdk({
channels: {
slack: {
providers: [{
type: 'webhook',
webhookUrl: 'https://hooks.slack.com/services/Txxxxxxxx/Bxxxxxxxx/xxxxxxxxxxxxxxxxxxxxxxxx'
}]
}
}
})
Custom (define your own)
new NotifmeSdk({
channels: {
slack: {
providers: [{
type: 'custom',
id: 'my-custom-slack-provider...',
send: async (request) => {
// Send slack
return 'id...'
}
}]
}
}
})
request
being of the following type.
See all options: Slack provider options
Multi-provider strategies
A multi-provider strategy allows you to customize the send process on a channel.
Predefined strategies
Strategy name | Description |
---|---|
fallback |
If the used provider returns an error, try the next in the list. |
roundrobin |
Use every provider in turns. If one of them returns an error, fallback to the next. |
no-fallback |
Deactivates fallback strategy. |
Custom
You can also provide your own strategy. You have to pass a function implementing:
(Provider[]) => Sender
// See examples below for more details
Examples:
Random strategy
/*
* `providers` is an array containing all the instances that were
* created from your configuration.
*/
const randomStrategy = (providers) => async (request) => {
// Choose one provider at random
const provider = providers[Math.floor(Math.random() * providers.length)];
try {
const id = await provider.send(request)
return {id, providerId: provider.id}
} catch (error) {
error.providerId = provider.id
throw error
}
}
new NotifmeSdk({
channels: {
email: { // Example for email channel
providers: [...],
multiProviderStrategy: randomStrategy
}
}
})
Cheap SMS strategy with fallback
import strategyFallback from 'notifme-sdk/lib/strategies/fallback'
function getCountryFromNumber(number) {
// extract the country from a phone number (+33670707070) -> 'fr'
}
function orderProvidersByPrice(country, providers) {
// giving a country return an array of ordered providers by price
}
const smsCheapStrategy = (providers) => async (request) => {
const country = getCountryFromNumber(request.from)
const providersOrdered = orderProvidersByPrice(country, providers)
return strategyFallback(providersOrdered)(request)
}
Adding a provider or a channel
If you would like to see another provider or channel, please upvote the corresponding issue (or create one if it does not exist yet).
3. Send a notification
Parameters
New: you can check notifme-template to help you define your templates.
Send an email
notifmeSdk.send({
email: {
from: '[email protected]',
to: '[email protected]',
subject: 'Hi John',
html: '<b>Hello John! How are you?</b>'
}
})
See all parameters.
Send a SMS
notifmeSdk.send({
sms: {
from: '+15000000000',
to: '+15000000001',
text: 'Hello John! How are you?'
}
})
See all parameters.
Send a push
notifmeSdk.send({
push: {
registrationToken: 'xxxxx',
title: 'Hi John',
body: 'Hello John! How are you?',
icon: 'https://notifme.github.io/notifme-sdk/img/icon.png'
}
})
See all parameters.
Send a webpush
notifmeSdk.send({
webpush: {
subscription: {
keys: {
auth: 'xxxxx',
p256dh: 'xxxxx'
},
endpoint: 'xxxxx'
},
title: 'Hi John',
body: 'Hello John! How are you?',
icon: 'https://notifme.github.io/notifme-sdk/img/icon.png'
}
})
See all parameters.
Send a multi-channel notification
notifmeSdk.send({
email: {
from: '[email protected]',
to: '[email protected]',
subject: 'Hi John',
html: '<b>Hello John! How are you?</b>'
},
sms: {
from: '+15000000000',
to: '+15000000001',
text: 'Hello John! How are you?'
},
push: {
registrationToken: 'xxxxx',
title: 'Hi John',
body: 'Hello John! How are you?',
icon: 'https://notifme.github.io/notifme-sdk/img/icon.png'
},
webpush: {
subscription: {
keys: {
auth: 'xxxxx',
p256dh: 'xxxxx'
},
endpoint: 'xxxxx'
},
title: 'Hi John',
body: 'Hello John! How are you?',
icon: 'https://notifme.github.io/notifme-sdk/img/icon.png'
},
slack: {
text: 'Slack webhook text'
}
})
See all parameters.
Returned type
send
returns a Promise resolving with an Object
of the following type:
type NotificationStatusType = {
status: 'success' | 'error',
channels?: {[channel: ChannelType]: {
id: string,
providerId: ?string
}},
errors?: {[channel: ChannelType]: Error}
}
Examples:
Case | Returned JSON |
---|---|
Success (when Promise resolves) |
{status: 'success', channels: {sms: {id: 'id-116561976', providerId: 'sms-default-provider'}}} |
Error (here Notification Catcher is not running) |
{status: 'error', channels: {sms: {id: undefined, providerId: 'sms-notificationcatcher-provider'}}, errors: {sms: 'connect ECONNREFUSED 127.0.0.1:1025'}} |
4. In production
Recommended options
Option name | Usage in production | Comment |
---|---|---|
useNotificationCatcher | false |
Don't forget to deactivate notification catcher (it overrides channels configuration). |
Logger
This project uses winston as logging library. You can add or remove loggers as you wish.
import NotifmeSdk from 'notifme-sdk'
import winston from 'winston'
const notifmeSdk = new NotifmeSdk({})
// To deactivate all loggers
notifmeSdk.logger.mute()
// Or set the loggers you want
notifmeSdk.logger.configure([
new (winston.transports.File)({filename: 'somefile.log'})
])
See winston's documentation for more details.
Use a request queue
- RabbitMQ: see RabbitMQ Notif.me plugin documentation.
Send us a message
So that we can make a list of people using this library ;)
Contributing
Contributions are very welcome!
To get started: fork this repository to your own GitHub account and then clone it to your local device.
$ git clone [email protected]:[YOUR_USERNAME]/notifme-sdk.git && cd notifme-sdk
$ yarn install
Before making a pull request, check that the code passes all the unit tests, respects the Standard JS rules, and the Flow type checker.
$ yarn run test
Next for this project
- Implement other providers for each channel (ask or vote for a provider)
- Add other types of notifications based on what people ask (slack, messenger, skype, telegram, kik, spark...)
- A plugin system (for queues, retry system on error, templating, strategies...)
Need Help? Found a bug?
Submit an issue to the project Github if you need any help. And, of course, feel free to submit pull requests with bug fixes or changes.