Skip to content

Commit 436715b

Browse files
committed
Merge pull request #5 from andris9/master
Better compatibility with Nodemailer mail options
2 parents 891c6cf + 0b3b918 commit 436715b

File tree

1 file changed

+110
-11
lines changed

1 file changed

+110
-11
lines changed

src/sendgrid-transport.js

Lines changed: 110 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -19,21 +19,120 @@ function SendGridTransport(options) {
1919
SendGridTransport.prototype.send = function(mail, callback) {
2020
var email = mail.data;
2121

22-
if (typeof(email.to) === 'string') {
23-
email.to = mail.data.to.split(/[ ,]+/);
22+
// fetch envelope data from the message object
23+
var addresses = mail.message.getAddresses();
24+
var from = [].concat(addresses.from || addresses.sender || addresses['reply-to'] || []).shift();
25+
var to = [].concat(addresses.to || []).concat(addresses.cc || []).concat(addresses.bcc || []);
26+
27+
// populate from and fromname
28+
if (from) {
29+
if (from.address) {
30+
email.from = from.address;
31+
}
32+
33+
if (from.name) {
34+
email.fromname = from.name;
35+
}
2436
}
2537

26-
if (email.attachments) {
27-
email.files = email.attachments;
38+
// populate to and toname arrays
39+
email.to = to.map(function(rcpt) {
40+
return rcpt.address || '';
41+
});
42+
43+
email.toname = to.map(function(rcpt) {
44+
return rcpt.name || '';
45+
});
46+
47+
// a list for processing attachments
48+
var contents = [];
49+
50+
// email.text could be a stream or a file, so store it for processing
51+
if (email.text) {
52+
contents.push({
53+
obj: email,
54+
key: 'text'
55+
});
2856
}
2957

30-
var fromSplit = email.from.match(/(.*)\<(.*)\>/)
31-
if(fromSplit){
32-
email.fromname = fromSplit[1].trim();
33-
email.from = fromSplit[2];
58+
// email.html could be a stream or a file, so store it for processing
59+
if (email.html) {
60+
contents.push({
61+
obj: email,
62+
key: 'html'
63+
});
3464
}
3565

36-
this.sendgrid.send(email, function(err, json) {
37-
callback(err, json);
66+
// store attachments for processing, to fetch files, urls and streams
67+
email.files = email.attachments;
68+
[].concat(email.files || []).forEach(function(attachment, i) {
69+
contents.push({
70+
obj: email.files,
71+
key: i,
72+
isAttachment: true
73+
});
3874
});
39-
};
75+
76+
// fetch values for text/html/attachments as strings or buffers
77+
// this is an asynchronous action, so we'll handle it with a simple recursion
78+
var _self = this;
79+
var pos = 0;
80+
var resolveContent = function() {
81+
82+
// if all parts are processed, send out the e-mail
83+
if (pos >= contents.length) {
84+
return _self.sendgrid.send(email, function(err, json) {
85+
callback(err, json);
86+
});
87+
}
88+
89+
// get the next element from the processing list
90+
var file = contents[pos++];
91+
/*
92+
We need to store a pointer to the original attachment object in case
93+
resolveContent replaces it with the Stream value
94+
*/
95+
var prevObj = file.obj[file.key];
96+
// ensure the object is an actual attachment object, not a string, buffer or a stream
97+
if (prevObj instanceof Buffer ||  typeof prevObj === 'string' || (prevObj && typeof prevObj.pipe === 'function')) {
98+
prevObj = {
99+
content: prevObj
100+
};
101+
}
102+
103+
// use the helper function to convert file paths, urls and streams to strings or buffers
104+
mail.resolveContent(file.obj, file.key, function(err, content) {
105+
if (err) {
106+
return callback(err);
107+
}
108+
109+
if (!file.isAttachment) {
110+
// overwrites email.text and email.html content
111+
file.obj[file.key] = content;
112+
} else {
113+
114+
// If the object is a String or a Buffer then it is most likely replaces by resolveContent
115+
if (file.obj[file.key] instanceof Buffer ||  typeof file.obj[file.key] === 'string') {
116+
file.obj[file.key] = prevObj;
117+
}
118+
file.obj[file.key].content = content;
119+
if (file.obj[file.key].path) {
120+
if (!file.obj[file.key].filename) {
121+
// try to detect the required filename from the path
122+
file.obj[file.key].filename = file.obj[file.key].path.split(/[\\\/]/).pop();
123+
}
124+
delete file.obj[file.key].path;
125+
}
126+
// set default filename if filename and content-type are not set (allowed for Nodemailer but not for SendGrid)
127+
if (!file.obj[file.key].filename && !file.obj[file.key].contentType) {
128+
file.obj[file.key].filename = 'attachment-' + pos + '.bin';
129+
}
130+
}
131+
132+
resolveContent();
133+
});
134+
};
135+
136+
// start the recursive function
137+
resolveContent();
138+
};

0 commit comments

Comments
 (0)