arn-rawmime 0.0.5 → 0.0.6

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/package.json CHANGED
@@ -1,9 +1,12 @@
1
1
  {
2
2
  "name": "arn-rawmime",
3
- "version": "0.0.5",
3
+ "version": "0.0.6",
4
4
  "description": "A lightweight, dependency-free raw MIME email builder with DKIM support.",
5
5
  "author": "ARNDESK",
6
6
  "type": "module",
7
+ "engines": {
8
+ "node": ">=16.0.0"
9
+ },
7
10
  "main": "src/index.js",
8
11
  "types": "src/index.d.ts",
9
12
  "files": [
@@ -13,22 +16,11 @@
13
16
  "test": "test"
14
17
  },
15
18
  "dependencies": {
16
- "deepmerge": "^4.3.1",
17
- "dom-serializer": "^2.0.0",
18
- "domelementtype": "^2.3.0",
19
- "domhandler": "^5.0.3",
20
- "domutils": "^3.2.2",
21
- "entities": "^4.5.0",
22
19
  "he": "^1.2.0",
23
- "html-to-text": "^9.0.5",
24
- "htmlparser2": "^8.0.2",
25
- "leac": "^0.6.0",
20
+ "html-to-text": "^10.0.0",
26
21
  "mailparser": "^3.9.0",
27
- "marked": "^17.0.1",
22
+ "marked": "^18.0.3",
28
23
  "mime-types": "^3.0.2",
29
- "parseley": "^0.12.1",
30
- "peberminta": "^0.9.0",
31
- "selderee": "^0.11.0",
32
24
  "turndown": "^7.2.2"
33
25
  },
34
26
  "scripts": {
@@ -68,12 +68,12 @@ function DKIMSign(email, options) {
68
68
  options = options || {};
69
69
  email = (email || "").toString("utf-8");
70
70
 
71
- var match = email.match(/^\r?\n|(?:\r?\n){2}/),
71
+ let match = email.match(/^\r?\n|(?:\r?\n){2}/),
72
72
  headers = (match && email.substring(0, match.index)) || "",
73
73
  body = (match && email.substring(match.index + match[0].length)) || email;
74
74
 
75
75
  // All listed fields from RFC4871 #5.5
76
- var defaultFieldNames =
76
+ const defaultFieldNames =
77
77
  "From:Sender:Reply-To:Subject:To:" +
78
78
  "Cc:MIME-Version:Content-Type:Content-Transfer-Encoding:Content-ID:" +
79
79
  "Content-Description:Resent-Date:Resent-From:Resent-Sender:" +
@@ -82,7 +82,7 @@ function DKIMSign(email, options) {
82
82
  "List-Owner:List-Archive:" +
83
83
  "List-Unsubscribe-Post:Date:Message-ID:Feedback-ID:DKIM-Signature:";
84
84
 
85
- var dkim = generateDKIMHeader(
85
+ let dkim = generateDKIMHeader(
86
86
  options.domainName,
87
87
  options.keySelector,
88
88
  options.headerFieldNames || defaultFieldNames,
@@ -117,7 +117,7 @@ function DKIMSign(email, options) {
117
117
  * @return {String} Mime folded DKIM-Signature string
118
118
  */
119
119
  function generateDKIMHeader(domainName, keySelector, headerFieldNames, headers, body) {
120
- var canonicalizedBody = DKIMCanonicalizer.relaxedBody(body),
120
+ let canonicalizedBody = DKIMCanonicalizer.relaxedBody(body),
121
121
  canonicalizedBodyHash = sha256(canonicalizedBody, "base64"),
122
122
  canonicalizedHeaderData = DKIMCanonicalizer.relaxedHeaders(headers, headerFieldNames),
123
123
  dkim;
@@ -176,7 +176,7 @@ const DKIMCanonicalizer = {
176
176
  * @return {Object} Canonicalized headers and field names
177
177
  */
178
178
  relaxedHeaders: function (headers, fieldNames) {
179
- var includedFields = (fieldNames || "").split(":").map(function (field) {
179
+ let includedFields = (fieldNames || "").split(":").map(function (field) {
180
180
  return field.trim();
181
181
  }),
182
182
  includedFieldsLower = includedFields.map(function (field) {
@@ -197,7 +197,7 @@ const DKIMCanonicalizer = {
197
197
  // Process header lines
198
198
  for (i = 0; i < headerLines.length; i++) {
199
199
  line = DKIMCanonicalizer.relaxedHeaderLine(headerLines[i]);
200
- var keyLower = line.key.toLowerCase();
200
+ let keyLower = line.key.toLowerCase();
201
201
 
202
202
  if (includedFieldsLower.indexOf(keyLower) >= 0 && !(keyLower in headerFields)) {
203
203
  headerFields[keyLower] = {
@@ -207,20 +207,20 @@ const DKIMCanonicalizer = {
207
207
  }
208
208
  }
209
209
 
210
- var headers = [];
211
- var usedFields = [];
210
+ let resultHeaders = [];
211
+ let usedFields = [];
212
212
  for (i = includedFields.length - 1; i >= 0; i--) {
213
- var keyLower = includedFields[i].toLowerCase();
213
+ let keyLower = includedFields[i].toLowerCase();
214
214
  if (!headerFields[keyLower]) {
215
215
  includedFields.splice(i, 1);
216
216
  } else {
217
- headers.unshift(headerFields[keyLower].key.toLowerCase() + ":" + headerFields[keyLower].value);
217
+ resultHeaders.unshift(headerFields[keyLower].key.toLowerCase() + ":" + headerFields[keyLower].value);
218
218
  usedFields.unshift(headerFields[keyLower].key);
219
219
  }
220
220
  }
221
221
 
222
222
  return {
223
- headers: headers.join("\r\n") + "\r\n",
223
+ headers: resultHeaders.join("\r\n") + "\r\n",
224
224
  fieldNames: usedFields.join(":"),
225
225
  };
226
226
  },
@@ -231,7 +231,7 @@ const DKIMCanonicalizer = {
231
231
  * @return {Object} Parsed header line with key and value
232
232
  */
233
233
  relaxedHeaderLine: function (line) {
234
- var parts = line.split(":"),
234
+ let parts = line.split(":"),
235
235
  key = (parts.shift() || "").trim(),
236
236
  value = parts.join(":").replace(/\s+/g, " ").trim();
237
237
 
@@ -250,7 +250,7 @@ const DKIMCanonicalizer = {
250
250
  * @return {String} SHA-256 hash in the selected output encoding
251
251
  */
252
252
  function sha256(str, encoding) {
253
- var shasum = crypto.createHash("sha256");
253
+ const shasum = crypto.createHash("sha256");
254
254
  shasum.update(str);
255
255
  return shasum.digest(encoding || "hex");
256
256
  }
@@ -262,7 +262,7 @@ function sha256(str, encoding) {
262
262
  * @return {Boolean} true if the string contains non-ASCII symbols
263
263
  */
264
264
  function hasUTFChars(str) {
265
- var rforeign = /[^\u0000-\u007f]/;
265
+ const rforeign = /[^\u0000-\u007f]/;
266
266
  return !!rforeign.test(str);
267
267
  }
268
268
 
@@ -4,7 +4,7 @@ import path from "path";
4
4
  import { randomBytes } from "crypto";
5
5
  import { convert } from "html-to-text";
6
6
  import { DKIMSign } from "./dkim-signer.js";
7
- import { processMarkDown } from "./processMarkDown.js"; // <--- IMPORT ADDED
7
+ import { processMarkDown } from "./processMarkDown.js";
8
8
 
9
9
  const desiredOrder = [
10
10
  "List-Unsubscribe-Post",
@@ -27,7 +27,7 @@ class MimeMessage {
27
27
  this.bodyParts = [];
28
28
  this.attachments = [];
29
29
  this.attachmentPromises = [];
30
- this.processingPromises = []; // <--- NEW: Track async ops
30
+ this.processingPromises = [];
31
31
  this.removedHeaders = new Set();
32
32
  }
33
33
 
@@ -38,7 +38,7 @@ class MimeMessage {
38
38
  wordwrap: 130,
39
39
  selectors: [
40
40
  { selector: "img", format: "skip" },
41
- { selector: "a", options: { hideLinkHrefIfSameAsText: true } },
41
+ { selector: "a", options: { hideLinkHrefIfSameAsText: true, linkBrackets: ["<", ">"] } },
42
42
  ],
43
43
  });
44
44
  }
@@ -212,7 +212,10 @@ class MimeMessage {
212
212
  formatMailboxes(mailboxes) {
213
213
  if (!mailboxes) return "";
214
214
  const mbs = Array.isArray(mailboxes) ? mailboxes : [mailboxes];
215
- return mbs.map((mb) => (mb.name ? `"${mb.name}" <${mb.email}>` : mb.email)).join(", ");
215
+ return mbs.map((mb) => {
216
+ if (typeof mb === "string") return mb;
217
+ return mb.name ? `"${mb.name}" <${mb.email}>` : mb.email;
218
+ }).join(", ");
216
219
  }
217
220
 
218
221
  setFrom(sender) {
@@ -376,7 +379,7 @@ class MimeMessage {
376
379
  encoding = "quoted-printable",
377
380
  autoTextPart = false,
378
381
  autoMinify = true,
379
- markdownToHtml = false, // <--- NEW OPTION
382
+ markdownToHtml = false,
380
383
  }) {
381
384
  if (markdownToHtml) {
382
385
  // Push the async operation to the queue
@@ -608,8 +611,8 @@ class MimeMessage {
608
611
  "references",
609
612
  "in-reply-to",
610
613
  "content-id",
611
- "list-unsubscribe", // <--- Added
612
- "list-unsubscribe-post", // <--- Added
614
+ "list-unsubscribe",
615
+ "list-unsubscribe-post",
613
616
  ];
614
617
 
615
618
  if (doNotFold.includes(lowerName)) {
@@ -1,5 +1,5 @@
1
1
  // src/utility/mailParser.d.ts
2
- import type { ProcessMarkDownResult } from "../processMarkDown";
2
+ import type { MarkdownResult } from "../processMarkDown";
3
3
 
4
4
  /**
5
5
  * Generates a random numeric ID string for Doublelist posts.
@@ -50,7 +50,7 @@ export interface ParsedMailData {
50
50
  /** HTML body with tracking images removed */
51
51
  html: string;
52
52
  /** Processed markdown result from processMarkDown */
53
- markdownResult: ProcessMarkDownResult;
53
+ markdownResult: MarkdownResult;
54
54
  /** Plain text body */
55
55
  text: string;
56
56
  /** Number of attachments */
@@ -11,8 +11,8 @@ export const randomizeDoublelistPostID = (length = 11) => {
11
11
  // 1. Pick the first digit (1-9)
12
12
  let result = firstDigit.charAt(Math.floor(Math.random() * firstDigit.length));
13
13
  // 2. Generate the rest, stopping 1 digit early
14
- // If length is 11, this loop generates 9 more digits (Total: 10)
15
- for (let i = 1; i < length - 1; i++) {
14
+ // If length is 11, this loop generates 10 more digits (Total: 11)
15
+ for (let i = 1; i < length; i++) {
16
16
  result += restDigits.charAt(Math.floor(Math.random() * restDigits.length));
17
17
  }
18
18
  return result;