@upyo/smtp 0.1.0-dev.14 → 0.1.0-dev.9
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 +46 -25
- package/dist/index.cjs +31 -23
- package/dist/index.js +31 -23
- package/package.json +3 -3
package/README.md
CHANGED
|
@@ -3,16 +3,7 @@
|
|
|
3
3
|
@upyo/smtp
|
|
4
4
|
==========
|
|
5
5
|
|
|
6
|
-
|
|
7
|
-
[![npm][npm badge]][npm]
|
|
8
|
-
|
|
9
|
-
SMTP transport implementation for the [Upyo] email library.
|
|
10
|
-
|
|
11
|
-
[JSR]: https://jsr.io/@upyo/smtp
|
|
12
|
-
[JSR badge]: https://jsr.io/badges/@upyo/smtp
|
|
13
|
-
[npm]: https://www.npmjs.com/package/@upyo/smtp
|
|
14
|
-
[npm badge]: https://img.shields.io/npm/v/@upyo/smtp?logo=npm
|
|
15
|
-
[Upyo]: https://upyo.org/
|
|
6
|
+
SMTP transport implementation for the Upyo email library.
|
|
16
7
|
|
|
17
8
|
|
|
18
9
|
Features
|
|
@@ -56,8 +47,8 @@ Usage
|
|
|
56
47
|
### Basic Email Sending
|
|
57
48
|
|
|
58
49
|
~~~~ typescript
|
|
59
|
-
import { createMessage } from "@upyo/core";
|
|
60
50
|
import { SmtpTransport } from "@upyo/smtp";
|
|
51
|
+
import { type Message } from "@upyo/core";
|
|
61
52
|
|
|
62
53
|
const transport = new SmtpTransport({
|
|
63
54
|
host: "smtp.example.com",
|
|
@@ -69,19 +60,53 @@ const transport = new SmtpTransport({
|
|
|
69
60
|
},
|
|
70
61
|
});
|
|
71
62
|
|
|
72
|
-
const message =
|
|
73
|
-
|
|
74
|
-
|
|
63
|
+
const message: Message = {
|
|
64
|
+
sender: { name: "John Doe", address: "john@example.com" },
|
|
65
|
+
recipients: [{ name: "Jane Doe", address: "jane@example.com" }],
|
|
66
|
+
ccRecipients: [],
|
|
67
|
+
bccRecipients: [],
|
|
68
|
+
replyRecipients: [],
|
|
75
69
|
subject: "Hello from Upyo!",
|
|
76
70
|
content: { text: "This is a test email." },
|
|
77
|
-
|
|
71
|
+
attachments: [],
|
|
72
|
+
priority: "normal",
|
|
73
|
+
tags: [],
|
|
74
|
+
headers: new Headers(),
|
|
75
|
+
};
|
|
76
|
+
|
|
77
|
+
const receipt = await transport.send(message);
|
|
78
|
+
console.log("Email sent:", receipt.successful);
|
|
79
|
+
~~~~
|
|
80
|
+
|
|
81
|
+
### HTML Email with Attachments
|
|
82
|
+
|
|
83
|
+
~~~~ typescript
|
|
84
|
+
const message: Message = {
|
|
85
|
+
sender: { address: "sender@example.com" },
|
|
86
|
+
recipients: [{ address: "recipient@example.com" }],
|
|
87
|
+
ccRecipients: [],
|
|
88
|
+
bccRecipients: [],
|
|
89
|
+
replyRecipients: [],
|
|
90
|
+
subject: "HTML Email with Attachment",
|
|
91
|
+
content: {
|
|
92
|
+
html: "<h1>Hello!</h1><p>This is an <strong>HTML</strong> email.</p>",
|
|
93
|
+
text: "Hello!\nThis is an HTML email.",
|
|
94
|
+
},
|
|
95
|
+
attachments: [
|
|
96
|
+
{
|
|
97
|
+
filename: "document.pdf",
|
|
98
|
+
content: new Uint8Array(pdfBytes),
|
|
99
|
+
contentType: "application/pdf",
|
|
100
|
+
contentId: "doc1",
|
|
101
|
+
inline: false,
|
|
102
|
+
},
|
|
103
|
+
],
|
|
104
|
+
priority: "high",
|
|
105
|
+
tags: ["newsletter"],
|
|
106
|
+
headers: new Headers([["X-Campaign-ID", "12345"]]),
|
|
107
|
+
};
|
|
78
108
|
|
|
79
109
|
const receipt = await transport.send(message);
|
|
80
|
-
if (receipt.successful) {
|
|
81
|
-
console.log("Message sent with ID:", receipt.messageId);
|
|
82
|
-
} else {
|
|
83
|
-
console.error("Send failed:", receipt.errorMessages.join(", "));
|
|
84
|
-
}
|
|
85
110
|
~~~~
|
|
86
111
|
|
|
87
112
|
### Sending Multiple Emails
|
|
@@ -90,11 +115,7 @@ if (receipt.successful) {
|
|
|
90
115
|
const messages = [message1, message2, message3];
|
|
91
116
|
|
|
92
117
|
for await (const receipt of transport.sendMany(messages)) {
|
|
93
|
-
|
|
94
|
-
console.log(`Email sent with ID: ${receipt.messageId}`);
|
|
95
|
-
} else {
|
|
96
|
-
console.error(`Email failed: ${receipt.errorMessages.join(", ")}`);
|
|
97
|
-
}
|
|
118
|
+
console.log(`Email ${receipt.messageId}: ${receipt.successful ? "sent" : "failed"}`);
|
|
98
119
|
}
|
|
99
120
|
~~~~
|
|
100
121
|
|
package/dist/index.cjs
CHANGED
|
@@ -266,7 +266,7 @@ var SmtpConnection = class {
|
|
|
266
266
|
|
|
267
267
|
//#endregion
|
|
268
268
|
//#region src/message-converter.ts
|
|
269
|
-
|
|
269
|
+
function convertMessage(message) {
|
|
270
270
|
const envelope = {
|
|
271
271
|
from: message.sender.address,
|
|
272
272
|
to: [
|
|
@@ -275,13 +275,13 @@ async function convertMessage(message) {
|
|
|
275
275
|
...message.bccRecipients.map((r) => r.address)
|
|
276
276
|
]
|
|
277
277
|
};
|
|
278
|
-
const raw =
|
|
278
|
+
const raw = buildRawMessage(message);
|
|
279
279
|
return {
|
|
280
280
|
envelope,
|
|
281
281
|
raw
|
|
282
282
|
};
|
|
283
283
|
}
|
|
284
|
-
|
|
284
|
+
function buildRawMessage(message) {
|
|
285
285
|
const lines = [];
|
|
286
286
|
const boundary = generateBoundary();
|
|
287
287
|
const hasAttachments = message.attachments.length > 0;
|
|
@@ -346,7 +346,7 @@ async function buildRawMessage(message) {
|
|
|
346
346
|
lines.push(`Content-ID: <${attachment.contentId}>`);
|
|
347
347
|
} else lines.push(`Content-Disposition: attachment; filename="${attachment.filename}"`);
|
|
348
348
|
lines.push("");
|
|
349
|
-
lines.push(encodeBase64(
|
|
349
|
+
lines.push(encodeBase64(attachment.content));
|
|
350
350
|
}
|
|
351
351
|
lines.push("");
|
|
352
352
|
lines.push(`--${boundary}--`);
|
|
@@ -472,19 +472,21 @@ var SmtpTransport = class {
|
|
|
472
472
|
const connection = await this.getConnection(options?.signal);
|
|
473
473
|
try {
|
|
474
474
|
options?.signal?.throwIfAborted();
|
|
475
|
-
const smtpMessage =
|
|
475
|
+
const smtpMessage = convertMessage(message);
|
|
476
476
|
options?.signal?.throwIfAborted();
|
|
477
477
|
const messageId = await connection.sendMessage(smtpMessage, options?.signal);
|
|
478
478
|
await this.returnConnection(connection);
|
|
479
479
|
return {
|
|
480
|
-
|
|
481
|
-
|
|
480
|
+
messageId,
|
|
481
|
+
errorMessages: [],
|
|
482
|
+
successful: true
|
|
482
483
|
};
|
|
483
484
|
} catch (error) {
|
|
484
485
|
await this.discardConnection(connection);
|
|
485
486
|
return {
|
|
486
|
-
|
|
487
|
-
errorMessages: [error instanceof Error ? error.message : String(error)]
|
|
487
|
+
messageId: "",
|
|
488
|
+
errorMessages: [error instanceof Error ? error.message : String(error)],
|
|
489
|
+
successful: false
|
|
488
490
|
};
|
|
489
491
|
}
|
|
490
492
|
}
|
|
@@ -526,24 +528,27 @@ var SmtpTransport = class {
|
|
|
526
528
|
options?.signal?.throwIfAborted();
|
|
527
529
|
if (!connectionValid) {
|
|
528
530
|
yield {
|
|
529
|
-
|
|
530
|
-
errorMessages: ["Connection is no longer valid"]
|
|
531
|
+
messageId: "",
|
|
532
|
+
errorMessages: ["Connection is no longer valid"],
|
|
533
|
+
successful: false
|
|
531
534
|
};
|
|
532
535
|
continue;
|
|
533
536
|
}
|
|
534
537
|
try {
|
|
535
|
-
const smtpMessage =
|
|
538
|
+
const smtpMessage = convertMessage(message);
|
|
536
539
|
options?.signal?.throwIfAborted();
|
|
537
540
|
const messageId = await connection.sendMessage(smtpMessage, options?.signal);
|
|
538
541
|
yield {
|
|
539
|
-
|
|
540
|
-
|
|
542
|
+
messageId,
|
|
543
|
+
errorMessages: [],
|
|
544
|
+
successful: true
|
|
541
545
|
};
|
|
542
546
|
} catch (error) {
|
|
543
547
|
connectionValid = false;
|
|
544
548
|
yield {
|
|
545
|
-
|
|
546
|
-
errorMessages: [error instanceof Error ? error.message : String(error)]
|
|
549
|
+
messageId: "",
|
|
550
|
+
errorMessages: [error instanceof Error ? error.message : String(error)],
|
|
551
|
+
successful: false
|
|
547
552
|
};
|
|
548
553
|
}
|
|
549
554
|
}
|
|
@@ -551,24 +556,27 @@ var SmtpTransport = class {
|
|
|
551
556
|
options?.signal?.throwIfAborted();
|
|
552
557
|
if (!connectionValid) {
|
|
553
558
|
yield {
|
|
554
|
-
|
|
555
|
-
errorMessages: ["Connection is no longer valid"]
|
|
559
|
+
messageId: "",
|
|
560
|
+
errorMessages: ["Connection is no longer valid"],
|
|
561
|
+
successful: false
|
|
556
562
|
};
|
|
557
563
|
continue;
|
|
558
564
|
}
|
|
559
565
|
try {
|
|
560
|
-
const smtpMessage =
|
|
566
|
+
const smtpMessage = convertMessage(message);
|
|
561
567
|
options?.signal?.throwIfAborted();
|
|
562
568
|
const messageId = await connection.sendMessage(smtpMessage, options?.signal);
|
|
563
569
|
yield {
|
|
564
|
-
|
|
565
|
-
|
|
570
|
+
messageId,
|
|
571
|
+
errorMessages: [],
|
|
572
|
+
successful: true
|
|
566
573
|
};
|
|
567
574
|
} catch (error) {
|
|
568
575
|
connectionValid = false;
|
|
569
576
|
yield {
|
|
570
|
-
|
|
571
|
-
errorMessages: [error instanceof Error ? error.message : String(error)]
|
|
577
|
+
messageId: "",
|
|
578
|
+
errorMessages: [error instanceof Error ? error.message : String(error)],
|
|
579
|
+
successful: false
|
|
572
580
|
};
|
|
573
581
|
}
|
|
574
582
|
}
|
package/dist/index.js
CHANGED
|
@@ -243,7 +243,7 @@ var SmtpConnection = class {
|
|
|
243
243
|
|
|
244
244
|
//#endregion
|
|
245
245
|
//#region src/message-converter.ts
|
|
246
|
-
|
|
246
|
+
function convertMessage(message) {
|
|
247
247
|
const envelope = {
|
|
248
248
|
from: message.sender.address,
|
|
249
249
|
to: [
|
|
@@ -252,13 +252,13 @@ async function convertMessage(message) {
|
|
|
252
252
|
...message.bccRecipients.map((r) => r.address)
|
|
253
253
|
]
|
|
254
254
|
};
|
|
255
|
-
const raw =
|
|
255
|
+
const raw = buildRawMessage(message);
|
|
256
256
|
return {
|
|
257
257
|
envelope,
|
|
258
258
|
raw
|
|
259
259
|
};
|
|
260
260
|
}
|
|
261
|
-
|
|
261
|
+
function buildRawMessage(message) {
|
|
262
262
|
const lines = [];
|
|
263
263
|
const boundary = generateBoundary();
|
|
264
264
|
const hasAttachments = message.attachments.length > 0;
|
|
@@ -323,7 +323,7 @@ async function buildRawMessage(message) {
|
|
|
323
323
|
lines.push(`Content-ID: <${attachment.contentId}>`);
|
|
324
324
|
} else lines.push(`Content-Disposition: attachment; filename="${attachment.filename}"`);
|
|
325
325
|
lines.push("");
|
|
326
|
-
lines.push(encodeBase64(
|
|
326
|
+
lines.push(encodeBase64(attachment.content));
|
|
327
327
|
}
|
|
328
328
|
lines.push("");
|
|
329
329
|
lines.push(`--${boundary}--`);
|
|
@@ -449,19 +449,21 @@ var SmtpTransport = class {
|
|
|
449
449
|
const connection = await this.getConnection(options?.signal);
|
|
450
450
|
try {
|
|
451
451
|
options?.signal?.throwIfAborted();
|
|
452
|
-
const smtpMessage =
|
|
452
|
+
const smtpMessage = convertMessage(message);
|
|
453
453
|
options?.signal?.throwIfAborted();
|
|
454
454
|
const messageId = await connection.sendMessage(smtpMessage, options?.signal);
|
|
455
455
|
await this.returnConnection(connection);
|
|
456
456
|
return {
|
|
457
|
-
|
|
458
|
-
|
|
457
|
+
messageId,
|
|
458
|
+
errorMessages: [],
|
|
459
|
+
successful: true
|
|
459
460
|
};
|
|
460
461
|
} catch (error) {
|
|
461
462
|
await this.discardConnection(connection);
|
|
462
463
|
return {
|
|
463
|
-
|
|
464
|
-
errorMessages: [error instanceof Error ? error.message : String(error)]
|
|
464
|
+
messageId: "",
|
|
465
|
+
errorMessages: [error instanceof Error ? error.message : String(error)],
|
|
466
|
+
successful: false
|
|
465
467
|
};
|
|
466
468
|
}
|
|
467
469
|
}
|
|
@@ -503,24 +505,27 @@ var SmtpTransport = class {
|
|
|
503
505
|
options?.signal?.throwIfAborted();
|
|
504
506
|
if (!connectionValid) {
|
|
505
507
|
yield {
|
|
506
|
-
|
|
507
|
-
errorMessages: ["Connection is no longer valid"]
|
|
508
|
+
messageId: "",
|
|
509
|
+
errorMessages: ["Connection is no longer valid"],
|
|
510
|
+
successful: false
|
|
508
511
|
};
|
|
509
512
|
continue;
|
|
510
513
|
}
|
|
511
514
|
try {
|
|
512
|
-
const smtpMessage =
|
|
515
|
+
const smtpMessage = convertMessage(message);
|
|
513
516
|
options?.signal?.throwIfAborted();
|
|
514
517
|
const messageId = await connection.sendMessage(smtpMessage, options?.signal);
|
|
515
518
|
yield {
|
|
516
|
-
|
|
517
|
-
|
|
519
|
+
messageId,
|
|
520
|
+
errorMessages: [],
|
|
521
|
+
successful: true
|
|
518
522
|
};
|
|
519
523
|
} catch (error) {
|
|
520
524
|
connectionValid = false;
|
|
521
525
|
yield {
|
|
522
|
-
|
|
523
|
-
errorMessages: [error instanceof Error ? error.message : String(error)]
|
|
526
|
+
messageId: "",
|
|
527
|
+
errorMessages: [error instanceof Error ? error.message : String(error)],
|
|
528
|
+
successful: false
|
|
524
529
|
};
|
|
525
530
|
}
|
|
526
531
|
}
|
|
@@ -528,24 +533,27 @@ var SmtpTransport = class {
|
|
|
528
533
|
options?.signal?.throwIfAborted();
|
|
529
534
|
if (!connectionValid) {
|
|
530
535
|
yield {
|
|
531
|
-
|
|
532
|
-
errorMessages: ["Connection is no longer valid"]
|
|
536
|
+
messageId: "",
|
|
537
|
+
errorMessages: ["Connection is no longer valid"],
|
|
538
|
+
successful: false
|
|
533
539
|
};
|
|
534
540
|
continue;
|
|
535
541
|
}
|
|
536
542
|
try {
|
|
537
|
-
const smtpMessage =
|
|
543
|
+
const smtpMessage = convertMessage(message);
|
|
538
544
|
options?.signal?.throwIfAborted();
|
|
539
545
|
const messageId = await connection.sendMessage(smtpMessage, options?.signal);
|
|
540
546
|
yield {
|
|
541
|
-
|
|
542
|
-
|
|
547
|
+
messageId,
|
|
548
|
+
errorMessages: [],
|
|
549
|
+
successful: true
|
|
543
550
|
};
|
|
544
551
|
} catch (error) {
|
|
545
552
|
connectionValid = false;
|
|
546
553
|
yield {
|
|
547
|
-
|
|
548
|
-
errorMessages: [error instanceof Error ? error.message : String(error)]
|
|
554
|
+
messageId: "",
|
|
555
|
+
errorMessages: [error instanceof Error ? error.message : String(error)],
|
|
556
|
+
successful: false
|
|
549
557
|
};
|
|
550
558
|
}
|
|
551
559
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@upyo/smtp",
|
|
3
|
-
"version": "0.1.0-dev.
|
|
3
|
+
"version": "0.1.0-dev.9+a57dde18",
|
|
4
4
|
"description": "SMTP transport for Upyo email library",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"email",
|
|
@@ -53,12 +53,12 @@
|
|
|
53
53
|
},
|
|
54
54
|
"sideEffects": false,
|
|
55
55
|
"peerDependencies": {
|
|
56
|
-
"@upyo/core": "0.1.0-dev.
|
|
56
|
+
"@upyo/core": "0.1.0-dev.9+a57dde18"
|
|
57
57
|
},
|
|
58
58
|
"devDependencies": {
|
|
59
59
|
"@dotenvx/dotenvx": "^1.47.3",
|
|
60
60
|
"tsdown": "^0.12.7",
|
|
61
|
-
"typescript": "5.8.3"
|
|
61
|
+
"typescript": "^5.8.3"
|
|
62
62
|
},
|
|
63
63
|
"scripts": {
|
|
64
64
|
"build": "tsdown",
|