nodemailer-sparkpost-transport
Advanced tools
Comparing version 0.1.2 to 1.0.0
## Change Log | ||
All notable changes to this project will be documented in this file. | ||
This project adheres to [Semantic Versioning](http://semver.org/). | ||
### v0.1.1 (2016/05/17) | ||
## [Unreleased][unreleased] | ||
### [1.0.0] - 2016/07/26 | ||
- [#7](https://github.com/SparkPost/nodemailer-sparkpost-transport/pull/7) Implemented the Nodemailer API (@ewandennis) | ||
### [0.1.2] - 2016/05/17 | ||
- [#4](https://github.com/SparkPost/nodemailer-sparkpost-transport/pull/4) Removed dotenv, updated README, and general cleanup. Closes #3 (@aydrian) | ||
@@ -8,3 +15,6 @@ - [#2](https://github.com/SparkPost/nodemailer-sparkpost-transport/pull/2) Sort available options lists (@simison) | ||
### v0.1.0 (2015/08/28) | ||
### [0.1.3] - 2016/05/17 | ||
- Unpublished from NPM. Republished as v0.1.2 | ||
### [0.1.0] - 2015/08/28 | ||
- Initial release |
'use strict'; | ||
// Dependencies | ||
var pkg = require('../package'); | ||
var SparkPost = require('sparkpost'); | ||
var pkg = require('../package') | ||
, SparkPost = require('sparkpost'); | ||
// Constructor | ||
var SparkPostTransport = function SparkPostTransport(options) { | ||
function SparkPostTransport(options) { | ||
var opt; | ||
// Set required properties | ||
@@ -16,44 +18,147 @@ this.name = 'SparkPost'; | ||
this.sparkPostApiKey = process.env.SPARKPOST_API_KEY || options.sparkPostApiKey; | ||
this.sparkPostEmailClient = new SparkPost( this.sparkPostApiKey ); | ||
this.sparkPostEmailClient = new SparkPost(this.sparkPostApiKey); | ||
// Set any options which are valid | ||
for( var opt in options ) { | ||
this[opt] = (options.hasOwnProperty( opt )) ? options[opt] : undefined; | ||
for(opt in options) { | ||
this[opt] = (options.hasOwnProperty(opt)) ? options[opt] : undefined; | ||
} | ||
return this; | ||
} | ||
function populateCustomFields(message, defaults, request) { | ||
var data = message.data | ||
, customFields = ['campaign_id', 'metadata', 'substitution_data', 'options', 'content', 'recipients']; | ||
// Apply default SP-centric options and override if provided in mail object | ||
customFields.forEach(function(fld) { | ||
if (data.hasOwnProperty(fld)) { | ||
request[fld] = data[fld]; | ||
} else if (defaults.hasOwnProperty(fld)) { | ||
request[fld] = defaults[fld]; | ||
} | ||
}); | ||
} | ||
function populateInlineStdFields(message, resolveme, request) { | ||
var data = message.data; | ||
if (data.from) { | ||
request.content.from = data.from; | ||
} | ||
// cc | ||
// bcc | ||
if (data.subject) { | ||
request.content.subject = data.subject; | ||
} | ||
if (data.html) { | ||
resolveme.html = 'html'; | ||
} | ||
if (data.text) { | ||
resolveme.text = 'text'; | ||
} | ||
// attachments | ||
// headers | ||
} | ||
SparkPostTransport.prototype.send = function send(message, callback) { | ||
var data = message.data | ||
, request = { | ||
content: {} | ||
} | ||
, resolveme = {}; | ||
// Conventional nodemailer fields override SparkPost-specific ones and defaults | ||
populateCustomFields(message, this, request); | ||
if (data.to) { | ||
request.recipients = emailList(data.to) || []; | ||
} | ||
if (data.raw) { | ||
resolveme.raw = 'email_rfc822'; | ||
} else { | ||
populateInlineStdFields(message, resolveme, request); | ||
} | ||
this.resolveAndSend(message, resolveme, request, callback); | ||
}; | ||
SparkPostTransport.prototype.send = function send(payload, callback) { | ||
var email = { | ||
transmissionBody: {} | ||
}; | ||
SparkPostTransport.prototype.resolveAndSend = function(mail, toresolve, request, callback) { | ||
var self = this | ||
, keys = Object.keys(toresolve) | ||
, srckey | ||
, dstkey; | ||
// Apply default options and override if provided in mail object | ||
email.transmissionBody.tags = (payload.data.tags) ? payload.data.tags : this.tags; | ||
email.transmissionBody.campaign_id = (payload.data.campaign_id) ? payload.data.campaign_id : this.campaign_id; | ||
email.transmissionBody.metadata = (payload.data.metadata) ? payload.data.metadata : this.metadata; | ||
email.transmissionBody.substitution_data = (payload.data.substitution_data) ? payload.data.substitution_data : this.substitution_data; | ||
email.transmissionBody.options = (payload.data.options) ? payload.data.options : this.options; | ||
email.transmissionBody.content = (payload.data.content) ? payload.data.content : this.content; | ||
email.transmissionBody.recipients = (payload.data.recipients) ? payload.data.recipients : this.recipients; | ||
if (keys.length === 0) { | ||
return this.sendWithSparkPost(request, callback); | ||
} | ||
// Send the transmission using Sparkpost | ||
this.sparkPostEmailClient.transmissions.send(email, function( err, res ) { | ||
if( err ) { | ||
return callback( err ); | ||
} else { | ||
// Example successful Sparkpost transmission response: | ||
// { "results": { "total_rejected_recipients": 0, "total_accepted_recipients": 1, "id": "66123596945797072" } } | ||
return callback( null, { | ||
messageId: res.body.results.id, | ||
accepted: res.body.results.total_accepted_recipients, | ||
rejected: res.body.results.total_rejected_recipients | ||
}); | ||
srckey = keys[0]; | ||
dstkey = toresolve[keys[0]]; | ||
delete toresolve[srckey]; | ||
this.loadContent(mail, srckey, function(err, content) { | ||
request.content[dstkey] = content; | ||
self.resolveAndSend(mail, toresolve, request, callback); | ||
}); | ||
}; | ||
SparkPostTransport.prototype.loadContent = function(mail, key, callback) { | ||
var content = mail.data[key]; | ||
if (typeof content === 'string') { | ||
return process.nextTick(function() { | ||
callback(null, content); | ||
}); | ||
} | ||
mail.resolveContent(mail.data, key, function(err, res) { | ||
if (err) { | ||
return callback(err); | ||
} | ||
callback(null, res.toString()); | ||
}); | ||
}; | ||
SparkPostTransport.prototype.sendWithSparkPost = function(transBody, callback) { | ||
this.sparkPostEmailClient.transmissions.send({transmissionBody: transBody}, function(err, res) { | ||
if (err) { | ||
return callback(err); | ||
} | ||
// Example successful Sparkpost transmission response: | ||
// { "results": { "total_rejected_recipients": 0, "total_accepted_recipients": 1, "id": "66123596945797072" } } | ||
return callback(null, { | ||
messageId: res.body.results.id, | ||
accepted: res.body.results.total_accepted_recipients, | ||
rejected: res.body.results.total_rejected_recipients | ||
}); | ||
}); | ||
}; | ||
function emailList(strOrLst) { | ||
var lst = strOrLst; | ||
if (typeof strOrLst === 'string') { | ||
lst = strOrLst.split(','); | ||
} | ||
return lst.map(function(addr) { | ||
if (typeof addr === 'string') { | ||
return {address: addr}; | ||
} | ||
return { | ||
address: { | ||
name: addr.name, | ||
email: addr.address | ||
}}; | ||
}); | ||
} | ||
module.exports = function(options) { | ||
return new SparkPostTransport(options); | ||
}; | ||
{ | ||
"name": "nodemailer-sparkpost-transport", | ||
"version": "0.1.2", | ||
"version": "1.0.0", | ||
"description": "SparkPost transport for Nodemailer", | ||
"main": "lib/sparkPostTransport.js", | ||
"scripts": { | ||
"pretest": "eslint examples lib test *.js", | ||
"test": "mocha", | ||
"release": "with-package git commit -am pkg.version && with-package git tag pkg.version && git push upstream && npm publish && git push --tags upstream" | ||
"release": "with-package git commit -am pkg.version && with-package git tag pkg.version && git push upstream && git push --tags upstream" | ||
}, | ||
@@ -29,3 +30,6 @@ "repository": { | ||
"chai": "^3.5.0", | ||
"eslint": "=3.0.0", | ||
"eslint-config-sparkpost": "^1.0.1", | ||
"mocha": "^2.4.5", | ||
"nodemailer": "^2.5.0", | ||
"sinon": "^1.17.4", | ||
@@ -32,0 +36,0 @@ "with-package": "^0.2.0" |
104
README.md
@@ -10,3 +10,3 @@ # nodemailer-sparkpost-transport | ||
Install with npm | ||
### Install | ||
@@ -17,3 +17,3 @@ ``` | ||
Require to your script | ||
### Create a Nodemailer transport object | ||
@@ -23,88 +23,46 @@ ```javascript | ||
var sparkPostTransport = require('nodemailer-sparkpost-transport'); | ||
``` | ||
Create a Nodemailer transport object | ||
```javascript | ||
var transporter = nodemailer.createTransport(sparkPostTransport(options)) | ||
``` | ||
Where | ||
where: | ||
- **options** defines connection and message data | ||
- **options** defines connection _default_ transmission properties | ||
- `sparkPostApiKey` - SparkPost [API Key](https://app.sparkpost.com/account/credentials). If not provided, it will use the `SPARKPOST_API_KEY` env var. | ||
- `campaign_id` - Name of the campaign | ||
- `content` - Content that will be used to construct a message | ||
- `metadata` - Transmission level metadata containing key/value pairs | ||
- `options` - JSON object in which transmission options are defined | ||
- `substitution_data` - Key/value pairs that are provided to the substitution engine | ||
- `campaign_id` - Name of the campaign (optional) | ||
- `metadata` - Transmission level metadata containing key/value pairs (optional) | ||
- `options` - JSON object in which transmission options are defined (optional) | ||
- `substitution_data` - Key/value pairs that are provided to the substitution engine (optional) | ||
For more information, see the [SparkPost API Documentation for Transmissions](https://developers.sparkpost.com/api/#/reference/transmissions) | ||
For more information, see the [SparkPost API Documentation for Transmissions](https://developers.sparkpost.com/api/transmissions) | ||
## Send a message | ||
Send a message | ||
```javascript | ||
transport.sendMail(options, function(err, info) {}); | ||
transport.sendMail({ | ||
from: 'me@here.com', | ||
to: 'you@there.com', | ||
subject: 'Very important stuff', | ||
text: 'Plain text', | ||
html: 'Rich taggery' | ||
}, function(err, info) { | ||
if (err) { | ||
console.log('Error: ' + err); | ||
} else { | ||
console.log('Success: ' + info); | ||
}); | ||
``` | ||
Where | ||
[Read more about Nodemailer's `sendMail()` method here](https://github.com/nodemailer/nodemailer#sending-mail). | ||
- **options** defines connection and message data | ||
- `recipients` - Inline recipient objects or object containing stored recipient list ID. See [SparkPost API Documentation for Recipient Lists](https://developers.sparkpost.com/api/#/reference/recipient-lists) for more information. | ||
- `campaign_id` - Override for option above | ||
- `content` - Override for option above | ||
- `metadata` - Override for option above | ||
- `options` - Override for option above | ||
- `substitution_data` - Override for option above | ||
### Additional Options | ||
## Example | ||
The SparkPost Nodemailer transport also supports a few SparkPost-specific `sendMail()` options in both the transport constructor and the 'sendMail()` method. | ||
```javascript | ||
'use strict'; | ||
Note: `sendMail()` options override their constructor counterparts: | ||
var nodemailer = require('nodemailer'); | ||
var sparkPostTransport = require('nodemailer-sparkpost-transport'); | ||
- **options** | ||
- `campaign_id` - Overrides for constructor option | ||
- `metadata` - Override for constructor option | ||
- `options` - Override for constructor option | ||
- `substitution_data` - Override for constructor option | ||
var transporter = nodemailer.createTransport(sparkPostTransport({ | ||
"sparkPostApiKey": "<YOUR_API_KEY>", | ||
"options": { | ||
"open_tracking": true, | ||
"click_tracking": true, | ||
"transactional": true | ||
}, | ||
"campaign_id": "Nodemailer Default", | ||
"metadata": { | ||
"some_useful_metadata": "testing_sparkpost" | ||
}, | ||
"substitution_data": { | ||
"sender": "YOUR NAME", | ||
"fullName": "YOUR NAME", | ||
"productName": "The coolest product ever", | ||
"sparkpostSupportEmail": "support@sparkpost.com", | ||
"sparkpostSupportPhone": "123-456-7890" | ||
}, | ||
"content": { | ||
"template_id": "ADD YOUR TEMPLATE ID HERE" | ||
} | ||
})); | ||
transporter.sendMail({ | ||
"recipients": [ | ||
{ | ||
"address": { | ||
"email": "CHANGE TO YOUR TARGET TEST EMAIL", | ||
"name": "CHANGE TO YOUR RECIPIENT NAME" | ||
} | ||
} | ||
] | ||
}, function(err, info) { | ||
if (err) { | ||
console.error(err); | ||
} else { | ||
console.log(info); | ||
} | ||
}); | ||
``` |
@@ -1,44 +0,43 @@ | ||
"use strict"; | ||
'use strict'; | ||
var sinon = require("sinon"); | ||
var expect = require("chai").expect; | ||
var sinon = require('sinon') | ||
, expect = require('chai').expect | ||
, nodemailer = require('nodemailer') | ||
, sparkPostTransport = require('../lib/sparkPostTransport.js') | ||
, pkg = require('../package.json'); | ||
var sparkPostTransport = require("../lib/sparkPostTransport.js"); | ||
describe('SparkPost Transport', function() { | ||
var transport = sparkPostTransport({sparkPostApiKey: '12345678901234567890'}); | ||
var pkg = require("../package.json"); | ||
describe("SparkPost Transport", function() { | ||
var transport = sparkPostTransport({sparkPostApiKey: "12345678901234567890"}); | ||
it("should have a name and version property", function(done) { | ||
expect(transport).to.have.property("name", "SparkPost"); | ||
expect(transport).to.have.property("version", pkg.version); | ||
it('should have a name and version property', function(done) { | ||
expect(transport).to.have.property('name', 'SparkPost'); | ||
expect(transport).to.have.property('version', pkg.version); | ||
done(); | ||
}); | ||
it("should expose a send method", function(done) { | ||
it('should expose a send method', function(done) { | ||
expect(transport.send).to.exist; | ||
expect(transport.send).to.be.a("function"); | ||
expect(transport.send).to.be.a('function'); | ||
done(); | ||
}); | ||
it("should be able to set options", function(done) { | ||
it('should be able to set options', function(done) { | ||
var transport = sparkPostTransport({ | ||
sparkPostApiKey: "12345678901234567890", | ||
campaign_id: "sample_campaign", | ||
tags: ["new-account-notification"], | ||
metadata: {"source": "event"}, | ||
substitution_data: {"salutatory": "Welcome to SparkPost!"}, | ||
options: {"click_tracking": true, "open_tracking": true}, | ||
content: {"template_id": "newAccountNotification"}, | ||
recipients: [{"email": "john.doe@example.com", "name": "John Doe"}] | ||
sparkPostApiKey: '12345678901234567890', | ||
campaign_id: 'sample_campaign', | ||
tags: ['new-account-notification'], | ||
metadata: {'source': 'event'}, | ||
substitution_data: {'salutatory': 'Welcome to SparkPost!'}, | ||
options: {'click_tracking': true, 'open_tracking': true}, | ||
content: {'template_id': 'newAccountNotification'}, | ||
recipients: [{'email': 'john.doe@example.com', 'name': 'John Doe'}] | ||
}); | ||
expect(transport.campaign_id).to.equal("sample_campaign"); | ||
expect(transport.tags).to.deep.equal(["new-account-notification"]); | ||
expect(transport.metadata).to.deep.equal({"source": "event"}); | ||
expect(transport.substitution_data).to.deep.equal({"salutatory": "Welcome to SparkPost!"}); | ||
expect(transport.options).to.deep.equal({"click_tracking": true, "open_tracking": true}); | ||
expect(transport.content).to.deep.equal({"template_id": "newAccountNotification"}); | ||
expect(transport.recipients).to.deep.equal([{"email": "john.doe@example.com", "name": "John Doe"}]); | ||
expect(transport.campaign_id).to.equal('sample_campaign'); | ||
expect(transport.tags).to.deep.equal(['new-account-notification']); | ||
expect(transport.metadata).to.deep.equal({'source': 'event'}); | ||
expect(transport.substitution_data).to.deep.equal({'salutatory': 'Welcome to SparkPost!'}); | ||
expect(transport.options).to.deep.equal({'click_tracking': true, 'open_tracking': true}); | ||
expect(transport.content).to.deep.equal({'template_id': 'newAccountNotification'}); | ||
expect(transport.recipients).to.deep.equal([{'email': 'john.doe@example.com', 'name': 'John Doe'}]); | ||
@@ -50,34 +49,107 @@ done(); | ||
describe("Send Method", function() { | ||
describe('Send Method', function() { | ||
it("should be able to overload options at the transmission", function(done) { | ||
// Create the default transport | ||
var transport = sparkPostTransport({ | ||
sparkPostApiKey: "12345678901234567890", | ||
campaign_id: "sample_campaign", | ||
tags: ["new-account-notification"], | ||
metadata: {"source": "event"}, | ||
substitution_data: {"salutatory": "Welcome to SparkPost!"}, | ||
options: {"click_tracking": true, "open_tracking": true}, | ||
content: {"template_id": "newAccountNotification"}, | ||
recipients: [{"email": "john.doe@example.com", "name": "John Doe"}] | ||
describe('SP-centric mail structure', function() { | ||
it('should be able to overload options at the transmission', function(done) { | ||
// Create the default transport | ||
var transport = sparkPostTransport({ | ||
sparkPostApiKey: '12345678901234567890', | ||
campaign_id: 'sample_campaign', | ||
tags: ['new-account-notification'], | ||
metadata: {'source': 'event'}, | ||
substitution_data: {'salutatory': 'Welcome to SparkPost!'}, | ||
options: {'click_tracking': true, 'open_tracking': true}, | ||
content: {'template_id': 'newAccountNotification'}, | ||
recipients: [{'email': 'john.doe@example.com', 'name': 'John Doe'}] | ||
}) | ||
// Create the modified options for use with the above stub test | ||
, overloadedTransmission = { | ||
campaign_id: 'another_sample_campaign', | ||
tags: ['alternative-tag'], | ||
metadata: {'changedKey': 'value'}, | ||
substitution_data: {'salutatory': 'And now...for something completely different'}, | ||
options: {'click_tracking': false, 'open_tracking': false, 'transactional': true}, | ||
recipients: [{ | ||
list_id: 'myStoredRecipientTestList' | ||
}], | ||
content: { | ||
template_id: 'someOtherTemplate' | ||
} | ||
}; | ||
// Stub the send method of the SDK out | ||
sinon.stub(transport, 'send', function(data, resolve) { | ||
// Grab the transmissionBody from the send() payload for assertions | ||
expect(data.campaign_id).to.equal('another_sample_campaign'); | ||
expect(data.tags).to.deep.equal(['alternative-tag']); | ||
expect(data.metadata).to.deep.equal({'changedKey': 'value'}); | ||
expect(data.substitution_data).to.deep.equal({'salutatory': 'And now...for something completely different'}); | ||
expect(data.options).to.deep.equal({'click_tracking': false, 'open_tracking': false, 'transactional': true}); | ||
expect(data.content).to.deep.equal({'template_id': 'someOtherTemplate'}); | ||
expect(data.recipients).to.deep.equal([{'list_id': 'myStoredRecipientTestList'}]); | ||
// Resolve the stub's spy | ||
resolve({ | ||
results: { | ||
total_rejected_recipients: 0, | ||
total_accepted_recipients: 1, | ||
id: '66123596945797072' | ||
} | ||
}); | ||
}); | ||
// Call the stub from above | ||
transport.send(overloadedTransmission, function(data) { | ||
expect(data.results.id).to.exist; | ||
expect(data.results.total_rejected_recipients).to.exist; | ||
expect(data.results.total_accepted_recipients).to.exist; | ||
done(); | ||
}); | ||
// Return the original method to its proper state | ||
transport.send.restore(); | ||
}); | ||
}); | ||
// Stub the send method of the SDK out | ||
sinon.stub(transport, "send", function(data, resolve) { | ||
// Grab the transmissionBody from the send() payload for assertions | ||
expect(data.campaign_id).to.equal("another_sample_campaign"); | ||
expect(data.tags).to.deep.equal(["alternative-tag"]); | ||
expect(data.metadata).to.deep.equal({"changedKey": "value"}); | ||
expect(data.substitution_data).to.deep.equal({"salutatory": "And now...for something completely different"}); | ||
expect(data.options).to.deep.equal({"click_tracking": false, "open_tracking": false, "transactional": true}); | ||
expect(data.content).to.deep.equal({"template_id": "someOtherTemplate"}); | ||
expect(data.recipients).to.deep.equal([{"list_id": "myStoredRecipientTestList"}]); | ||
describe('conventional nodemailer mail structure', function() { | ||
var sptrans | ||
, transport | ||
, rcp1 | ||
, rcp2; | ||
// Resolve the stub's spy | ||
resolve({ | ||
function checkTo(done) { | ||
var req = sptrans.sparkPostEmailClient.transmissions.send.firstCall.args[0] | ||
, transBody = req.transmissionBody; | ||
expect(req).to.have.keys('transmissionBody'); | ||
expect(transBody).to.have.keys(['recipients', 'content']); | ||
expect(transBody.recipients).to.have.length(2); | ||
expect(transBody.recipients[0]).to.deep.equal({ address: rcp1 }); | ||
expect(transBody.recipients[1]).to.deep.equal({ address: rcp2 }); | ||
done(); | ||
} | ||
beforeEach(function() { | ||
sptrans = sparkPostTransport({ | ||
sparkPostApiKey: '12345678901234567890' | ||
}); | ||
transport = nodemailer.createTransport(sptrans); | ||
rcp1 = 'Mrs. Asoni <a@a.com>'; | ||
rcp2 = 'b@b.com'; | ||
mail = { | ||
from: 'roberto@from.example.com', | ||
to: 'kingcnut@to.example.com', | ||
subject: 'Modern Kinging', | ||
text: 'Edicts and surfeits...', | ||
html: '<p>Edicts and surfeits...</p>' | ||
}; | ||
sptrans.sparkPostEmailClient.transmissions.send = sinon.stub().yields({ | ||
results: { | ||
total_rejected_recipients: 0, | ||
total_accepted_recipients: 1, | ||
id: "66123596945797072" | ||
id: '66123596945797072' | ||
} | ||
@@ -87,27 +159,57 @@ }); | ||
// Create the modified options for use with the above stub test | ||
var overloadedTransmission = { | ||
campaign_id: "another_sample_campaign", | ||
tags: ["alternative-tag"], | ||
metadata: {"changedKey": "value"}, | ||
substitution_data: {"salutatory": "And now...for something completely different"}, | ||
options: {"click_tracking": false, "open_tracking": false, "transactional": true}, | ||
recipients: [{ | ||
list_id: "myStoredRecipientTestList" | ||
}], | ||
content: { | ||
template_id: "someOtherTemplate" | ||
} | ||
}; | ||
it('should accept basic nodemailer mail content fields', function(done) { | ||
transport.sendMail(mail, function() { | ||
var req = sptrans.sparkPostEmailClient.transmissions.send.firstCall.args[0] | ||
, transBody = req.transmissionBody; | ||
// Call the stub from above | ||
transport.send(overloadedTransmission, function(data) { | ||
expect(data.results.id).to.exist; | ||
expect(data.results.total_rejected_recipients).to.exist; | ||
expect(data.results.total_accepted_recipients).to.exist; | ||
done(); | ||
expect(req).to.have.keys('transmissionBody'); | ||
expect(transBody).to.have.keys(['recipients', 'content']); | ||
expect(transBody.content.html).to.equal(mail.html); | ||
expect(transBody.content.text).to.equal(mail.text); | ||
expect(transBody.content.subject).to.equal(mail.subject); | ||
expect(transBody.content.from).to.equal(mail.from); | ||
expect(transBody.recipients).to.have.length(1); | ||
expect(transBody.recipients[0]).to.have.keys('address'); | ||
expect(transBody.recipients[0].address).to.be.a('string'); | ||
expect(transBody.recipients[0].address).to.equal(mail.to); | ||
done(); | ||
}); | ||
}); | ||
// Return the original method to its proper state | ||
transport.send.restore(); | ||
it('should accept raw mail structure', function(done) { | ||
delete mail.subject; | ||
delete mail.text; | ||
delete mail.html; | ||
delete mail.from; | ||
mail.raw = 'rawmsg'; | ||
transport.sendMail(mail, function() { | ||
var req = sptrans.sparkPostEmailClient.transmissions.send.firstCall.args[0] | ||
, transBody = req.transmissionBody; | ||
expect(req).to.have.keys('transmissionBody'); | ||
expect(transBody).to.have.keys(['recipients', 'content']); | ||
expect(transBody.content).to.have.keys('email_rfc822'); | ||
expect(transBody.recipients).to.have.length(1); | ||
expect(transBody.recipients[0]).to.have.keys('address'); | ||
expect(transBody.recipients[0].address).to.be.a('string'); | ||
expect(transBody.recipients[0].address).to.equal(mail.to); | ||
done(); | ||
}); | ||
}); | ||
it('should accept to as an array', function(done) { | ||
mail.to = [rcp1, rcp2]; | ||
transport.sendMail(mail, function() { | ||
checkTo(done); | ||
}); | ||
}); | ||
it('should accept to as a string', function(done) { | ||
mail.to = [rcp1, rcp2].join(','); | ||
transport.sendMail(mail, function() { | ||
checkTo(done); | ||
}); | ||
}); | ||
}); | ||
}); | ||
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
No v1
QualityPackage is not semver >=1. This means it is not stable and does not support ^ ranges.
Found 1 instance in 1 package
53142
20
343
0
7
66
1