mikromail 0.0.5 → 0.0.7
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/README.md +4 -3
- package/lib/MikroMail.js +26 -17
- package/lib/MikroMail.mjs +2 -2
- package/lib/SMTPClient.js +18 -14
- package/lib/SMTPClient.mjs +1 -1
- package/lib/{chunk-JNBOBHOL.mjs → chunk-422R3NOG.mjs} +9 -4
- package/lib/{chunk-NGYJ2CZH.mjs → chunk-NGT3KX7A.mjs} +18 -14
- package/lib/index.js +26 -17
- package/lib/index.mjs +2 -2
- package/lib/interfaces/index.d.mts +1 -1
- package/lib/interfaces/index.d.ts +1 -1
- package/package.json +3 -2
package/README.md
CHANGED
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
**Lightweight replacement for Nodemailer, supporting HTML, international symbols, and more**.
|
|
4
4
|
|
|
5
5
|

|
|
6
|
+
[](https://opensource.org/licenses/MIT)
|
|
6
7
|
|
|
7
8
|
---
|
|
8
9
|
|
|
@@ -14,7 +15,7 @@
|
|
|
14
15
|
|
|
15
16
|
## Usage
|
|
16
17
|
|
|
17
|
-
###
|
|
18
|
+
### Quick Start
|
|
18
19
|
|
|
19
20
|
```typescript
|
|
20
21
|
import { MikroMail } from 'MikroMail';
|
|
@@ -29,7 +30,7 @@ const emailOptions = {
|
|
|
29
30
|
from: 'me@mydomain.com',
|
|
30
31
|
subject: 'Test Email',
|
|
31
32
|
text: 'Hello!',
|
|
32
|
-
to: 'you@yourdomain.com'
|
|
33
|
+
to: 'you@yourdomain.com' // You can also send to multiple recipients: ['sam@acmecorp.cloud', 'sammy@acmecorp.cloud']
|
|
33
34
|
};
|
|
34
35
|
|
|
35
36
|
await new MikroMail({ config }).send(emailOptions);
|
|
@@ -98,4 +99,4 @@ Some of the tests require faking an SMTP server. Here we use [Mailpit](https://g
|
|
|
98
99
|
|
|
99
100
|
## License
|
|
100
101
|
|
|
101
|
-
MIT
|
|
102
|
+
MIT. See the `LICENSE` file.
|
package/lib/MikroMail.js
CHANGED
|
@@ -546,23 +546,21 @@ var SMTPClient = class {
|
|
|
546
546
|
const messageId = this.generateMessageId();
|
|
547
547
|
const date = (/* @__PURE__ */ new Date()).toUTCString();
|
|
548
548
|
const from = options.from || this.config.user;
|
|
549
|
-
const
|
|
549
|
+
const recipients = Array.isArray(options.to) ? options.to.join(", ") : options.to;
|
|
550
550
|
const headers = [
|
|
551
551
|
`From: ${this.sanitizeHeader(from)}`,
|
|
552
|
-
`To: ${this.sanitizeHeader(
|
|
552
|
+
`To: ${this.sanitizeHeader(recipients)}`,
|
|
553
553
|
`Subject: ${this.sanitizeHeader(options.subject)}`,
|
|
554
554
|
`Message-ID: ${messageId}`,
|
|
555
555
|
`Date: ${date}`,
|
|
556
|
-
"MIME-Version: 1.0"
|
|
557
|
-
"Content-Transfer-Encoding: quoted-printable"
|
|
556
|
+
"MIME-Version: 1.0"
|
|
558
557
|
];
|
|
559
558
|
if (options.cc) {
|
|
560
559
|
const cc = Array.isArray(options.cc) ? options.cc.join(", ") : options.cc;
|
|
561
560
|
headers.push(`Cc: ${this.sanitizeHeader(cc)}`);
|
|
562
561
|
}
|
|
563
|
-
if (options.replyTo)
|
|
562
|
+
if (options.replyTo)
|
|
564
563
|
headers.push(`Reply-To: ${this.sanitizeHeader(options.replyTo)}`);
|
|
565
|
-
}
|
|
566
564
|
if (options.headers) {
|
|
567
565
|
for (const [name, value] of Object.entries(options.headers)) {
|
|
568
566
|
if (!/^[a-zA-Z0-9-]+$/.test(name)) continue;
|
|
@@ -587,13 +585,11 @@ var SMTPClient = class {
|
|
|
587
585
|
\r
|
|
588
586
|
--${boundary}\r
|
|
589
587
|
Content-Type: text/plain; charset=utf-8\r
|
|
590
|
-
Content-Transfer-Encoding: quoted-printable\r
|
|
591
588
|
\r
|
|
592
589
|
${text || ""}\r
|
|
593
590
|
\r
|
|
594
591
|
--${boundary}\r
|
|
595
592
|
Content-Type: text/html; charset=utf-8\r
|
|
596
|
-
Content-Transfer-Encoding: quoted-printable\r
|
|
597
593
|
\r
|
|
598
594
|
${html || ""}\r
|
|
599
595
|
\r
|
|
@@ -646,12 +642,21 @@ ${text || ""}`;
|
|
|
646
642
|
error: "Missing required email parameters (from, to, subject, and either text or html)"
|
|
647
643
|
};
|
|
648
644
|
}
|
|
649
|
-
if (!validateEmail(from)
|
|
645
|
+
if (!validateEmail(from)) {
|
|
650
646
|
return {
|
|
651
647
|
success: false,
|
|
652
648
|
error: "Invalid email address format"
|
|
653
649
|
};
|
|
654
650
|
}
|
|
651
|
+
const recipients = Array.isArray(options.to) ? options.to : [options.to];
|
|
652
|
+
for (const recipient of recipients) {
|
|
653
|
+
if (!validateEmail(recipient)) {
|
|
654
|
+
return {
|
|
655
|
+
success: false,
|
|
656
|
+
error: `Invalid recipient email address format: ${recipient}`
|
|
657
|
+
};
|
|
658
|
+
}
|
|
659
|
+
}
|
|
655
660
|
for (this.retryCount = 0; this.retryCount <= this.config.maxRetries; this.retryCount++) {
|
|
656
661
|
try {
|
|
657
662
|
if (this.retryCount > 0) {
|
|
@@ -667,21 +672,20 @@ ${text || ""}`;
|
|
|
667
672
|
await this.smtpHandshake();
|
|
668
673
|
}
|
|
669
674
|
await this.sendCommand(`MAIL FROM:<${from}>`, 250);
|
|
670
|
-
|
|
675
|
+
for (const recipient of recipients)
|
|
676
|
+
await this.sendCommand(`RCPT TO:<${recipient}>`, 250);
|
|
671
677
|
if (options.cc) {
|
|
672
678
|
const ccList = Array.isArray(options.cc) ? options.cc : [options.cc];
|
|
673
679
|
for (const cc of ccList) {
|
|
674
|
-
if (validateEmail(cc))
|
|
680
|
+
if (validateEmail(cc))
|
|
675
681
|
await this.sendCommand(`RCPT TO:<${cc}>`, 250);
|
|
676
|
-
}
|
|
677
682
|
}
|
|
678
683
|
}
|
|
679
684
|
if (options.bcc) {
|
|
680
685
|
const bccList = Array.isArray(options.bcc) ? options.bcc : [options.bcc];
|
|
681
686
|
for (const bcc of bccList) {
|
|
682
|
-
if (validateEmail(bcc))
|
|
687
|
+
if (validateEmail(bcc))
|
|
683
688
|
await this.sendCommand(`RCPT TO:<${bcc}>`, 250);
|
|
684
|
-
}
|
|
685
689
|
}
|
|
686
690
|
}
|
|
687
691
|
await this.sendCommand("DATA", 354);
|
|
@@ -760,9 +764,14 @@ var MikroMail = class {
|
|
|
760
764
|
*/
|
|
761
765
|
async send(emailOptions) {
|
|
762
766
|
try {
|
|
763
|
-
const
|
|
764
|
-
|
|
765
|
-
|
|
767
|
+
const recipients = Array.isArray(emailOptions.to) ? emailOptions.to : [emailOptions.to];
|
|
768
|
+
for (const recipient of recipients) {
|
|
769
|
+
const hasMXRecords = await verifyEmailDomain(recipient);
|
|
770
|
+
if (!hasMXRecords)
|
|
771
|
+
console.error(
|
|
772
|
+
`Warning: No MX records found for recipient domain: ${recipient}`
|
|
773
|
+
);
|
|
774
|
+
}
|
|
766
775
|
const result = await this.smtpClient.sendEmail(emailOptions);
|
|
767
776
|
if (result.success) console.log(`Message ID: ${result.messageId}`);
|
|
768
777
|
else console.error(`Failed to send email: ${result.error}`);
|
package/lib/MikroMail.mjs
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import {
|
|
2
2
|
MikroMail
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-422R3NOG.mjs";
|
|
4
4
|
import "./chunk-YVXB6HCK.mjs";
|
|
5
|
-
import "./chunk-
|
|
5
|
+
import "./chunk-NGT3KX7A.mjs";
|
|
6
6
|
import "./chunk-47VXJTWV.mjs";
|
|
7
7
|
import "./chunk-UDLJWUFN.mjs";
|
|
8
8
|
export {
|
package/lib/SMTPClient.js
CHANGED
|
@@ -402,23 +402,21 @@ var SMTPClient = class {
|
|
|
402
402
|
const messageId = this.generateMessageId();
|
|
403
403
|
const date = (/* @__PURE__ */ new Date()).toUTCString();
|
|
404
404
|
const from = options.from || this.config.user;
|
|
405
|
-
const
|
|
405
|
+
const recipients = Array.isArray(options.to) ? options.to.join(", ") : options.to;
|
|
406
406
|
const headers = [
|
|
407
407
|
`From: ${this.sanitizeHeader(from)}`,
|
|
408
|
-
`To: ${this.sanitizeHeader(
|
|
408
|
+
`To: ${this.sanitizeHeader(recipients)}`,
|
|
409
409
|
`Subject: ${this.sanitizeHeader(options.subject)}`,
|
|
410
410
|
`Message-ID: ${messageId}`,
|
|
411
411
|
`Date: ${date}`,
|
|
412
|
-
"MIME-Version: 1.0"
|
|
413
|
-
"Content-Transfer-Encoding: quoted-printable"
|
|
412
|
+
"MIME-Version: 1.0"
|
|
414
413
|
];
|
|
415
414
|
if (options.cc) {
|
|
416
415
|
const cc = Array.isArray(options.cc) ? options.cc.join(", ") : options.cc;
|
|
417
416
|
headers.push(`Cc: ${this.sanitizeHeader(cc)}`);
|
|
418
417
|
}
|
|
419
|
-
if (options.replyTo)
|
|
418
|
+
if (options.replyTo)
|
|
420
419
|
headers.push(`Reply-To: ${this.sanitizeHeader(options.replyTo)}`);
|
|
421
|
-
}
|
|
422
420
|
if (options.headers) {
|
|
423
421
|
for (const [name, value] of Object.entries(options.headers)) {
|
|
424
422
|
if (!/^[a-zA-Z0-9-]+$/.test(name)) continue;
|
|
@@ -443,13 +441,11 @@ var SMTPClient = class {
|
|
|
443
441
|
\r
|
|
444
442
|
--${boundary}\r
|
|
445
443
|
Content-Type: text/plain; charset=utf-8\r
|
|
446
|
-
Content-Transfer-Encoding: quoted-printable\r
|
|
447
444
|
\r
|
|
448
445
|
${text || ""}\r
|
|
449
446
|
\r
|
|
450
447
|
--${boundary}\r
|
|
451
448
|
Content-Type: text/html; charset=utf-8\r
|
|
452
|
-
Content-Transfer-Encoding: quoted-printable\r
|
|
453
449
|
\r
|
|
454
450
|
${html || ""}\r
|
|
455
451
|
\r
|
|
@@ -502,12 +498,21 @@ ${text || ""}`;
|
|
|
502
498
|
error: "Missing required email parameters (from, to, subject, and either text or html)"
|
|
503
499
|
};
|
|
504
500
|
}
|
|
505
|
-
if (!validateEmail(from)
|
|
501
|
+
if (!validateEmail(from)) {
|
|
506
502
|
return {
|
|
507
503
|
success: false,
|
|
508
504
|
error: "Invalid email address format"
|
|
509
505
|
};
|
|
510
506
|
}
|
|
507
|
+
const recipients = Array.isArray(options.to) ? options.to : [options.to];
|
|
508
|
+
for (const recipient of recipients) {
|
|
509
|
+
if (!validateEmail(recipient)) {
|
|
510
|
+
return {
|
|
511
|
+
success: false,
|
|
512
|
+
error: `Invalid recipient email address format: ${recipient}`
|
|
513
|
+
};
|
|
514
|
+
}
|
|
515
|
+
}
|
|
511
516
|
for (this.retryCount = 0; this.retryCount <= this.config.maxRetries; this.retryCount++) {
|
|
512
517
|
try {
|
|
513
518
|
if (this.retryCount > 0) {
|
|
@@ -523,21 +528,20 @@ ${text || ""}`;
|
|
|
523
528
|
await this.smtpHandshake();
|
|
524
529
|
}
|
|
525
530
|
await this.sendCommand(`MAIL FROM:<${from}>`, 250);
|
|
526
|
-
|
|
531
|
+
for (const recipient of recipients)
|
|
532
|
+
await this.sendCommand(`RCPT TO:<${recipient}>`, 250);
|
|
527
533
|
if (options.cc) {
|
|
528
534
|
const ccList = Array.isArray(options.cc) ? options.cc : [options.cc];
|
|
529
535
|
for (const cc of ccList) {
|
|
530
|
-
if (validateEmail(cc))
|
|
536
|
+
if (validateEmail(cc))
|
|
531
537
|
await this.sendCommand(`RCPT TO:<${cc}>`, 250);
|
|
532
|
-
}
|
|
533
538
|
}
|
|
534
539
|
}
|
|
535
540
|
if (options.bcc) {
|
|
536
541
|
const bccList = Array.isArray(options.bcc) ? options.bcc : [options.bcc];
|
|
537
542
|
for (const bcc of bccList) {
|
|
538
|
-
if (validateEmail(bcc))
|
|
543
|
+
if (validateEmail(bcc))
|
|
539
544
|
await this.sendCommand(`RCPT TO:<${bcc}>`, 250);
|
|
540
|
-
}
|
|
541
545
|
}
|
|
542
546
|
}
|
|
543
547
|
await this.sendCommand("DATA", 354);
|
package/lib/SMTPClient.mjs
CHANGED
|
@@ -3,7 +3,7 @@ import {
|
|
|
3
3
|
} from "./chunk-YVXB6HCK.mjs";
|
|
4
4
|
import {
|
|
5
5
|
SMTPClient
|
|
6
|
-
} from "./chunk-
|
|
6
|
+
} from "./chunk-NGT3KX7A.mjs";
|
|
7
7
|
import {
|
|
8
8
|
verifyEmailDomain
|
|
9
9
|
} from "./chunk-UDLJWUFN.mjs";
|
|
@@ -21,9 +21,14 @@ var MikroMail = class {
|
|
|
21
21
|
*/
|
|
22
22
|
async send(emailOptions) {
|
|
23
23
|
try {
|
|
24
|
-
const
|
|
25
|
-
|
|
26
|
-
|
|
24
|
+
const recipients = Array.isArray(emailOptions.to) ? emailOptions.to : [emailOptions.to];
|
|
25
|
+
for (const recipient of recipients) {
|
|
26
|
+
const hasMXRecords = await verifyEmailDomain(recipient);
|
|
27
|
+
if (!hasMXRecords)
|
|
28
|
+
console.error(
|
|
29
|
+
`Warning: No MX records found for recipient domain: ${recipient}`
|
|
30
|
+
);
|
|
31
|
+
}
|
|
27
32
|
const result = await this.smtpClient.sendEmail(emailOptions);
|
|
28
33
|
if (result.success) console.log(`Message ID: ${result.messageId}`);
|
|
29
34
|
else console.error(`Failed to send email: ${result.error}`);
|
|
@@ -339,23 +339,21 @@ var SMTPClient = class {
|
|
|
339
339
|
const messageId = this.generateMessageId();
|
|
340
340
|
const date = (/* @__PURE__ */ new Date()).toUTCString();
|
|
341
341
|
const from = options.from || this.config.user;
|
|
342
|
-
const
|
|
342
|
+
const recipients = Array.isArray(options.to) ? options.to.join(", ") : options.to;
|
|
343
343
|
const headers = [
|
|
344
344
|
`From: ${this.sanitizeHeader(from)}`,
|
|
345
|
-
`To: ${this.sanitizeHeader(
|
|
345
|
+
`To: ${this.sanitizeHeader(recipients)}`,
|
|
346
346
|
`Subject: ${this.sanitizeHeader(options.subject)}`,
|
|
347
347
|
`Message-ID: ${messageId}`,
|
|
348
348
|
`Date: ${date}`,
|
|
349
|
-
"MIME-Version: 1.0"
|
|
350
|
-
"Content-Transfer-Encoding: quoted-printable"
|
|
349
|
+
"MIME-Version: 1.0"
|
|
351
350
|
];
|
|
352
351
|
if (options.cc) {
|
|
353
352
|
const cc = Array.isArray(options.cc) ? options.cc.join(", ") : options.cc;
|
|
354
353
|
headers.push(`Cc: ${this.sanitizeHeader(cc)}`);
|
|
355
354
|
}
|
|
356
|
-
if (options.replyTo)
|
|
355
|
+
if (options.replyTo)
|
|
357
356
|
headers.push(`Reply-To: ${this.sanitizeHeader(options.replyTo)}`);
|
|
358
|
-
}
|
|
359
357
|
if (options.headers) {
|
|
360
358
|
for (const [name, value] of Object.entries(options.headers)) {
|
|
361
359
|
if (!/^[a-zA-Z0-9-]+$/.test(name)) continue;
|
|
@@ -380,13 +378,11 @@ var SMTPClient = class {
|
|
|
380
378
|
\r
|
|
381
379
|
--${boundary}\r
|
|
382
380
|
Content-Type: text/plain; charset=utf-8\r
|
|
383
|
-
Content-Transfer-Encoding: quoted-printable\r
|
|
384
381
|
\r
|
|
385
382
|
${text || ""}\r
|
|
386
383
|
\r
|
|
387
384
|
--${boundary}\r
|
|
388
385
|
Content-Type: text/html; charset=utf-8\r
|
|
389
|
-
Content-Transfer-Encoding: quoted-printable\r
|
|
390
386
|
\r
|
|
391
387
|
${html || ""}\r
|
|
392
388
|
\r
|
|
@@ -439,12 +435,21 @@ ${text || ""}`;
|
|
|
439
435
|
error: "Missing required email parameters (from, to, subject, and either text or html)"
|
|
440
436
|
};
|
|
441
437
|
}
|
|
442
|
-
if (!validateEmail(from)
|
|
438
|
+
if (!validateEmail(from)) {
|
|
443
439
|
return {
|
|
444
440
|
success: false,
|
|
445
441
|
error: "Invalid email address format"
|
|
446
442
|
};
|
|
447
443
|
}
|
|
444
|
+
const recipients = Array.isArray(options.to) ? options.to : [options.to];
|
|
445
|
+
for (const recipient of recipients) {
|
|
446
|
+
if (!validateEmail(recipient)) {
|
|
447
|
+
return {
|
|
448
|
+
success: false,
|
|
449
|
+
error: `Invalid recipient email address format: ${recipient}`
|
|
450
|
+
};
|
|
451
|
+
}
|
|
452
|
+
}
|
|
448
453
|
for (this.retryCount = 0; this.retryCount <= this.config.maxRetries; this.retryCount++) {
|
|
449
454
|
try {
|
|
450
455
|
if (this.retryCount > 0) {
|
|
@@ -460,21 +465,20 @@ ${text || ""}`;
|
|
|
460
465
|
await this.smtpHandshake();
|
|
461
466
|
}
|
|
462
467
|
await this.sendCommand(`MAIL FROM:<${from}>`, 250);
|
|
463
|
-
|
|
468
|
+
for (const recipient of recipients)
|
|
469
|
+
await this.sendCommand(`RCPT TO:<${recipient}>`, 250);
|
|
464
470
|
if (options.cc) {
|
|
465
471
|
const ccList = Array.isArray(options.cc) ? options.cc : [options.cc];
|
|
466
472
|
for (const cc of ccList) {
|
|
467
|
-
if (validateEmail(cc))
|
|
473
|
+
if (validateEmail(cc))
|
|
468
474
|
await this.sendCommand(`RCPT TO:<${cc}>`, 250);
|
|
469
|
-
}
|
|
470
475
|
}
|
|
471
476
|
}
|
|
472
477
|
if (options.bcc) {
|
|
473
478
|
const bccList = Array.isArray(options.bcc) ? options.bcc : [options.bcc];
|
|
474
479
|
for (const bcc of bccList) {
|
|
475
|
-
if (validateEmail(bcc))
|
|
480
|
+
if (validateEmail(bcc))
|
|
476
481
|
await this.sendCommand(`RCPT TO:<${bcc}>`, 250);
|
|
477
|
-
}
|
|
478
482
|
}
|
|
479
483
|
}
|
|
480
484
|
await this.sendCommand("DATA", 354);
|
package/lib/index.js
CHANGED
|
@@ -546,23 +546,21 @@ var SMTPClient = class {
|
|
|
546
546
|
const messageId = this.generateMessageId();
|
|
547
547
|
const date = (/* @__PURE__ */ new Date()).toUTCString();
|
|
548
548
|
const from = options.from || this.config.user;
|
|
549
|
-
const
|
|
549
|
+
const recipients = Array.isArray(options.to) ? options.to.join(", ") : options.to;
|
|
550
550
|
const headers = [
|
|
551
551
|
`From: ${this.sanitizeHeader(from)}`,
|
|
552
|
-
`To: ${this.sanitizeHeader(
|
|
552
|
+
`To: ${this.sanitizeHeader(recipients)}`,
|
|
553
553
|
`Subject: ${this.sanitizeHeader(options.subject)}`,
|
|
554
554
|
`Message-ID: ${messageId}`,
|
|
555
555
|
`Date: ${date}`,
|
|
556
|
-
"MIME-Version: 1.0"
|
|
557
|
-
"Content-Transfer-Encoding: quoted-printable"
|
|
556
|
+
"MIME-Version: 1.0"
|
|
558
557
|
];
|
|
559
558
|
if (options.cc) {
|
|
560
559
|
const cc = Array.isArray(options.cc) ? options.cc.join(", ") : options.cc;
|
|
561
560
|
headers.push(`Cc: ${this.sanitizeHeader(cc)}`);
|
|
562
561
|
}
|
|
563
|
-
if (options.replyTo)
|
|
562
|
+
if (options.replyTo)
|
|
564
563
|
headers.push(`Reply-To: ${this.sanitizeHeader(options.replyTo)}`);
|
|
565
|
-
}
|
|
566
564
|
if (options.headers) {
|
|
567
565
|
for (const [name, value] of Object.entries(options.headers)) {
|
|
568
566
|
if (!/^[a-zA-Z0-9-]+$/.test(name)) continue;
|
|
@@ -587,13 +585,11 @@ var SMTPClient = class {
|
|
|
587
585
|
\r
|
|
588
586
|
--${boundary}\r
|
|
589
587
|
Content-Type: text/plain; charset=utf-8\r
|
|
590
|
-
Content-Transfer-Encoding: quoted-printable\r
|
|
591
588
|
\r
|
|
592
589
|
${text || ""}\r
|
|
593
590
|
\r
|
|
594
591
|
--${boundary}\r
|
|
595
592
|
Content-Type: text/html; charset=utf-8\r
|
|
596
|
-
Content-Transfer-Encoding: quoted-printable\r
|
|
597
593
|
\r
|
|
598
594
|
${html || ""}\r
|
|
599
595
|
\r
|
|
@@ -646,12 +642,21 @@ ${text || ""}`;
|
|
|
646
642
|
error: "Missing required email parameters (from, to, subject, and either text or html)"
|
|
647
643
|
};
|
|
648
644
|
}
|
|
649
|
-
if (!validateEmail(from)
|
|
645
|
+
if (!validateEmail(from)) {
|
|
650
646
|
return {
|
|
651
647
|
success: false,
|
|
652
648
|
error: "Invalid email address format"
|
|
653
649
|
};
|
|
654
650
|
}
|
|
651
|
+
const recipients = Array.isArray(options.to) ? options.to : [options.to];
|
|
652
|
+
for (const recipient of recipients) {
|
|
653
|
+
if (!validateEmail(recipient)) {
|
|
654
|
+
return {
|
|
655
|
+
success: false,
|
|
656
|
+
error: `Invalid recipient email address format: ${recipient}`
|
|
657
|
+
};
|
|
658
|
+
}
|
|
659
|
+
}
|
|
655
660
|
for (this.retryCount = 0; this.retryCount <= this.config.maxRetries; this.retryCount++) {
|
|
656
661
|
try {
|
|
657
662
|
if (this.retryCount > 0) {
|
|
@@ -667,21 +672,20 @@ ${text || ""}`;
|
|
|
667
672
|
await this.smtpHandshake();
|
|
668
673
|
}
|
|
669
674
|
await this.sendCommand(`MAIL FROM:<${from}>`, 250);
|
|
670
|
-
|
|
675
|
+
for (const recipient of recipients)
|
|
676
|
+
await this.sendCommand(`RCPT TO:<${recipient}>`, 250);
|
|
671
677
|
if (options.cc) {
|
|
672
678
|
const ccList = Array.isArray(options.cc) ? options.cc : [options.cc];
|
|
673
679
|
for (const cc of ccList) {
|
|
674
|
-
if (validateEmail(cc))
|
|
680
|
+
if (validateEmail(cc))
|
|
675
681
|
await this.sendCommand(`RCPT TO:<${cc}>`, 250);
|
|
676
|
-
}
|
|
677
682
|
}
|
|
678
683
|
}
|
|
679
684
|
if (options.bcc) {
|
|
680
685
|
const bccList = Array.isArray(options.bcc) ? options.bcc : [options.bcc];
|
|
681
686
|
for (const bcc of bccList) {
|
|
682
|
-
if (validateEmail(bcc))
|
|
687
|
+
if (validateEmail(bcc))
|
|
683
688
|
await this.sendCommand(`RCPT TO:<${bcc}>`, 250);
|
|
684
|
-
}
|
|
685
689
|
}
|
|
686
690
|
}
|
|
687
691
|
await this.sendCommand("DATA", 354);
|
|
@@ -760,9 +764,14 @@ var MikroMail = class {
|
|
|
760
764
|
*/
|
|
761
765
|
async send(emailOptions) {
|
|
762
766
|
try {
|
|
763
|
-
const
|
|
764
|
-
|
|
765
|
-
|
|
767
|
+
const recipients = Array.isArray(emailOptions.to) ? emailOptions.to : [emailOptions.to];
|
|
768
|
+
for (const recipient of recipients) {
|
|
769
|
+
const hasMXRecords = await verifyEmailDomain(recipient);
|
|
770
|
+
if (!hasMXRecords)
|
|
771
|
+
console.error(
|
|
772
|
+
`Warning: No MX records found for recipient domain: ${recipient}`
|
|
773
|
+
);
|
|
774
|
+
}
|
|
766
775
|
const result = await this.smtpClient.sendEmail(emailOptions);
|
|
767
776
|
if (result.success) console.log(`Message ID: ${result.messageId}`);
|
|
768
777
|
else console.error(`Failed to send email: ${result.error}`);
|
package/lib/index.mjs
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import {
|
|
2
2
|
MikroMail
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-422R3NOG.mjs";
|
|
4
4
|
import "./chunk-YVXB6HCK.mjs";
|
|
5
|
-
import "./chunk-
|
|
5
|
+
import "./chunk-NGT3KX7A.mjs";
|
|
6
6
|
import "./chunk-47VXJTWV.mjs";
|
|
7
7
|
import "./chunk-UDLJWUFN.mjs";
|
|
8
8
|
export {
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "mikromail",
|
|
3
3
|
"description": "Lightweight replacement for Nodemailer, supporting HTML, international symbols, and more.",
|
|
4
|
-
"version": "0.0.
|
|
4
|
+
"version": "0.0.7",
|
|
5
5
|
"author": "Mikael Vesavuori",
|
|
6
6
|
"license": "MIT",
|
|
7
7
|
"keywords": [
|
|
@@ -41,7 +41,8 @@
|
|
|
41
41
|
"clean": "rm -rf lib && rm -rf dist",
|
|
42
42
|
"lint": "npx @biomejs/biome check --write ./src ./tests",
|
|
43
43
|
"package": "npm pack",
|
|
44
|
-
"prepublishOnly": "npm run build"
|
|
44
|
+
"prepublishOnly": "npm run build",
|
|
45
|
+
"prepare": "husky"
|
|
45
46
|
},
|
|
46
47
|
"devDependencies": {
|
|
47
48
|
"@biomejs/biome": "1",
|