nodemailer 8.0.2 → 8.0.4

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.
@@ -11,12 +11,10 @@ class MailMessage {
11
11
  this.message = null;
12
12
 
13
13
  data = data || {};
14
- let options = mailer.options || {};
15
- let defaults = mailer._defaults || {};
14
+ const options = mailer.options || {};
15
+ const defaults = mailer._defaults || {};
16
16
 
17
- Object.keys(data).forEach(key => {
18
- this.data[key] = data[key];
19
- });
17
+ Object.assign(this.data, data);
20
18
 
21
19
  this.data.headers = this.data.headers || {};
22
20
 
@@ -47,7 +45,7 @@ class MailMessage {
47
45
  }
48
46
 
49
47
  resolveAll(callback) {
50
- let keys = [
48
+ const keys = [
51
49
  [this.data, 'html'],
52
50
  [this.data, 'text'],
53
51
  [this.data, 'watchHtml'],
@@ -79,9 +77,9 @@ class MailMessage {
79
77
  });
80
78
  }
81
79
 
82
- let mimeNode = new MimeNode();
80
+ const mimeNode = new MimeNode();
83
81
 
84
- let addressKeys = ['from', 'to', 'cc', 'bcc', 'sender', 'replyTo'];
82
+ const addressKeys = ['from', 'to', 'cc', 'bcc', 'sender', 'replyTo'];
85
83
 
86
84
  addressKeys.forEach(address => {
87
85
  let value;
@@ -97,7 +95,7 @@ class MailMessage {
97
95
  }
98
96
  });
99
97
 
100
- let singleKeys = ['from', 'sender'];
98
+ const singleKeys = ['from', 'sender'];
101
99
  singleKeys.forEach(address => {
102
100
  if (this.data[address]) {
103
101
  this.data[address] = this.data[address].shift();
@@ -105,11 +103,11 @@ class MailMessage {
105
103
  });
106
104
 
107
105
  let pos = 0;
108
- let resolveNext = () => {
106
+ const resolveNext = () => {
109
107
  if (pos >= keys.length) {
110
108
  return callback(null, this.data);
111
109
  }
112
- let args = keys[pos++];
110
+ const args = keys[pos++];
113
111
  if (!args[0] || !args[0][args[1]]) {
114
112
  return resolveNext();
115
113
  }
@@ -118,7 +116,7 @@ class MailMessage {
118
116
  return callback(err);
119
117
  }
120
118
 
121
- let node = {
119
+ const node = {
122
120
  content: value
123
121
  };
124
122
  if (args[0][args[1]] && typeof args[0][args[1]] === 'object' && !Buffer.isBuffer(args[0][args[1]])) {
@@ -138,8 +136,8 @@ class MailMessage {
138
136
  }
139
137
 
140
138
  normalize(callback) {
141
- let envelope = this.data.envelope || this.message.getEnvelope();
142
- let messageId = this.message.messageId();
139
+ const envelope = this.data.envelope || this.message.getEnvelope();
140
+ const messageId = this.message.messageId();
143
141
 
144
142
  this.resolveAll((err, data) => {
145
143
  if (err) {
@@ -195,7 +193,7 @@ class MailMessage {
195
193
  });
196
194
 
197
195
  if (data.list && typeof data.list === 'object') {
198
- let listHeaders = this._getListHeaders(data.list);
196
+ const listHeaders = this._getListHeaders(data.list);
199
197
  listHeaders.forEach(entry => {
200
198
  data.normalizedHeaders[entry.key] = entry.value.map(val => (val && val.value) || val).join(', ');
201
199
  });
@@ -245,13 +243,11 @@ class MailMessage {
245
243
  return;
246
244
  }
247
245
  // add optional List-* headers
248
- if (this.data.list && typeof this.data.list === 'object') {
249
- this._getListHeaders(this.data.list).forEach(listHeader => {
250
- listHeader.value.forEach(value => {
251
- this.message.addHeader(listHeader.key, value);
252
- });
246
+ this._getListHeaders(this.data.list).forEach(listHeader => {
247
+ listHeader.value.forEach(value => {
248
+ this.message.addHeader(listHeader.key, value);
253
249
  });
254
- }
250
+ });
255
251
  }
256
252
 
257
253
  _getListHeaders(listData) {
@@ -15,11 +15,7 @@ module.exports = {
15
15
  */
16
16
  isPlainText(value, isParam) {
17
17
  const re = isParam ? /[\x00-\x08\x0b\x0c\x0e-\x1f"\u0080-\uFFFF]/ : /[\x00-\x08\x0b\x0c\x0e-\x1f\u0080-\uFFFF]/;
18
- if (typeof value !== 'string' || re.test(value)) {
19
- return false;
20
- } else {
21
- return true;
22
- }
18
+ return typeof value === 'string' && !re.test(value);
23
19
  },
24
20
 
25
21
  /**
@@ -54,7 +50,7 @@ module.exports = {
54
50
  maxLength = maxLength || 0;
55
51
 
56
52
  let encodedStr;
57
- let toCharset = 'UTF-8';
53
+ const toCharset = 'UTF-8';
58
54
 
59
55
  if (maxLength && maxLength > 7 + toCharset.length) {
60
56
  maxLength -= 7 + toCharset.length;
@@ -63,12 +59,11 @@ module.exports = {
63
59
  if (mimeWordEncoding === 'Q') {
64
60
  // https://tools.ietf.org/html/rfc2047#section-5 rule (3)
65
61
  encodedStr = qp.encode(data).replace(/[^a-z0-9!*+\-/=]/gi, chr => {
66
- let ord = chr.charCodeAt(0).toString(16).toUpperCase();
62
+ const ord = chr.charCodeAt(0).toString(16).toUpperCase();
67
63
  if (chr === ' ') {
68
64
  return '_';
69
- } else {
70
- return '=' + (ord.length === 1 ? '0' + ord : ord);
71
65
  }
66
+ return '=' + (ord.length === 1 ? '0' + ord : ord);
72
67
  });
73
68
  } else if (mimeWordEncoding === 'B') {
74
69
  encodedStr = typeof data === 'string' ? data : base64.encode(data);
@@ -80,7 +75,7 @@ module.exports = {
80
75
  encodedStr = this.splitMimeEncodedString(encodedStr, maxLength).join('?= =?' + toCharset + '?' + mimeWordEncoding + '?');
81
76
  } else {
82
77
  // RFC2047 6.3 (2) states that encoded-word must include an integral number of characters, so no chopping unicode sequences
83
- let parts = [];
78
+ const parts = [];
84
79
  let lpart = '';
85
80
  for (let i = 0, len = encodedStr.length; i < len; i++) {
86
81
  let chr = encodedStr.charAt(i);
@@ -129,42 +124,38 @@ module.exports = {
129
124
  encodeWords(value, mimeWordEncoding, maxLength, encodeAll) {
130
125
  maxLength = maxLength || 0;
131
126
 
132
- let encodedValue;
133
-
134
127
  // find first word with a non-printable ascii or special symbol in it
135
- let firstMatch = value.match(/(?:^|\s)([^\s]*["\u0080-\uFFFF])/);
128
+ const firstMatch = value.match(/(?:^|\s)([^\s]*["\u0080-\uFFFF])/);
136
129
  if (!firstMatch) {
137
130
  return value;
138
131
  }
139
132
 
140
133
  if (encodeAll) {
141
134
  // if it is requested to encode everything or the string contains something that resebles encoded word, then encode everything
142
-
143
135
  return this.encodeWord(value, mimeWordEncoding, maxLength);
144
136
  }
145
137
 
146
138
  // find the last word with a non-printable ascii in it
147
- let lastMatch = value.match(/(["\u0080-\uFFFF][^\s]*)[^"\u0080-\uFFFF]*$/);
139
+ const lastMatch = value.match(/(["\u0080-\uFFFF][^\s]*)[^"\u0080-\uFFFF]*$/);
148
140
  if (!lastMatch) {
149
141
  // should not happen
150
142
  return value;
151
143
  }
152
144
 
153
- let startIndex =
145
+ const startIndex =
154
146
  firstMatch.index +
155
147
  (
156
148
  firstMatch[0].match(/[^\s]/) || {
157
149
  index: 0
158
150
  }
159
151
  ).index;
160
- let endIndex = lastMatch.index + (lastMatch[1] || '').length;
152
+ const endIndex = lastMatch.index + (lastMatch[1] || '').length;
161
153
 
162
- encodedValue =
154
+ return (
163
155
  (startIndex ? value.substr(0, startIndex) : '') +
164
156
  this.encodeWord(value.substring(startIndex, endIndex), mimeWordEncoding || 'Q', maxLength) +
165
- (endIndex < value.length ? value.substr(endIndex) : '');
166
-
167
- return encodedValue;
157
+ (endIndex < value.length ? value.substr(endIndex) : '')
158
+ );
168
159
  },
169
160
 
170
161
  /**
@@ -175,12 +166,12 @@ module.exports = {
175
166
  * @return {String} joined header value
176
167
  */
177
168
  buildHeaderValue(structured) {
178
- let paramsArray = [];
169
+ const paramsArray = [];
179
170
 
180
171
  Object.keys(structured.params || {}).forEach(param => {
181
172
  // filename might include unicode characters so it is a special case
182
173
  // other values probably do not
183
- let value = structured.params[param];
174
+ const value = structured.params[param];
184
175
  if (!this.isPlainText(value, true) || value.length >= 75) {
185
176
  this.buildHeaderParam(param, value, 50).forEach(encodedParam => {
186
177
  if (!/[\s"\\;:/=(),<>@[\]?]|^[-']|'$/.test(encodedParam.value) || encodedParam.key.substr(-1) === '*') {
@@ -215,9 +206,8 @@ module.exports = {
215
206
  * @return {Array} A list of encoded keys and headers
216
207
  */
217
208
  buildHeaderParam(key, data, maxLength) {
218
- let list = [];
209
+ const list = [];
219
210
  let encodedStr = typeof data === 'string' ? data : (data || '').toString();
220
- let encodedStrArr;
221
211
  let chr, ord;
222
212
  let line;
223
213
  let startPos = 0;
@@ -252,7 +242,7 @@ module.exports = {
252
242
  } else {
253
243
  if (/[\uD800-\uDBFF]/.test(encodedStr)) {
254
244
  // string containts surrogate pairs, so normalize it to an array of bytes
255
- encodedStrArr = [];
245
+ const encodedStrArr = [];
256
246
  for (i = 0, len = encodedStr.length; i < len; i++) {
257
247
  chr = encodedStr.charAt(i);
258
248
  ord = chr.charCodeAt(0);
@@ -356,7 +346,7 @@ module.exports = {
356
346
  * @return {Object} Header value as a parsed structure
357
347
  */
358
348
  parseHeaderValue(str) {
359
- let response = {
349
+ const response = {
360
350
  value: false,
361
351
  params: {}
362
352
  };
@@ -458,12 +448,11 @@ module.exports = {
458
448
  value
459
449
  // fix invalidly encoded chars
460
450
  .replace(/[=?_\s]/g, s => {
461
- let c = s.charCodeAt(0).toString(16);
451
+ const c = s.charCodeAt(0).toString(16);
462
452
  if (s === ' ') {
463
453
  return '_';
464
- } else {
465
- return '%' + (c.length < 2 ? '0' : '') + c;
466
454
  }
455
+ return '%' + (c.length < 2 ? '0' : '') + c;
467
456
  })
468
457
  // change from urlencoding to percent encoding
469
458
  .replace(/%/g, '=') +
@@ -508,11 +497,10 @@ module.exports = {
508
497
  str = (str || '').toString();
509
498
  lineLength = lineLength || 76;
510
499
 
511
- let pos = 0,
512
- len = str.length,
513
- result = '',
514
- line,
515
- match;
500
+ let pos = 0;
501
+ const len = str.length;
502
+ let result = '';
503
+ let line, match;
516
504
 
517
505
  while (pos < len) {
518
506
  line = str.substr(pos, lineLength);
@@ -549,11 +537,8 @@ module.exports = {
549
537
  * @return {Array} Split string
550
538
  */
551
539
  splitMimeEncodedString: (str, maxlen) => {
552
- let curLine,
553
- match,
554
- chr,
555
- done,
556
- lines = [];
540
+ const lines = [];
541
+ let curLine, match, chr, done;
557
542
 
558
543
  // require at least 12 symbols to fit possible 4 octet UTF-8 sequences
559
544
  maxlen = Math.max(maxlen || 0, 12);
@@ -2073,13 +2073,9 @@ module.exports = {
2073
2073
  return defaultMimeType;
2074
2074
  }
2075
2075
 
2076
- let parsed = path.parse(filename);
2077
- let extension = (parsed.ext.substr(1) || parsed.name || '').split('?').shift().trim().toLowerCase();
2078
- let value = defaultMimeType;
2079
-
2080
- if (extensions.has(extension)) {
2081
- value = extensions.get(extension);
2082
- }
2076
+ const parsed = path.parse(filename);
2077
+ const extension = (parsed.ext.substr(1) || parsed.name || '').split('?').shift().trim().toLowerCase();
2078
+ const value = extensions.has(extension) ? extensions.get(extension) : defaultMimeType;
2083
2079
 
2084
2080
  if (Array.isArray(value)) {
2085
2081
  return value[0];
@@ -2091,12 +2087,12 @@ module.exports = {
2091
2087
  if (!mimeType) {
2092
2088
  return defaultExtension;
2093
2089
  }
2094
- let parts = (mimeType || '').toLowerCase().trim().split('/');
2095
- let rootType = parts.shift().trim();
2096
- let subType = parts.join('/').trim();
2090
+ const parts = (mimeType || '').toLowerCase().trim().split('/');
2091
+ const rootType = parts.shift().trim();
2092
+ const subType = parts.join('/').trim();
2097
2093
 
2098
2094
  if (mimeTypes.has(rootType + '/' + subType)) {
2099
- let value = mimeTypes.get(rootType + '/' + subType);
2095
+ const value = mimeTypes.get(rootType + '/' + subType);
2100
2096
  if (Array.isArray(value)) {
2101
2097
  return value[0];
2102
2098
  }