Skip to content
This repository has been archived by the owner on Jan 21, 2024. It is now read-only.

Attachments support #36

Open
wants to merge 8 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 6 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,12 @@ transport.sendMail({
}, /* ... */);
```

## Attachments

The content of attachments **must** be a base64 encoded string.
Examples of this can be found in the test file.


## Sending Images to Mandrill

To send images as attachments:
Expand Down
24 changes: 23 additions & 1 deletion lib/mandrill-transport.js
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,27 @@ MandrillTransport.prototype.send = function(mail, callback) {
var bccAddrs = addressparser(data.bcc) || [];
var fromAddr = addressparser(data.from)[0] || {};
var mandrillOptions = data.mandrillOptions || {};
var attachments = [];

// convert attachments passed to nodemailer to the structure used by mandrill
if (mail.message && mail.message.childNodes) {
mail.message.childNodes.forEach(function(node) {
var headersAsMap = {};

node._headers && node._headers.forEach(function(headerEntry) {
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[].find?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

there could be multiple attachments, so find wont fit.
can use filter for that though, will give it a quick try and if good will push it

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

actually find should work, just noticed now this happens in the forEach of child nodes.
will use it.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

tried it and it failed for me, im running node 0.10.x, on which Array.prototype.find is not available.
i use nvm, so tried changing to nodejs 4.x and worked there.

but for sake of compatibility i left code as is, your'e welcome to refactor if you want to.

headersAsMap[headerEntry.key] = headerEntry.value;
});

// a node is an attachment with header 'Content-Disposition' : 'attachment'
if (headersAsMap['Content-Disposition'] === 'attachment') {
attachments.push({
'name': node.filename,
'type': headersAsMap['Content-Type'],
'content': node.content
});
}
});
}

var payload = extend(true, {
async: true,
Expand Down Expand Up @@ -53,7 +74,8 @@ MandrillTransport.prototype.send = function(mail, callback) {
subject: data.subject,
headers: data.headers,
text: data.text,
html: data.html
html: data.html,
attachments: attachments
}
}, mandrillOptions);

Expand Down
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
"devDependencies": {
"chai": "^3.5.0",
"mocha": "^2.4.5",
"nodemailer": "^2.2.1",
"sinon": "^1.17.3"
}
}
79 changes: 72 additions & 7 deletions test/mandrill-transport.js
Original file line number Diff line number Diff line change
@@ -1,11 +1,9 @@
'use strict';

var sinon = require('sinon');
var expect = require('chai').expect;

var mandrillTransport = require('../');

var packageData = require('../package.json');
var sinon = require('sinon'),
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

NO

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

sry for changing the project style, just happened out of habit

expect = require('chai').expect,
mandrillTransport = require('../'),
packageData = require('../package.json');

describe('MandrillTransport', function() {
it('should expose name and version', function() {
Expand All @@ -14,7 +12,7 @@ describe('MandrillTransport', function() {
expect(transport.version).to.equal(packageData.version);
});

describe('#send', function(done) {
describe('#send', function() {
var transport = mandrillTransport();
var client = transport.mandrillClient;

Expand Down Expand Up @@ -165,4 +163,71 @@ describe('MandrillTransport', function() {
});
});
});

describe('#send attachments usage', function() {
var nodemailer = require('nodemailer'),
transport = mandrillTransport(),
client = transport.mandrillClient,
wrappedTransport = nodemailer.createTransport(transport),
sendOptions;

before(function() {
sinon.stub(client.messages, 'send', function(options, cb) {
sendOptions = options;
cb([]);
});
});

beforeEach(function() {
sendOptions = {};
});

after(function() {
client.messages.send.restore();
});

it('attachments object', function(done) {
wrappedTransport.sendMail({
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

dont merge yet, i thought of something that needs to be tested:

i should call sendMail with full details (from, to etc...) and make sure that it doesn't somehow interfere with the attachments logic.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done already.

attachments: [
{
filename: 'bufferIsABase64.txt',
content: new Buffer('hello world!', 'utf-8')
},
{
filename: 'text.csv',
content: new Buffer('hello;world!\n1;2','utf-8'),
contentType: 'text/csv'
},
{
filename: 'encoded.txt',
content: new Buffer('i am base64', 'utf-8').toString('base64'),
encoding: 'base64'
},
{ // data uri as an attachment
path: 'data:text/plain;base64,' + new Buffer('HELLOWORLD', 'utf-8').toString('base64')
}
]
}, function(err) {
expect(err).to.be.null;
expect(sendOptions.message.attachments).to.have.lengthOf(4);

expect(sendOptions.message.attachments[0].name).to.equal('bufferIsABase64.txt');
expect(sendOptions.message.attachments[0].type).to.equal('text/plain');
expect(new Buffer(sendOptions.message.attachments[0].content, 'base64').toString('utf-8')).to.equal('hello world!');

expect(sendOptions.message.attachments[1].name).to.equal('text.csv');
expect(sendOptions.message.attachments[1].type).to.equal('text/csv');
expect(new Buffer(sendOptions.message.attachments[1].content, 'base64').toString('utf-8')).to.equal('hello;world!\n1;2');

expect(sendOptions.message.attachments[2].name).to.equal('encoded.txt');
expect(sendOptions.message.attachments[2].type).to.equal('text/plain');
expect(new Buffer(sendOptions.message.attachments[2].content, 'base64').toString('utf-8')).to.equal('i am base64');

expect(sendOptions.message.attachments[3].name).to.equal('attachment-4.txt');
expect(sendOptions.message.attachments[3].type).to.equal('text/plain');
expect(new Buffer(sendOptions.message.attachments[3].content, 'base64').toString('utf-8')).to.equal('HELLOWORLD');
done();
});
});
});
});