@upyo/smtp 0.5.3 → 0.5.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/dist/index.cjs +55 -3
- package/dist/index.js +55 -3
- package/package.json +2 -2
package/dist/index.cjs
CHANGED
|
@@ -1164,6 +1164,8 @@ function arrayBufferToBase64(buffer) {
|
|
|
1164
1164
|
* @returns The converted SMTP message.
|
|
1165
1165
|
* @throws {RangeError} If a header contains a token that cannot be folded
|
|
1166
1166
|
* within the RFC 5322 hard line-length limit.
|
|
1167
|
+
* @throws {TypeError} If a `Date` or `Message-ID` header supplied by the
|
|
1168
|
+
* message contains a carriage return or line feed.
|
|
1167
1169
|
*/
|
|
1168
1170
|
async function convertMessage(message, dkimConfig) {
|
|
1169
1171
|
const envelope = {
|
|
@@ -1201,14 +1203,29 @@ async function buildRawMessage(message) {
|
|
|
1201
1203
|
if (message.ccRecipients.length > 0) lines.push(foldHeader("Cc", message.ccRecipients.map(encodeAddress).join(", ")));
|
|
1202
1204
|
if (message.replyRecipients.length > 0) lines.push(foldHeader("Reply-To", message.replyRecipients.map(encodeAddress).join(", ")));
|
|
1203
1205
|
lines.push(foldHeader("Subject", encodeHeaderValue(message.subject, true)));
|
|
1204
|
-
lines.push(
|
|
1205
|
-
lines.push(
|
|
1206
|
+
lines.push(foldHeader("Date", overridden(message, "Date") ?? (/* @__PURE__ */ new Date()).toUTCString()));
|
|
1207
|
+
lines.push(foldHeader("Message-ID", overridden(message, "Message-ID") ?? `<${generateMessageId()}>`));
|
|
1208
|
+
const composed = new Set([
|
|
1209
|
+
"from",
|
|
1210
|
+
"to",
|
|
1211
|
+
"cc",
|
|
1212
|
+
"reply-to",
|
|
1213
|
+
"subject",
|
|
1214
|
+
"date",
|
|
1215
|
+
"message-id"
|
|
1216
|
+
]);
|
|
1206
1217
|
if (message.priority !== "normal") {
|
|
1207
1218
|
const priorityValue = message.priority === "high" ? "1" : "5";
|
|
1208
1219
|
lines.push(`X-Priority: ${priorityValue}`);
|
|
1209
1220
|
lines.push(`X-MSMail-Priority: ${message.priority === "high" ? "High" : "Low"}`);
|
|
1221
|
+
composed.add("x-priority");
|
|
1222
|
+
composed.add("x-msmail-priority");
|
|
1223
|
+
}
|
|
1224
|
+
for (const [key, value] of message.headers) {
|
|
1225
|
+
const name = key.toLowerCase();
|
|
1226
|
+
if (composed.has(name) || reservedHeaders.has(name)) continue;
|
|
1227
|
+
lines.push(foldHeader(key, encodeHeaderValue(value)));
|
|
1210
1228
|
}
|
|
1211
|
-
for (const [key, value] of message.headers) lines.push(foldHeader(key, encodeHeaderValue(value)));
|
|
1212
1229
|
lines.push("MIME-Version: 1.0");
|
|
1213
1230
|
if (isMultipart) {
|
|
1214
1231
|
lines.push(`Content-Type: multipart/mixed; boundary="${boundary}"`);
|
|
@@ -1271,6 +1288,41 @@ async function buildRawMessage(message) {
|
|
|
1271
1288
|
}
|
|
1272
1289
|
return lines.join("\r\n");
|
|
1273
1290
|
}
|
|
1291
|
+
/**
|
|
1292
|
+
* Reads a header field that overrides a generated default.
|
|
1293
|
+
*
|
|
1294
|
+
* Unlike custom headers, the value is written verbatim rather than RFC 2047
|
|
1295
|
+
* encoded, so it cannot rely on `encodeHeaderValue()` to neutralize control
|
|
1296
|
+
* characters. `ImmutableHeaders` is a structural type, so a `Message` may
|
|
1297
|
+
* carry an adapter that never rejected CR or LF the way a platform `Headers`
|
|
1298
|
+
* does.
|
|
1299
|
+
*
|
|
1300
|
+
* @param message The message whose headers are read.
|
|
1301
|
+
* @param name The header field name.
|
|
1302
|
+
* @returns The supplied value, or `undefined` when the message has none.
|
|
1303
|
+
* @throws {TypeError} If the value contains a carriage return or line feed,
|
|
1304
|
+
* which would inject additional header fields into the message.
|
|
1305
|
+
*/
|
|
1306
|
+
function overridden(message, name) {
|
|
1307
|
+
const value = message.headers.get(name);
|
|
1308
|
+
if (value == null) return void 0;
|
|
1309
|
+
if (/[\r\n]/.test(value)) throw new TypeError(`Header field ${name} must not contain a carriage return or line feed.`);
|
|
1310
|
+
return value;
|
|
1311
|
+
}
|
|
1312
|
+
/**
|
|
1313
|
+
* Header fields the composer owns but writes after the custom headers, or
|
|
1314
|
+
* deliberately omits. A custom header with one of these names is dropped
|
|
1315
|
+
* rather than appended: the structured `Message` fields are authoritative,
|
|
1316
|
+
* RFC 5322 §3.6 allows at most one of each, and a duplicate placed before the
|
|
1317
|
+
* composer's own field makes parsers that take the first occurrence read the
|
|
1318
|
+
* wrong value.
|
|
1319
|
+
*/
|
|
1320
|
+
const reservedHeaders = new Set([
|
|
1321
|
+
"bcc",
|
|
1322
|
+
"content-transfer-encoding",
|
|
1323
|
+
"content-type",
|
|
1324
|
+
"mime-version"
|
|
1325
|
+
]);
|
|
1274
1326
|
function generateBoundary() {
|
|
1275
1327
|
return `boundary-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`;
|
|
1276
1328
|
}
|
package/dist/index.js
CHANGED
|
@@ -1141,6 +1141,8 @@ function arrayBufferToBase64(buffer) {
|
|
|
1141
1141
|
* @returns The converted SMTP message.
|
|
1142
1142
|
* @throws {RangeError} If a header contains a token that cannot be folded
|
|
1143
1143
|
* within the RFC 5322 hard line-length limit.
|
|
1144
|
+
* @throws {TypeError} If a `Date` or `Message-ID` header supplied by the
|
|
1145
|
+
* message contains a carriage return or line feed.
|
|
1144
1146
|
*/
|
|
1145
1147
|
async function convertMessage(message, dkimConfig) {
|
|
1146
1148
|
const envelope = {
|
|
@@ -1178,14 +1180,29 @@ async function buildRawMessage(message) {
|
|
|
1178
1180
|
if (message.ccRecipients.length > 0) lines.push(foldHeader("Cc", message.ccRecipients.map(encodeAddress).join(", ")));
|
|
1179
1181
|
if (message.replyRecipients.length > 0) lines.push(foldHeader("Reply-To", message.replyRecipients.map(encodeAddress).join(", ")));
|
|
1180
1182
|
lines.push(foldHeader("Subject", encodeHeaderValue(message.subject, true)));
|
|
1181
|
-
lines.push(
|
|
1182
|
-
lines.push(
|
|
1183
|
+
lines.push(foldHeader("Date", overridden(message, "Date") ?? (/* @__PURE__ */ new Date()).toUTCString()));
|
|
1184
|
+
lines.push(foldHeader("Message-ID", overridden(message, "Message-ID") ?? `<${generateMessageId()}>`));
|
|
1185
|
+
const composed = new Set([
|
|
1186
|
+
"from",
|
|
1187
|
+
"to",
|
|
1188
|
+
"cc",
|
|
1189
|
+
"reply-to",
|
|
1190
|
+
"subject",
|
|
1191
|
+
"date",
|
|
1192
|
+
"message-id"
|
|
1193
|
+
]);
|
|
1183
1194
|
if (message.priority !== "normal") {
|
|
1184
1195
|
const priorityValue = message.priority === "high" ? "1" : "5";
|
|
1185
1196
|
lines.push(`X-Priority: ${priorityValue}`);
|
|
1186
1197
|
lines.push(`X-MSMail-Priority: ${message.priority === "high" ? "High" : "Low"}`);
|
|
1198
|
+
composed.add("x-priority");
|
|
1199
|
+
composed.add("x-msmail-priority");
|
|
1200
|
+
}
|
|
1201
|
+
for (const [key, value] of message.headers) {
|
|
1202
|
+
const name = key.toLowerCase();
|
|
1203
|
+
if (composed.has(name) || reservedHeaders.has(name)) continue;
|
|
1204
|
+
lines.push(foldHeader(key, encodeHeaderValue(value)));
|
|
1187
1205
|
}
|
|
1188
|
-
for (const [key, value] of message.headers) lines.push(foldHeader(key, encodeHeaderValue(value)));
|
|
1189
1206
|
lines.push("MIME-Version: 1.0");
|
|
1190
1207
|
if (isMultipart) {
|
|
1191
1208
|
lines.push(`Content-Type: multipart/mixed; boundary="${boundary}"`);
|
|
@@ -1248,6 +1265,41 @@ async function buildRawMessage(message) {
|
|
|
1248
1265
|
}
|
|
1249
1266
|
return lines.join("\r\n");
|
|
1250
1267
|
}
|
|
1268
|
+
/**
|
|
1269
|
+
* Reads a header field that overrides a generated default.
|
|
1270
|
+
*
|
|
1271
|
+
* Unlike custom headers, the value is written verbatim rather than RFC 2047
|
|
1272
|
+
* encoded, so it cannot rely on `encodeHeaderValue()` to neutralize control
|
|
1273
|
+
* characters. `ImmutableHeaders` is a structural type, so a `Message` may
|
|
1274
|
+
* carry an adapter that never rejected CR or LF the way a platform `Headers`
|
|
1275
|
+
* does.
|
|
1276
|
+
*
|
|
1277
|
+
* @param message The message whose headers are read.
|
|
1278
|
+
* @param name The header field name.
|
|
1279
|
+
* @returns The supplied value, or `undefined` when the message has none.
|
|
1280
|
+
* @throws {TypeError} If the value contains a carriage return or line feed,
|
|
1281
|
+
* which would inject additional header fields into the message.
|
|
1282
|
+
*/
|
|
1283
|
+
function overridden(message, name) {
|
|
1284
|
+
const value = message.headers.get(name);
|
|
1285
|
+
if (value == null) return void 0;
|
|
1286
|
+
if (/[\r\n]/.test(value)) throw new TypeError(`Header field ${name} must not contain a carriage return or line feed.`);
|
|
1287
|
+
return value;
|
|
1288
|
+
}
|
|
1289
|
+
/**
|
|
1290
|
+
* Header fields the composer owns but writes after the custom headers, or
|
|
1291
|
+
* deliberately omits. A custom header with one of these names is dropped
|
|
1292
|
+
* rather than appended: the structured `Message` fields are authoritative,
|
|
1293
|
+
* RFC 5322 §3.6 allows at most one of each, and a duplicate placed before the
|
|
1294
|
+
* composer's own field makes parsers that take the first occurrence read the
|
|
1295
|
+
* wrong value.
|
|
1296
|
+
*/
|
|
1297
|
+
const reservedHeaders = new Set([
|
|
1298
|
+
"bcc",
|
|
1299
|
+
"content-transfer-encoding",
|
|
1300
|
+
"content-type",
|
|
1301
|
+
"mime-version"
|
|
1302
|
+
]);
|
|
1251
1303
|
function generateBoundary() {
|
|
1252
1304
|
return `boundary-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`;
|
|
1253
1305
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@upyo/smtp",
|
|
3
|
-
"version": "0.5.
|
|
3
|
+
"version": "0.5.4",
|
|
4
4
|
"description": "SMTP transport for Upyo email library",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"email",
|
|
@@ -53,7 +53,7 @@
|
|
|
53
53
|
},
|
|
54
54
|
"sideEffects": false,
|
|
55
55
|
"peerDependencies": {
|
|
56
|
-
"@upyo/core": "0.5.
|
|
56
|
+
"@upyo/core": "0.5.4"
|
|
57
57
|
},
|
|
58
58
|
"devDependencies": {
|
|
59
59
|
"tsdown": "^0.12.7",
|