Testing SparkPost - the world\'s most awesomest email service!
' 136 | }, 137 | recipients: [ 138 | {address: 'Hi {{address.name}} \nSave big this Christmas in your area {{place}}! \nClick http://www.mysite.com and get huge discount\n
Hurry, this offer is only to {{customer_type}}\n
{{sender}}
' 51 | } 52 | }; 53 | 54 | // Promise 55 | client.transmissions.send(transmission) 56 | .then(data => { 57 | console.log('Congrats you can use our client library!'); 58 | console.log(data); 59 | }) 60 | .catch(err => { 61 | console.log('Whoops! Something went wrong'); 62 | console.log(err); 63 | }); 64 | 65 | // Callback 66 | client.transmissions.send(tranmission, function(err, data) { 67 | if (err) { 68 | console.log('Whoops! Something went wrong'); 69 | console.log(err); 70 | } else { 71 | console.log('Congrats you can use our client library!'); 72 | console.log(data); 73 | } 74 | }); 75 | -------------------------------------------------------------------------------- /examples/transmissions/send_inline_image.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | const key = 'YOURAPIKEY'; 4 | const SparkPost = require('sparkpost'); 5 | const client = new SparkPost(key); 6 | const transmission = { 7 | recipients: [{address: {email: 'john.doe@example.com'}}], 8 | content: { 9 | from: 'From EnvelopeMy fantastic HTML content.
SparkPost
Hello World!
', 12 | text: 'Hello World!' 13 | }, 14 | options: { 15 | open_tracking: true, 16 | click_tracking: true 17 | } 18 | }; 19 | 20 | // Promise 21 | client.transmissions.send(transmission) 22 | .then(data => { 23 | console.log('Congrats you can use our client library!'); 24 | console.log(data); 25 | }) 26 | .catch(err => { 27 | console.log('Whoops! Something went wrong'); 28 | console.log(err); 29 | }); 30 | 31 | // Callback 32 | client.transmissions.send(transmission, function(err, data) { 33 | if (err) { 34 | console.log('Whoops! Something went wrong'); 35 | console.log(err); 36 | } else { 37 | console.log('Congrats you can use our client library!'); 38 | console.log(data); 39 | } 40 | }); 41 | -------------------------------------------------------------------------------- /examples/transmissions/send_rfc822.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | var key = 'YOURAPIKEY' 4 | , SparkPost = require('sparkpost') 5 | , client = new SparkPost(key) 6 | , transmission = { 7 | recipients: [{address: {email: 'john.doe@example.com'}}], 8 | content: { 9 | email_rfc822: 'Content-Type: text/plain\nFrom: From EnvelopeHello World
', 14 | text: 'Hello World!' 15 | } 16 | }; 17 | 18 | // Promise 19 | client.transmissions.send(transmission) 20 | .then(data => { 21 | console.log('Congrats you can use our client library!'); 22 | console.log(data); 23 | }) 24 | .catch(err => { 25 | console.log('Whoops! Something went wrong'); 26 | console.log(err); 27 | }); 28 | 29 | // Callback 30 | client.transmissions.send(transmission, function(err, data) { 31 | if (err) { 32 | console.log('Whoops! Something went wrong'); 33 | console.log(err); 34 | } else { 35 | console.log('Congrats you can use our client library!'); 36 | console.log(data); 37 | } 38 | }); 39 | -------------------------------------------------------------------------------- /examples/transmissions/send_stored_recipients_stored_content.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | var key = 'YOURAPIKEY' 4 | , SparkPost = require('sparkpost') 5 | , client = new SparkPost(key) 6 | , transmission = { 7 | recipients: { 8 | list_id: 'example-list' 9 | }, 10 | content: { 11 | from: 'From EnvelopeAn example email using bcc with SparkPost to the {{recipient_type}} recipient.
' 35 | } 36 | }; 37 | 38 | // Promise 39 | client.transmissions.send(transmission) 40 | .then(data => { 41 | console.log(data); 42 | console.log('Congrats! You sent an email with bcc using SparkPost!'); 43 | }) 44 | .catch(err => { 45 | console.log('Whoops! Something went wrong'); 46 | console.log(err); 47 | }); 48 | 49 | // Callback 50 | client.transmissions.send(transmission, function(err, data) { 51 | if (err) { 52 | console.log('Whoops! Something went wrong'); 53 | console.log(err); 54 | } else { 55 | console.log('Congrats! You sent an email with bcc using SparkPost!'); 56 | console.log(data); 57 | } 58 | }); 59 | -------------------------------------------------------------------------------- /examples/transmissions/send_with_bcc_sugar.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | var key = 'YOURAPIKEY' 4 | , SparkPost = require('sparkpost') 5 | , client = new SparkPost(key) 6 | , transmission = { 7 | recipients: [ 8 | { 9 | address: { 10 | email: 'original.recipient@example.com', 11 | name: 'Original Recipient' 12 | }, 13 | substitution_data: { 14 | recipient_type: 'Original' 15 | } 16 | } 17 | ], 18 | bcc: [ 19 | { 20 | address: { 21 | email: 'bcc.recipient@example.com', 22 | }, 23 | substitution_data: { 24 | recipient_type: 'BCC' 25 | } 26 | } 27 | ], 28 | content: { 29 | from: { 30 | name: 'Node BCC Test', 31 | email: 'from@example.com' 32 | }, 33 | subject: 'Example email using bcc', 34 | text: 'An example email using bcc with SparkPost to the {{recipient_type}} recipient.', 35 | html: 'An example email using bcc with SparkPost to the {{recipient_type}} recipient.
' 36 | } 37 | }; 38 | 39 | // Promise 40 | client.transmissions.send(transmission) 41 | .then(data => { 42 | console.log('Congrats! You sent an email with bcc using SparkPost!'); 43 | console.log(data); 44 | }) 45 | .catch(err => { 46 | console.log('Whoops! Something went wrong'); 47 | console.log(err); 48 | }); 49 | 50 | // Callback 51 | client.transmissions.send(transmission, function(err, data) { 52 | if (err) { 53 | console.log('Whoops! Something went wrong'); 54 | console.log(err); 55 | } else { 56 | console.log('Congrats! You sent an email with bcc using SparkPost!'); 57 | console.log(data); 58 | } 59 | }); 60 | -------------------------------------------------------------------------------- /examples/transmissions/send_with_cc.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | var key = 'YOURAPIKEY' 4 | , SparkPost = require('sparkpost') 5 | , client = new SparkPost(key) 6 | , transmission = { 7 | recipients: [ 8 | { 9 | address: { 10 | email: 'original.recipient@example.com', 11 | name: 'Original Recipient' 12 | }, 13 | substitution_data: { 14 | recipient_type: 'Original' 15 | } 16 | }, 17 | { 18 | address: { 19 | email: 'cc.recipient@example.com', 20 | name: 'Carbon Copy Recipient', 21 | header_to: '"Original Recipient"An example email using cc with SparkPost to the {{recipient_type}} recipient.
' 39 | } 40 | }; 41 | 42 | // Promise 43 | client.transmissions.send(transmission) 44 | .then(data => { 45 | console.log('Congrats! You sent an email with cc using SparkPost!'); 46 | console.log(data); 47 | }) 48 | .catch(err => { 49 | console.log('Whoops! Something went wrong'); 50 | console.log(err); 51 | }); 52 | 53 | // Callback 54 | client.transmissions.send(transmission, function(err, data) { 55 | if (err) { 56 | console.log('Whoops! Something went wrong'); 57 | console.log(err); 58 | } else { 59 | console.log('Congrats! You sent an email with cc using SparkPost!'); 60 | console.log(data); 61 | } 62 | }); -------------------------------------------------------------------------------- /examples/transmissions/send_with_cc_sugar.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | var key = 'YOURAPIKEY' 4 | , SparkPost = require('sparkpost') 5 | , client = new SparkPost(key) 6 | , transmission = { 7 | recipients: [ 8 | { 9 | address: { 10 | email: 'original.recipient@example.com', 11 | name: 'Original Recipient' 12 | }, 13 | substitution_data: { 14 | recipient_type: 'Original' 15 | } 16 | }, 17 | ], 18 | cc: [ 19 | { 20 | address: { 21 | email: 'cc.recipient@example.com', 22 | name: 'Carbon Copy Recipient', 23 | }, 24 | substitution_data: { 25 | recipient_type: 'CC' 26 | } 27 | } 28 | ], 29 | content: { 30 | from: { 31 | name: 'Node CC Test', 32 | email: 'from@example.com' 33 | }, 34 | subject: 'Example email using cc', 35 | text: 'An example email using cc with SparkPost to the {{recipient_type}} recipient.', 36 | html: 'An example email using cc with SparkPost to the {{recipient_type}} recipient.
' 37 | } 38 | }; 39 | 40 | // Promise 41 | client.transmissions.send(transmission) 42 | .then(data => { 43 | console.log('Congrats! You sent an email with cc using SparkPost!'); 44 | console.log(data); 45 | }) 46 | .catch(err => { 47 | console.log('Whoops! Something went wrong'); 48 | console.log(err); 49 | }); 50 | 51 | // Callback 52 | client.transmissions.send(transmission, function(err, data) { 53 | if (err) { 54 | console.log('Whoops! Something went wrong'); 55 | console.log(err); 56 | } else { 57 | console.log('Congrats! You sent an email with cc using SparkPost!'); 58 | console.log(data); 59 | } 60 | }); 61 | -------------------------------------------------------------------------------- /examples/webhooks/create.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | var key = 'YOURAPIKEY' 4 | , SparkPost = require('sparkpost') 5 | , client = new SparkPost(key) 6 | , webhook = { 7 | name: 'Test Webhook', 8 | target: 'http://client.test.com/test-webhook', 9 | auth_token: 'AUTH_TOKEN', 10 | events: [ 11 | 'delivery', 12 | 'injection', 13 | 'open', 14 | 'click' 15 | ] 16 | }; 17 | 18 | // Promise 19 | client.webhooks.create(webhook) 20 | .then(data => { 21 | console.log('Congrats you can use our client library!'); 22 | console.log(data); 23 | }) 24 | .catch(err => { 25 | console.log('Whoops! Something went wrong'); 26 | console.log(err); 27 | }); 28 | 29 | // Callback 30 | client.webhooks.create(webhook, function(err, data) { 31 | if (err) { 32 | console.log('Whoops! Something went wrong'); 33 | console.log(err); 34 | } else { 35 | console.log('Congrats you can use our client library!'); 36 | console.log(data); 37 | } 38 | }); 39 | -------------------------------------------------------------------------------- /examples/webhooks/delete.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | var key = 'YOURAPIKEY' 4 | , SparkPost = require('sparkpost') 5 | , client = new SparkPost(key); 6 | 7 | // Promise 8 | client.webhooks.delete('TEST_WEBHOOK_UUID') 9 | .then(data => { 10 | console.log('Congrats you can use our client library!'); 11 | console.log(data); 12 | }) 13 | .catch(err => { 14 | console.log('Whoops! Something went wrong'); 15 | console.log(err); 16 | }); 17 | 18 | // Callback 19 | client.webhooks.delete('TEST_WEBHOOK_UUID', function(err, data) { 20 | if (err) { 21 | console.log('Whoops! Something went wrong'); 22 | console.log(err); 23 | } else { 24 | console.log('Congrats you can use our client library!'); 25 | console.log(data); 26 | } 27 | }); 28 | -------------------------------------------------------------------------------- /examples/webhooks/get.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | var key = 'YOURAPIKEY' 4 | , SparkPost = require('sparkpost') 5 | , client = new SparkPost(key) 6 | , options = { 7 | timezone: 'America/New_York' 8 | }; 9 | 10 | // Promise 11 | client.webhooks.get('TEST_WEBHOOK_UUID', options) 12 | .then(data => { 13 | console.log('Congrats you can use our client library!'); 14 | console.log(data); 15 | }) 16 | .catch(err => { 17 | console.log('Whoops! Something went wrong'); 18 | console.log(err); 19 | }); 20 | 21 | // Callback 22 | client.webhooks.get('TEST_WEBHOOK_UUID', options, function(err, data) { 23 | if (err) { 24 | console.log('Whoops! Something went wrong'); 25 | console.log(err); 26 | } else { 27 | console.log('Congrats you can use our client library!'); 28 | console.log(data); 29 | } 30 | }); 31 | -------------------------------------------------------------------------------- /examples/webhooks/getBatchStatus.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | var key = 'YOURAPIKEY' 4 | , SparkPost = require('sparkpost') 5 | , client = new SparkPost(key) 6 | , options = { 7 | limit: 1000 8 | }; 9 | 10 | // Promise 11 | client.webhooks.getBatchStatus('TEST_WEBHOOK_UUID', options) 12 | .then(data => { 13 | console.log('Congrats you can use our client library!'); 14 | console.log(data); 15 | }) 16 | .catch(err => { 17 | console.log('Whoops! Something went wrong'); 18 | console.log(err); 19 | }); 20 | 21 | // Callback 22 | client.webhooks.getBatchStatus('TEST_WEBHOOK_UUID', options, function(err, data) { 23 | if (err) { 24 | console.log('Whoops! Something went wrong'); 25 | console.log(err); 26 | } else { 27 | console.log('Congrats you can use our client library!'); 28 | console.log(data); 29 | } 30 | }); 31 | -------------------------------------------------------------------------------- /examples/webhooks/getDocumentation.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | var key = 'YOURAPIKEY' 4 | , SparkPost = require('sparkpost') 5 | , client = new SparkPost(key); 6 | 7 | // Promise 8 | client.webhooks.getDocumentation() 9 | .then(data => { 10 | console.log('Congrats you can use our client library!'); 11 | console.log(data); 12 | }) 13 | .catch(err => { 14 | console.log('Whoops! Something went wrong'); 15 | console.log(err); 16 | }); 17 | 18 | // Callback 19 | client.webhooks.getDocumentation(function(err, data) { 20 | if (err) { 21 | console.log('Whoops! Something went wrong'); 22 | console.log(err); 23 | } else { 24 | console.log('Congrats you can use our client library!'); 25 | console.log(data); 26 | } 27 | }); 28 | -------------------------------------------------------------------------------- /examples/webhooks/getSamples.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | var key = 'YOURAPIKEY' 4 | , SparkPost = require('sparkpost') 5 | , client = new SparkPost(key) 6 | , options = { 7 | events: 'bounce' 8 | }; 9 | 10 | // Promise 11 | client.webhooks.getSamples(options) 12 | .then(data => { 13 | console.log('Congrats you can use our client library!'); 14 | console.log(data); 15 | }) 16 | .catch(err => { 17 | console.log('Whoops! Something went wrong'); 18 | console.log(err); 19 | }); 20 | 21 | // Callback 22 | client.webhooks.getSamples(options, function(err, data) { 23 | if (err) { 24 | console.log('Whoops! Something went wrong'); 25 | console.log(err); 26 | } else { 27 | console.log('Congrats you can use our client library!'); 28 | console.log(data); 29 | } 30 | }); 31 | -------------------------------------------------------------------------------- /examples/webhooks/list.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | var key = 'YOURAPIKEY' 4 | , SparkPost = require('sparkpost') 5 | , client = new SparkPost(key); 6 | 7 | // Promise 8 | client.webhooks.list() 9 | .then(data => { 10 | console.log('Congrats you can use our client library!'); 11 | console.log(data); 12 | }) 13 | .catch(err => { 14 | console.log('Whoops! Something went wrong'); 15 | console.log(err); 16 | }); 17 | 18 | // Callback 19 | client.webhooks.list(function(err, data) { 20 | if (err) { 21 | console.log('Whoops! Something went wrong'); 22 | console.log(err); 23 | } else { 24 | console.log('Congrats you can use our client library!'); 25 | console.log(data); 26 | } 27 | }); 28 | -------------------------------------------------------------------------------- /examples/webhooks/update.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | var key = 'YOURAPIKEY' 4 | , SparkPost = require('sparkpost') 5 | , client = new SparkPost(key) 6 | , webhook = { 7 | name: 'Renamed Test Webhook', 8 | events: [ 9 | 'policy_rejection', 10 | 'delay' 11 | ] 12 | }; 13 | 14 | // Promise 15 | client.webhooks.update('TEST_WEBHOOK_UUID', webhook) 16 | .then(data => { 17 | console.log('Congrats you can use our client library!'); 18 | console.log(data); 19 | }) 20 | .catch(err => { 21 | console.log('Whoops! Something went wrong'); 22 | console.log(err); 23 | }); 24 | 25 | // Callback 26 | client.webhooks.update('TEST_WEBHOOK_UUID', webhook, function(err, data) { 27 | if (err) { 28 | console.log('Whoops! Something went wrong'); 29 | console.log(err); 30 | } else { 31 | console.log('Congrats you can use our client library!'); 32 | console.log(data); 33 | } 34 | }); 35 | -------------------------------------------------------------------------------- /examples/webhooks/validate.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | var key = 'YOURAPIKEY' 4 | , SparkPost = require('sparkpost') 5 | , client = new SparkPost(key) 6 | , options = { 7 | message: { 8 | msys: {} 9 | } 10 | }; 11 | 12 | // Promise 13 | client.webhooks.validate('TEST_WEBHOOK_UUID', options) 14 | .then(data => { 15 | console.log('Congrats you can use our client library!'); 16 | console.log(data); 17 | }) 18 | .catch(err => { 19 | console.log('Whoops! Something went wrong'); 20 | console.log(err); 21 | }); 22 | 23 | // Callback 24 | client.webhooks.validate('TEST_WEBHOOK_UUID', options, function(err, data) { 25 | if (err) { 26 | console.log('Whoops! Something went wrong'); 27 | console.log(err); 28 | } else { 29 | console.log('Congrats you can use our client library!'); 30 | console.log(data); 31 | } 32 | }); 33 | -------------------------------------------------------------------------------- /lib/events.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | const api = 'events'; 4 | 5 | /* 6 | * "Class" declaration, Events API exposes one function: 7 | * - search: retrieves list of message events according to given params 8 | */ 9 | module.exports = function(client) { 10 | return { 11 | /** 12 | * Search for events using given parameters 13 | * 14 | * @param {Object} parameters 15 | * @param {RequestCb} [callback] 16 | * @returns {Promise} 17 | */ 18 | searchMessage: function(parameters, callback) { 19 | const options = { 20 | uri: `${api}/message` 21 | , qs: {} 22 | }; 23 | 24 | Object.keys(parameters).forEach(function(paramname) { 25 | if (Array.isArray(parameters[paramname])) { 26 | options.qs[paramname] = parameters[paramname].join(','); 27 | } else { 28 | options.qs[paramname] = parameters[paramname]; 29 | } 30 | }); 31 | return client.get(options, callback); 32 | } 33 | }; 34 | }; 35 | -------------------------------------------------------------------------------- /lib/inboundDomains.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | const api = 'inbound-domains'; 4 | 5 | module.exports = function(client) { 6 | return { 7 | /** 8 | * List an overview of all inbound domains in the account. 9 | * 10 | * @param {RequestCb} [callback] 11 | * @returns {Promise} 12 | */ 13 | list: function(callback) { 14 | const options = { 15 | uri: api 16 | }; 17 | return client.get(options, callback); 18 | }, 19 | /** 20 | * Get an inbound domain by its domain name 21 | * 22 | * @param {string} domain 23 | * @param {RequestCb} [callback] 24 | * @returns {Promise} 25 | */ 26 | get: function(domain, callback) { 27 | if (!domain || typeof domain !== 'string') { 28 | return client.reject(new Error('domain is required'), callback); 29 | } 30 | 31 | const options = { 32 | uri: `${api}/${domain}` 33 | }; 34 | return client.get(options, callback); 35 | }, 36 | /** 37 | * Create a new inbound domain 38 | * 39 | * @param {Object} createOpts 40 | * @param {RequestCb} [callback] 41 | * @returns {Promise} 42 | */ 43 | create: function(createOpts, callback) { 44 | if (!createOpts || typeof createOpts !== 'object') { 45 | return client.reject(new Error('create options are required'), callback); 46 | } 47 | 48 | const options = { 49 | uri: api 50 | , json: createOpts 51 | }; 52 | return client.post(options, callback); 53 | }, 54 | /** 55 | * Delete an existing inbound domain 56 | * 57 | * @param {string} domain 58 | * @param {RequestCb} [callback] 59 | * @returns {Promise} 60 | */ 61 | delete: function(domain, callback) { 62 | if (!domain || typeof domain !== 'string') { 63 | return client.reject(new Error('domain is required'), callback); 64 | } 65 | 66 | const options = { 67 | uri: `${api}/${domain}` 68 | }; 69 | return client.delete(options, callback); 70 | } 71 | }; 72 | }; 73 | -------------------------------------------------------------------------------- /lib/messageEvents.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | const api = 'message-events'; 4 | 5 | /* 6 | * "Class" declaration, Message Events API exposes one function: 7 | * - search: retrieves list of message events according to given params 8 | */ 9 | module.exports = function(client) { 10 | return { 11 | /** 12 | * Search for message events using given parameters 13 | * 14 | * @param {Object} parameters 15 | * @param {RequestCb} [callback] 16 | * @returns {Promise} 17 | */ 18 | search: function(parameters, callback) { 19 | const options = { 20 | uri: api 21 | , qs: {} 22 | }; 23 | 24 | Object.keys(parameters).forEach(function(paramname) { 25 | if (Array.isArray(parameters[paramname])) { 26 | options.qs[paramname] = parameters[paramname].join(','); 27 | } else { 28 | options.qs[paramname] = parameters[paramname]; 29 | } 30 | }); 31 | return client.get(options, callback); 32 | } 33 | }; 34 | }; 35 | -------------------------------------------------------------------------------- /lib/recipientLists.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | const api = 'recipient-lists'; 4 | 5 | module.exports = function(client) { 6 | return { 7 | /** 8 | * Get a list of all your recipient lists 9 | * https://developers.sparkpost.com/api/recipient-lists#recipient-lists-retrieve-get 10 | * 11 | * @param {RequestCb} [callback] 12 | * @return {Promise} 13 | */ 14 | list: function(callback) { 15 | const reqOpts = { 16 | uri: api 17 | }; 18 | return client.get(reqOpts, callback); 19 | }, 20 | 21 | /** 22 | * Get a list of all your recipient lists 23 | * https://developers.sparkpost.com/api/recipient-lists#recipient-lists-list-get 24 | * 25 | * @param {string} id - Unique ID of the list to return 26 | * @param {Object} options - Hash of request options 27 | * @param {RequestCb} [callback] 28 | * @return {Promise} 29 | */ 30 | get: function(id, options, callback) { 31 | options = options || {}; 32 | 33 | // Handle optional options argument 34 | if (typeof options === 'function') { 35 | callback = options; 36 | options = {}; 37 | } 38 | 39 | if (!id) { 40 | return client.reject(new Error('id is required'), callback); 41 | } 42 | 43 | const reqOpts = { 44 | uri: `${api}/${id}`, 45 | qs: options 46 | }; 47 | 48 | return client.get(reqOpts, callback); 49 | }, 50 | 51 | 52 | /** 53 | * Create a new recipient list 54 | * https://developers.sparkpost.com/api/recipient-lists#recipient-lists-create-post 55 | * 56 | * @param {Object} recipientList - recipient list object 57 | * @param {Array} recipientList.recipients - Array of recipient objects 58 | * @param {RequestCb} callback 59 | * @return {Promise} 60 | */ 61 | create: function(recipientList, callback) { 62 | if (!recipientList || typeof recipientList !== 'object' || !recipientList.recipients) { 63 | return client.reject(new Error('recipient list is required'), callback); 64 | } 65 | 66 | const reqOpts = { 67 | uri: api, 68 | json: recipientList, 69 | qs: { 70 | num_rcpt_errors: recipientList.num_rcpt_errors 71 | } 72 | }; 73 | 74 | return client.post(reqOpts, callback); 75 | }, 76 | 77 | /** 78 | * Update an existing list 79 | * https://developers.sparkpost.com/api/recipient-lists#recipient-lists-update-put 80 | * 81 | * @param {string} id - Unique ID of the list to be updated 82 | * @param {Object} recipientList - recipient list object 83 | * @param {Array} recipientList.recipients - Array of recipient objects 84 | * @param {RequestCb} callback 85 | * @return {Promise} 86 | * 87 | */ 88 | update: function(id, recipientList, callback) { 89 | if (!id) { 90 | return client.reject(new Error('recipient list id is required'), callback); 91 | } 92 | 93 | if (!recipientList || typeof recipientList === 'function') { 94 | return client.reject(new Error('recipient list is required'), callback); 95 | } 96 | 97 | const reqOpts = { 98 | uri: `${api}/${id}`, 99 | json: recipientList, 100 | qs: { 101 | num_rcpt_errors: recipientList.num_rcpt_errors 102 | } 103 | }; 104 | 105 | return client.put(reqOpts, callback); 106 | }, 107 | 108 | /** 109 | * Delete an existing recipient list 110 | * https://developers.sparkpost.com/api/recipient-lists#recipient-lists-delete-delete 111 | * 112 | * @param {string} id - ID of the list to be updated 113 | * @param {RequestCb} callback 114 | * @return {Promise} 115 | * 116 | */ 117 | delete: function(id, callback) { 118 | if (!id || typeof id !== 'string') { 119 | return client.reject(new Error('id is required'), callback); 120 | } 121 | 122 | const reqOpts = { 123 | uri: `${api}/${id}` 124 | }; 125 | 126 | return client.delete(reqOpts, callback); 127 | } 128 | }; 129 | 130 | }; 131 | -------------------------------------------------------------------------------- /lib/relayWebhooks.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | const api = 'relay-webhooks'; 4 | 5 | module.exports = function(client) { 6 | return { 7 | /** 8 | * List all relay webhooks 9 | * 10 | * @param {RequestCb} [callback] 11 | * @returns {Promise} 12 | */ 13 | list: function(callback) { 14 | const reqOpts = { 15 | uri: api 16 | }; 17 | return client.get(reqOpts, callback); 18 | }, 19 | /** 20 | * Get details about a specified relay webhook by its id 21 | * 22 | * @param {string} id - the id of the relay webhook you want to look up 23 | * @param {RequestCb} [callback] 24 | * @returns {Promise} 25 | */ 26 | get: function(id, callback) { 27 | if (!id || typeof id !== 'string') { 28 | return client.reject(new Error('id is required'), callback); 29 | } 30 | 31 | const options = { 32 | uri: `${api}/${id}` 33 | }; 34 | 35 | return client.get(options, callback); 36 | }, 37 | /** 38 | * Create a new relay webhook 39 | * 40 | * @param {Object} webhook - an object of [relay webhook attributes]{https://developers.sparkpost.com/api/relay-webhooks#header-relay-webhooks-object-properties} 41 | * @param {RequestCb} [callback] 42 | * @returns {Promise} 43 | */ 44 | create: function(webhook, callback) { 45 | if (!webhook || typeof webhook !== 'object') { 46 | return client.reject(new Error('webhook object is required'), callback); 47 | } 48 | 49 | const reqOpts = { 50 | uri: api 51 | , json: webhook 52 | }; 53 | 54 | return client.post(reqOpts, callback); 55 | }, 56 | /** 57 | * Update an existing relay webhook 58 | * 59 | * @param {string} id - the id of the relay webhook you want to update 60 | * @param {Object} webhook - an object of [relay webhook attributes]{https://developers.sparkpost.com/api/relay-webhooks#header-relay-webhooks-object-properties} 61 | * @param {RequestCb} [callback] 62 | * @returns {Promise} 63 | */ 64 | update: function(id, webhook, callback) { 65 | if (!id || typeof id !== 'string') { 66 | return client.reject(new Error('id is required'), callback); 67 | } 68 | 69 | if (!webhook || typeof webhook !== 'object') { 70 | return client.reject(new Error('webhook object is required'), callback); 71 | } 72 | 73 | const reqOpts = { 74 | uri: `${api}/${id}` 75 | , json: webhook 76 | }; 77 | 78 | return client.put(reqOpts, callback); 79 | }, 80 | /** 81 | * Delete an existing relay webhook 82 | * 83 | * @param {string} id - the id of the relay webhook you want to delete 84 | * @param {RequestCb} [callback] 85 | * @returns {Promise} 86 | */ 87 | delete: function(id, callback) { 88 | if (!id || typeof id !== 'string') { 89 | return client.reject(new Error('id is required'), callback); 90 | } 91 | 92 | const options = { 93 | uri: `${api}/${id}` 94 | }; 95 | 96 | return client.delete(options, callback); 97 | } 98 | }; 99 | }; 100 | -------------------------------------------------------------------------------- /lib/sendingDomains.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | const api = 'sending-domains'; 4 | 5 | module.exports = function(client) { 6 | return { 7 | /** 8 | * Lists all sending domains 9 | * 10 | * @param {RequestCb} [callback] 11 | * @return {Promise} 12 | */ 13 | list: function(callback) { 14 | const options = { 15 | uri: api 16 | }; 17 | 18 | return client.get(options, callback); 19 | }, 20 | 21 | /** 22 | * Get a single sending domain, by domain 23 | * 24 | * @param {string} domain - The domain name to get 25 | * @param {RequestCb} [callback] 26 | * @return {Promise} 27 | */ 28 | get: function(domain, callback) { 29 | if (!domain || typeof domain === 'function') { 30 | return client.reject(new Error('domain is required'), callback); 31 | } 32 | 33 | const options = { 34 | uri: `${api}/${domain}` 35 | }; 36 | 37 | return client.get(options, callback); 38 | }, 39 | 40 | /** 41 | * Creates a new sending domain 42 | * 43 | * @param {Object} createOpts - attributes used to create the new domain 44 | * @param {RequestCb} [callback] 45 | * @return {Promise} 46 | */ 47 | create: function(createOpts, callback) { 48 | if (!createOpts || typeof createOpts !== 'object') { 49 | return client.reject(new Error('create options are required'), callback); 50 | } 51 | 52 | const options = { 53 | uri: api, 54 | json: createOpts 55 | }; 56 | 57 | return client.post(options, callback); 58 | }, 59 | 60 | /** 61 | * Update an existing sending domain 62 | * 63 | * @param {string} domain - The domain to update 64 | * @param {Object} updateOpts - Hash of the sending domain attributes to update 65 | * @param {RequestCb} [callback] 66 | * @return {Promise} 67 | */ 68 | update: function(domain, updateOpts, callback) { 69 | if (typeof domain !== 'string') { 70 | return client.reject(new Error('domain is required'), callback); 71 | } 72 | 73 | if (!updateOpts || typeof updateOpts !== 'object') { 74 | return client.reject(new Error('update options are required'), callback); 75 | } 76 | 77 | const options = { 78 | uri: `${api}/${domain}`, 79 | json: updateOpts 80 | }; 81 | 82 | return client.put(options, callback); 83 | }, 84 | 85 | /** 86 | * Delete an existing sending domain 87 | * 88 | * @param {string} domain - The domain to delete 89 | * @param {RequestCb} [callback] 90 | * @return {Promise} 91 | */ 92 | delete: function(domain, callback) { 93 | if (typeof domain !== 'string') { 94 | return client.reject(new Error('domain is required'), callback); 95 | } 96 | 97 | const options = { 98 | uri: `${api}/${domain}` 99 | }; 100 | 101 | return client.delete(options, callback); 102 | }, 103 | 104 | /** 105 | * Verify an existing sending domain 106 | * 107 | * @param {string} domain - The domain to verify 108 | * @param {Object} options - Hash of options to include in verification request 109 | * @param {RequestCb} [callback] 110 | * @return {Promise} 111 | */ 112 | verify: function(domain, options, callback) { 113 | if (typeof domain !== 'string') { 114 | return client.reject(new Error('domain is required'), callback); 115 | } 116 | 117 | if (!options || typeof options !== 'object') { 118 | return client.reject(new Error('verification options are required'), callback); 119 | } 120 | 121 | const reqOpts = { 122 | uri: `${api}/${domain}/verify`, 123 | json: options 124 | }; 125 | 126 | return client.post(reqOpts, callback); 127 | } 128 | }; 129 | 130 | }; 131 | -------------------------------------------------------------------------------- /lib/sparkpost.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | const version = require('../package.json').version; 4 | const url = require('url'); 5 | const withCallback = require('./withCallback'); 6 | const request = require('request'); 7 | const _ = require('lodash'); 8 | 9 | //REST API Config Defaults 10 | const defaults = { 11 | origin: 'https://api.sparkpost.com:443', 12 | apiVersion: 'v1', 13 | debug: false 14 | }; 15 | 16 | const resolveUri = function(origin, uri) { 17 | if (!/^http/.test(uri)) { 18 | uri = url.resolve(origin, uri); 19 | } 20 | return uri; 21 | }; 22 | 23 | const handleOptions = function(apiKey, options) { 24 | if (typeof apiKey === 'object') { 25 | options = apiKey; 26 | options.key = process.env.SPARKPOST_API_KEY; 27 | } else { 28 | options = options || {}; 29 | options.key = apiKey; 30 | } 31 | 32 | options.origin = options.origin || options.endpoint || defaults.origin; 33 | 34 | return options; 35 | }; 36 | 37 | const createSparkPostError = function(res, body) { 38 | const err = new Error(res.statusMessage); 39 | body = body || {}; 40 | err.name = 'SparkPostError'; 41 | err.errors = body.errors; 42 | err.statusCode = res.statusCode; 43 | 44 | return err; 45 | }; 46 | 47 | const createVersionStr = function(version, options) { 48 | let versionStr = `node-sparkpost/${version} node.js/${process.version}`; 49 | if (options.stackIdentity) { 50 | versionStr += `${options.stackIdentity} ${versionStr}`; 51 | } 52 | return versionStr; 53 | }; 54 | 55 | const SparkPost = function(apiKey, options) { 56 | 57 | options = handleOptions(apiKey, options); 58 | 59 | this.apiKey = options.key || process.env.SPARKPOST_API_KEY; 60 | 61 | if (typeof this.apiKey === 'undefined') { 62 | throw new Error('Client requires an API Key.'); 63 | } 64 | 65 | // adding version to object 66 | this.version = version; 67 | 68 | // setting up default headers 69 | this.defaultHeaders = _.merge({ 70 | 'User-Agent': createVersionStr(version, options) 71 | , 'Content-Type': 'application/json' 72 | }, options.headers); 73 | 74 | //Optional client config 75 | this.origin = options.origin; 76 | this.apiVersion = options.apiVersion || defaults.apiVersion; 77 | this.debug = (typeof options.debug === 'boolean') ? options.debug : defaults.debug; 78 | 79 | this.inboundDomains = require('./inboundDomains')(this); 80 | this.messageEvents = require('./messageEvents')(this); 81 | this.events = require('./events')(this); 82 | this.recipientLists = require('./recipientLists')(this); 83 | this.relayWebhooks = require('./relayWebhooks')(this); 84 | this.sendingDomains = require('./sendingDomains')(this); 85 | this.subaccounts = require('./subaccounts')(this); 86 | this.suppressionList = require('./suppressionList')(this); 87 | this.templates = require('./templates')(this); 88 | this.transmissions = require('./transmissions')(this); 89 | this.webhooks = require('./webhooks')(this); 90 | }; 91 | 92 | SparkPost.prototype.request = function(options, callback) { 93 | const baseUrl = `${this.origin}/api/${this.apiVersion}/`; 94 | 95 | // we need options 96 | if (!_.isPlainObject(options)) { 97 | throw new TypeError('options argument is required'); 98 | } 99 | 100 | // if we don't have a fully qualified URL let's make one 101 | options.uri = resolveUri(baseUrl, options.uri); 102 | 103 | // merge headers 104 | options.headers = _.merge({}, this.defaultHeaders, options.headers); 105 | 106 | // add Authorization with API Key 107 | options.headers.Authorization = this.apiKey; 108 | 109 | // set Strict SSL (Always true) 110 | options.strictSSL = true; 111 | 112 | // default to accepting gzipped responses 113 | if (typeof options.gzip === 'undefined') { 114 | options.gzip = true; 115 | } 116 | 117 | // set debug 118 | options.debug = (typeof options.debug === 'boolean') ? options.debug : this.debug; 119 | 120 | return withCallback(new Promise(function(resolve, reject) { 121 | request(options, function(err, res, body) { 122 | const invalidCodeRegex = /(5|4)[0-9]{2}/; 123 | let response; 124 | 125 | if (err) { 126 | reject(err); 127 | } else if (invalidCodeRegex.test(res.statusCode)) { 128 | err = createSparkPostError(res, body); 129 | reject(err); 130 | } else { 131 | response = body; 132 | if (options.debug) { 133 | response.debug = res; 134 | } 135 | resolve(response); 136 | } 137 | }); 138 | }), callback); 139 | }; 140 | 141 | SparkPost.prototype.get = function(options, callback) { 142 | options.method = 'GET'; 143 | options.json = true; 144 | 145 | return this.request(options, callback); 146 | }; 147 | 148 | SparkPost.prototype.post = function(options, callback) { 149 | options.method = 'POST'; 150 | 151 | return this.request(options, callback); 152 | }; 153 | 154 | SparkPost.prototype.put = function(options, callback) { 155 | options.method = 'PUT'; 156 | 157 | return this.request(options, callback); 158 | }; 159 | 160 | SparkPost.prototype.delete = function(options, callback) { 161 | options.method = 'DELETE'; 162 | 163 | return this.request(options, callback); 164 | }; 165 | 166 | SparkPost.prototype.reject = function(error, callback) { 167 | return withCallback(Promise.reject(error), callback); 168 | }; 169 | 170 | module.exports = SparkPost; 171 | 172 | /** 173 | * Standard error-first callback for HTTP requests 174 | 175 | * @callback RequestCb 176 | * @param {Error} err - Any error that occurred 177 | * @param {Object} [data] - API response body (or just the value of `body.results`, if it exists) 178 | */ 179 | -------------------------------------------------------------------------------- /lib/subaccounts.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | const api = 'subaccounts'; 4 | 5 | module.exports = function(client) { 6 | const subaccounts = { 7 | /** 8 | * List a summary of all subaccounts 9 | * 10 | * @param {RequestCb} [callback] 11 | * @return {Promise} 12 | */ 13 | list: function(callback) { 14 | const options = { 15 | uri: api 16 | }; 17 | return client.get(options, callback); 18 | }, 19 | /** 20 | * Get details about a specified subaccount by its id 21 | * 22 | * @param {string} id - the id of the subaccount you want to look up 23 | * @param {RequestCb} [callback] 24 | * @returns {Promise} 25 | */ 26 | get: function(id, callback) { 27 | if (!id || typeof id !== 'string') { 28 | return client.reject(new Error('id is required'), callback); 29 | } 30 | 31 | const options = { 32 | uri: `${api}/${id}` 33 | }; 34 | return client.get(options, callback); 35 | }, 36 | /** 37 | * Create a new subaccount 38 | * 39 | * @param subaccount - an object of [subaccount attributes]{https://developers.sparkpost.com/api/subaccounts#header-request-body-attributes} 40 | * @param {RequestCb} [callback] 41 | * @returns {Promise} 42 | */ 43 | create: function(subaccount, callback) { 44 | if (!subaccount || typeof subaccount !== 'object') { 45 | return client.reject(new Error('subaccount object is required'), callback); 46 | } 47 | 48 | const reqOpts = { 49 | uri: api, 50 | json: subaccount 51 | }; 52 | return client.post(reqOpts, callback); 53 | }, 54 | /** 55 | * Update existing subaccount by id 56 | * 57 | * @param {string} id - the id of the subaccount you want to update 58 | * @param {Object} subaccount - an object of [subaccount attributes]{https://developers.sparkpost.com/api/subaccounts#header-request-body-attributes-1} 59 | * @param {RequestCb} callback 60 | * @returns {Promise} 61 | */ 62 | update: function(id, subaccount, callback) { 63 | if (!id || typeof id !== 'string') { 64 | return client.reject(new Error('id is required'), callback); 65 | } 66 | 67 | if (!subaccount || typeof subaccount !== 'object') { 68 | return client.reject(new Error('subaccount object is required'), callback); 69 | } 70 | 71 | const reqOpts = { 72 | uri: `${api}/${id}`, 73 | json: subaccount 74 | }; 75 | 76 | return client.put(reqOpts, callback); 77 | } 78 | }; 79 | 80 | return subaccounts; 81 | }; 82 | -------------------------------------------------------------------------------- /lib/suppressionList.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | const api = 'suppression-list'; 4 | 5 | module.exports = function(client) { 6 | 7 | return { 8 | /** 9 | * Lists all entries in your suppression list, 10 | * filtered by an optional set of parameters 11 | * 12 | * @param {Object} [parameters] - Hash of parameters to filter results 13 | * @param {RequestCb} [callback] 14 | * @return {Promise} 15 | */ 16 | list: function(parameters, callback) { 17 | const options = { 18 | uri: api 19 | , qs: parameters 20 | }; 21 | return client.get(options, callback); 22 | }, 23 | 24 | /** 25 | * Gets a single entry by email address ID 26 | * 27 | * @param {String} email 28 | * @param {RequestCb} [callback] 29 | * @return {Promise} 30 | */ 31 | get: function(email, callback) { 32 | if (!email || typeof email === 'function') { 33 | return client.reject(new Error('email is required'), callback); 34 | } 35 | 36 | const options = { 37 | uri: `${api}/${email}` 38 | }; 39 | return client.get(options, callback); 40 | }, 41 | 42 | /** 43 | * Updates existing entries, or creates entries 44 | * if they don't exist for that email address ID 45 | * 46 | * @param {Array|Object} listEntries - List of suppression entry objects to upsert 47 | * @param {RequestCb} [callback] 48 | * @return {Promise} 49 | */ 50 | upsert: function(listEntries, callback) { 51 | if (!listEntries || typeof listEntries === 'function') { 52 | return client.reject(new Error('list entries is required'), callback); 53 | } 54 | 55 | if (!Array.isArray(listEntries)) { 56 | listEntries = [listEntries]; 57 | } 58 | 59 | const options = { 60 | uri: api, 61 | json: { recipients: listEntries } 62 | }; 63 | 64 | return client.put(options, callback); 65 | }, 66 | 67 | /** 68 | * Deletes a single entry, by email address ID 69 | * 70 | * @param {String} email 71 | * @param {RequestCb} [callback] 72 | * @return {Promise} 73 | */ 74 | delete: function(email, callback) { 75 | if (!email || typeof email === 'function') { 76 | return client.reject(new Error('email is required'), callback); 77 | } 78 | 79 | const options = { 80 | uri: `${api}/${email}` 81 | }; 82 | return client.delete(options, callback); 83 | } 84 | }; 85 | 86 | }; 87 | -------------------------------------------------------------------------------- /lib/templates.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | const api = 'templates'; 4 | 5 | const _ = require('lodash'); 6 | 7 | module.exports = function(client) { 8 | return { 9 | /** 10 | * List an overview of all templates. 11 | * 12 | * @param {RequestCb} [callback] 13 | * @returns {Promise} 14 | */ 15 | list: function(callback) { 16 | const options = { 17 | uri: api 18 | }; 19 | return client.get(options, callback); 20 | }, 21 | /** 22 | * Get details about a specified template by its id. 23 | * 24 | * @param {string} id 25 | * @param {Object} options 26 | * @param {RequestCb} [callback] 27 | * @returns {Promise} 28 | */ 29 | get: function(id, options, callback) { 30 | options = options || {}; 31 | 32 | if (typeof options === 'function') { 33 | callback = options; 34 | options = {}; 35 | } 36 | 37 | if (!id) { 38 | return client.reject(new Error('template id is required'), callback); 39 | } 40 | 41 | const reqOpts = { 42 | uri: `${api}/${id}` 43 | , qs: options 44 | }; 45 | 46 | return client.get(reqOpts, callback); 47 | }, 48 | /** 49 | * Create a new template. 50 | * 51 | * @param {Object} template 52 | * @param {RequestCb} [callback] 53 | * @returns {Promise} 54 | */ 55 | create: function(template, callback) { 56 | if (!template || typeof template !== 'object') { 57 | return client.reject(new Error('template object is required'), callback); 58 | } 59 | 60 | const reqOpts = { 61 | uri: api 62 | , json: template 63 | }; 64 | 65 | return client.post(reqOpts, callback); 66 | }, 67 | /** 68 | * Update an existing template. 69 | * 70 | * @param {String} id 71 | * @param {Object} template 72 | * @param {Object} options 73 | * @param {RequestCb} callback 74 | * @returns {Promise} 75 | */ 76 | update: function(id, template, options, callback) { 77 | // Handle optional options argument 78 | if (typeof options === 'function') { 79 | callback = options; 80 | options = {}; 81 | } 82 | 83 | if (!id) { 84 | return client.reject(new Error('template id is required'), callback); 85 | } 86 | 87 | if (!template || typeof template !== 'object') { 88 | return client.reject(new Error('template object is required'), callback); 89 | } 90 | 91 | const reqOpts = { 92 | uri: `${api}/${id}` 93 | , json: template 94 | , qs: options 95 | }; 96 | 97 | return client.put(reqOpts, callback); 98 | }, 99 | /** 100 | * Delete an existing template. 101 | * 102 | * @param {String} id 103 | * @param {RequestCb} [callback] 104 | * @returns {Promise} 105 | */ 106 | delete: function(id, callback) { 107 | if (!id || typeof id !== 'string') { 108 | return client.reject(new Error('template id is required'), callback); 109 | } 110 | 111 | const options = { 112 | uri: `${api}/${id}` 113 | }; 114 | return client.delete(options, callback); 115 | }, 116 | /** 117 | * Preview the most recent version of an existing template by id. 118 | * 119 | * @param {String} id 120 | * @param {Object} options 121 | * @param {RequestCb} [callback] 122 | * @returns {Promise} 123 | */ 124 | preview: function(id, options, callback) { 125 | options = options || {}; 126 | 127 | // Handle optional options argument 128 | if (typeof options === 'function') { 129 | callback = options; 130 | options = {}; 131 | } 132 | 133 | if (!id) { 134 | return client.reject(new Error('template id is required'), callback); 135 | } 136 | 137 | const reqOpts = { 138 | uri: `${api}/${id}/preview` 139 | , json: _.cloneDeep(options) 140 | , qs: {} 141 | }; 142 | 143 | // Add draft to query params 144 | if (reqOpts.json.hasOwnProperty('draft')) { 145 | reqOpts.qs.draft = reqOpts.json.draft; 146 | delete reqOpts.json.draft; 147 | } 148 | 149 | return client.post(reqOpts, callback); 150 | } 151 | }; 152 | }; 153 | -------------------------------------------------------------------------------- /lib/transmissions.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | const _ = require('lodash'); 4 | const api = 'transmissions'; 5 | 6 | /* 7 | * "Class" declaration, Transmissions exposes three functions, one for sending a transmission, 8 | * another for getting a list of transmissions that have been sent, and another for getting 9 | * info about a specific transmission 10 | */ 11 | module.exports = function(client) { 12 | return { 13 | /** 14 | * List an overview of all transmissions in the account 15 | * 16 | * @param {Object} options 17 | * @param {RequestCb} [callback] 18 | * @returns {Promise} 19 | */ 20 | list: function(options, callback) { 21 | // Handle optional options argument 22 | if (typeof options === 'function') { 23 | callback = options; 24 | options = {}; 25 | } 26 | 27 | const reqOpts = { 28 | uri: api, 29 | qs: options 30 | }; 31 | 32 | return client.get(reqOpts, callback); 33 | }, 34 | /** 35 | * Retrieve the details about a transmission by its id 36 | * 37 | * @param {String} id 38 | * @param {RequestCb} [callback] 39 | * @returns {Promise} 40 | */ 41 | get: function(id, callback) { 42 | if (typeof id !== 'string') { 43 | return client.reject(new Error('id is required'), callback); 44 | } 45 | 46 | const options = { 47 | uri: `${api}/${id}` 48 | }; 49 | 50 | return client.get(options, callback); 51 | }, 52 | /** 53 | * Sends a message by creating a new transmission 54 | * 55 | * @param {Object} transmission 56 | * @param {Object} options 57 | * @param {RequestCb} [callback] 58 | * @returns {Promise} 59 | */ 60 | send: function(transmission, options, callback) { 61 | // Handle optional options argument 62 | if (typeof options === 'function') { 63 | callback = options; 64 | options = {}; 65 | } 66 | 67 | if (!transmission || typeof transmission !== 'object') { 68 | return client.reject(new Error('transmission object is required'), callback); 69 | } 70 | 71 | transmission = formatPayload(transmission); 72 | 73 | const reqOpts = { 74 | uri: api, 75 | json: transmission, 76 | qs: options 77 | }; 78 | 79 | return client.post(reqOpts, callback); 80 | } 81 | }; 82 | 83 | }; 84 | 85 | function formatPayload(originalTransmission) { 86 | const transmission = _.cloneDeep(originalTransmission); 87 | 88 | // don't format the payload if we are not given an array of recipients 89 | if (!_.isArray(transmission.recipients)) { 90 | return transmission; 91 | } 92 | 93 | // format all the original recipients to be in the object format 94 | transmission.recipients = _.map(transmission.recipients, (recipient) => { 95 | recipient.address = addressToObject(recipient.address); 96 | 97 | return recipient; 98 | }); 99 | 100 | // add the CC headers 101 | if (_.isArray(transmission.cc) && transmission.cc.length > 0) { 102 | _.set(transmission, 'content.headers.CC', generateCCHeader(transmission)); 103 | } 104 | 105 | const headerTo = generateHeaderTo(transmission.recipients); 106 | 107 | transmission.recipients = addListToRecipients(transmission, 'cc', headerTo); 108 | transmission.recipients = addListToRecipients(transmission, 'bcc', headerTo); 109 | 110 | delete transmission.cc; 111 | delete transmission.bcc; 112 | 113 | return transmission; 114 | } 115 | 116 | function addListToRecipients(transmission, listName, headerTo) { 117 | if (!_.isArray(transmission[listName])) { 118 | return transmission.recipients; 119 | } 120 | 121 | return transmission.recipients.concat(_.map(transmission[listName], (recipient) => { 122 | recipient.address = addressToObject(recipient.address); 123 | 124 | recipient.address.header_to = headerTo; 125 | 126 | // remove name from address - name is only put in the header for cc and not at all for bcc 127 | if (_.has(recipient.address, 'name')) { 128 | delete recipient.address.name; 129 | } 130 | 131 | return recipient; 132 | })); 133 | } 134 | 135 | function generateCCHeader(transmission) { 136 | return _.map(transmission.cc, (ccRecipient) => addressToString(ccRecipient.address)).join(', '); 137 | } 138 | 139 | function generateHeaderTo(recipients) { 140 | // if a recipient has a header_to then it is cc'd or bcc'd and we don't want it in the header_to value 141 | const originalRecipients = _.filter(recipients, (recipient) => !_.has(recipient.address, 'header_to')); 142 | 143 | return _.map(originalRecipients, (recipient) => addressToString(recipient.address)).join(', '); 144 | } 145 | 146 | function addressToString(address) { 147 | if (_.isPlainObject(address)) { 148 | if (_.has(address, 'name')) { 149 | address = `"${address.name}" <${address.email}>`; 150 | } else { 151 | address = address.email; 152 | } 153 | } 154 | 155 | return address; 156 | } 157 | 158 | function addressToObject(address) { 159 | let addressObject = address; 160 | 161 | if (_.isString(address)) { 162 | addressObject = {}; 163 | 164 | const matches = /"?(.[^"]*)?"?\s*<(.+)>/gi.exec(address); 165 | 166 | if (matches) { 167 | addressObject.name = matches[1]; 168 | addressObject.email = matches[2]; 169 | } else { 170 | addressObject.email = address; 171 | } 172 | } 173 | 174 | return addressObject; 175 | } 176 | -------------------------------------------------------------------------------- /lib/webhooks.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | const api = 'webhooks'; 4 | 5 | module.exports = function(client) { 6 | return { 7 | 8 | /** 9 | * Lists all webhooks 10 | * 11 | * @param {Object} [options] - Hash of options 12 | * @param {string} [options.timezone] - The timezone to use for the last_successful and last_failure properties. 13 | * @param {RequestCb} [callback] 14 | * @returns {Promise} 15 | */ 16 | list: function(options, callback) { 17 | const reqOpts = { 18 | uri: api, 19 | qs: {} 20 | }; 21 | 22 | if (!options || typeof options === 'function') { 23 | callback = options; 24 | options = {}; 25 | } 26 | 27 | if (options.timezone) { 28 | reqOpts.qs.timezone = options.timezone; 29 | } 30 | 31 | return client.get(reqOpts, callback); 32 | }, 33 | 34 | /** 35 | * Get a single webhook by ID 36 | * 37 | * @param {string} id - The ID of the webhook to get 38 | * @param {Object} [options] - Hash of options 39 | * @param {string} [options.timezone] - The timezone to use for the last_successful and last_failure properties. 40 | * @param {RequestCb} [callback] 41 | * @returns {Promise} 42 | */ 43 | get: function(id, options, callback) { 44 | if (!options || typeof options === 'function') { 45 | callback = options; 46 | options = {}; 47 | } 48 | 49 | if (typeof id !== 'string') { 50 | return client.reject(new Error('id is required'), callback); 51 | } 52 | 53 | const reqOpts = { 54 | uri: `${api}/${id}`, 55 | qs: {} 56 | }; 57 | 58 | if (options.timezone) { 59 | reqOpts.qs.timezone = options.timezone; 60 | } 61 | 62 | return client.get(reqOpts, callback); 63 | }, 64 | 65 | /** 66 | * Creates a new webhook 67 | * 68 | * @param {Object} webhook - attributes used to create the new webhook 69 | * @param {RequestCb} [callback] 70 | * @returns {Promise} 71 | */ 72 | create: function(webhook, callback) { 73 | if (!webhook || typeof webhook === 'function') { 74 | return client.reject(new Error('webhook object is required'), callback); 75 | } 76 | 77 | const options = { 78 | uri: api, 79 | json: webhook 80 | }; 81 | 82 | return client.post(options, callback); 83 | }, 84 | 85 | /** 86 | * Update an existing webhook 87 | * 88 | * @param {string} id - The ID of the webhook to update 89 | * @param {Object} webhook - Hash of the webhook attributes to update 90 | * @param {RequestCb} [callback] 91 | * @returns {Promise} 92 | */ 93 | update: function(id, webhook, callback) { 94 | if (!id) { 95 | return client.reject(new Error('id is required'), callback); 96 | } 97 | 98 | if (!webhook || typeof webhook === 'function') { 99 | return client.reject(new Error('webhook object is required'), callback); 100 | } 101 | 102 | const options = { 103 | uri: `${api}/${id}`, 104 | json: webhook 105 | }; 106 | 107 | delete options.json.id; 108 | 109 | return client.put(options, callback); 110 | }, 111 | 112 | /** 113 | * Delete an existing webhook 114 | * 115 | * @param {string} id - The ID of the webhook to delete 116 | * @param {RequestCb} [callback] 117 | * @returns {Promise} 118 | */ 119 | delete: function(id, callback) { 120 | if (!id || typeof id === 'function') { 121 | return client.reject(new Error('id is required'), callback); 122 | } 123 | 124 | const options = { 125 | uri: `${api}/${id}` 126 | }; 127 | 128 | return client.delete(options, callback); 129 | }, 130 | 131 | /** 132 | * Sends an example message event batch from the Webhook API to the target URL. 133 | * 134 | * @param {string} id - The ID of the webhook to validate 135 | * @param {Object} options - Hash of options used to validate the webhook 136 | * @param {string} options.message - The message (payload) to send to the webhook consumer. 137 | * @param {RequestCb} [callback] 138 | * @returns {Promise} 139 | */ 140 | validate: function(id, options, callback) { 141 | if (typeof id !== 'string') { 142 | return client.reject(new Error('id is required'), callback); 143 | } 144 | 145 | if (!options || typeof options === 'function' || !options.message) { 146 | return client.reject(new Error('message is required'), callback); 147 | } 148 | 149 | const reqOpts = { 150 | uri: `${api}/${id}/validate`, 151 | json: { 152 | message: options.message 153 | } 154 | }; 155 | 156 | return client.post(reqOpts, callback); 157 | }, 158 | 159 | /** 160 | * Gets recent status information about a webhook. 161 | * 162 | * @param {string} id - The ID of the webhook to check 163 | * @param {Object} [options] - Hash of options 164 | * @param {string} [options.limit] - The maximum number of results to return. 165 | * @param {RequestCb} [callback] 166 | * @returns {Promise} 167 | */ 168 | getBatchStatus: function(id, options, callback) { 169 | if (!options || typeof options === 'function') { 170 | callback = options; 171 | options = {}; 172 | } 173 | 174 | if (typeof id !== 'string') { 175 | return client.reject(new Error('id is required'), callback); 176 | } 177 | 178 | const reqOpts = { 179 | uri: `${api}/${id}/batch-status`, 180 | qs: {} 181 | }; 182 | 183 | if (options.limit) { 184 | reqOpts.qs.limit = options.limit; 185 | } 186 | 187 | return client.get(reqOpts, callback); 188 | }, 189 | 190 | /** 191 | * Lists descriptions of the events, event types, and event fields that could be included in a Webhooks post to your target URL. 192 | * 193 | * @param {RequestCb} [callback] 194 | * @returns {Promise} 195 | */ 196 | getDocumentation: function(callback) { 197 | const reqOpts = { 198 | uri: `${api}/events/documentation` 199 | }; 200 | return client.get(reqOpts, callback); 201 | }, 202 | 203 | /** 204 | * Lists examples of the event data that will be posted to a webhook consumer. 205 | * 206 | * @param {Object} [options] - Hash of options 207 | * @param {string} [options.events] - A comma delimited list of events to get samples of. 208 | * @param {RequestCb} [callback] 209 | * @returns {Promise} 210 | */ 211 | getSamples: function(options, callback) { 212 | const reqOpts = { 213 | uri: `${api}/events/samples`, 214 | qs: {} 215 | }; 216 | 217 | if (!options || typeof options === 'function') { 218 | callback = options; 219 | options = {}; 220 | } 221 | 222 | if (options.events) { 223 | reqOpts.qs.events = options.events; 224 | } 225 | 226 | return client.get(reqOpts, callback); 227 | } 228 | }; 229 | }; 230 | -------------------------------------------------------------------------------- /lib/withCallback.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | /** 4 | * withCallback handles an optional nodeback 5 | * and return the promise object 6 | * 7 | * @param promise {Promise} 8 | * @param cb {Function} 9 | * @return Promise 10 | * 11 | * @example 12 | * function eitherOr(options, callback) { 13 | * return withCallback(promiseThingy(options), callback); 14 | * } 15 | */ 16 | 17 | function withCallback(promise, cb) { 18 | if (typeof cb !== 'function') { 19 | cb = noop; 20 | } 21 | 22 | promise.then((result) => { 23 | cb(null, result); 24 | }).catch((err) => { 25 | cb(err); 26 | }); 27 | 28 | return promise; 29 | } 30 | 31 | function noop() {} 32 | 33 | module.exports = withCallback; 34 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "sparkpost", 3 | "version": "2.1.4", 4 | "description": "A Node.js wrapper for interfacing with your favorite SparkPost APIs", 5 | "main": "./lib/sparkpost.js", 6 | "scripts": { 7 | "coveralls": "cat ./test/reports/lcov.info | coveralls", 8 | "pretest": "eslint lib/**", 9 | "test": "istanbul cover --report lcov --dir test/reports/ _mocha --recursive ./test/spec --grep ./test/**/*.spec.js -- --colors --reporter spec", 10 | "postversion": "git push upstream && git push --tags upstream" 11 | }, 12 | "keywords": [ 13 | "email", 14 | "messaging" 15 | ], 16 | "repository": { 17 | "type": "git", 18 | "url": "https://github.com/SparkPost/node-sparkpost" 19 | }, 20 | "author": "Message Systems, Inc.", 21 | "license": "Apache-2.0", 22 | "bugs": { 23 | "url": "https://github.com/SparkPost/node-sparkpost/issues" 24 | }, 25 | "homepage": "https://github.com/SparkPost/node-sparkpost", 26 | "engines": { 27 | "node": ">=4" 28 | }, 29 | "devDependencies": { 30 | "chai": "^3.5.0", 31 | "chai-as-promised": "^6.0.0", 32 | "coveralls": "^3.0.2", 33 | "eslint": "^3.12.2", 34 | "eslint-config-sparkpost": "1.3.1", 35 | "istanbul": "^0.4.5", 36 | "mocha": "^5.2.0", 37 | "nock": "^9.0.0", 38 | "sinon": "^1.17.5", 39 | "sinon-as-promised": "^4.0.2", 40 | "sinon-chai": "^2.8.0" 41 | }, 42 | "dependencies": { 43 | "lodash": "^4.17.2", 44 | "request": "^2.79.0" 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /test/mocha.opts: -------------------------------------------------------------------------------- 1 | --recursive 2 | --reporter spec 3 | --timeout 20000 4 | -------------------------------------------------------------------------------- /test/spec/events.spec.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | var chai = require('chai') 4 | , expect = chai.expect 5 | , sinon = require('sinon'); 6 | 7 | require('sinon-as-promised'); 8 | 9 | chai.use(require('sinon-chai')); 10 | chai.use(require('chai-as-promised')); 11 | 12 | describe('Events Library', function() { 13 | let client, events, callback; 14 | 15 | beforeEach(function() { 16 | client = { 17 | get: sinon.stub().resolves({}) 18 | }; 19 | 20 | callback = function() {}; 21 | 22 | events = require('../../lib/events')(client); 23 | }); 24 | 25 | describe('Message Tests', function(){ 26 | describe('search Method', function() { 27 | it('should call client get method with the appropriate parameters', function() { 28 | var options = { 29 | bounce_classes: '10,50', 30 | campaign_ids: 'test_campaign', 31 | events: 'bounce', 32 | event_ids: '1234, 5678', 33 | friendly_froms: 'bob@example.com', 34 | from: '2015-11-14T16:15', 35 | message_ids: '0e0d94b7-9085-4e3c-ab30-e3f2cd9c273e', 36 | page: 1, 37 | per_page: 5, 38 | reason: '%5.2.0%', 39 | recipients: 'jim@example.com', 40 | template_ids: 'newsletter_template', 41 | timezone: 'America/New_York', 42 | to: '2016-11-14T16:15', 43 | transmission_ids: '65832150921904138' 44 | }; 45 | return events.searchMessage(options, callback) 46 | .then(function() { 47 | Object.keys(options).forEach(function(key) { 48 | expect(client.get.firstCall.args[0].qs).to.have.property(key).and.equal(options[key]); 49 | }); 50 | expect(client.get.firstCall.args[1]).to.equal(callback); 51 | }); 52 | }); 53 | 54 | it('should accept arrays as parameters where appropriate', function() { 55 | var arroptions = { 56 | bounce_classes: [10,50], 57 | campaign_ids: ['campaign1', 'campaignTwo'], 58 | events: ['bounce', 'out_of_band'], 59 | friendly_froms: ['bob@example.com', 'jim@example.com'], 60 | message_ids: ['0e0d94b7-9085-4e3c-ab30-e3f2cd9c273e', '338ac622-4321-5678-0123456789'], 61 | recipients: ['jim@example.com', 'bob@example.com'], 62 | template_ids: ['newsletter_template', 'newsflash_template'], 63 | transmission_ids: ['65832150921904138', '54673829032039839'], 64 | page: 1, 65 | per_page: 5, 66 | timezone: 'America/New_York' 67 | }; 68 | return events.searchMessage(arroptions) 69 | .then(function() { 70 | Object.keys(arroptions).forEach(function(key) { 71 | var opt = arroptions[key] 72 | , firstCallQS = client.get.firstCall.args[0].qs; 73 | if (Array.isArray(opt)) { 74 | expect(firstCallQS).to.have.property(key).and.equal(opt.toString()); 75 | } 76 | }); 77 | }); 78 | }); 79 | }); 80 | }); 81 | 82 | }); 83 | -------------------------------------------------------------------------------- /test/spec/inboundDomains.spec.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | var chai = require('chai') 4 | , expect = chai.expect 5 | , SparkPost = require('../../lib/sparkpost') 6 | , sinon = require('sinon'); 7 | 8 | require('sinon-as-promised'); 9 | 10 | chai.use(require('sinon-chai')); 11 | chai.use(require('chai-as-promised')); 12 | 13 | describe('Inbound Domains Library', function() { 14 | let client, inboundDomains, callback; 15 | 16 | beforeEach(function() { 17 | client = { 18 | get: sinon.stub().resolves({}), 19 | post: sinon.stub().resolves({}), 20 | delete: sinon.stub().resolves({}), 21 | reject: SparkPost.prototype.reject 22 | }; 23 | 24 | callback = function() {}; 25 | 26 | inboundDomains = require('../../lib/inboundDomains')(client); 27 | }); 28 | 29 | describe('list Method', function() { 30 | it('should call client get method with the appropriate uri', function() { 31 | 32 | return inboundDomains.list(callback) 33 | .then(function() { 34 | expect(client.get.firstCall.args[0]).to.deep.equal({uri: 'inbound-domains'}); 35 | expect(client.get.firstCall.args[1]).to.equal(callback); 36 | }); 37 | }); 38 | }); 39 | 40 | describe('get Method', function() { 41 | it('should call client get method with the appropriate uri', function() { 42 | return inboundDomains.get('test', callback) 43 | .then(function() { 44 | expect(client.get.firstCall.args[0]).to.deep.equal({uri: 'inbound-domains/test'}); 45 | expect(client.get.firstCall.args[1]).to.equal(callback); 46 | }); 47 | }); 48 | 49 | 50 | it('should throw an error if domain is missing', function() { 51 | return expect(inboundDomains.get()).to.be.rejectedWith('domain is required'); 52 | }); 53 | }); 54 | 55 | describe('create Method', function() { 56 | it('should call client post method with the appropriate uri and payload', function() { 57 | let createOpts = {domain: 'test'}; 58 | return inboundDomains.create(createOpts, callback) 59 | .then(function() { 60 | expect(client.post.firstCall.args[0].uri).to.equal('inbound-domains'); 61 | expect(client.post.firstCall.args[0].json).to.deep.equal(createOpts); 62 | expect(client.post.firstCall.args[1]).to.equal(callback); 63 | }); 64 | }); 65 | 66 | it('should throw an error if domain is missing', function() { 67 | return expect(inboundDomains.create()).to.be.rejectedWith('create options are required'); 68 | }); 69 | }); 70 | 71 | describe('delete Method', function() { 72 | it('should call client delete method with the appropriate uri', function() { 73 | return inboundDomains.delete('test', callback) 74 | .then(function () { 75 | expect(client.delete.firstCall.args[0].uri).to.equal('inbound-domains/test'); 76 | expect(client.delete.firstCall.args[1]).to.equal(callback); 77 | }); 78 | }); 79 | 80 | it('should throw an error if domain is missing', function() { 81 | return expect(inboundDomains.delete()).to.be.rejectedWith('domain is required'); 82 | }); 83 | }); 84 | }); 85 | -------------------------------------------------------------------------------- /test/spec/messageEvents.spec.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | var chai = require('chai') 4 | , expect = chai.expect 5 | , sinon = require('sinon'); 6 | 7 | require('sinon-as-promised'); 8 | 9 | chai.use(require('sinon-chai')); 10 | chai.use(require('chai-as-promised')); 11 | 12 | describe('Message Events Library', function() { 13 | let client, messageEvents, callback; 14 | 15 | beforeEach(function() { 16 | client = { 17 | get: sinon.stub().resolves({}) 18 | }; 19 | 20 | callback = function() {}; 21 | 22 | messageEvents = require('../../lib/messageEvents')(client); 23 | }); 24 | 25 | describe('search Method', function() { 26 | it('should call client get method with the appropriate parameters', function() { 27 | var options = { 28 | bounce_classes: '10,50', 29 | campaign_ids: 'test_campaign', 30 | events: 'bounce', 31 | friendly_froms: 'bob@example.com', 32 | from: '2015-11-14T16:15', 33 | message_ids: '0e0d94b7-9085-4e3c-ab30-e3f2cd9c273e', 34 | page: 1, 35 | per_page: 5, 36 | reason: '%5.2.0%', 37 | recipients: 'jim@example.com', 38 | template_ids: 'newsletter_template', 39 | timezone: 'America/New_York', 40 | to: '2016-11-14T16:15', 41 | transmission_ids: '65832150921904138' 42 | }; 43 | return messageEvents.search(options, callback) 44 | .then(function() { 45 | Object.keys(options).forEach(function(key) { 46 | expect(client.get.firstCall.args[0].qs).to.have.property(key).and.equal(options[key]); 47 | }); 48 | expect(client.get.firstCall.args[1]).to.equal(callback); 49 | }); 50 | }); 51 | 52 | it('should accept arrays as parameters where appropriate', function() { 53 | var arroptions = { 54 | bounce_classes: [10,50], 55 | campaign_ids: ['campaign1', 'campaignTwo'], 56 | events: ['bounce', 'out_of_band'], 57 | friendly_froms: ['bob@example.com', 'jim@example.com'], 58 | message_ids: ['0e0d94b7-9085-4e3c-ab30-e3f2cd9c273e', '338ac622-4321-5678-0123456789'], 59 | recipients: ['jim@example.com', 'bob@example.com'], 60 | template_ids: ['newsletter_template', 'newsflash_template'], 61 | transmission_ids: ['65832150921904138', '54673829032039839'], 62 | page: 1, 63 | per_page: 5, 64 | timezone: 'America/New_York' 65 | }; 66 | return messageEvents.search(arroptions) 67 | .then(function() { 68 | Object.keys(arroptions).forEach(function(key) { 69 | var opt = arroptions[key] 70 | , firstCallQS = client.get.firstCall.args[0].qs; 71 | if (Array.isArray(opt)) { 72 | expect(firstCallQS).to.have.property(key).and.equal(opt.toString()); 73 | } 74 | }); 75 | }); 76 | }); 77 | }); 78 | }); 79 | -------------------------------------------------------------------------------- /test/spec/recipientLists.spec.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | var _ = require('lodash') 4 | , chai = require('chai') 5 | , expect = chai.expect 6 | , SparkPost = require('../../lib/sparkpost') 7 | , sinon = require('sinon'); 8 | 9 | require('sinon-as-promised'); 10 | 11 | chai.use(require('sinon-chai')); 12 | chai.use(require('chai-as-promised')); 13 | 14 | describe('Recipient Lists Library', function() { 15 | var client, recipientLists, callback; 16 | 17 | beforeEach(function() { 18 | client = { 19 | get: sinon.stub().resolves({}), 20 | post: sinon.stub().resolves({}), 21 | put: sinon.stub().resolves({}), 22 | delete: sinon.stub().resolves({}), 23 | reject: SparkPost.prototype.reject 24 | }; 25 | 26 | callback = function() {}; 27 | 28 | recipientLists = require('../../lib/recipientLists')(client); 29 | }); 30 | 31 | describe('list', function() { 32 | 33 | it('should call client get method with the appropriate uri', function() { 34 | return recipientLists.list(callback) 35 | .then(function() { 36 | expect(client.get.firstCall.args[0].uri).to.equal('recipient-lists'); 37 | expect(client.get.firstCall.args[1]).to.equal(callback); 38 | }); 39 | }); 40 | }); 41 | 42 | describe('get', function() { 43 | 44 | it('should call client get method with the appropriate uri', function() { 45 | return recipientLists.get('test-id', callback) 46 | .then(function() { 47 | expect(client.get.firstCall.args[0].uri).to.equal('recipient-lists/test-id'); 48 | expect(client.get.firstCall.args[1]).to.equal(callback); 49 | }); 50 | }); 51 | 52 | it('should throw an error if id is missing', function() { 53 | return expect(recipientLists.get()).to.be.rejectedWith('id is required'); 54 | }); 55 | 56 | it('should not throw an error if optional 2nd argument is a function (callback)', function() { 57 | let cb = sinon.stub(); 58 | 59 | client.get.yields(); 60 | 61 | return recipientLists.get('test-id', cb).then(() => { 62 | expect(cb.callCount).to.equal(1); 63 | }); 64 | }); 65 | 66 | it('should allow show_recipients to be set in options', function() { 67 | var options = { 68 | show_recipients: true 69 | }; 70 | 71 | return recipientLists.get('test-id', options) 72 | .then(function() { 73 | expect(client.get.firstCall.args[0].qs).to.deep.equal({show_recipients: true}); 74 | }); 75 | }); 76 | 77 | }); 78 | 79 | describe('create', function() { 80 | 81 | it('should call client post method with the appropriate uri and payload', function() { 82 | let testList = { 83 | id: 'test_list', 84 | recipients: [ 85 | { 86 | address: { 87 | email: 'test@test.com', 88 | name: 'test' 89 | } 90 | } 91 | ] 92 | }; 93 | 94 | return recipientLists.create(testList, callback) 95 | .then(function() { 96 | expect(client.post.firstCall.args[0].uri).to.equal('recipient-lists'); 97 | expect(client.post.firstCall.args[0].json).to.deep.equal(testList); 98 | expect(client.post.firstCall.args[1]).to.equal(callback); 99 | }); 100 | }); 101 | 102 | it('should throw an error if no recipients are provided', function() { 103 | return Promise.all([ 104 | expect(recipientLists.create(), 'no recipient list hash at all').to.be.rejectedWith('recipient list is required'), 105 | expect(recipientLists.create({}), 'no recipients key').to.be.rejectedWith('recipient list is required'), 106 | expect(recipientLists.create(function() {}), 'recipient list is actually a callback').to.be.rejectedWith('recipient list is required') 107 | ]); 108 | }); 109 | 110 | it('should allow num_rcpt_errors to be set in options', function() { 111 | var testList = { 112 | id: 'test_list', 113 | recipients: [ 114 | { 115 | address: { 116 | email: 'test@test.com', 117 | name: 'test' 118 | } 119 | } 120 | ], 121 | num_rcpt_errors: 3 122 | }; 123 | 124 | return recipientLists.create(testList) 125 | .then(function() { 126 | expect(client.post.firstCall.args[0].qs).to.deep.equal({num_rcpt_errors: 3}); 127 | }); 128 | }); 129 | 130 | }); 131 | 132 | describe('update', function() { 133 | 134 | it('should call client put method with the appropriate uri and payload', function() { 135 | const testList = { 136 | recipients: [ 137 | { 138 | address: { 139 | email: 'test@test.com', 140 | name: 'test' 141 | } 142 | } 143 | ] 144 | }; 145 | const testId = 'test-id'; 146 | 147 | return recipientLists.update(testId, testList, callback) 148 | .then(function() { 149 | expect(client.put.firstCall.args[0].uri).to.equal('recipient-lists/' + testId); 150 | expect(client.put.firstCall.args[0].json).to.deep.equal(testList); 151 | expect(client.put.firstCall.args[1]).to.equal(callback); 152 | }); 153 | }); 154 | 155 | it('should throw an error if recipient list is missing', function() { 156 | return expect(recipientLists.update('test-id')).to.be.rejectedWith('recipient list is required'); 157 | }); 158 | 159 | it('should throw an error if id is missing', function() { 160 | return expect(recipientLists.update()).to.be.rejectedWith('recipient list id is required'); 161 | }); 162 | 163 | it('should allow num_rcpt_errors to be set in options', function() { 164 | var testList = { 165 | recipients: [ 166 | { 167 | address: { 168 | email: 'test@test.com', 169 | name: 'test' 170 | } 171 | } 172 | ], 173 | num_rcpt_errors: 3 174 | }; 175 | 176 | return recipientLists.update('test-id', testList) 177 | .then(function() { 178 | expect(client.put.firstCall.args[0].qs).to.deep.equal({num_rcpt_errors: 3}); 179 | }); 180 | }); 181 | 182 | }); 183 | 184 | describe('delete', function() { 185 | 186 | it('should call client delete method with the appropriate uri', function() { 187 | return recipientLists.delete('test', callback) 188 | .then(function() { 189 | expect(client.delete.firstCall.args[0].uri).to.equal('recipient-lists/test'); 190 | expect(client.delete.firstCall.args[1]).to.equal(callback); 191 | }); 192 | }); 193 | 194 | it('should throw an error if id is missing', function() { 195 | return expect(recipientLists.delete()).to.be.rejectedWith('id is required'); 196 | }); 197 | 198 | }); 199 | 200 | }); 201 | -------------------------------------------------------------------------------- /test/spec/relayWebhooks.spec.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | var chai = require('chai') 4 | , expect = chai.expect 5 | , SparkPost = require('../../lib/sparkpost') 6 | , sinon = require('sinon'); 7 | 8 | require('sinon-as-promised'); 9 | 10 | chai.use(require('sinon-chai')); 11 | chai.use(require('chai-as-promised')); 12 | 13 | describe('Relay Webhooks Library', function() { 14 | let client, relayWebhooks, callback; 15 | 16 | beforeEach(function() { 17 | client = { 18 | get: sinon.stub().resolves({}), 19 | post: sinon.stub().resolves({}), 20 | put: sinon.stub().resolves({}), 21 | delete: sinon.stub().resolves({}), 22 | reject: SparkPost.prototype.reject 23 | }; 24 | 25 | callback = function() {}; 26 | 27 | relayWebhooks = require('../../lib/relayWebhooks')(client); 28 | }); 29 | 30 | describe('list Method', function() { 31 | it('should call client get method with the appropriate uri', function() { 32 | return relayWebhooks.list(callback) 33 | .then(function() { 34 | expect(client.get.firstCall.args[0].uri).to.equal('relay-webhooks'); 35 | expect(client.get.firstCall.args[1]).to.equal(callback); 36 | }); 37 | }); 38 | }); 39 | 40 | describe('get Method', function() { 41 | it('should call client get method with the appropriate uri', function() { 42 | return relayWebhooks.get('test', callback) 43 | .then(function() { 44 | expect(client.get.firstCall.args[0]).to.deep.equal({uri: 'relay-webhooks/test'}); 45 | expect(client.get.firstCall.args[1]).to.equal(callback); 46 | }); 47 | }); 48 | 49 | it('should throw an error if id is missing', function() { 50 | return expect(relayWebhooks.get()).to.be.rejectedWith('id is required'); 51 | }); 52 | }); 53 | 54 | describe('create Method', function() { 55 | it('should call client post method with the appropriate uri and payload', function() { 56 | let webhook = { 57 | target: 'test', 58 | domain: 'inbound.example.com' 59 | }; 60 | 61 | return relayWebhooks.create(webhook, callback) 62 | .then(function() { 63 | expect(client.post.firstCall.args[0].uri).to.equal('relay-webhooks'); 64 | expect(client.post.firstCall.args[0].json).to.deep.equal(webhook); 65 | expect(client.post.firstCall.args[1]).to.equal(callback); 66 | }); 67 | }); 68 | 69 | it('should throw an error if webhook object is missing', function() { 70 | return expect(relayWebhooks.create()).to.be.rejectedWith('webhook object is required'); 71 | }); 72 | }); 73 | 74 | describe('update Method', function() { 75 | it('should call client put method with the appropriate uri and payload', function() { 76 | let webhook = { 77 | name: 'New Replies Webhook' 78 | }; 79 | 80 | return relayWebhooks.update('test', webhook, callback) 81 | .then(function() { 82 | expect(client.put.firstCall.args[0].uri).to.equal('relay-webhooks/test'); 83 | expect(client.put.firstCall.args[0].json).to.deep.equal(webhook); 84 | expect(client.put.firstCall.args[1]).to.equal(callback); 85 | }); 86 | }); 87 | 88 | it('should throw an error if webhook.id is missing', function() { 89 | return expect(relayWebhooks.update()).to.be.rejectedWith('id is required'); 90 | }); 91 | 92 | it('should throw an error if webhook object is missing', function() { 93 | return expect(relayWebhooks.update('test')).to.be.rejectedWith('webhook object is required'); 94 | }); 95 | }); 96 | 97 | describe('delete Method', function() { 98 | it('should call client delete method with the appropriate uri', function() { 99 | return relayWebhooks.delete('test', callback) 100 | .then(function() { 101 | expect(client.delete.firstCall.args[0].uri).to.equal('relay-webhooks/test'); 102 | expect(client.delete.firstCall.args[1]).to.equal(callback); 103 | }); 104 | }); 105 | 106 | it('should throw an error if id is missing', function() { 107 | return expect(relayWebhooks.delete()).to.be.rejectedWith('id is required'); 108 | }); 109 | }); 110 | }); 111 | -------------------------------------------------------------------------------- /test/spec/sendingDomains.spec.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | var _ = require('lodash') 4 | , chai = require('chai') 5 | , expect = chai.expect 6 | , SparkPost = require('../../lib/sparkpost') 7 | , sinon = require('sinon'); 8 | 9 | require('sinon-as-promised'); 10 | 11 | chai.use(require('sinon-chai')); 12 | chai.use(require('chai-as-promised')); 13 | 14 | describe('Sending Domains Library', function() { 15 | var client, sendingDomains, callback; 16 | 17 | beforeEach(function() { 18 | client = { 19 | get: sinon.stub().resolves({}), 20 | post: sinon.stub().resolves({}), 21 | put: sinon.stub().resolves({}), 22 | delete: sinon.stub().resolves({}), 23 | reject: SparkPost.prototype.reject 24 | }; 25 | 26 | callback = function() {}; 27 | 28 | sendingDomains = require('../../lib/sendingDomains')(client); 29 | }); 30 | 31 | describe('list', function() { 32 | it('should call client get method with the appropriate uri', function() { 33 | return sendingDomains.list(callback) 34 | .then(function() { 35 | expect(client.get.firstCall.args[0]).to.deep.equal({uri: 'sending-domains'}); 36 | expect(client.get.firstCall.args[1]).to.equal(callback); 37 | }); 38 | }); 39 | }); 40 | 41 | describe('get', function() { 42 | it('should call client get method with the appropriate uri', function() { 43 | return sendingDomains.get('test', callback) 44 | .then(function() { 45 | expect(client.get.firstCall.args[0]).to.deep.equal({uri: 'sending-domains/test'}); 46 | expect(client.get.firstCall.args[1]).to.equal(callback); 47 | }); 48 | }); 49 | 50 | it('should throw an error if domain is missing', function() { 51 | return expect(sendingDomains.get()).to.be.rejectedWith('domain is required'); 52 | }); 53 | }); 54 | 55 | describe('create', function() { 56 | it('should call client post method with the appropriate uri and payload', function() { 57 | var sendingDomain = { 58 | domain: 'test' 59 | }; 60 | 61 | return sendingDomains.create(sendingDomain, callback).then(function() { 62 | expect(client.post.firstCall.args[0].uri).to.equal('sending-domains'); 63 | expect(client.post.firstCall.args[0].json).to.deep.equal(sendingDomain); 64 | expect(client.post.firstCall.args[1]).to.equal(callback); 65 | }); 66 | }); 67 | 68 | it('should throw an error if create options are missing', function() { 69 | return expect(sendingDomains.create()).to.be.rejectedWith('create options are required'); 70 | }); 71 | }); 72 | 73 | describe('update', function() { 74 | it('should call client put method with the appropriate uri and payload', function() { 75 | var sendingDomain = { 76 | tracking_domain: 'click.example1.com' 77 | }; 78 | 79 | return sendingDomains.update('test', sendingDomain, callback) 80 | .then(function() { 81 | expect(client.put.firstCall.args[0].uri).to.equal('sending-domains/test'); 82 | expect(client.put.firstCall.args[0].json).to.deep.equal(_.omit(sendingDomain, 'domain')); 83 | expect(client.put.firstCall.args[1]).to.equal(callback); 84 | }); 85 | }); 86 | 87 | it('should throw an error if update options are missing', function() { 88 | return expect(sendingDomains.update('test')).to.be.rejectedWith('update options are required'); 89 | }); 90 | 91 | it('should throw an error if domain is missing', function() { 92 | return expect(sendingDomains.update()).to.be.rejectedWith('domain is required'); 93 | }); 94 | }); 95 | 96 | describe('delete', function() { 97 | it('should call client delete method with the appropriate uri', function() { 98 | return sendingDomains.delete('test', callback) 99 | .then(function() { 100 | expect(client.delete.firstCall.args[0].uri).to.equal('sending-domains/test'); 101 | expect(client.delete.firstCall.args[1]).to.equal(callback); 102 | }); 103 | }); 104 | 105 | it('should throw an error if domain is missing', function() { 106 | return expect(sendingDomains.delete()).to.be.rejectedWith('domain is required'); 107 | }); 108 | }); 109 | 110 | describe('verify', function() { 111 | it('should call client post method with the appropriate uri and payload', function() { 112 | var options = { 113 | dkim_verify: true, 114 | spf_verify: true 115 | }; 116 | 117 | return sendingDomains.verify('test', options, callback) 118 | .then(function() { 119 | expect(client.post.firstCall.args[0].uri).to.equal('sending-domains/test/verify'); 120 | expect(client.post.firstCall.args[0].json).to.deep.equal(_.omit(options, 'domain')); 121 | expect(client.post.firstCall.args[1]).to.equal(callback); 122 | }); 123 | }); 124 | 125 | it('should throw an error if domain is missing', function() { 126 | return expect(sendingDomains.verify()).to.be.rejectedWith('domain is required'); 127 | }); 128 | 129 | it('should throw an error if verification options are missing', function() { 130 | return expect(sendingDomains.verify('test')).to.be.rejectedWith('verification options are required'); 131 | }); 132 | }); 133 | 134 | }); 135 | -------------------------------------------------------------------------------- /test/spec/subaccounts.spec.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | var chai = require('chai') 4 | , expect = chai.expect 5 | , SparkPost = require('../../lib/sparkpost') 6 | , sinon = require('sinon'); 7 | 8 | require('sinon-as-promised'); 9 | 10 | chai.use(require('sinon-chai')); 11 | chai.use(require('chai-as-promised')); 12 | 13 | describe('Subaccounts Library', function() { 14 | let client, subaccounts, callback; 15 | 16 | beforeEach(function() { 17 | client = { 18 | get: sinon.stub().resolves({}), 19 | post: sinon.stub().resolves({}), 20 | put: sinon.stub().resolves({}), 21 | reject: SparkPost.prototype.reject 22 | }; 23 | 24 | callback = function() {}; 25 | 26 | subaccounts = require('../../lib/subaccounts')(client); 27 | }); 28 | 29 | describe('list Method', function() { 30 | it('should call client get method with the appropriate uri', function() { 31 | return subaccounts.list(callback) 32 | .then(function() { 33 | expect(client.get.firstCall.args[0].uri).to.equal('subaccounts'); 34 | expect(client.get.firstCall.args[1]).to.equal(callback); 35 | }); 36 | }); 37 | }); 38 | 39 | describe('get Method', function() { 40 | it('should call client get method with the appropriate uri', function() { 41 | return subaccounts.get('test', callback) 42 | .then(function() { 43 | expect(client.get.firstCall.args[0].uri).to.equal('subaccounts/test'); 44 | expect(client.get.firstCall.args[1]).to.equal(callback); 45 | }); 46 | }); 47 | 48 | it('should throw an error if id is missing', function() { 49 | return expect(subaccounts.get()).to.be.rejectedWith('id is required'); 50 | }); 51 | }); 52 | 53 | describe('create Method', function() { 54 | it('should call client post method with the appropriate uri and payload', function() { 55 | var subaccount = { 56 | name: 'test', 57 | key_label: 'test', 58 | key_grants: [] 59 | }; 60 | 61 | return subaccounts.create(subaccount, callback) 62 | .then(function() { 63 | expect(client.post.firstCall.args[0].uri).to.equal('subaccounts'); 64 | expect(client.post.firstCall.args[0].json).to.deep.equal(subaccount); 65 | expect(client.post.firstCall.args[1]).to.equal(callback); 66 | }); 67 | }); 68 | 69 | it('should throw an error if subaccount object is missing', function() { 70 | return expect(subaccounts.create()).to.be.rejectedWith('subaccount object is required'); 71 | }); 72 | }); 73 | 74 | describe('update Method', function() { 75 | it('should call client put method with the appropriate uri and payload', function() { 76 | var subaccount = { 77 | name: 'Hey Joe! Garage and Parts', 78 | status: 'suspended', 79 | ip_pool: '' 80 | }; 81 | 82 | return subaccounts.update('test', subaccount, callback) 83 | .then(function() { 84 | expect(client.put.firstCall.args[0].uri).to.equal('subaccounts/test'); 85 | expect(client.put.firstCall.args[0].json).to.deep.equal(subaccount); 86 | expect(client.put.firstCall.args[1]).to.equal(callback); 87 | }); 88 | }); 89 | 90 | it('should throw an error if subaccount id is missing from options', function() { 91 | return expect(subaccounts.update()).to.be.rejectedWith('id is required'); 92 | }); 93 | 94 | it('should throw an error if subaccount object is missing', function() { 95 | return expect(subaccounts.update('test')).to.be.rejectedWith('subaccount object is required'); 96 | }); 97 | }); 98 | }); 99 | -------------------------------------------------------------------------------- /test/spec/suppressionList.spec.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | var chai = require('chai') 4 | , expect = chai.expect 5 | , SparkPost = require('../../lib/sparkpost') 6 | , sinon = require('sinon'); 7 | 8 | require('sinon-as-promised'); 9 | 10 | chai.use(require('sinon-chai')); 11 | chai.use(require('chai-as-promised')); 12 | 13 | describe('Suppression List Library', function() { 14 | let client, suppressionList, callback; 15 | 16 | beforeEach(function() { 17 | client = { 18 | get: sinon.stub().resolves({}), 19 | post: sinon.stub().resolves({}), 20 | put: sinon.stub().resolves({}), 21 | delete: sinon.stub().resolves({}), 22 | reject: SparkPost.prototype.reject 23 | }; 24 | 25 | callback = function() {}; 26 | 27 | suppressionList = require('../../lib/suppressionList')(client); 28 | }); 29 | 30 | describe('list', function() { 31 | it('should call client get method with the appropriate uri', function() { 32 | return suppressionList.list({limit: 5}, callback) 33 | .then(function() { 34 | expect(client.get.firstCall.args[0].uri).to.equal('suppression-list'); 35 | expect(client.get.firstCall.args[1]).to.equal(callback); 36 | }); 37 | }); 38 | }); 39 | 40 | describe('get', function() { 41 | it('should call client get method with the appropriate uri', function() { 42 | return suppressionList.get('test@test.com', callback) 43 | .then(function() { 44 | expect(client.get.firstCall.args[0].uri).to.equal('suppression-list/test@test.com'); 45 | expect(client.get.firstCall.args[1]).to.equal(callback); 46 | }); 47 | }); 48 | 49 | it('should throw an error if email is missing', function() { 50 | return expect(suppressionList.get()).to.be.rejectedWith('email is required'); 51 | }); 52 | }); 53 | 54 | describe('upsert', function() { 55 | it('should accept a single list entry', function() { 56 | var listEntry = { email: 'test@test.com' }; 57 | 58 | return suppressionList.upsert(listEntry, callback) 59 | .then(function() { 60 | expect(client.put.firstCall.args[0].uri).to.equal('suppression-list'); 61 | expect(client.put.firstCall.args[0].json.recipients).to.deep.equal([listEntry]); 62 | expect(client.put.firstCall.args[1]).to.equal(callback); 63 | }); 64 | }); 65 | 66 | it('should accept an array of list entries', function() { 67 | var listEntries = [ 68 | { email: 'test1@test.com' }, 69 | { email: 'test2@test.com' } 70 | ]; 71 | 72 | return suppressionList.upsert(listEntries) 73 | .then(function() { 74 | expect(client.put.firstCall.args[0].uri).to.equal('suppression-list'); 75 | expect(client.put.firstCall.args[0].json.recipients).to.deep.equal(listEntries); 76 | }); 77 | }); 78 | 79 | it('should throw an error if recipient is missing', function() { 80 | return expect(suppressionList.upsert()).to.be.rejectedWith('list entries is required'); 81 | }); 82 | }); 83 | 84 | describe('delete', function() { 85 | it('should call client delete method with the appropriate uri', function() { 86 | return suppressionList.delete('test@test.com', callback) 87 | .then(function() { 88 | expect(client.delete.firstCall.args[0].uri).to.equal('suppression-list/test@test.com'); 89 | expect(client.delete.firstCall.args[1]).to.equal(callback); 90 | }); 91 | }); 92 | 93 | it('should throw an error if email deleteEntry missing', function() { 94 | return expect(suppressionList.delete()).to.be.rejectedWith('email is required'); 95 | }); 96 | }); 97 | 98 | }); 99 | -------------------------------------------------------------------------------- /test/spec/templates.spec.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | var _ = require('lodash') 3 | , chai = require('chai') 4 | , expect = chai.expect 5 | , SparkPost = require('../../lib/sparkpost') 6 | , sinon = require('sinon'); 7 | 8 | require('sinon-as-promised'); 9 | 10 | chai.use(require('sinon-chai')); 11 | chai.use(require('chai-as-promised')); 12 | 13 | describe('Templates Library', function() { 14 | var client, templates, callback; 15 | 16 | beforeEach(function() { 17 | client = { 18 | get: sinon.stub().resolves({}), 19 | post: sinon.stub().resolves({}), 20 | put: sinon.stub().resolves({}), 21 | delete: sinon.stub().resolves({}), 22 | reject: SparkPost.prototype.reject 23 | }; 24 | 25 | callback = function() {}; 26 | 27 | templates = require('../../lib/templates')(client); 28 | }); 29 | 30 | describe('list Method', function() { 31 | it('should call client get method with the appropriate uri', function() { 32 | return templates.list(callback) 33 | .then(function() { 34 | expect(client.get.firstCall.args[0].uri).to.equal('templates'); 35 | expect(client.get.firstCall.args[1]).to.equal(callback); 36 | }); 37 | }); 38 | }); 39 | 40 | describe('get Method', function() { 41 | it('should call client get method with the appropriate uri', function() { 42 | var id = 'test'; 43 | return templates.get(id, callback) 44 | .then(function() { 45 | expect(client.get.firstCall.args[0].uri).to.equal('templates/test'); 46 | expect(client.get.firstCall.args[1]).to.equal(callback); 47 | }); 48 | }); 49 | 50 | it('should throw an error if id is missing', function() { 51 | return expect(templates.get()).to.be.rejectedWith('template id is required'); 52 | }); 53 | 54 | it('should allow draft to be set in options', function() { 55 | var id = 'test' 56 | , options = { 57 | draft: true 58 | }; 59 | 60 | 61 | return templates.get(id, options) 62 | .then(function() { 63 | expect(client.get.firstCall.args[0].qs).to.deep.equal({draft: true}); 64 | }); 65 | }); 66 | }); 67 | 68 | describe('create Method', function() { 69 | it('should call client post method with the appropriate uri and payload', function() { 70 | var template = { 71 | id: 'test' 72 | }; 73 | 74 | return templates.create(template, callback) 75 | .then(function() { 76 | expect(client.post.firstCall.args[0].uri).to.equal('templates'); 77 | expect(client.post.firstCall.args[0].json).to.deep.equal(template); 78 | expect(client.post.firstCall.args[1]).to.equal(callback); 79 | }); 80 | }); 81 | 82 | it('should throw an error if template object is missing', function() { 83 | return expect(templates.create()).to.be.rejectedWith('template object is required'); 84 | }); 85 | }); 86 | 87 | describe('update Method', function() { 88 | it('should call client put method with the appropriate uri and payload', function() { 89 | var id = 'test' 90 | , template = { 91 | name: 'A new name!' 92 | }; 93 | 94 | return templates.update(id, template, callback) 95 | .then(function() { 96 | expect(client.put.firstCall.args[0].uri).to.equal('templates/test'); 97 | expect(client.put.firstCall.args[0].json).to.deep.equal(template); 98 | expect(client.put.firstCall.args[1]).to.equal(callback); 99 | }); 100 | }); 101 | 102 | it('should throw an error if template id is missing', function() { 103 | return expect(templates.update()).to.be.rejectedWith('template id is required'); 104 | }); 105 | 106 | it('should throw an error if template object is missing', function() { 107 | return expect(templates.update('test')).to.be.rejectedWith('template object is required'); 108 | }); 109 | 110 | it('should not throw an error if optional 3nd argument is a function (callback)', function() { 111 | let cb = sinon.stub() 112 | , id = 'test' 113 | , template = { 114 | name: 'A new name!' 115 | }; 116 | 117 | client.put.yields(); 118 | 119 | return templates.update(id, template, cb).then(function() { 120 | expect(cb.callCount).to.equal(1); 121 | }); 122 | }); 123 | 124 | it('should allow update_published to be set in options', function() { 125 | var id = 'test' 126 | , template = { 127 | name: 'Test Template' 128 | } 129 | , options = { 130 | update_published: true 131 | }; 132 | 133 | return templates.update(id, template, options) 134 | .then(function() { 135 | expect(client.put.firstCall.args[0].qs).to.deep.equal(options); 136 | }); 137 | }); 138 | }); 139 | 140 | describe('delete Method', function() { 141 | it('should call client delete method with the appropriate uri', function() { 142 | return templates.delete('test', callback) 143 | .then(function() { 144 | expect(client.delete.firstCall.args[0].uri).to.equal('templates/test'); 145 | expect(client.delete.firstCall.args[1]).to.equal(callback); 146 | }); 147 | }); 148 | 149 | it('should throw an error if id is missing', function() { 150 | return expect(templates.delete()).to.be.rejectedWith('template id is required'); 151 | }); 152 | }); 153 | 154 | describe('preview Method', function() { 155 | it('should call client post method with the appropriate uri and payload', function() { 156 | var id = 'test' 157 | , options = { 158 | substitution_data: { 159 | 'name': 'Natalie', 160 | 'age': 35, 161 | 'member': true 162 | } 163 | }; 164 | return templates.preview(id, options, callback) 165 | .then(function() { 166 | expect(client.post.firstCall.args[0].uri).to.equal('templates/test/preview'); 167 | expect(client.post.firstCall.args[0].json).to.deep.equal(options); 168 | expect(client.post.firstCall.args[1]).to.equal(callback); 169 | }); 170 | }); 171 | 172 | it('should throw an error if id is missing', function() { 173 | return expect(templates.preview()).to.be.rejectedWith('template id is required'); 174 | }); 175 | 176 | it('should not throw an error if optional 2nd argument is a function (callback)', function() { 177 | let cb = sinon.stub(); 178 | 179 | client.post.yields(); 180 | 181 | return templates.preview('test', cb).then(function() { 182 | expect(cb.callCount).to.equal(1); 183 | }); 184 | }); 185 | 186 | it('should add the draft option to query params', function() { 187 | var id = 'test' 188 | , options = { 189 | draft: false 190 | }; 191 | 192 | return templates.preview(id, options) 193 | .then(function() { 194 | expect(client.post.firstCall.args[0].qs).to.deep.equal({draft: false}); 195 | }); 196 | }); 197 | }); 198 | }); 199 | -------------------------------------------------------------------------------- /test/spec/transmissions.spec.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | var chai = require('chai') 4 | , expect = chai.expect 5 | , SparkPost = require('../../lib/sparkpost') 6 | , sinon = require('sinon'); 7 | 8 | require('sinon-as-promised'); 9 | 10 | chai.use(require('sinon-chai')); 11 | chai.use(require('chai-as-promised')); 12 | var ccTransmission = { 13 | recipients: [ 14 | { 15 | address: '"Bob"An example email using bcc with SparkPost to the {{recipient_type}} recipient.
' 297 | } 298 | }; 299 | 300 | return transmissions.send(transmission) 301 | .then(function() { 302 | expect(client.post.firstCall.args[0].json).to.deep.equal(transmission); 303 | }); 304 | }); 305 | }); 306 | }); 307 | -------------------------------------------------------------------------------- /test/spec/webhooks.spec.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | var _ = require('lodash') 4 | , chai = require('chai') 5 | , expect = chai.expect 6 | , SparkPost = require('../../lib/sparkpost') 7 | , sinon = require('sinon'); 8 | 9 | require('sinon-as-promised'); 10 | 11 | chai.use(require('sinon-chai')); 12 | chai.use(require('chai-as-promised')); 13 | 14 | describe('Webhooks Library', function() { 15 | var client, webhooks, callback; 16 | 17 | beforeEach(function() { 18 | client = { 19 | get: sinon.stub().resolves({}), 20 | post: sinon.stub().resolves({}), 21 | put: sinon.stub().resolves({}), 22 | delete: sinon.stub().resolves({}), 23 | reject: SparkPost.prototype.reject 24 | }; 25 | 26 | callback = function() {}; 27 | 28 | webhooks = require('../../lib/webhooks')(client); 29 | }); 30 | 31 | describe('list Method', function() { 32 | it('should call client get method with the appropriate uri', function() { 33 | return webhooks.list(callback) 34 | .then(function() { 35 | expect(client.get.firstCall.args[0].uri).to.equal('webhooks'); 36 | expect(client.get.firstCall.args[1]).to.equal(callback); 37 | }); 38 | }); 39 | 40 | it('should allow timezone to be set in options', function() { 41 | var options = { 42 | timezone: 'America/New_York' 43 | }; 44 | 45 | return webhooks.list(options) 46 | .then(function() { 47 | expect(client.get.firstCall.args[0].qs).to.deep.equal({timezone: 'America/New_York'}); 48 | }); 49 | }); 50 | }); 51 | 52 | describe('get Method', function() { 53 | it('should call client get method with the appropriate uri', function() { 54 | return webhooks.get('test', callback) 55 | .then(function() { 56 | expect(client.get.firstCall.args[0].uri).to.equal('webhooks/test'); 57 | expect(client.get.firstCall.args[1]).to.equal(callback); 58 | }); 59 | }); 60 | 61 | it('should throw an error if id is missing', function() { 62 | return expect(webhooks.get()).to.be.rejectedWith('id is required'); 63 | }); 64 | 65 | it('should allow timezone to be set in options', function() { 66 | var options = { 67 | timezone: 'America/New_York' 68 | }; 69 | 70 | return webhooks.get('test', options) 71 | .then(function() { 72 | expect(client.get.firstCall.args[0].qs).to.deep.equal({timezone: 'America/New_York'}); 73 | }); 74 | }); 75 | }); 76 | 77 | describe('create Method', function() { 78 | it('should call client post method with the appropriate uri and payload', function() { 79 | var webhook = { 80 | name: 'Example webhook', 81 | target: 'http://client.example.com/example-webhook', 82 | events: ['delivery', 'injection', 'open', 'click'] 83 | }; 84 | 85 | return webhooks.create(webhook, callback) 86 | .then(function() { 87 | expect(client.post.firstCall.args[0].uri).to.equal('webhooks'); 88 | expect(client.post.firstCall.args[0].json).to.deep.equal(webhook); 89 | expect(client.post.firstCall.args[1]).to.equal(callback); 90 | }); 91 | }); 92 | 93 | it('should throw an error if webhook is missing', function() { 94 | return expect(webhooks.create()).to.be.rejectedWith('webhook object is required'); 95 | }); 96 | }); 97 | 98 | describe('update Method', function() { 99 | it('should call client put method with the appropriate uri', function() { 100 | var webhook = { 101 | name: 'Renamed webhook', 102 | events: ['rejection', 'delay'], 103 | auth_type: 'none' 104 | }; 105 | 106 | return webhooks.update('test', webhook, callback) 107 | .then(function() { 108 | expect(client.put.firstCall.args[0].uri).to.equal('webhooks/test'); 109 | expect(client.put.firstCall.args[0].json).to.deep.equal(webhook); 110 | expect(client.put.firstCall.args[1]).to.equal(callback); 111 | }); 112 | }); 113 | 114 | it('should throw an error if id is missing', function() { 115 | return expect(webhooks.update()).to.be.rejectedWith('id is required'); 116 | }); 117 | 118 | it('should throw an error if webhook is missing', function() { 119 | return expect(webhooks.update('test')).to.be.rejectedWith('webhook object is required'); 120 | }); 121 | }); 122 | 123 | describe('delete Method', function() { 124 | it('should call client delete method with the appropriate uri', function() { 125 | return webhooks.delete('test', callback) 126 | .then(function() { 127 | expect(client.delete.firstCall.args[0].uri).to.equal('webhooks/test'); 128 | expect(client.delete.firstCall.args[1]).to.equal(callback); 129 | }); 130 | }); 131 | 132 | it('should throw an error if id is missing', function() { 133 | return expect(webhooks.delete()).to.be.rejectedWith('id is required'); 134 | }); 135 | }); 136 | 137 | describe('validate Method', function() { 138 | it('should call client post method with the appropriate uri and payload', function() { 139 | var options = { 140 | message: { 141 | msys: {} 142 | } 143 | }; 144 | 145 | return webhooks.validate('test', options, callback) 146 | .then(function() { 147 | expect(client.post.firstCall.args[0].uri).to.equal('webhooks/test/validate'); 148 | expect(client.post.firstCall.args[0].json).to.deep.equal(options); 149 | expect(client.post.firstCall.args[1]).to.equal(callback); 150 | }); 151 | }); 152 | 153 | it('should throw an error if id is missing', function() { 154 | return expect(webhooks.validate()).to.be.rejectedWith('id is required'); 155 | }); 156 | 157 | it('should throw an error if message is missing', function() { 158 | return expect(webhooks.validate('test')).to.be.rejectedWith('message is required'); 159 | }); 160 | }); 161 | 162 | describe('getBatchStatus Method', function() { 163 | it('should call client get method with the appropriate uri', function() { 164 | return webhooks.getBatchStatus('test', callback) 165 | .then(function() { 166 | expect(client.get.firstCall.args[0].uri).to.equal('webhooks/test/batch-status'); 167 | expect(client.get.firstCall.args[1]).to.equal(callback); 168 | }); 169 | }); 170 | 171 | it('should throw an error if id is missing', function() { 172 | return expect(webhooks.getBatchStatus()).to.be.rejectedWith('id is required'); 173 | }); 174 | 175 | it('should allow limit to be set in options', function() { 176 | var options = { 177 | limit: 1000 178 | }; 179 | 180 | return webhooks.getBatchStatus('test', options) 181 | .then(function() { 182 | expect(client.get.firstCall.args[0].qs).to.deep.equal({limit: 1000}); 183 | }); 184 | }); 185 | }); 186 | 187 | describe('getDocumentation Method', function() { 188 | it('should call client get method with the appropriate uri', function() { 189 | return webhooks.getDocumentation(callback) 190 | .then(function() { 191 | expect(client.get.firstCall.args[0].uri).to.equal('webhooks/events/documentation'); 192 | expect(client.get.firstCall.args[1]).to.equal(callback); 193 | }); 194 | }); 195 | }); 196 | 197 | describe('getSamples Method', function() { 198 | it('should call client get method with the appropriate uri', function() { 199 | return webhooks.getSamples(callback) 200 | .then(function() { 201 | expect(client.get.firstCall.args[0].uri).to.equal('webhooks/events/samples'); 202 | expect(client.get.firstCall.args[1]).to.equal(callback); 203 | }); 204 | }); 205 | 206 | it('should allow events to be set in options', function() { 207 | var options = { 208 | events: 'bounces' 209 | }; 210 | 211 | return webhooks.getSamples(options) 212 | .then(function() { 213 | expect(client.get.firstCall.args[0].qs).to.deep.equal({events: 'bounces'}); 214 | }); 215 | }); 216 | }); 217 | }); 218 | --------------------------------------------------------------------------------