nodemailer 0.6.3 → 0.7.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/.npmignore CHANGED
@@ -1,3 +1,6 @@
1
- node_modules
2
- npm-debug.log
3
- .DS_Store
1
+ .travis.yml
2
+ CONTRIBUTING.md
3
+ assets
4
+ examples
5
+ test
6
+
package/CHANGELOG.md CHANGED
@@ -1,5 +1,30 @@
1
1
  # Changelog
2
2
 
3
+ ## v0.7.1 2014-07-09
4
+
5
+ * Upgraded aws-sdk to 2.0.5
6
+
7
+ ## v0.7.0 2014-06-17
8
+
9
+ * Bumped version to v0.7.0
10
+ * Fix AWS-SES usage [5b6bc144]
11
+ * Replace current SES with new SES using AWS-SDK (Elanorr) [c79d797a]
12
+ * Updated README.md about Node Email Templates (niftylettuce) [e52bef81]
13
+
14
+ ## v0.6.5 2014-05-15
15
+
16
+ * Bumped version to v0.6.5
17
+ * Use tildes instead of carets for dependency listing [5296ce41]
18
+ * Allow clients to set a custom identityString (venables) [5373287d]
19
+ * bugfix (adding "-i" to sendmail command line for each new mail) by copying this.args (vrodic) [05a8a9a3]
20
+ * update copyright (gdi2290) [3a6cba3a]
21
+
22
+ ## v0.6.4 2014-05-13
23
+
24
+ * Bumped version to v0.6.4
25
+ * added npmignore, bumped dependencies [21bddcd9]
26
+ * Add AOL to well-known services (msouce) [da7dd3b7]
27
+
3
28
  ## v0.6.3 2014-04-16
4
29
 
5
30
  * Bumped version to v0.6.3
package/LICENSE CHANGED
@@ -1,4 +1,4 @@
1
- Copyright (c) 2011-2013 Andris Reinman
1
+ Copyright (c) 2011-2014 Andris Reinman
2
2
 
3
3
  Permission is hereby granted, free of charge, to any person obtaining a copy
4
4
  of this software and associated documentation files (the "Software"), to deal
@@ -13,4 +13,4 @@ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
13
13
  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
14
14
  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
15
15
  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
16
- SOFTWARE.
16
+ SOFTWARE.
package/README.md CHANGED
@@ -58,8 +58,8 @@ check out [simplesmtp](https://github.com/andris9/simplesmtp).
58
58
 
59
59
  To use Nodemailer with templates, please see documentation for these projects.
60
60
 
61
+ * [node-email-templates](https://github.com/niftylettuce/node-email-templates) - ejs, jade, swig, handlebars, less, sass, stylus, styl
61
62
  * [swig-email-templates](https://github.com/superjoe30/swig-email-templates) - swig, template inheritance, dummy context
62
- * [node-email-templates](https://github.com/niftylettuce/node-email-templates) - ejs
63
63
 
64
64
  ## TL;DR Usage Example
65
65
 
@@ -174,7 +174,7 @@ transport.sendMail({
174
174
  `type` parameter can be one of the following:
175
175
 
176
176
  * **SMTP** for using SMTP
177
- * **SES** for using Amazon SES
177
+ * **SES** for using Amazon SES with AWS Identity and Access Management (IAM) roles
178
178
  * **Sendmail** for utilizing systems *sendmail* command
179
179
  * **Pickup** for storing the e-mail in a directory on your machine
180
180
  * **Direct** for sending e-mails directly to recipients MTA servers
@@ -325,15 +325,25 @@ var transportOptions = {
325
325
 
326
326
  ### Setting up SES
327
327
 
328
- SES is actually a HTTP based protocol, the compiled e-mail and related info
329
- (signatures and such) are sent as a HTTP request to SES servers.
328
+ SES use the aws-sdk node module that wraps all the HTTP requests to SES servers.
329
+ If running on an Amazon EC2 instance, it allows the use of IAM Roles instead of AWS credentials.
330
+ If necessary, the AWS credentials can still be provided to the *createTransport* method or through environment variables ( AWS_ACCESS_KEY_ID and AWS_SECRET_ACCESS_KEY ).
330
331
 
331
- Possible SES options are the following:
332
+ The SES options were renamed in v0.7. The new names are compatible with the naming convention of the AWS SDK for javascript in nodeJS used in Nodemailer. Thus you can pass a configuration object compatible with the AWS SDK to the createTransport() function.
332
333
 
333
- * **AWSAccessKeyID** - AWS access key (required)
334
- * **AWSSecretKey** - AWS secret (required)
335
- * **ServiceUrl** - *optional* API end point URL (defaults to *"https://email.us-east-1.amazonaws.com"*)
336
- * **AWSSecurityToken** - *optional* security token
334
+ Possible SES options are the following:
335
+
336
+ * **accessKeyId** - *optional* AWS access key.
337
+ * **secretAccessKey** - *optional* AWS secret.
338
+ * **sessionToken** - *optional* session token.
339
+ * **region** - *optional* Specify the region to send the service request to. Default to *us-east-1*
340
+
341
+ Deprecated parameters. These are kept for backward compatibility reasons to support users of Nodemailer prior to v0.7. Any new development should use the new parameters above:
342
+
343
+ * **AWSAccessKeyID** - *optional* AWS access key. The option **accessKeyId** should be used instead.
344
+ * **AWSSecretKey** - *optional* AWS secret. The option **secretAccessKey** should be used instead.
345
+ * **ServiceUrl** - *optional* API end point URL (defaults to *"https://email.us-east-1.amazonaws.com"*). The option **region** should be used instead.
346
+ * **AWSSecurityToken** - *optional* security token. The option **sessionToken** should be used instead.
337
347
 
338
348
  Example:
339
349
 
@@ -343,6 +353,7 @@ var transport = nodemailer.createTransport("SES", {
343
353
  AWSSecretKey: "AWS/Secret/key"
344
354
  });
345
355
  ```
356
+ **As of v0.7, ```sendmail()``` return only ```messageId``` instead of ```message```, ```response``` and ```messageID```**
346
357
 
347
358
  ### Setting up Sendmail
348
359
 
@@ -564,6 +575,7 @@ to enter the hostname or port number, just use the `service` parameter
564
575
 
565
576
  Currently supported services are:
566
577
 
578
+ * **AOL**
567
579
  * **DynectEmail**
568
580
  * **Gmail**
569
581
  * **hot.ee**
@@ -54,7 +54,7 @@ function SendmailTransport(config){
54
54
  SendmailTransport.prototype.sendMail = function sendMail(emailMessage, callback){
55
55
 
56
56
  var envelope = emailMessage.getEnvelope(),
57
- args = this.args || ["-f"].concat(envelope.from).concat(envelope.to),
57
+ args = this.args ? this.args.slice() : ["-f"].concat(envelope.from).concat(envelope.to),
58
58
  sendmail,
59
59
  cbCounter = 2,
60
60
  didCb,
@@ -2,38 +2,45 @@
2
2
 
3
3
  /*
4
4
  * This file is based on the original SES module for Nodemailer by dfellis
5
- * https://github.com/andris9/Nodemailer/blob/11fb3ef560b87e1c25e8bc15c2179df5647ea6f5/lib/engines/SES.js
6
- */
5
+ * https://github.com/andris9/Nodemailer/blob/11fb3ef560b87e1c25e8bc15c2179df5647ea6f5/lib/engines/SES.js
6
+ * and on the rewrite by andris9
7
+ * https://github.com/andris9/Nodemailer/blob/3ac11ae9a9faf95aabd9bffb37ca702fe33105e4/lib/engines/ses.js
8
+ */
7
9
 
8
10
  // NB! Amazon SES does not allow unicode filenames on attachments!
9
11
 
10
- var http = require('http'),
11
- https = require('https'),
12
- crypto = require('crypto'),
13
- urllib = require("url");
12
+ var AWS = require('aws-sdk');
14
13
 
15
14
  // Expose to the world
16
15
  module.exports = SESTransport;
17
16
 
18
17
  /**
19
- * <p>Generates a Transport object for Amazon SES</p>
18
+ * <p>Generates a Transport object for Amazon SES with aws-sdk</p>
20
19
  *
21
20
  * <p>Possible options can be the following:</p>
22
21
  *
23
22
  * <ul>
24
- * <li><b>AWSAccessKeyID</b> - AWS access key (required)</li>
25
- * <li><b>AWSSecretKey</b> - AWS secret (required)</li>
26
- * <li><b>ServiceUrl</b> - optional API endpoint URL (defaults to <code>"https://email.us-east-1.amazonaws.com"</code>)
23
+ * <li><b>accessKeyId</b> - AWS access key (optional)</li>
24
+ * <li><b>secretAccessKey</b> - AWS secret (optional)</li>
25
+ * <li><b>region</b> - optional region (defaults to <code>"us-east-1"</code>)
27
26
  * </ul>
28
27
  *
29
28
  * @constructor
30
- * @param {Object} options Options object for the SES transport
29
+ * @param {Object} optional config parameter for the AWS SES service
31
30
  */
32
- function SESTransport(options){
31
+ function SESTransport(options) {
32
+
33
+ var pattern = /(.*)email(.*)\.(.*).amazonaws.com/i,
34
+ result = pattern.exec(options.ServiceUrl);
35
+
33
36
  this.options = options || {};
37
+ this.options.accessKeyId = options.accessKeyId || options.AWSAccessKeyID;
38
+ this.options.secretAccessKey = options.secretAccessKey || options.AWSSecretKey;
39
+ this.options.sessionToken = options.sessionToken || options.AWSSecurityToken;
40
+ this.options.apiVersion = '2010-12-01';
41
+ this.options.region = options.region || (result && result[3]) || 'us-east-1';
34
42
 
35
- //Set defaults if necessary
36
- this.options.ServiceUrl = this.options.ServiceUrl || "https://email.us-east-1.amazonaws.com";
43
+ this.ses = new AWS.SES(this.options);
37
44
  }
38
45
 
39
46
  /**
@@ -42,19 +49,13 @@ function SESTransport(options){
42
49
  * @param {Object} emailMessage MailComposer object
43
50
  * @param {Function} callback Callback function to run when the sending is completed
44
51
  */
45
- SESTransport.prototype.sendMail = function(emailMessage, callback) {
46
-
52
+ SESTransport.prototype.sendMail = function (emailMessage, callback) {
47
53
  // SES strips this header line by itself
48
54
  emailMessage.options.keepBcc = true;
49
55
 
50
- //Check if required config settings set
51
- if(!this.options.AWSAccessKeyID || !this.options.AWSSecretKey) {
52
- return callback(new Error("Missing AWS Credentials"));
53
- }
54
-
55
- this.generateMessage(emailMessage, (function(err, email){
56
- if(err){
57
- return typeof callback == "function" && callback(err);
56
+ this.generateMessage(emailMessage, (function (err, email) {
57
+ if (err) {
58
+ return typeof callback === "function" && callback(err);
58
59
  }
59
60
  this.handleMessage(email, callback);
60
61
  }).bind(this));
@@ -66,181 +67,54 @@ SESTransport.prototype.sendMail = function(emailMessage, callback) {
66
67
  * @param {String} email Compiled raw e-mail as a string
67
68
  * @param {Function} callback Callback function to run once the message has been sent
68
69
  */
69
- SESTransport.prototype.handleMessage = function(email, callback) {
70
- var request,
71
- date = new Date(),
72
- urlparts = urllib.parse(this.options.ServiceUrl),
73
- pairs = {
74
- 'Action': 'SendRawEmail',
75
- 'RawMessage.Data': (new Buffer(email, "utf-8")).toString('base64'),
76
- 'Version': '2010-12-01',
77
- 'Timestamp': this.ISODateString(date)
78
- };
79
-
80
- if (this.options.AWSSecurityToken) {
81
- pairs.SecurityToken = this.options.AWSSecurityToken;
82
- }
83
-
84
- var params = this.buildKeyValPairs(pairs),
85
-
86
- reqObj = {
87
- host: urlparts.hostname,
88
- path: urlparts.path || "/",
89
- method: "POST",
90
- headers: {
91
- 'Content-Type': 'application/x-www-form-urlencoded',
92
- 'Content-Length': params.length,
93
- 'Date': date.toUTCString(),
94
- 'X-Amzn-Authorization':
95
- ['AWS3-HTTPS AWSAccessKeyID='+this.options.AWSAccessKeyID,
96
- "Signature="+this.buildSignature(date.toUTCString(), this.options.AWSSecretKey),
97
- "Algorithm=HmacSHA256"].join(",")
70
+ SESTransport.prototype.handleMessage = function (email, callback) {
71
+ var params = {
72
+ RawMessage: { // required
73
+ Data: new Buffer(email, "utf-8") // required
98
74
  }
99
75
  };
100
-
101
- //Execute the request on the correct protocol
102
- if(urlparts.protocol.substr() == "https:") {
103
- request = https.request(reqObj, this.responseHandler.bind(this, callback));
104
- } else {
105
- request = http.request(reqObj, this.responseHandler.bind(this, callback));
106
- }
107
- request.end(params);
108
-
109
- // Handle fatal errors
110
- request.on("error", this.errorHandler.bind(this, callback) );
76
+ this.ses.sendRawEmail(params, this.responseHandler.bind(this, callback));
111
77
  };
112
78
 
113
-
114
-
115
- /**
116
- * <p>Handles a fatal error response for the HTTP request to SES</p>
117
- *
118
- * @param {Function} callback Callback function to run on end (binded)
119
- * @param {Object} response HTTP Response object
120
- */
121
- SESTransport.prototype.errorHandler = function(callback, err) {
122
- if( ! ( err instanceof Error) ) {
123
- err = new Error('Email failed ' + ("statusCode" in err ? err.statusCode : null ), {response:err});
124
- }
125
- return typeof callback == "function" && callback(err, null);
126
- };
127
-
128
-
129
79
  /**
130
80
  * <p>Handles the response for the HTTP request to SES</p>
131
81
  *
132
82
  * @param {Function} callback Callback function to run on end (binded)
133
- * @param {Object} response HTTP Response object
83
+ * @param {Object} err Error object returned from the request
84
+ * @param {Object} data De-serialized data returned from the request
134
85
  */
135
- SESTransport.prototype.responseHandler = function(callback, response) {
136
- var body = "", match;
137
- response.setEncoding('utf8');
138
-
139
- //Re-assembles response data
140
- response.on('data', function(d) {
141
- body += d.toString();
142
- });
143
-
144
- //Performs error handling and executes callback, if it exists
145
- response.on('end', function(err) {
146
- if(err instanceof Error) {
147
- return typeof callback == "function" && callback(err, null);
86
+ SESTransport.prototype.responseHandler = function (callback, err, data) {
87
+ if (err) {
88
+ if (!(err instanceof Error)) {
89
+ err = new Error('Email failed: ' + err);
148
90
  }
149
- if(response.statusCode != 200) {
150
- return typeof callback == "function" &&
151
- callback(new Error('Email failed: ' + response.statusCode + '\n' + body), {
152
- message: body,
153
- response: response
154
- });
155
- }
156
- match = (body || "").toString().match(/<MessageId\b[^>]*>([^<]+)<\/MessageId\b[^>]*>/i);
157
- return typeof callback == "function" && callback(null, {
158
- message: body,
159
- response: response,
160
- messageId: match && match[1] && match[1] + "@email.amazonses.com"
161
- });
91
+ return typeof callback === "function" && callback(err, null);
92
+ }
93
+ return typeof callback === "function" && callback(null, {
94
+ messageId: data && data.MessageId && data.MessageId + "@email.amazonses.com"
162
95
  });
163
96
  };
164
97
 
165
98
  /**
166
99
  * <p>Compiles the messagecomposer object to a string.</p>
167
100
  *
168
- * <p>It really sucks but I don't know a good way to stream a POST request with
169
- * unknown legth, so the message needs to be fully composed as a string.</p>
101
+ * <p>SES requires strings as parameter so the message needs to be fully composed as a string.</p>
170
102
  *
171
103
  * @param {Object} emailMessage MailComposer object
172
104
  * @param {Function} callback Callback function to run once the message has been compiled
173
105
  */
174
106
 
175
- SESTransport.prototype.generateMessage = function(emailMessage, callback) {
107
+ SESTransport.prototype.generateMessage = function (emailMessage, callback) {
176
108
  var email = "";
177
109
 
178
- emailMessage.on("data", function(chunk){
110
+ emailMessage.on("data", function (chunk) {
179
111
  email += (chunk || "").toString("utf-8");
180
112
  });
181
113
 
182
- emailMessage.on("end", function(chunk){
114
+ emailMessage.on("end", function (chunk) {
183
115
  email += (chunk || "").toString("utf-8");
184
116
  callback(null, email);
185
117
  });
186
118
 
187
119
  emailMessage.streamMessage();
188
120
  };
189
-
190
- /**
191
- * <p>Converts an object into a Array with "key=value" values</p>
192
- *
193
- * @param {Object} config Object with keys and values
194
- * @return {Array} Array of key-value pairs
195
- */
196
- SESTransport.prototype.buildKeyValPairs = function(config){
197
- var keys = Object.keys(config).sort(),
198
- keyValPairs = [],
199
- key, i, len;
200
-
201
- for(i=0, len = keys.length; i < len; i++) {
202
- key = keys[i];
203
- if(key != "ServiceUrl") {
204
- keyValPairs.push((encodeURIComponent(key) + "=" + encodeURIComponent(config[key])));
205
- }
206
- }
207
-
208
- return keyValPairs.join("&");
209
- };
210
-
211
- /**
212
- * <p>Uses SHA-256 HMAC with AWS key on date string to generate a signature</p>
213
- *
214
- * @param {String} date ISO UTC date string
215
- * @param {String} AWSSecretKey ASW secret key
216
- */
217
- SESTransport.prototype.buildSignature = function(date, AWSSecretKey) {
218
- var sha256 = crypto.createHmac('sha256', AWSSecretKey);
219
- sha256.update(date);
220
- return sha256.digest('base64');
221
- };
222
-
223
- /**
224
- * <p>Generates an UTC string in the format of YYY-MM-DDTHH:MM:SSZ</p>
225
- *
226
- * @param {Date} d Date object
227
- * @return {String} Date string
228
- */
229
- SESTransport.prototype.ISODateString = function(d){
230
- return d.getUTCFullYear() + '-' +
231
- this.strPad(d.getUTCMonth()+1) + '-' +
232
- this.strPad(d.getUTCDate()) + 'T' +
233
- this.strPad(d.getUTCHours()) + ':' +
234
- this.strPad(d.getUTCMinutes()) + ':' +
235
- this.strPad(d.getUTCSeconds()) + 'Z';
236
- };
237
-
238
- /**
239
- * <p>Simple padding function. If the number is below 10, add a zero</p>
240
- *
241
- * @param {Number} n Number to pad with 0
242
- * @return {String} 0 padded number
243
- */
244
- SESTransport.prototype.strPad = function(n){
245
- return n<10 ? '0'+n : n;
246
- };
package/lib/nodemailer.js CHANGED
@@ -89,6 +89,10 @@ function Nodemailer(options){
89
89
 
90
90
  mailcomposerOptions.identityString = X_MAILER_NAME + " " + packageData.version;
91
91
 
92
+ if(this.options.identityString){
93
+ mailcomposerOptions.identityString = this.options.identityString;
94
+ }
95
+
92
96
  if(this.options.encoding){
93
97
  mailcomposerOptions.encoding = this.options.encoding;
94
98
  }
@@ -171,22 +175,25 @@ Nodemailer.prototype.getGlobalTransport = function(){
171
175
  * @param {Function} callback Callback function to run after validation
172
176
  */
173
177
  Nodemailer.prototype.validateSettings = function(callback){
174
- if(!this.transport || !this.transport.transport){
175
- return callback(new Error("No transport method defined"));
176
- }
178
+ var self = this;
179
+ process.nextTick(function(){
180
+ if(!self.transport || !self.transport.transport){
181
+ return callback(new Error("No transport method defined"));
182
+ }
177
183
 
178
- // transport.options.resolveHostname is set to true, resolve pulbic
179
- // hostname for the machine and use this when generating Message-ID values
180
- // or when communicating with SMTP
181
- if(this.transport.options && this.transport.options.resolveHostname && !this.transport.options.name){
182
- return publicHostnameResolver.resolve((function(err, resolved){
183
- this.transport.options.name = this.resolveHostname(
184
- resolved ? resolved.hostname : this.options.name);
185
- callback();
186
- }).bind(this));
187
- }
184
+ // transport.options.resolveHostname is set to true, resolve pulbic
185
+ // hostname for the machine and use self when generating Message-ID values
186
+ // or when communicating with SMTP
187
+ if(self.transport.options && self.transport.options.resolveHostname && !self.transport.options.name){
188
+ return publicHostnameResolver.resolve((function(err, resolved){
189
+ self.transport.options.name = self.resolveHostname(
190
+ resolved ? resolved.hostname : self.options.name);
191
+ callback();
192
+ }).bind(self));
193
+ }
188
194
 
189
- callback(null);
195
+ callback(null);
196
+ });
190
197
  };
191
198
 
192
199
  /**
package/lib/wellknown.js CHANGED
@@ -161,9 +161,17 @@ module.exports = {
161
161
  domains: ['fastmail.fm']
162
162
  },
163
163
  "SendCloud": {
164
- transport: "SMPT",
164
+ transport: "SMTP",
165
165
  host: "smtpcloud.sohu.com",
166
166
  port: 25,
167
167
  requiresAuth: true
168
+ },
169
+ // http://help.aol.com/help/microsites/microsite.do?cmd=displayKC&externalId=73332
170
+ "AOL":{
171
+ transport: "SMTP",
172
+ host: "smtp.aol.com",
173
+ port: 587,
174
+ requiresAuth: true,
175
+ domains: ["aol.com"]
168
176
  }
169
177
  };
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "nodemailer",
3
3
  "description": "Easy to use module to send e-mails, supports unicode and SSL/TLS",
4
- "version": "0.6.3",
4
+ "version": "0.7.1",
5
5
  "author": "Andris Reinman",
6
6
  "maintainers": [
7
7
  {
@@ -25,11 +25,12 @@
25
25
  }
26
26
  ],
27
27
  "dependencies": {
28
- "mailcomposer": "~0.2.7",
29
- "simplesmtp": "~0.2 || ^0.3.25",
30
- "directmail": "~0.1.6",
28
+ "mailcomposer": "~0.2.10",
29
+ "simplesmtp": "~0.2 || ~0.3.30",
30
+ "directmail": "~0.1.7",
31
31
  "he": "~0.3.6",
32
- "public-address": "~0.1.0"
32
+ "public-address": "~0.1.1",
33
+ "aws-sdk": "2.0.5"
33
34
  },
34
35
  "devDependencies": {
35
36
  "nodeunit": "*"
package/.travis.yml DELETED
@@ -1,12 +0,0 @@
1
- language: node_js
2
- node_js:
3
- - 0.8
4
- - "0.10"
5
- - "0.11"
6
-
7
- notifications:
8
- email:
9
- recipients:
10
- - andris@kreata.ee
11
- on_success: change
12
- on_failure: change
package/CONTRIBUTING.md DELETED
@@ -1,11 +0,0 @@
1
- # Contributing
2
-
3
- All SMTP related issues are high priority. Report these here or at [simplesmtp](https://github.com/andris9/simplesmtp).
4
-
5
- "Sendmail" transport related issues are low priority. If you want something to get fixed, making a pull request instead of filing an issue helps a lot to speed things up. Most probably the issue is related with a specific sendmail implementation and I'm not able to test every sendmail clone out there.
6
-
7
- When making a pull request try not to introduce anything that is not backwards compatible.
8
-
9
- ## Formatting
10
-
11
- Use 4 spaces instead of tabs. Commas last. Use double quotes instead of single quotes where possible.
Binary file
Binary file
Binary file
Binary file
Binary file