mikromail 0.0.1 → 0.0.3

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/LICENSE ADDED
@@ -0,0 +1,7 @@
1
+ Copyright 2025-present Mikael Vesavuori
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
4
+
5
+ The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
6
+
7
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
package/README.md CHANGED
@@ -6,9 +6,11 @@
6
6
 
7
7
  ---
8
8
 
9
- - Tiny (~X.X KB gzipped)
9
+ - Supports international symbols
10
+ - Supports HTML emails
11
+ - Defaults to secure transmission
12
+ - Tiny (~4.4 KB gzipped), which is ~13x smaller than Nodemailer
10
13
  - Zero dependencies
11
- - High test coverage
12
14
 
13
15
  ## Usage
14
16
 
@@ -1,39 +1,38 @@
1
1
  import { ConfigurationOptions, SMTPConfiguration } from './interfaces/index.mjs';
2
2
 
3
3
  /**
4
- * @description Configuration class that handles both CLI arguments and config file settings
4
+ * @description Configuration class that handles both CLI arguments and config file settings.
5
5
  */
6
6
  declare class Configuration {
7
7
  private readonly config;
8
8
  private readonly defaults;
9
9
  /**
10
- * @description Creates a new Configuration instance
11
- * @param configFilePath Path to the configuration file (e.g., 'mikromail.config.json')
12
- * @param args Command line arguments array from process.argv
10
+ * @description Creates a new Configuration instance.
13
11
  */
14
12
  constructor(options?: ConfigurationOptions);
15
13
  /**
16
14
  * @description Creates a configuration object by merging defaults, config file settings,
17
15
  * and CLI arguments (in order of increasing precedence)
18
- * @param configFilePath Path to the configuration file
19
- * @param args Command line arguments array
20
- * @returns The merged configuration object
16
+ * @param configFilePath Path to the configuration file.
17
+ * @param args Command line arguments array.
18
+ * @param configuration User-provided configuration input.
19
+ * @returns The merged configuration object.
21
20
  */
22
21
  private create;
23
22
  /**
24
- * @description Parses command line arguments into a configuration object
25
- * @param args Command line arguments array
26
- * @returns Parsed CLI configuration
23
+ * @description Parses command line arguments into a configuration object.
24
+ * @param args Command line arguments array.
25
+ * @returns Parsed CLI configuration.
27
26
  */
28
27
  private parseCliArgs;
29
28
  /**
30
- * @description Validates the configuration
31
- * @throws Error if the configuration is invalid
29
+ * @description Validates the configuration.
30
+ * @throws Error if the configuration is invalid.
32
31
  */
33
32
  private validate;
34
33
  /**
35
- * @description Returns the complete configuration
36
- * @returns The configuration object
34
+ * @description Returns the complete configuration.
35
+ * @returns The configuration object.
37
36
  */
38
37
  get(): SMTPConfiguration;
39
38
  }
@@ -1,39 +1,38 @@
1
1
  import { ConfigurationOptions, SMTPConfiguration } from './interfaces/index.js';
2
2
 
3
3
  /**
4
- * @description Configuration class that handles both CLI arguments and config file settings
4
+ * @description Configuration class that handles both CLI arguments and config file settings.
5
5
  */
6
6
  declare class Configuration {
7
7
  private readonly config;
8
8
  private readonly defaults;
9
9
  /**
10
- * @description Creates a new Configuration instance
11
- * @param configFilePath Path to the configuration file (e.g., 'mikromail.config.json')
12
- * @param args Command line arguments array from process.argv
10
+ * @description Creates a new Configuration instance.
13
11
  */
14
12
  constructor(options?: ConfigurationOptions);
15
13
  /**
16
14
  * @description Creates a configuration object by merging defaults, config file settings,
17
15
  * and CLI arguments (in order of increasing precedence)
18
- * @param configFilePath Path to the configuration file
19
- * @param args Command line arguments array
20
- * @returns The merged configuration object
16
+ * @param configFilePath Path to the configuration file.
17
+ * @param args Command line arguments array.
18
+ * @param configuration User-provided configuration input.
19
+ * @returns The merged configuration object.
21
20
  */
22
21
  private create;
23
22
  /**
24
- * @description Parses command line arguments into a configuration object
25
- * @param args Command line arguments array
26
- * @returns Parsed CLI configuration
23
+ * @description Parses command line arguments into a configuration object.
24
+ * @param args Command line arguments array.
25
+ * @returns Parsed CLI configuration.
27
26
  */
28
27
  private parseCliArgs;
29
28
  /**
30
- * @description Validates the configuration
31
- * @throws Error if the configuration is invalid
29
+ * @description Validates the configuration.
30
+ * @throws Error if the configuration is invalid.
32
31
  */
33
32
  private validate;
34
33
  /**
35
- * @description Returns the complete configuration
36
- * @returns The configuration object
34
+ * @description Returns the complete configuration.
35
+ * @returns The configuration object.
37
36
  */
38
37
  get(): SMTPConfiguration;
39
38
  }
@@ -43,9 +43,7 @@ var Configuration = class {
43
43
  args: []
44
44
  };
45
45
  /**
46
- * @description Creates a new Configuration instance
47
- * @param configFilePath Path to the configuration file (e.g., 'mikromail.config.json')
48
- * @param args Command line arguments array from process.argv
46
+ * @description Creates a new Configuration instance.
49
47
  */
50
48
  constructor(options) {
51
49
  const configuration = options?.config || {};
@@ -56,9 +54,10 @@ var Configuration = class {
56
54
  /**
57
55
  * @description Creates a configuration object by merging defaults, config file settings,
58
56
  * and CLI arguments (in order of increasing precedence)
59
- * @param configFilePath Path to the configuration file
60
- * @param args Command line arguments array
61
- * @returns The merged configuration object
57
+ * @param configFilePath Path to the configuration file.
58
+ * @param args Command line arguments array.
59
+ * @param configuration User-provided configuration input.
60
+ * @returns The merged configuration object.
62
61
  */
63
62
  create(configFilePath, args, configuration) {
64
63
  const defaults = {
@@ -91,9 +90,9 @@ var Configuration = class {
91
90
  };
92
91
  }
93
92
  /**
94
- * @description Parses command line arguments into a configuration object
95
- * @param args Command line arguments array
96
- * @returns Parsed CLI configuration
93
+ * @description Parses command line arguments into a configuration object.
94
+ * @param args Command line arguments array.
95
+ * @returns Parsed CLI configuration.
97
96
  */
98
97
  parseCliArgs(args) {
99
98
  const cliConfig = {};
@@ -132,15 +131,15 @@ var Configuration = class {
132
131
  return cliConfig;
133
132
  }
134
133
  /**
135
- * @description Validates the configuration
136
- * @throws Error if the configuration is invalid
134
+ * @description Validates the configuration.
135
+ * @throws Error if the configuration is invalid.
137
136
  */
138
137
  validate() {
139
138
  if (!this.config.host) throw new ValidationError("Host value not found");
140
139
  }
141
140
  /**
142
- * @description Returns the complete configuration
143
- * @returns The configuration object
141
+ * @description Returns the complete configuration.
142
+ * @returns The configuration object.
144
143
  */
145
144
  get() {
146
145
  this.validate();
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  Configuration
3
- } from "./chunk-V2NYOKWA.mjs";
3
+ } from "./chunk-YVXB6HCK.mjs";
4
4
  import "./chunk-47VXJTWV.mjs";
5
5
  export {
6
6
  Configuration
package/lib/MikroMail.js CHANGED
@@ -55,9 +55,7 @@ var Configuration = class {
55
55
  args: []
56
56
  };
57
57
  /**
58
- * @description Creates a new Configuration instance
59
- * @param configFilePath Path to the configuration file (e.g., 'mikromail.config.json')
60
- * @param args Command line arguments array from process.argv
58
+ * @description Creates a new Configuration instance.
61
59
  */
62
60
  constructor(options) {
63
61
  const configuration = options?.config || {};
@@ -68,9 +66,10 @@ var Configuration = class {
68
66
  /**
69
67
  * @description Creates a configuration object by merging defaults, config file settings,
70
68
  * and CLI arguments (in order of increasing precedence)
71
- * @param configFilePath Path to the configuration file
72
- * @param args Command line arguments array
73
- * @returns The merged configuration object
69
+ * @param configFilePath Path to the configuration file.
70
+ * @param args Command line arguments array.
71
+ * @param configuration User-provided configuration input.
72
+ * @returns The merged configuration object.
74
73
  */
75
74
  create(configFilePath, args, configuration) {
76
75
  const defaults = {
@@ -103,9 +102,9 @@ var Configuration = class {
103
102
  };
104
103
  }
105
104
  /**
106
- * @description Parses command line arguments into a configuration object
107
- * @param args Command line arguments array
108
- * @returns Parsed CLI configuration
105
+ * @description Parses command line arguments into a configuration object.
106
+ * @param args Command line arguments array.
107
+ * @returns Parsed CLI configuration.
109
108
  */
110
109
  parseCliArgs(args) {
111
110
  const cliConfig = {};
@@ -144,15 +143,15 @@ var Configuration = class {
144
143
  return cliConfig;
145
144
  }
146
145
  /**
147
- * @description Validates the configuration
148
- * @throws Error if the configuration is invalid
146
+ * @description Validates the configuration.
147
+ * @throws Error if the configuration is invalid.
149
148
  */
150
149
  validate() {
151
150
  if (!this.config.host) throw new ValidationError("Host value not found");
152
151
  }
153
152
  /**
154
- * @description Returns the complete configuration
155
- * @returns The configuration object
153
+ * @description Returns the complete configuration.
154
+ * @returns The configuration object.
156
155
  */
157
156
  get() {
158
157
  this.validate();
@@ -253,6 +252,8 @@ var SMTPClient = class {
253
252
  serverCapabilities;
254
253
  secureMode;
255
254
  retryCount;
255
+ maxEmailSize = 10485760;
256
+ // 10MB
256
257
  constructor(config) {
257
258
  this.config = {
258
259
  host: config.host,
@@ -564,7 +565,7 @@ var SMTPClient = class {
564
565
  * Sanitize and encode header value to prevent injection and handle internationalization
565
566
  */
566
567
  sanitizeHeader(value) {
567
- const sanitized = value.replace(/[\r\n]+/g, " ");
568
+ const sanitized = value.replace(/[\r\n\t]+/g, " ").replace(/\s{2,}/g, " ").trim();
568
569
  return this.encodeHeaderValue(sanitized);
569
570
  }
570
571
  /**
@@ -581,7 +582,8 @@ var SMTPClient = class {
581
582
  `Subject: ${this.sanitizeHeader(options.subject)}`,
582
583
  `Message-ID: ${messageId}`,
583
584
  `Date: ${date}`,
584
- "MIME-Version: 1.0"
585
+ "MIME-Version: 1.0",
586
+ "Content-Transfer-Encoding: quoted-printable"
585
587
  ];
586
588
  if (options.cc) {
587
589
  const cc = Array.isArray(options.cc) ? options.cc.join(", ") : options.cc;
@@ -629,16 +631,14 @@ ${encodeQuotedPrintable(html || "")}\r
629
631
  }
630
632
  if (html) {
631
633
  headers.push("Content-Type: text/html; charset=utf-8");
632
- headers.push("Content-Transfer-Encoding: quoted-printable");
633
634
  return `${headers.join("\r\n")}\r
634
635
  \r
635
- ${encodeQuotedPrintable(html)}`;
636
+ ${html}`;
636
637
  }
637
638
  headers.push("Content-Type: text/plain; charset=utf-8");
638
- headers.push("Content-Transfer-Encoding: quoted-printable");
639
639
  return `${headers.join("\r\n")}\r
640
640
  \r
641
- ${encodeQuotedPrintable(text || "")}`;
641
+ ${text || ""}`;
642
642
  }
643
643
  /**
644
644
  * Perform full SMTP handshake, including STARTTLS if needed
@@ -718,6 +718,12 @@ ${encodeQuotedPrintable(text || "")}`;
718
718
  }
719
719
  await this.sendCommand("DATA", 354);
720
720
  const emailContent = this.createMultipartEmail(options);
721
+ if (emailContent.length > this.maxEmailSize) {
722
+ return {
723
+ success: false,
724
+ error: "Email size exceeds maximum allowed"
725
+ };
726
+ }
721
727
  await this.sendCommand(`${emailContent}\r
722
728
  .`, 250);
723
729
  const messageIdMatch = /Message-ID: (.*)/i.exec(emailContent);
@@ -765,7 +771,8 @@ ${encodeQuotedPrintable(text || "")}`;
765
771
  this.log(`Error during QUIT: ${e.message}`, true);
766
772
  } finally {
767
773
  if (this.socket) {
768
- this.socket.end();
774
+ this.socket.destroy();
775
+ this.socket = null;
769
776
  this.connected = false;
770
777
  }
771
778
  }
package/lib/MikroMail.mjs CHANGED
@@ -1,8 +1,8 @@
1
1
  import {
2
2
  MikroMail
3
- } from "./chunk-XNGASLEZ.mjs";
4
- import "./chunk-V2NYOKWA.mjs";
5
- import "./chunk-TCYL3UFZ.mjs";
3
+ } from "./chunk-6FVSAIJD.mjs";
4
+ import "./chunk-YVXB6HCK.mjs";
5
+ import "./chunk-LKO73BCK.mjs";
6
6
  import "./chunk-47VXJTWV.mjs";
7
7
  import "./chunk-UDLJWUFN.mjs";
8
8
  export {
@@ -12,6 +12,7 @@ declare class SMTPClient {
12
12
  private serverCapabilities;
13
13
  private secureMode;
14
14
  private retryCount;
15
+ private readonly maxEmailSize;
15
16
  constructor(config: SMTPConfiguration);
16
17
  /**
17
18
  * Log debug messages if debug mode is enabled
@@ -12,6 +12,7 @@ declare class SMTPClient {
12
12
  private serverCapabilities;
13
13
  private secureMode;
14
14
  private retryCount;
15
+ private readonly maxEmailSize;
15
16
  constructor(config: SMTPConfiguration);
16
17
  /**
17
18
  * Log debug messages if debug mode is enabled
package/lib/SMTPClient.js CHANGED
@@ -108,6 +108,8 @@ var SMTPClient = class {
108
108
  serverCapabilities;
109
109
  secureMode;
110
110
  retryCount;
111
+ maxEmailSize = 10485760;
112
+ // 10MB
111
113
  constructor(config) {
112
114
  this.config = {
113
115
  host: config.host,
@@ -419,7 +421,7 @@ var SMTPClient = class {
419
421
  * Sanitize and encode header value to prevent injection and handle internationalization
420
422
  */
421
423
  sanitizeHeader(value) {
422
- const sanitized = value.replace(/[\r\n]+/g, " ");
424
+ const sanitized = value.replace(/[\r\n\t]+/g, " ").replace(/\s{2,}/g, " ").trim();
423
425
  return this.encodeHeaderValue(sanitized);
424
426
  }
425
427
  /**
@@ -436,7 +438,8 @@ var SMTPClient = class {
436
438
  `Subject: ${this.sanitizeHeader(options.subject)}`,
437
439
  `Message-ID: ${messageId}`,
438
440
  `Date: ${date}`,
439
- "MIME-Version: 1.0"
441
+ "MIME-Version: 1.0",
442
+ "Content-Transfer-Encoding: quoted-printable"
440
443
  ];
441
444
  if (options.cc) {
442
445
  const cc = Array.isArray(options.cc) ? options.cc.join(", ") : options.cc;
@@ -484,16 +487,14 @@ ${encodeQuotedPrintable(html || "")}\r
484
487
  }
485
488
  if (html) {
486
489
  headers.push("Content-Type: text/html; charset=utf-8");
487
- headers.push("Content-Transfer-Encoding: quoted-printable");
488
490
  return `${headers.join("\r\n")}\r
489
491
  \r
490
- ${encodeQuotedPrintable(html)}`;
492
+ ${html}`;
491
493
  }
492
494
  headers.push("Content-Type: text/plain; charset=utf-8");
493
- headers.push("Content-Transfer-Encoding: quoted-printable");
494
495
  return `${headers.join("\r\n")}\r
495
496
  \r
496
- ${encodeQuotedPrintable(text || "")}`;
497
+ ${text || ""}`;
497
498
  }
498
499
  /**
499
500
  * Perform full SMTP handshake, including STARTTLS if needed
@@ -573,6 +574,12 @@ ${encodeQuotedPrintable(text || "")}`;
573
574
  }
574
575
  await this.sendCommand("DATA", 354);
575
576
  const emailContent = this.createMultipartEmail(options);
577
+ if (emailContent.length > this.maxEmailSize) {
578
+ return {
579
+ success: false,
580
+ error: "Email size exceeds maximum allowed"
581
+ };
582
+ }
576
583
  await this.sendCommand(`${emailContent}\r
577
584
  .`, 250);
578
585
  const messageIdMatch = /Message-ID: (.*)/i.exec(emailContent);
@@ -620,7 +627,8 @@ ${encodeQuotedPrintable(text || "")}`;
620
627
  this.log(`Error during QUIT: ${e.message}`, true);
621
628
  } finally {
622
629
  if (this.socket) {
623
- this.socket.end();
630
+ this.socket.destroy();
631
+ this.socket = null;
624
632
  this.connected = false;
625
633
  }
626
634
  }
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  SMTPClient
3
- } from "./chunk-TCYL3UFZ.mjs";
3
+ } from "./chunk-LKO73BCK.mjs";
4
4
  import "./chunk-UDLJWUFN.mjs";
5
5
  export {
6
6
  SMTPClient
@@ -1,9 +1,9 @@
1
1
  import {
2
2
  Configuration
3
- } from "./chunk-V2NYOKWA.mjs";
3
+ } from "./chunk-YVXB6HCK.mjs";
4
4
  import {
5
5
  SMTPClient
6
- } from "./chunk-TCYL3UFZ.mjs";
6
+ } from "./chunk-LKO73BCK.mjs";
7
7
  import {
8
8
  verifyEmailDomain
9
9
  } from "./chunk-UDLJWUFN.mjs";
@@ -17,6 +17,8 @@ var SMTPClient = class {
17
17
  serverCapabilities;
18
18
  secureMode;
19
19
  retryCount;
20
+ maxEmailSize = 10485760;
21
+ // 10MB
20
22
  constructor(config) {
21
23
  this.config = {
22
24
  host: config.host,
@@ -328,7 +330,7 @@ var SMTPClient = class {
328
330
  * Sanitize and encode header value to prevent injection and handle internationalization
329
331
  */
330
332
  sanitizeHeader(value) {
331
- const sanitized = value.replace(/[\r\n]+/g, " ");
333
+ const sanitized = value.replace(/[\r\n\t]+/g, " ").replace(/\s{2,}/g, " ").trim();
332
334
  return this.encodeHeaderValue(sanitized);
333
335
  }
334
336
  /**
@@ -345,7 +347,8 @@ var SMTPClient = class {
345
347
  `Subject: ${this.sanitizeHeader(options.subject)}`,
346
348
  `Message-ID: ${messageId}`,
347
349
  `Date: ${date}`,
348
- "MIME-Version: 1.0"
350
+ "MIME-Version: 1.0",
351
+ "Content-Transfer-Encoding: quoted-printable"
349
352
  ];
350
353
  if (options.cc) {
351
354
  const cc = Array.isArray(options.cc) ? options.cc.join(", ") : options.cc;
@@ -393,16 +396,14 @@ ${encodeQuotedPrintable(html || "")}\r
393
396
  }
394
397
  if (html) {
395
398
  headers.push("Content-Type: text/html; charset=utf-8");
396
- headers.push("Content-Transfer-Encoding: quoted-printable");
397
399
  return `${headers.join("\r\n")}\r
398
400
  \r
399
- ${encodeQuotedPrintable(html)}`;
401
+ ${html}`;
400
402
  }
401
403
  headers.push("Content-Type: text/plain; charset=utf-8");
402
- headers.push("Content-Transfer-Encoding: quoted-printable");
403
404
  return `${headers.join("\r\n")}\r
404
405
  \r
405
- ${encodeQuotedPrintable(text || "")}`;
406
+ ${text || ""}`;
406
407
  }
407
408
  /**
408
409
  * Perform full SMTP handshake, including STARTTLS if needed
@@ -482,6 +483,12 @@ ${encodeQuotedPrintable(text || "")}`;
482
483
  }
483
484
  await this.sendCommand("DATA", 354);
484
485
  const emailContent = this.createMultipartEmail(options);
486
+ if (emailContent.length > this.maxEmailSize) {
487
+ return {
488
+ success: false,
489
+ error: "Email size exceeds maximum allowed"
490
+ };
491
+ }
485
492
  await this.sendCommand(`${emailContent}\r
486
493
  .`, 250);
487
494
  const messageIdMatch = /Message-ID: (.*)/i.exec(emailContent);
@@ -529,7 +536,8 @@ ${encodeQuotedPrintable(text || "")}`;
529
536
  this.log(`Error during QUIT: ${e.message}`, true);
530
537
  } finally {
531
538
  if (this.socket) {
532
- this.socket.end();
539
+ this.socket.destroy();
540
+ this.socket = null;
533
541
  this.connected = false;
534
542
  }
535
543
  }
@@ -11,9 +11,7 @@ var Configuration = class {
11
11
  args: []
12
12
  };
13
13
  /**
14
- * @description Creates a new Configuration instance
15
- * @param configFilePath Path to the configuration file (e.g., 'mikromail.config.json')
16
- * @param args Command line arguments array from process.argv
14
+ * @description Creates a new Configuration instance.
17
15
  */
18
16
  constructor(options) {
19
17
  const configuration = options?.config || {};
@@ -24,9 +22,10 @@ var Configuration = class {
24
22
  /**
25
23
  * @description Creates a configuration object by merging defaults, config file settings,
26
24
  * and CLI arguments (in order of increasing precedence)
27
- * @param configFilePath Path to the configuration file
28
- * @param args Command line arguments array
29
- * @returns The merged configuration object
25
+ * @param configFilePath Path to the configuration file.
26
+ * @param args Command line arguments array.
27
+ * @param configuration User-provided configuration input.
28
+ * @returns The merged configuration object.
30
29
  */
31
30
  create(configFilePath, args, configuration) {
32
31
  const defaults = {
@@ -59,9 +58,9 @@ var Configuration = class {
59
58
  };
60
59
  }
61
60
  /**
62
- * @description Parses command line arguments into a configuration object
63
- * @param args Command line arguments array
64
- * @returns Parsed CLI configuration
61
+ * @description Parses command line arguments into a configuration object.
62
+ * @param args Command line arguments array.
63
+ * @returns Parsed CLI configuration.
65
64
  */
66
65
  parseCliArgs(args) {
67
66
  const cliConfig = {};
@@ -100,15 +99,15 @@ var Configuration = class {
100
99
  return cliConfig;
101
100
  }
102
101
  /**
103
- * @description Validates the configuration
104
- * @throws Error if the configuration is invalid
102
+ * @description Validates the configuration.
103
+ * @throws Error if the configuration is invalid.
105
104
  */
106
105
  validate() {
107
106
  if (!this.config.host) throw new ValidationError("Host value not found");
108
107
  }
109
108
  /**
110
- * @description Returns the complete configuration
111
- * @returns The configuration object
109
+ * @description Returns the complete configuration.
110
+ * @returns The configuration object.
112
111
  */
113
112
  get() {
114
113
  this.validate();
package/lib/index.js CHANGED
@@ -55,9 +55,7 @@ var Configuration = class {
55
55
  args: []
56
56
  };
57
57
  /**
58
- * @description Creates a new Configuration instance
59
- * @param configFilePath Path to the configuration file (e.g., 'mikromail.config.json')
60
- * @param args Command line arguments array from process.argv
58
+ * @description Creates a new Configuration instance.
61
59
  */
62
60
  constructor(options) {
63
61
  const configuration = options?.config || {};
@@ -68,9 +66,10 @@ var Configuration = class {
68
66
  /**
69
67
  * @description Creates a configuration object by merging defaults, config file settings,
70
68
  * and CLI arguments (in order of increasing precedence)
71
- * @param configFilePath Path to the configuration file
72
- * @param args Command line arguments array
73
- * @returns The merged configuration object
69
+ * @param configFilePath Path to the configuration file.
70
+ * @param args Command line arguments array.
71
+ * @param configuration User-provided configuration input.
72
+ * @returns The merged configuration object.
74
73
  */
75
74
  create(configFilePath, args, configuration) {
76
75
  const defaults = {
@@ -103,9 +102,9 @@ var Configuration = class {
103
102
  };
104
103
  }
105
104
  /**
106
- * @description Parses command line arguments into a configuration object
107
- * @param args Command line arguments array
108
- * @returns Parsed CLI configuration
105
+ * @description Parses command line arguments into a configuration object.
106
+ * @param args Command line arguments array.
107
+ * @returns Parsed CLI configuration.
109
108
  */
110
109
  parseCliArgs(args) {
111
110
  const cliConfig = {};
@@ -144,15 +143,15 @@ var Configuration = class {
144
143
  return cliConfig;
145
144
  }
146
145
  /**
147
- * @description Validates the configuration
148
- * @throws Error if the configuration is invalid
146
+ * @description Validates the configuration.
147
+ * @throws Error if the configuration is invalid.
149
148
  */
150
149
  validate() {
151
150
  if (!this.config.host) throw new ValidationError("Host value not found");
152
151
  }
153
152
  /**
154
- * @description Returns the complete configuration
155
- * @returns The configuration object
153
+ * @description Returns the complete configuration.
154
+ * @returns The configuration object.
156
155
  */
157
156
  get() {
158
157
  this.validate();
@@ -253,6 +252,8 @@ var SMTPClient = class {
253
252
  serverCapabilities;
254
253
  secureMode;
255
254
  retryCount;
255
+ maxEmailSize = 10485760;
256
+ // 10MB
256
257
  constructor(config) {
257
258
  this.config = {
258
259
  host: config.host,
@@ -564,7 +565,7 @@ var SMTPClient = class {
564
565
  * Sanitize and encode header value to prevent injection and handle internationalization
565
566
  */
566
567
  sanitizeHeader(value) {
567
- const sanitized = value.replace(/[\r\n]+/g, " ");
568
+ const sanitized = value.replace(/[\r\n\t]+/g, " ").replace(/\s{2,}/g, " ").trim();
568
569
  return this.encodeHeaderValue(sanitized);
569
570
  }
570
571
  /**
@@ -581,7 +582,8 @@ var SMTPClient = class {
581
582
  `Subject: ${this.sanitizeHeader(options.subject)}`,
582
583
  `Message-ID: ${messageId}`,
583
584
  `Date: ${date}`,
584
- "MIME-Version: 1.0"
585
+ "MIME-Version: 1.0",
586
+ "Content-Transfer-Encoding: quoted-printable"
585
587
  ];
586
588
  if (options.cc) {
587
589
  const cc = Array.isArray(options.cc) ? options.cc.join(", ") : options.cc;
@@ -629,16 +631,14 @@ ${encodeQuotedPrintable(html || "")}\r
629
631
  }
630
632
  if (html) {
631
633
  headers.push("Content-Type: text/html; charset=utf-8");
632
- headers.push("Content-Transfer-Encoding: quoted-printable");
633
634
  return `${headers.join("\r\n")}\r
634
635
  \r
635
- ${encodeQuotedPrintable(html)}`;
636
+ ${html}`;
636
637
  }
637
638
  headers.push("Content-Type: text/plain; charset=utf-8");
638
- headers.push("Content-Transfer-Encoding: quoted-printable");
639
639
  return `${headers.join("\r\n")}\r
640
640
  \r
641
- ${encodeQuotedPrintable(text || "")}`;
641
+ ${text || ""}`;
642
642
  }
643
643
  /**
644
644
  * Perform full SMTP handshake, including STARTTLS if needed
@@ -718,6 +718,12 @@ ${encodeQuotedPrintable(text || "")}`;
718
718
  }
719
719
  await this.sendCommand("DATA", 354);
720
720
  const emailContent = this.createMultipartEmail(options);
721
+ if (emailContent.length > this.maxEmailSize) {
722
+ return {
723
+ success: false,
724
+ error: "Email size exceeds maximum allowed"
725
+ };
726
+ }
721
727
  await this.sendCommand(`${emailContent}\r
722
728
  .`, 250);
723
729
  const messageIdMatch = /Message-ID: (.*)/i.exec(emailContent);
@@ -765,7 +771,8 @@ ${encodeQuotedPrintable(text || "")}`;
765
771
  this.log(`Error during QUIT: ${e.message}`, true);
766
772
  } finally {
767
773
  if (this.socket) {
768
- this.socket.end();
774
+ this.socket.destroy();
775
+ this.socket = null;
769
776
  this.connected = false;
770
777
  }
771
778
  }
package/lib/index.mjs CHANGED
@@ -1,8 +1,8 @@
1
1
  import {
2
2
  MikroMail
3
- } from "./chunk-XNGASLEZ.mjs";
4
- import "./chunk-V2NYOKWA.mjs";
5
- import "./chunk-TCYL3UFZ.mjs";
3
+ } from "./chunk-6FVSAIJD.mjs";
4
+ import "./chunk-YVXB6HCK.mjs";
5
+ import "./chunk-LKO73BCK.mjs";
6
6
  import "./chunk-47VXJTWV.mjs";
7
7
  import "./chunk-UDLJWUFN.mjs";
8
8
  export {
package/package.json CHANGED
@@ -1,15 +1,18 @@
1
1
  {
2
2
  "name": "mikromail",
3
3
  "description": "Lightweight replacement for Nodemailer, supporting HTML, international symbols, and more.",
4
- "version": "0.0.1",
4
+ "version": "0.0.3",
5
5
  "author": "Mikael Vesavuori",
6
6
  "license": "MIT",
7
- "keywords": [],
7
+ "keywords": [
8
+ "email",
9
+ "node"
10
+ ],
8
11
  "main": "lib/index.js",
9
12
  "module": "lib/index.mjs",
10
13
  "repository": {
11
14
  "type": "git",
12
- "url": "git+https://github.com/mikaelvesavuori/mikromail"
15
+ "url": "git+https://github.com/mikaelvesavuori/mikromail.git"
13
16
  },
14
17
  "bugs": {
15
18
  "url": "https://github.com/mikaelvesavuori/mikromail/issues"