nodemailer 10.0.3 → 10.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.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,16 @@
1
1
  # CHANGELOG
2
2
 
3
+ ## [10.0.4](https://github.com/nodemailer/nodemailer/compare/v10.0.3...v10.0.4) (2026-09-11)
4
+
5
+
6
+ ### Bug Fixes
7
+
8
+ * **fetch:** scope a cookie without a Path to the RFC 6265 default path ([2f907cb](https://github.com/nodemailer/nodemailer/commit/2f907cb71396860d0b2534dc72c3d252ef16339d))
9
+ * **fetch:** send cookies set with Path back to the exact path ([#1861](https://github.com/nodemailer/nodemailer/issues/1861)) ([d557113](https://github.com/nodemailer/nodemailer/commit/d5571139750de47abbac73a3b07ae90ff39a7bdd))
10
+ * **mail-composer:** keep httpHeaders and tls for href alternatives and icalEvent ([#1862](https://github.com/nodemailer/nodemailer/issues/1862)) ([7f502be](https://github.com/nodemailer/nodemailer/commit/7f502bee4a6b0386099c66c0a35d92850ec462f7))
11
+ * resolve well-known services by their primary domains ([#1859](https://github.com/nodemailer/nodemailer/issues/1859)) ([085f525](https://github.com/nodemailer/nodemailer/commit/085f525e6b292f0ca32ab1b20d4a4ee82fc40e2d))
12
+ * **ses-transport:** throw a configuration error when the SES client is missing ([#1863](https://github.com/nodemailer/nodemailer/issues/1863)) ([4d9c4c9](https://github.com/nodemailer/nodemailer/commit/4d9c4c966aaca61ff6d7649a1ac0aa0ceac6ef1e))
13
+
3
14
  ## [10.0.3](https://github.com/nodemailer/nodemailer/compare/v10.0.2...v10.0.3) (2026-09-10)
4
15
 
5
16
 
@@ -85,10 +85,12 @@ export default class Cookies {
85
85
  */
86
86
  isExpired(cookie: Cookie): boolean;
87
87
  /**
88
- * Returns normalized cookie path for an URL path argument
88
+ * Returns the default path for an URL path argument, the default-path of
89
+ * RFC 6265 section 5.1.4. A cookie that carries no Path attribute is scoped
90
+ * to the directory of the URL it was set from
89
91
  *
90
92
  * @param pathname
91
- * @returns Normalized path
93
+ * @returns Default path
92
94
  */
93
95
  getPath(pathname?: string | null): string;
94
96
  }
@@ -195,9 +195,13 @@ class Cookies {
195
195
  ('.' + urlparts.hostname).substr(-cookie.domain.length) !== cookie.domain)) {
196
196
  return false;
197
197
  }
198
- // check if path matches
199
- const path = this.getPath(urlparts.pathname);
200
- if (path.substr(0, cookie.path.length) !== cookie.path) {
198
+ // check if the request path path-matches the cookie path (RFC 6265 section 5.1.4):
199
+ // identical paths match, otherwise the cookie path must be a directory prefix
200
+ const pathname = urlparts.pathname || '/';
201
+ const cookiePath = cookie.path;
202
+ const pathMatches = pathname === cookiePath ||
203
+ (pathname.startsWith(cookiePath) && (cookiePath.endsWith('/') || pathname.charAt(cookiePath.length) === '/'));
204
+ if (!pathMatches) {
201
205
  return false;
202
206
  }
203
207
  // check secure argument
@@ -254,22 +258,21 @@ class Cookies {
254
258
  return (cookie.expires && cookie.expires < new Date()) || !cookie.value;
255
259
  }
256
260
  /**
257
- * Returns normalized cookie path for an URL path argument
261
+ * Returns the default path for an URL path argument, the default-path of
262
+ * RFC 6265 section 5.1.4. A cookie that carries no Path attribute is scoped
263
+ * to the directory of the URL it was set from
258
264
  *
259
265
  * @param pathname
260
- * @returns Normalized path
266
+ * @returns Default path
261
267
  */
262
268
  getPath(pathname) {
263
269
  const pathParts = (pathname || '/').split('/');
264
270
  pathParts.pop(); // remove filename part
265
- let path = pathParts.join('/').trim();
266
- // ensure path prefix /
271
+ const path = pathParts.join('/').trim();
272
+ // a path that holds no more than one '/' is scoped to the root path, and so
273
+ // is one that does not start with '/' at all
267
274
  if (path.charAt(0) !== '/') {
268
- path = '/' + path;
269
- }
270
- // ensure path suffix /
271
- if (path.substr(-1) !== '/') {
272
- path += '/';
275
+ return '/';
273
276
  }
274
277
  return path;
275
278
  }
@@ -253,7 +253,8 @@ class MailComposer {
253
253
  else if (icalEvent.href) {
254
254
  icalEvent.content = {
255
255
  href: icalEvent.href,
256
- httpHeaders: icalEvent.httpHeaders
256
+ httpHeaders: icalEvent.httpHeaders,
257
+ tls: icalEvent.tls
257
258
  };
258
259
  icalEvent.href = undefined;
259
260
  }
@@ -362,7 +363,9 @@ class MailComposer {
362
363
  }
363
364
  else if (alternative.href) {
364
365
  data.content = {
365
- href: alternative.href
366
+ href: alternative.href,
367
+ httpHeaders: alternative.httpHeaders,
368
+ tls: alternative.tls
366
369
  };
367
370
  }
368
371
  else {
@@ -1,3 +1,3 @@
1
1
  export declare const name = "nodemailer";
2
- export declare const version = "10.0.3";
2
+ export declare const version = "10.0.4";
3
3
  export declare const homepage = "https://nodemailer.com/";
@@ -3,5 +3,5 @@
3
3
  Object.defineProperty(exports, "__esModule", { value: true });
4
4
  exports.homepage = exports.version = exports.name = void 0;
5
5
  exports.name = 'nodemailer';
6
- exports.version = '10.0.3';
6
+ exports.version = '10.0.4';
7
7
  exports.homepage = 'https://nodemailer.com/';
@@ -62,7 +62,11 @@ function tagSesError(err) {
62
62
  class SESTransport extends node_events_1.default {
63
63
  constructor(options) {
64
64
  super();
65
- options = options || {};
65
+ if (!options || !options.SES || !options.SES.sesClient) {
66
+ const error = new Error('Missing SES configuration, expecting { sesClient, SendEmailCommand } from @aws-sdk/client-sesv2, see https://nodemailer.com/transports/ses/');
67
+ error.code = errors.ECONFIG;
68
+ throw error;
69
+ }
66
70
  this.options = options;
67
71
  this.ses = this.options.SES;
68
72
  this.name = 'SESTransport';
@@ -119,6 +119,7 @@ exports.services = {
119
119
  "FastMail": {
120
120
  "description": "FastMail",
121
121
  "domains": [
122
+ "fastmail.com",
122
123
  "fastmail.fm"
123
124
  ],
124
125
  "host": "smtp.fastmail.com",
@@ -232,6 +233,7 @@ exports.services = {
232
233
  "Mac"
233
234
  ],
234
235
  "domains": [
236
+ "icloud.com",
235
237
  "me.com",
236
238
  "mac.com"
237
239
  ],
@@ -85,10 +85,12 @@ export default class Cookies {
85
85
  */
86
86
  isExpired(cookie: Cookie): boolean;
87
87
  /**
88
- * Returns normalized cookie path for an URL path argument
88
+ * Returns the default path for an URL path argument, the default-path of
89
+ * RFC 6265 section 5.1.4. A cookie that carries no Path attribute is scoped
90
+ * to the directory of the URL it was set from
89
91
  *
90
92
  * @param pathname
91
- * @returns Normalized path
93
+ * @returns Default path
92
94
  */
93
95
  getPath(pathname?: string | null): string;
94
96
  }
@@ -157,9 +157,13 @@ export default class Cookies {
157
157
  ('.' + urlparts.hostname).substr(-cookie.domain.length) !== cookie.domain)) {
158
158
  return false;
159
159
  }
160
- // check if path matches
161
- const path = this.getPath(urlparts.pathname);
162
- if (path.substr(0, cookie.path.length) !== cookie.path) {
160
+ // check if the request path path-matches the cookie path (RFC 6265 section 5.1.4):
161
+ // identical paths match, otherwise the cookie path must be a directory prefix
162
+ const pathname = urlparts.pathname || '/';
163
+ const cookiePath = cookie.path;
164
+ const pathMatches = pathname === cookiePath ||
165
+ (pathname.startsWith(cookiePath) && (cookiePath.endsWith('/') || pathname.charAt(cookiePath.length) === '/'));
166
+ if (!pathMatches) {
163
167
  return false;
164
168
  }
165
169
  // check secure argument
@@ -216,22 +220,21 @@ export default class Cookies {
216
220
  return (cookie.expires && cookie.expires < new Date()) || !cookie.value;
217
221
  }
218
222
  /**
219
- * Returns normalized cookie path for an URL path argument
223
+ * Returns the default path for an URL path argument, the default-path of
224
+ * RFC 6265 section 5.1.4. A cookie that carries no Path attribute is scoped
225
+ * to the directory of the URL it was set from
220
226
  *
221
227
  * @param pathname
222
- * @returns Normalized path
228
+ * @returns Default path
223
229
  */
224
230
  getPath(pathname) {
225
231
  const pathParts = (pathname || '/').split('/');
226
232
  pathParts.pop(); // remove filename part
227
- let path = pathParts.join('/').trim();
228
- // ensure path prefix /
233
+ const path = pathParts.join('/').trim();
234
+ // a path that holds no more than one '/' is scoped to the root path, and so
235
+ // is one that does not start with '/' at all
229
236
  if (path.charAt(0) !== '/') {
230
- path = '/' + path;
231
- }
232
- // ensure path suffix /
233
- if (path.substr(-1) !== '/') {
234
- path += '/';
237
+ return '/';
235
238
  }
236
239
  return path;
237
240
  }
@@ -215,7 +215,8 @@ class MailComposer {
215
215
  else if (icalEvent.href) {
216
216
  icalEvent.content = {
217
217
  href: icalEvent.href,
218
- httpHeaders: icalEvent.httpHeaders
218
+ httpHeaders: icalEvent.httpHeaders,
219
+ tls: icalEvent.tls
219
220
  };
220
221
  icalEvent.href = undefined;
221
222
  }
@@ -324,7 +325,9 @@ class MailComposer {
324
325
  }
325
326
  else if (alternative.href) {
326
327
  data.content = {
327
- href: alternative.href
328
+ href: alternative.href,
329
+ httpHeaders: alternative.httpHeaders,
330
+ tls: alternative.tls
328
331
  };
329
332
  }
330
333
  else {
@@ -1,3 +1,3 @@
1
1
  export declare const name = "nodemailer";
2
- export declare const version = "10.0.3";
2
+ export declare const version = "10.0.4";
3
3
  export declare const homepage = "https://nodemailer.com/";
@@ -1,4 +1,4 @@
1
1
  // Generated by scripts/build.js from package.json. Do not edit by hand.
2
2
  export const name = 'nodemailer';
3
- export const version = '10.0.3';
3
+ export const version = '10.0.4';
4
4
  export const homepage = 'https://nodemailer.com/';
@@ -24,7 +24,11 @@ function tagSesError(err) {
24
24
  class SESTransport extends EventEmitter {
25
25
  constructor(options) {
26
26
  super();
27
- options = options || {};
27
+ if (!options || !options.SES || !options.SES.sesClient) {
28
+ const error = new Error('Missing SES configuration, expecting { sesClient, SendEmailCommand } from @aws-sdk/client-sesv2, see https://nodemailer.com/transports/ses/');
29
+ error.code = errors.ECONFIG;
30
+ throw error;
31
+ }
28
32
  this.options = options;
29
33
  this.ses = this.options.SES;
30
34
  this.name = 'SESTransport';
@@ -116,6 +116,7 @@ export const services = {
116
116
  "FastMail": {
117
117
  "description": "FastMail",
118
118
  "domains": [
119
+ "fastmail.com",
119
120
  "fastmail.fm"
120
121
  ],
121
122
  "host": "smtp.fastmail.com",
@@ -229,6 +230,7 @@ export const services = {
229
230
  "Mac"
230
231
  ],
231
232
  "domains": [
233
+ "icloud.com",
232
234
  "me.com",
233
235
  "mac.com"
234
236
  ],
@@ -107,7 +107,7 @@
107
107
 
108
108
  "FastMail": {
109
109
  "description": "FastMail",
110
- "domains": ["fastmail.fm"],
110
+ "domains": ["fastmail.com", "fastmail.fm"],
111
111
  "host": "smtp.fastmail.com",
112
112
  "port": 465,
113
113
  "secure": true
@@ -196,7 +196,7 @@
196
196
  "iCloud": {
197
197
  "description": "iCloud Mail",
198
198
  "aliases": ["Me", "Mac"],
199
- "domains": ["me.com", "mac.com"],
199
+ "domains": ["icloud.com", "me.com", "mac.com"],
200
200
  "host": "smtp.mail.me.com",
201
201
  "port": 587
202
202
  },
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "nodemailer",
3
- "version": "10.0.3",
3
+ "version": "10.0.4",
4
4
  "description": "Easy as cake e-mail sending from your Node.js applications",
5
5
  "type": "module",
6
6
  "main": "./dist/cjs/nodemailer.js",