@utilix-tech/sdk 0.38.0 → 0.39.0

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/CHANGELOG.md CHANGED
@@ -2,6 +2,10 @@
2
2
 
3
3
  Full release notes for all Utilix surfaces (browser tools, REST API, SDKs, MCP server) live at [utilix.tech/changelog](https://utilix.tech/changelog). This file tracks just this package.
4
4
 
5
+ ## 0.39.0
6
+ - Add `generateSri`, `generateSriAll` (sri-hash-generator): compute SHA-256/384/512 Subresource Integrity hashes for a script or stylesheet's content, formatted as the `<algorithm>-<base64>` string an HTML `integrity` attribute expects.
7
+ - Add `analyzeEmailHeaders` (email-header-analyzer): parse a raw email header block into structured From/To/Subject fields, the Received hop chain in order, and SPF/DKIM/DMARC results from an Authentication-Results header.
8
+
5
9
  ## 0.38.0
6
10
  - Add `compareUnitPrices` (unit-price-comparator): compare two or more package options by price and quantity to find the true cost per unit, flag the cheapest, and report how much more expensive each other option is by percentage.
7
11
  - Add `csvToSqlInsert` (csv-to-sql-insert-generator): convert CSV data with a header row into parameterless SQL INSERT statements, with basic type inference (numbers/booleans unquoted, empty cells NULL) and ANSI/MySQL identifier quoting.
package/README.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # @utilix-tech/sdk
2
2
 
3
- **606 developer utility functions for Node.js: runs locally, no API key required.**
3
+ **610 developer utility functions for Node.js: runs locally, no API key required.**
4
4
 
5
5
  [![npm version](https://img.shields.io/npm/v/@utilix-tech/sdk?style=flat-square&color=cb3837)](https://www.npmjs.com/package/@utilix-tech/sdk)
6
6
  [![npm downloads](https://img.shields.io/npm/dm/@utilix-tech/sdk?style=flat-square)](https://www.npmjs.com/package/@utilix-tech/sdk)
@@ -119,7 +119,7 @@ base62Encode("hello world"); // "AAwf93rvy4aWQVw"
119
119
  ### `/hashing`: Hash & Password
120
120
 
121
121
  ```ts
122
- import { hashAll, hashOne, hashPassword, verifyPassword, generateHtpasswdFile } from "@utilix-tech/sdk/hashing";
122
+ import { hashAll, hashOne, hashPassword, verifyPassword, generateHtpasswdFile, generateSriAll } from "@utilix-tech/sdk/hashing";
123
123
 
124
124
  // Hash with MD5, SHA-1, SHA-256, SHA-512 in one call
125
125
  const hashes = await hashAll("my-string");
@@ -131,6 +131,10 @@ const valid = await verifyPassword("my-password", hash);
131
131
 
132
132
  // Generate .htpasswd file
133
133
  generateHtpasswdFile([{ username: "alice", password: "secret" }]);
134
+
135
+ // Subresource Integrity hashes for a script/stylesheet's content (SHA-256/384/512)
136
+ generateSriAll("console.log(1)");
137
+ // [{ algorithm: "SHA-256", base64: "...", integrity: "sha256-..." }, ...]
134
138
  ```
135
139
 
136
140
  ---
@@ -412,7 +416,7 @@ compareUnitPrices([{ label: "12-pack", price: 6, quantity: 12 }, { label: "24-pa
412
416
  import { getStatusCode, isValidIp, isValidIpv4, isValidIpv6,
413
417
  searchStatusCodes, buildGeoUrl, countryCodeToFlag,
414
418
  parseHar, validateSitemap, validateRobotsTxt,
415
- parseUserAgent, buildCacheControl, buildReferrerPolicy, parseIpv6Address, buildLinkHeader, checkSetCookieHeader } from "@utilix-tech/sdk/network";
419
+ parseUserAgent, buildCacheControl, buildReferrerPolicy, parseIpv6Address, buildLinkHeader, checkSetCookieHeader, analyzeEmailHeaders } from "@utilix-tech/sdk/network";
416
420
 
417
421
  getStatusCode(404);
418
422
  // { code: 404, text: "Not Found", description: "...", category: "Client Error" }
@@ -463,6 +467,10 @@ buildLinkHeader([{ url: "/fonts/inter.woff2", rel: "preload", as: "font", type:
463
467
  // Parse and validate a Set-Cookie header's attribute combination
464
468
  checkSetCookieHeader("session=abc123; SameSite=None");
465
469
  // { cookie: {...}, issues: ["SameSite=None requires the Secure attribute..."], warnings: [...], valid: false }
470
+
471
+ // Parse a raw email header block: fields, Received hop chain, SPF/DKIM/DMARC results
472
+ analyzeEmailHeaders(rawHeaderText);
473
+ // { from: "...", to: "...", receivedHops: [...], hopCount: 2, spf: "pass", dkim: "pass", dmarc: "pass", warnings: [] }
466
474
  ```
467
475
 
468
476
  ---
@@ -9,12 +9,15 @@ __export(hashing_exports, {
9
9
  HASH_ALGORITHMS: () => HASH_ALGORITHMS,
10
10
  HASH_BITS: () => HASH_BITS,
11
11
  ROUND_OPTIONS: () => ROUND_OPTIONS,
12
+ SRI_ALGORITHMS: () => SRI_ALGORITHMS,
12
13
  createEntry: () => createEntry,
13
14
  generateBcryptHash: () => generateBcryptHash,
14
15
  generateHtpasswdFile: () => generateHtpasswdFile,
15
16
  generateMd5Hash: () => generateMd5Hash,
16
17
  generatePlain: () => generatePlain,
17
18
  generateSha1Hash: () => generateSha1Hash,
19
+ generateSri: () => generateSri,
20
+ generateSriAll: () => generateSriAll,
18
21
  hashAll: () => hashAll,
19
22
  hashOne: () => hashOne,
20
23
  hashPassword: () => hashPassword,
@@ -247,5 +250,27 @@ function generateHtpasswdFile(entries) {
247
250
  function validateUsername(username) {
248
251
  return /^[^\s:]{1,255}$/.test(username);
249
252
  }
253
+ var SRI_ALGORITHMS = ["SHA-256", "SHA-384", "SHA-512"];
254
+ var SRI_NODE_ALG_MAP = {
255
+ "SHA-256": "sha256",
256
+ "SHA-384": "sha384",
257
+ "SHA-512": "sha512"
258
+ };
259
+ function generateSri(content, algorithm = "SHA-384") {
260
+ if (typeof content !== "string" || content.length === 0) {
261
+ return { error: "Content is required" };
262
+ }
263
+ if (!SRI_ALGORITHMS.includes(algorithm)) {
264
+ return { error: `Unknown algorithm: ${algorithm}. Must be one of ${SRI_ALGORITHMS.join(", ")}` };
265
+ }
266
+ const base64 = createHash(SRI_NODE_ALG_MAP[algorithm]).update(content, "utf8").digest("base64");
267
+ return { algorithm, base64, integrity: `${SRI_NODE_ALG_MAP[algorithm]}-${base64}` };
268
+ }
269
+ function generateSriAll(content) {
270
+ if (typeof content !== "string" || content.length === 0) {
271
+ return { error: "Content is required" };
272
+ }
273
+ return SRI_ALGORITHMS.map((alg) => generateSri(content, alg));
274
+ }
250
275
 
251
- export { HASH_ALGORITHMS, HASH_BITS, ROUND_OPTIONS, createEntry, generateBcryptHash, generateHtpasswdFile, generateMd5Hash, generatePlain, generateSha1Hash, hashAll, hashOne, hashPassword, hashWithTiming, hashing_exports, parseHtpasswdFile, validateRounds, validateUsername, verifyPassword };
276
+ export { HASH_ALGORITHMS, HASH_BITS, ROUND_OPTIONS, SRI_ALGORITHMS, createEntry, generateBcryptHash, generateHtpasswdFile, generateMd5Hash, generatePlain, generateSha1Hash, generateSri, generateSriAll, hashAll, hashOne, hashPassword, hashWithTiming, hashing_exports, parseHtpasswdFile, validateRounds, validateUsername, verifyPassword };
@@ -8,6 +8,7 @@ __export(network_exports, {
8
8
  LINK_REL_VALUES: () => LINK_REL_VALUES,
9
9
  REFERRER_POLICY_VALUES: () => REFERRER_POLICY_VALUES,
10
10
  STATUS_CODES: () => STATUS_CODES,
11
+ analyzeEmailHeaders: () => analyzeEmailHeaders,
11
12
  buildCacheControl: () => buildCacheControl,
12
13
  buildDnsQueryUrl: () => buildDnsQueryUrl,
13
14
  buildGeoUrl: () => buildGeoUrl,
@@ -2130,5 +2131,83 @@ function checkSetCookieHeader(header) {
2130
2131
  }
2131
2132
  return { cookie, issues, warnings, valid: issues.length === 0 };
2132
2133
  }
2134
+ function analyzeEmailHeaders(raw) {
2135
+ if (typeof raw !== "string" || !raw.trim()) {
2136
+ return { error: "Raw email header text is required" };
2137
+ }
2138
+ const normalized = raw.replace(/\r\n/g, "\n");
2139
+ const blockEnd = normalized.indexOf("\n\n");
2140
+ const headerBlock = blockEnd === -1 ? normalized : normalized.slice(0, blockEnd);
2141
+ const rawLines = headerBlock.split("\n");
2142
+ const unfolded = [];
2143
+ for (const line of rawLines) {
2144
+ if (/^[ \t]/.test(line) && unfolded.length > 0) {
2145
+ unfolded[unfolded.length - 1] += " " + line.trim();
2146
+ } else if (line.trim() !== "") {
2147
+ unfolded.push(line);
2148
+ }
2149
+ }
2150
+ const headers = [];
2151
+ for (const line of unfolded) {
2152
+ const colonIdx = line.indexOf(":");
2153
+ if (colonIdx === -1) continue;
2154
+ const name = line.slice(0, colonIdx).trim();
2155
+ const value = line.slice(colonIdx + 1).trim();
2156
+ if (!name) continue;
2157
+ headers.push({ name, value });
2158
+ }
2159
+ if (headers.length === 0) {
2160
+ return { error: 'No parseable headers found \u2014 expected lines like "From: ..." or "Received: ..."' };
2161
+ }
2162
+ const findFirst = (name) => headers.find((h) => h.name.toLowerCase() === name.toLowerCase())?.value ?? null;
2163
+ const findAll = (name) => headers.filter((h) => h.name.toLowerCase() === name.toLowerCase());
2164
+ const receivedHops = findAll("received").map((h, i) => {
2165
+ const fromMatch = h.value.match(/from\s+([^\s;]+(?:\s*\([^)]*\))?)/i);
2166
+ const byMatch = h.value.match(/\bby\s+([^\s;]+)/i);
2167
+ const segments = h.value.split(";");
2168
+ const date = segments.length > 1 ? segments[segments.length - 1].trim() : null;
2169
+ return {
2170
+ index: i + 1,
2171
+ raw: h.value,
2172
+ from: fromMatch ? fromMatch[1].trim() : null,
2173
+ by: byMatch ? byMatch[1].trim() : null,
2174
+ date: date || null
2175
+ };
2176
+ });
2177
+ const authResultsHeader = findFirst("authentication-results");
2178
+ const authResults = [];
2179
+ if (authResultsHeader) {
2180
+ const re = /\b(spf|dkim|dmarc)=(\w+)/gi;
2181
+ let m;
2182
+ while ((m = re.exec(authResultsHeader)) !== null) {
2183
+ authResults.push({ mechanism: m[1].toLowerCase(), result: m[2].toLowerCase() });
2184
+ }
2185
+ }
2186
+ const findAuth = (mechanism) => authResults.find((a) => a.mechanism === mechanism)?.result ?? null;
2187
+ const warnings = [];
2188
+ if (receivedHops.length === 0) {
2189
+ warnings.push("No Received headers found \u2014 this may be a partial header block rather than a full raw source.");
2190
+ }
2191
+ if (!authResultsHeader) {
2192
+ warnings.push("No Authentication-Results header found \u2014 SPF/DKIM/DMARC cannot be determined from this header block alone.");
2193
+ }
2194
+ return {
2195
+ headers,
2196
+ from: findFirst("from"),
2197
+ to: findFirst("to"),
2198
+ subject: findFirst("subject"),
2199
+ date: findFirst("date"),
2200
+ messageId: findFirst("message-id"),
2201
+ returnPath: findFirst("return-path"),
2202
+ replyTo: findFirst("reply-to"),
2203
+ receivedHops,
2204
+ hopCount: receivedHops.length,
2205
+ authResults,
2206
+ spf: findAuth("spf"),
2207
+ dkim: findAuth("dkim"),
2208
+ dmarc: findAuth("dmarc"),
2209
+ warnings
2210
+ };
2211
+ }
2133
2212
 
2134
- export { DNS_RECORD_TYPES, HTTP_HEADERS, LINK_REL_VALUES, REFERRER_POLICY_VALUES, STATUS_CODES, buildCacheControl, buildDnsQueryUrl, buildGeoUrl, buildLinkHeader, buildMapUrl, buildReferrerPolicy, checkSetCookieHeader, countryCodeToFlag, formatCoordinates, formatTtl, getByCategory, getHeader, getHeadersByCategory, getStatusByCategory, getStatusCode, isClientError, isServerError, isSuccess, isValidIp, isValidIpv4, isValidIpv6, network_exports, parseDnsResponse, parseGeoResponse, parseHar, parseIpv6Address, parseUserAgent, searchHeaders, searchStatusCodes, statusCodeToText, typeNumberToLabel, validateDomain, validateHeaderName, validateHeaderValue, validateRobotsTxt, validateSitemap };
2213
+ export { DNS_RECORD_TYPES, HTTP_HEADERS, LINK_REL_VALUES, REFERRER_POLICY_VALUES, STATUS_CODES, analyzeEmailHeaders, buildCacheControl, buildDnsQueryUrl, buildGeoUrl, buildLinkHeader, buildMapUrl, buildReferrerPolicy, checkSetCookieHeader, countryCodeToFlag, formatCoordinates, formatTtl, getByCategory, getHeader, getHeadersByCategory, getStatusByCategory, getStatusCode, isClientError, isServerError, isSuccess, isValidIp, isValidIpv4, isValidIpv6, network_exports, parseDnsResponse, parseGeoResponse, parseHar, parseIpv6Address, parseUserAgent, searchHeaders, searchStatusCodes, statusCodeToText, typeNumberToLabel, validateDomain, validateHeaderName, validateHeaderValue, validateRobotsTxt, validateSitemap };
@@ -7,6 +7,7 @@
7
7
  * - htpasswd : generateSha1Hash, generateMd5Hash, generateBcryptHash,
8
8
  * generatePlain, createEntry, parseHtpasswdFile,
9
9
  * generateHtpasswdFile, validateUsername
10
+ * - sri-hash-generator: generateSri, generateSriAll (SHA-256/384/512 Subresource Integrity hashes)
10
11
  */
11
12
  type HashAlgorithm = 'MD5' | 'SHA-1' | 'SHA-256' | 'SHA-384' | 'SHA-512';
12
13
  declare const HASH_ALGORITHMS: HashAlgorithm[];
@@ -46,6 +47,25 @@ declare function createEntry(username: string, password: string, algorithm?: Htp
46
47
  declare function parseHtpasswdFile(content: string): HtpasswdEntry[];
47
48
  declare function generateHtpasswdFile(entries: HtpasswdEntry[]): string;
48
49
  declare function validateUsername(username: string): boolean;
50
+ type SriAlgorithm = 'SHA-256' | 'SHA-384' | 'SHA-512';
51
+ declare const SRI_ALGORITHMS: SriAlgorithm[];
52
+ interface SriResult {
53
+ algorithm: SriAlgorithm;
54
+ base64: string;
55
+ integrity: string;
56
+ }
57
+ /**
58
+ * Compute a Subresource Integrity hash for the given file/script content:
59
+ * digest it with the chosen algorithm and base64-encode it into the
60
+ * `<algorithm>-<base64>` form used by an HTML `integrity` attribute.
61
+ */
62
+ declare function generateSri(content: string, algorithm?: SriAlgorithm): SriResult | {
63
+ error: string;
64
+ };
65
+ /** Compute SRI hashes for all three algorithms SRI supports (SHA-256/384/512). */
66
+ declare function generateSriAll(content: string): SriResult[] | {
67
+ error: string;
68
+ };
49
69
 
50
70
  type hashing_BcryptResult = BcryptResult;
51
71
  declare const hashing_HASH_ALGORITHMS: typeof HASH_ALGORITHMS;
@@ -55,12 +75,17 @@ type hashing_HashResult = HashResult;
55
75
  type hashing_HtpasswdAlgorithm = HtpasswdAlgorithm;
56
76
  type hashing_HtpasswdEntry = HtpasswdEntry;
57
77
  declare const hashing_ROUND_OPTIONS: typeof ROUND_OPTIONS;
78
+ declare const hashing_SRI_ALGORITHMS: typeof SRI_ALGORITHMS;
79
+ type hashing_SriAlgorithm = SriAlgorithm;
80
+ type hashing_SriResult = SriResult;
58
81
  declare const hashing_createEntry: typeof createEntry;
59
82
  declare const hashing_generateBcryptHash: typeof generateBcryptHash;
60
83
  declare const hashing_generateHtpasswdFile: typeof generateHtpasswdFile;
61
84
  declare const hashing_generateMd5Hash: typeof generateMd5Hash;
62
85
  declare const hashing_generatePlain: typeof generatePlain;
63
86
  declare const hashing_generateSha1Hash: typeof generateSha1Hash;
87
+ declare const hashing_generateSri: typeof generateSri;
88
+ declare const hashing_generateSriAll: typeof generateSriAll;
64
89
  declare const hashing_hashAll: typeof hashAll;
65
90
  declare const hashing_hashOne: typeof hashOne;
66
91
  declare const hashing_hashPassword: typeof hashPassword;
@@ -70,7 +95,7 @@ declare const hashing_validateRounds: typeof validateRounds;
70
95
  declare const hashing_validateUsername: typeof validateUsername;
71
96
  declare const hashing_verifyPassword: typeof verifyPassword;
72
97
  declare namespace hashing {
73
- export { type hashing_BcryptResult as BcryptResult, hashing_HASH_ALGORITHMS as HASH_ALGORITHMS, hashing_HASH_BITS as HASH_BITS, type hashing_HashAlgorithm as HashAlgorithm, type hashing_HashResult as HashResult, type hashing_HtpasswdAlgorithm as HtpasswdAlgorithm, type hashing_HtpasswdEntry as HtpasswdEntry, hashing_ROUND_OPTIONS as ROUND_OPTIONS, hashing_createEntry as createEntry, hashing_generateBcryptHash as generateBcryptHash, hashing_generateHtpasswdFile as generateHtpasswdFile, hashing_generateMd5Hash as generateMd5Hash, hashing_generatePlain as generatePlain, hashing_generateSha1Hash as generateSha1Hash, hashing_hashAll as hashAll, hashing_hashOne as hashOne, hashing_hashPassword as hashPassword, hashing_hashWithTiming as hashWithTiming, hashing_parseHtpasswdFile as parseHtpasswdFile, hashing_validateRounds as validateRounds, hashing_validateUsername as validateUsername, hashing_verifyPassword as verifyPassword };
98
+ export { type hashing_BcryptResult as BcryptResult, hashing_HASH_ALGORITHMS as HASH_ALGORITHMS, hashing_HASH_BITS as HASH_BITS, type hashing_HashAlgorithm as HashAlgorithm, type hashing_HashResult as HashResult, type hashing_HtpasswdAlgorithm as HtpasswdAlgorithm, type hashing_HtpasswdEntry as HtpasswdEntry, hashing_ROUND_OPTIONS as ROUND_OPTIONS, hashing_SRI_ALGORITHMS as SRI_ALGORITHMS, type hashing_SriAlgorithm as SriAlgorithm, type hashing_SriResult as SriResult, hashing_createEntry as createEntry, hashing_generateBcryptHash as generateBcryptHash, hashing_generateHtpasswdFile as generateHtpasswdFile, hashing_generateMd5Hash as generateMd5Hash, hashing_generatePlain as generatePlain, hashing_generateSha1Hash as generateSha1Hash, hashing_generateSri as generateSri, hashing_generateSriAll as generateSriAll, hashing_hashAll as hashAll, hashing_hashOne as hashOne, hashing_hashPassword as hashPassword, hashing_hashWithTiming as hashWithTiming, hashing_parseHtpasswdFile as parseHtpasswdFile, hashing_validateRounds as validateRounds, hashing_validateUsername as validateUsername, hashing_verifyPassword as verifyPassword };
74
99
  }
75
100
 
76
- export { type BcryptResult as B, HASH_ALGORITHMS as H, ROUND_OPTIONS as R, HASH_BITS as a, type HashAlgorithm as b, type HashResult as c, type HtpasswdAlgorithm as d, type HtpasswdEntry as e, createEntry as f, generateBcryptHash as g, hashing as h, generateHtpasswdFile as i, generateMd5Hash as j, generatePlain as k, generateSha1Hash as l, hashAll as m, hashOne as n, hashPassword as o, hashWithTiming as p, parseHtpasswdFile as q, validateUsername as r, verifyPassword as s, validateRounds as v };
101
+ export { type BcryptResult as B, HASH_ALGORITHMS as H, ROUND_OPTIONS as R, SRI_ALGORITHMS as S, HASH_BITS as a, type HashAlgorithm as b, type HashResult as c, type HtpasswdAlgorithm as d, type HtpasswdEntry as e, type SriAlgorithm as f, type SriResult as g, hashing as h, createEntry as i, generateBcryptHash as j, generateHtpasswdFile as k, generateMd5Hash as l, generatePlain as m, generateSha1Hash as n, generateSri as o, generateSriAll as p, hashAll as q, hashOne as r, hashPassword as s, hashWithTiming as t, parseHtpasswdFile as u, validateRounds as v, validateUsername as w, verifyPassword as x };
@@ -7,6 +7,7 @@
7
7
  * - htpasswd : generateSha1Hash, generateMd5Hash, generateBcryptHash,
8
8
  * generatePlain, createEntry, parseHtpasswdFile,
9
9
  * generateHtpasswdFile, validateUsername
10
+ * - sri-hash-generator: generateSri, generateSriAll (SHA-256/384/512 Subresource Integrity hashes)
10
11
  */
11
12
  type HashAlgorithm = 'MD5' | 'SHA-1' | 'SHA-256' | 'SHA-384' | 'SHA-512';
12
13
  declare const HASH_ALGORITHMS: HashAlgorithm[];
@@ -46,6 +47,25 @@ declare function createEntry(username: string, password: string, algorithm?: Htp
46
47
  declare function parseHtpasswdFile(content: string): HtpasswdEntry[];
47
48
  declare function generateHtpasswdFile(entries: HtpasswdEntry[]): string;
48
49
  declare function validateUsername(username: string): boolean;
50
+ type SriAlgorithm = 'SHA-256' | 'SHA-384' | 'SHA-512';
51
+ declare const SRI_ALGORITHMS: SriAlgorithm[];
52
+ interface SriResult {
53
+ algorithm: SriAlgorithm;
54
+ base64: string;
55
+ integrity: string;
56
+ }
57
+ /**
58
+ * Compute a Subresource Integrity hash for the given file/script content:
59
+ * digest it with the chosen algorithm and base64-encode it into the
60
+ * `<algorithm>-<base64>` form used by an HTML `integrity` attribute.
61
+ */
62
+ declare function generateSri(content: string, algorithm?: SriAlgorithm): SriResult | {
63
+ error: string;
64
+ };
65
+ /** Compute SRI hashes for all three algorithms SRI supports (SHA-256/384/512). */
66
+ declare function generateSriAll(content: string): SriResult[] | {
67
+ error: string;
68
+ };
49
69
 
50
70
  type hashing_BcryptResult = BcryptResult;
51
71
  declare const hashing_HASH_ALGORITHMS: typeof HASH_ALGORITHMS;
@@ -55,12 +75,17 @@ type hashing_HashResult = HashResult;
55
75
  type hashing_HtpasswdAlgorithm = HtpasswdAlgorithm;
56
76
  type hashing_HtpasswdEntry = HtpasswdEntry;
57
77
  declare const hashing_ROUND_OPTIONS: typeof ROUND_OPTIONS;
78
+ declare const hashing_SRI_ALGORITHMS: typeof SRI_ALGORITHMS;
79
+ type hashing_SriAlgorithm = SriAlgorithm;
80
+ type hashing_SriResult = SriResult;
58
81
  declare const hashing_createEntry: typeof createEntry;
59
82
  declare const hashing_generateBcryptHash: typeof generateBcryptHash;
60
83
  declare const hashing_generateHtpasswdFile: typeof generateHtpasswdFile;
61
84
  declare const hashing_generateMd5Hash: typeof generateMd5Hash;
62
85
  declare const hashing_generatePlain: typeof generatePlain;
63
86
  declare const hashing_generateSha1Hash: typeof generateSha1Hash;
87
+ declare const hashing_generateSri: typeof generateSri;
88
+ declare const hashing_generateSriAll: typeof generateSriAll;
64
89
  declare const hashing_hashAll: typeof hashAll;
65
90
  declare const hashing_hashOne: typeof hashOne;
66
91
  declare const hashing_hashPassword: typeof hashPassword;
@@ -70,7 +95,7 @@ declare const hashing_validateRounds: typeof validateRounds;
70
95
  declare const hashing_validateUsername: typeof validateUsername;
71
96
  declare const hashing_verifyPassword: typeof verifyPassword;
72
97
  declare namespace hashing {
73
- export { type hashing_BcryptResult as BcryptResult, hashing_HASH_ALGORITHMS as HASH_ALGORITHMS, hashing_HASH_BITS as HASH_BITS, type hashing_HashAlgorithm as HashAlgorithm, type hashing_HashResult as HashResult, type hashing_HtpasswdAlgorithm as HtpasswdAlgorithm, type hashing_HtpasswdEntry as HtpasswdEntry, hashing_ROUND_OPTIONS as ROUND_OPTIONS, hashing_createEntry as createEntry, hashing_generateBcryptHash as generateBcryptHash, hashing_generateHtpasswdFile as generateHtpasswdFile, hashing_generateMd5Hash as generateMd5Hash, hashing_generatePlain as generatePlain, hashing_generateSha1Hash as generateSha1Hash, hashing_hashAll as hashAll, hashing_hashOne as hashOne, hashing_hashPassword as hashPassword, hashing_hashWithTiming as hashWithTiming, hashing_parseHtpasswdFile as parseHtpasswdFile, hashing_validateRounds as validateRounds, hashing_validateUsername as validateUsername, hashing_verifyPassword as verifyPassword };
98
+ export { type hashing_BcryptResult as BcryptResult, hashing_HASH_ALGORITHMS as HASH_ALGORITHMS, hashing_HASH_BITS as HASH_BITS, type hashing_HashAlgorithm as HashAlgorithm, type hashing_HashResult as HashResult, type hashing_HtpasswdAlgorithm as HtpasswdAlgorithm, type hashing_HtpasswdEntry as HtpasswdEntry, hashing_ROUND_OPTIONS as ROUND_OPTIONS, hashing_SRI_ALGORITHMS as SRI_ALGORITHMS, type hashing_SriAlgorithm as SriAlgorithm, type hashing_SriResult as SriResult, hashing_createEntry as createEntry, hashing_generateBcryptHash as generateBcryptHash, hashing_generateHtpasswdFile as generateHtpasswdFile, hashing_generateMd5Hash as generateMd5Hash, hashing_generatePlain as generatePlain, hashing_generateSha1Hash as generateSha1Hash, hashing_generateSri as generateSri, hashing_generateSriAll as generateSriAll, hashing_hashAll as hashAll, hashing_hashOne as hashOne, hashing_hashPassword as hashPassword, hashing_hashWithTiming as hashWithTiming, hashing_parseHtpasswdFile as parseHtpasswdFile, hashing_validateRounds as validateRounds, hashing_validateUsername as validateUsername, hashing_verifyPassword as verifyPassword };
74
99
  }
75
100
 
76
- export { type BcryptResult as B, HASH_ALGORITHMS as H, ROUND_OPTIONS as R, HASH_BITS as a, type HashAlgorithm as b, type HashResult as c, type HtpasswdAlgorithm as d, type HtpasswdEntry as e, createEntry as f, generateBcryptHash as g, hashing as h, generateHtpasswdFile as i, generateMd5Hash as j, generatePlain as k, generateSha1Hash as l, hashAll as m, hashOne as n, hashPassword as o, hashWithTiming as p, parseHtpasswdFile as q, validateUsername as r, verifyPassword as s, validateRounds as v };
101
+ export { type BcryptResult as B, HASH_ALGORITHMS as H, ROUND_OPTIONS as R, SRI_ALGORITHMS as S, HASH_BITS as a, type HashAlgorithm as b, type HashResult as c, type HtpasswdAlgorithm as d, type HtpasswdEntry as e, type SriAlgorithm as f, type SriResult as g, hashing as h, createEntry as i, generateBcryptHash as j, generateHtpasswdFile as k, generateMd5Hash as l, generatePlain as m, generateSha1Hash as n, generateSri as o, generateSriAll as p, hashAll as q, hashOne as r, hashPassword as s, hashWithTiming as t, parseHtpasswdFile as u, validateRounds as v, validateUsername as w, verifyPassword as x };
package/dist/index.cjs CHANGED
@@ -1769,12 +1769,15 @@ __export(hashing_exports, {
1769
1769
  HASH_ALGORITHMS: () => HASH_ALGORITHMS,
1770
1770
  HASH_BITS: () => HASH_BITS,
1771
1771
  ROUND_OPTIONS: () => ROUND_OPTIONS,
1772
+ SRI_ALGORITHMS: () => SRI_ALGORITHMS,
1772
1773
  createEntry: () => createEntry,
1773
1774
  generateBcryptHash: () => generateBcryptHash,
1774
1775
  generateHtpasswdFile: () => generateHtpasswdFile,
1775
1776
  generateMd5Hash: () => generateMd5Hash,
1776
1777
  generatePlain: () => generatePlain,
1777
1778
  generateSha1Hash: () => generateSha1Hash,
1779
+ generateSri: () => generateSri,
1780
+ generateSriAll: () => generateSriAll,
1778
1781
  hashAll: () => hashAll,
1779
1782
  hashOne: () => hashOne,
1780
1783
  hashPassword: () => hashPassword,
@@ -2007,6 +2010,28 @@ function generateHtpasswdFile(entries) {
2007
2010
  function validateUsername(username) {
2008
2011
  return /^[^\s:]{1,255}$/.test(username);
2009
2012
  }
2013
+ var SRI_ALGORITHMS = ["SHA-256", "SHA-384", "SHA-512"];
2014
+ var SRI_NODE_ALG_MAP = {
2015
+ "SHA-256": "sha256",
2016
+ "SHA-384": "sha384",
2017
+ "SHA-512": "sha512"
2018
+ };
2019
+ function generateSri(content, algorithm = "SHA-384") {
2020
+ if (typeof content !== "string" || content.length === 0) {
2021
+ return { error: "Content is required" };
2022
+ }
2023
+ if (!SRI_ALGORITHMS.includes(algorithm)) {
2024
+ return { error: `Unknown algorithm: ${algorithm}. Must be one of ${SRI_ALGORITHMS.join(", ")}` };
2025
+ }
2026
+ const base64 = crypto.createHash(SRI_NODE_ALG_MAP[algorithm]).update(content, "utf8").digest("base64");
2027
+ return { algorithm, base64, integrity: `${SRI_NODE_ALG_MAP[algorithm]}-${base64}` };
2028
+ }
2029
+ function generateSriAll(content) {
2030
+ if (typeof content !== "string" || content.length === 0) {
2031
+ return { error: "Content is required" };
2032
+ }
2033
+ return SRI_ALGORITHMS.map((alg) => generateSri(content, alg));
2034
+ }
2010
2035
 
2011
2036
  // src/tools/text.ts
2012
2037
  var text_exports = {};
@@ -9748,6 +9773,7 @@ __export(network_exports, {
9748
9773
  LINK_REL_VALUES: () => LINK_REL_VALUES,
9749
9774
  REFERRER_POLICY_VALUES: () => REFERRER_POLICY_VALUES,
9750
9775
  STATUS_CODES: () => STATUS_CODES,
9776
+ analyzeEmailHeaders: () => analyzeEmailHeaders,
9751
9777
  buildCacheControl: () => buildCacheControl,
9752
9778
  buildDnsQueryUrl: () => buildDnsQueryUrl,
9753
9779
  buildGeoUrl: () => buildGeoUrl,
@@ -11870,6 +11896,84 @@ function checkSetCookieHeader(header) {
11870
11896
  }
11871
11897
  return { cookie, issues, warnings, valid: issues.length === 0 };
11872
11898
  }
11899
+ function analyzeEmailHeaders(raw) {
11900
+ if (typeof raw !== "string" || !raw.trim()) {
11901
+ return { error: "Raw email header text is required" };
11902
+ }
11903
+ const normalized = raw.replace(/\r\n/g, "\n");
11904
+ const blockEnd = normalized.indexOf("\n\n");
11905
+ const headerBlock = blockEnd === -1 ? normalized : normalized.slice(0, blockEnd);
11906
+ const rawLines = headerBlock.split("\n");
11907
+ const unfolded = [];
11908
+ for (const line of rawLines) {
11909
+ if (/^[ \t]/.test(line) && unfolded.length > 0) {
11910
+ unfolded[unfolded.length - 1] += " " + line.trim();
11911
+ } else if (line.trim() !== "") {
11912
+ unfolded.push(line);
11913
+ }
11914
+ }
11915
+ const headers = [];
11916
+ for (const line of unfolded) {
11917
+ const colonIdx = line.indexOf(":");
11918
+ if (colonIdx === -1) continue;
11919
+ const name = line.slice(0, colonIdx).trim();
11920
+ const value = line.slice(colonIdx + 1).trim();
11921
+ if (!name) continue;
11922
+ headers.push({ name, value });
11923
+ }
11924
+ if (headers.length === 0) {
11925
+ return { error: 'No parseable headers found \u2014 expected lines like "From: ..." or "Received: ..."' };
11926
+ }
11927
+ const findFirst = (name) => headers.find((h) => h.name.toLowerCase() === name.toLowerCase())?.value ?? null;
11928
+ const findAll = (name) => headers.filter((h) => h.name.toLowerCase() === name.toLowerCase());
11929
+ const receivedHops = findAll("received").map((h, i) => {
11930
+ const fromMatch = h.value.match(/from\s+([^\s;]+(?:\s*\([^)]*\))?)/i);
11931
+ const byMatch = h.value.match(/\bby\s+([^\s;]+)/i);
11932
+ const segments = h.value.split(";");
11933
+ const date = segments.length > 1 ? segments[segments.length - 1].trim() : null;
11934
+ return {
11935
+ index: i + 1,
11936
+ raw: h.value,
11937
+ from: fromMatch ? fromMatch[1].trim() : null,
11938
+ by: byMatch ? byMatch[1].trim() : null,
11939
+ date: date || null
11940
+ };
11941
+ });
11942
+ const authResultsHeader = findFirst("authentication-results");
11943
+ const authResults = [];
11944
+ if (authResultsHeader) {
11945
+ const re = /\b(spf|dkim|dmarc)=(\w+)/gi;
11946
+ let m;
11947
+ while ((m = re.exec(authResultsHeader)) !== null) {
11948
+ authResults.push({ mechanism: m[1].toLowerCase(), result: m[2].toLowerCase() });
11949
+ }
11950
+ }
11951
+ const findAuth = (mechanism) => authResults.find((a) => a.mechanism === mechanism)?.result ?? null;
11952
+ const warnings = [];
11953
+ if (receivedHops.length === 0) {
11954
+ warnings.push("No Received headers found \u2014 this may be a partial header block rather than a full raw source.");
11955
+ }
11956
+ if (!authResultsHeader) {
11957
+ warnings.push("No Authentication-Results header found \u2014 SPF/DKIM/DMARC cannot be determined from this header block alone.");
11958
+ }
11959
+ return {
11960
+ headers,
11961
+ from: findFirst("from"),
11962
+ to: findFirst("to"),
11963
+ subject: findFirst("subject"),
11964
+ date: findFirst("date"),
11965
+ messageId: findFirst("message-id"),
11966
+ returnPath: findFirst("return-path"),
11967
+ replyTo: findFirst("reply-to"),
11968
+ receivedHops,
11969
+ hopCount: receivedHops.length,
11970
+ authResults,
11971
+ spf: findAuth("spf"),
11972
+ dkim: findAuth("dkim"),
11973
+ dmarc: findAuth("dmarc"),
11974
+ warnings
11975
+ };
11976
+ }
11873
11977
 
11874
11978
  // src/tools/api.ts
11875
11979
  var api_exports = {};
package/dist/index.d.cts CHANGED
@@ -1,12 +1,12 @@
1
1
  export { j as json } from './json-Ta9JykSB.cjs';
2
2
  export { e as encoding } from './encoding-Dk3wpmb3.cjs';
3
- export { h as hashing } from './hashing-CnetQFD_.cjs';
3
+ export { h as hashing } from './hashing-Dnj0IAZf.cjs';
4
4
  export { t as text } from './text-kHkT9VtT.cjs';
5
5
  export { d as data } from './data-BCf3dm-E.cjs';
6
6
  export { g as generators } from './generators-Du8cBesn.cjs';
7
7
  export { t as time } from './time-KqJjdqII.cjs';
8
8
  export { u as units } from './units-HQrMCiNM.cjs';
9
- export { n as network } from './network-CnKUQT4g.cjs';
9
+ export { n as network } from './network-CKPoesdD.cjs';
10
10
  export { a as api } from './api-DmTNE4c1.cjs';
11
11
  export { c as code } from './code-KXoRsHtl.cjs';
12
12
  export { c as color } from './color-tPwZCr9H.cjs';
package/dist/index.d.ts CHANGED
@@ -1,12 +1,12 @@
1
1
  export { j as json } from './json-Ta9JykSB.js';
2
2
  export { e as encoding } from './encoding-Dk3wpmb3.js';
3
- export { h as hashing } from './hashing-CnetQFD_.js';
3
+ export { h as hashing } from './hashing-Dnj0IAZf.js';
4
4
  export { t as text } from './text-kHkT9VtT.js';
5
5
  export { d as data } from './data-BCf3dm-E.js';
6
6
  export { g as generators } from './generators-Du8cBesn.js';
7
7
  export { t as time } from './time-KqJjdqII.js';
8
8
  export { u as units } from './units-HQrMCiNM.js';
9
- export { n as network } from './network-CnKUQT4g.js';
9
+ export { n as network } from './network-CKPoesdD.js';
10
10
  export { a as api } from './api-DmTNE4c1.js';
11
11
  export { c as code } from './code-KXoRsHtl.js';
12
12
  export { c as color } from './color-tPwZCr9H.js';
package/dist/index.js CHANGED
@@ -1,6 +1,6 @@
1
1
  export { media_exports as media } from './chunk-L6V4W4SU.js';
2
2
  export { units_exports as units } from './chunk-47RI5V3B.js';
3
- export { network_exports as network } from './chunk-DBNTO3YO.js';
3
+ export { network_exports as network } from './chunk-Y4BVU76A.js';
4
4
  export { api_exports as api } from './chunk-52ZDKSIX.js';
5
5
  export { code_exports as code } from './chunk-JL7YTXRB.js';
6
6
  export { color_exports as color } from './chunk-BPVAB4P2.js';
@@ -9,7 +9,7 @@ export { misc_exports as misc } from './chunk-GX7H6TAX.js';
9
9
  export { ai_agent_exports as ai_agent } from './chunk-W3J7GZVQ.js';
10
10
  export { json_exports as json } from './chunk-WVEKRKGU.js';
11
11
  export { encoding_exports as encoding } from './chunk-DOWQZUTP.js';
12
- export { hashing_exports as hashing } from './chunk-GEFVMGZR.js';
12
+ export { hashing_exports as hashing } from './chunk-VEVNIGJ6.js';
13
13
  export { text_exports as text } from './chunk-F2CEN226.js';
14
14
  export { data_exports as data } from './chunk-RZUNTYEH.js';
15
15
  export { generators_exports as generators } from './chunk-3TYWIX3B.js';
@@ -16,6 +16,7 @@
16
16
  * - ipv6-compressor: parseIpv6Address
17
17
  * - link-header-builder: buildLinkHeader
18
18
  * - same-site-cookie-checker: checkSetCookieHeader
19
+ * - email-header-analyzer: analyzeEmailHeaders
19
20
  */
20
21
  declare const DNS_RECORD_TYPES: readonly ["A", "AAAA", "CNAME", "MX", "TXT", "NS", "SOA", "PTR", "SRV", "CAA"];
21
22
  type DnsRecordType = typeof DNS_RECORD_TYPES[number];
@@ -402,7 +403,52 @@ interface CookieCheckResult {
402
403
  declare function checkSetCookieHeader(header: string): CookieCheckResult | {
403
404
  error: string;
404
405
  };
406
+ interface EmailHeaderField {
407
+ name: string;
408
+ value: string;
409
+ }
410
+ interface ReceivedHop {
411
+ index: number;
412
+ raw: string;
413
+ from: string | null;
414
+ by: string | null;
415
+ date: string | null;
416
+ }
417
+ interface AuthResultEntry {
418
+ mechanism: string;
419
+ result: string;
420
+ }
421
+ interface EmailHeaderAnalysis {
422
+ headers: EmailHeaderField[];
423
+ from: string | null;
424
+ to: string | null;
425
+ subject: string | null;
426
+ date: string | null;
427
+ messageId: string | null;
428
+ returnPath: string | null;
429
+ replyTo: string | null;
430
+ receivedHops: ReceivedHop[];
431
+ hopCount: number;
432
+ authResults: AuthResultEntry[];
433
+ spf: string | null;
434
+ dkim: string | null;
435
+ dmarc: string | null;
436
+ warnings: string[];
437
+ }
438
+ /**
439
+ * Parse a raw email header block (e.g. Gmail's "Show original", or the
440
+ * headers from a .eml file) into structured fields, the Received hop chain
441
+ * in the order they appear (top = most recently added, i.e. closest to the
442
+ * final destination), and any SPF/DKIM/DMARC verdicts found in an
443
+ * Authentication-Results header. Header folding (continuation lines starting
444
+ * with whitespace) is unfolded before parsing. This never performs a live
445
+ * DNS/SPF/DKIM check — it only reports what the headers already claim.
446
+ */
447
+ declare function analyzeEmailHeaders(raw: string): EmailHeaderAnalysis | {
448
+ error: string;
449
+ };
405
450
 
451
+ type network_AuthResultEntry = AuthResultEntry;
406
452
  type network_CacheControlDirective = CacheControlDirective;
407
453
  type network_CacheControlOptions = CacheControlOptions;
408
454
  type network_CacheControlResult = CacheControlResult;
@@ -412,6 +458,8 @@ declare const network_DNS_RECORD_TYPES: typeof DNS_RECORD_TYPES;
412
458
  type network_DnsRecord = DnsRecord;
413
459
  type network_DnsRecordType = DnsRecordType;
414
460
  type network_DnsResponse = DnsResponse;
461
+ type network_EmailHeaderAnalysis = EmailHeaderAnalysis;
462
+ type network_EmailHeaderField = EmailHeaderField;
415
463
  type network_GeoResult = GeoResult;
416
464
  declare const network_HTTP_HEADERS: typeof HTTP_HEADERS;
417
465
  type network_HarEntry = HarEntry;
@@ -429,6 +477,7 @@ type network_LinkRel = LinkRel;
429
477
  type network_ParsedDnsResult = ParsedDnsResult;
430
478
  type network_ParsedGeoResult = ParsedGeoResult;
431
479
  declare const network_REFERRER_POLICY_VALUES: typeof REFERRER_POLICY_VALUES;
480
+ type network_ReceivedHop = ReceivedHop;
432
481
  type network_ReferrerPolicyEntry = ReferrerPolicyEntry;
433
482
  type network_ReferrerPolicyResult = ReferrerPolicyResult;
434
483
  type network_ReferrerPolicyValue = ReferrerPolicyValue;
@@ -445,6 +494,7 @@ type network_SitemapValidationResult = SitemapValidationResult;
445
494
  type network_StatusCode = StatusCode;
446
495
  type network_UaDeviceType = UaDeviceType;
447
496
  type network_UserAgentInfo = UserAgentInfo;
497
+ declare const network_analyzeEmailHeaders: typeof analyzeEmailHeaders;
448
498
  declare const network_buildCacheControl: typeof buildCacheControl;
449
499
  declare const network_buildDnsQueryUrl: typeof buildDnsQueryUrl;
450
500
  declare const network_buildGeoUrl: typeof buildGeoUrl;
@@ -481,7 +531,7 @@ declare const network_validateHeaderValue: typeof validateHeaderValue;
481
531
  declare const network_validateRobotsTxt: typeof validateRobotsTxt;
482
532
  declare const network_validateSitemap: typeof validateSitemap;
483
533
  declare namespace network {
484
- export { type network_CacheControlDirective as CacheControlDirective, type network_CacheControlOptions as CacheControlOptions, type network_CacheControlResult as CacheControlResult, type network_CookieAttributes as CookieAttributes, type network_CookieCheckResult as CookieCheckResult, network_DNS_RECORD_TYPES as DNS_RECORD_TYPES, type network_DnsRecord as DnsRecord, type network_DnsRecordType as DnsRecordType, type network_DnsResponse as DnsResponse, type network_GeoResult as GeoResult, network_HTTP_HEADERS as HTTP_HEADERS, type network_HarEntry as HarEntry, type network_HarParseResult as HarParseResult, type network_HarSummary as HarSummary, type network_HeaderCategory as HeaderCategory, type network_HttpHeader as HttpHeader, type network_Ipv6AddressType as Ipv6AddressType, type network_Ipv6ParseResult as Ipv6ParseResult, network_LINK_REL_VALUES as LINK_REL_VALUES, type network_LinkHeaderEntry as LinkHeaderEntry, type network_LinkHeaderEntryInput as LinkHeaderEntryInput, type network_LinkHeaderResult as LinkHeaderResult, type network_LinkRel as LinkRel, type network_ParsedDnsResult as ParsedDnsResult, type network_ParsedGeoResult as ParsedGeoResult, network_REFERRER_POLICY_VALUES as REFERRER_POLICY_VALUES, type network_ReferrerPolicyEntry as ReferrerPolicyEntry, type network_ReferrerPolicyResult as ReferrerPolicyResult, type network_ReferrerPolicyValue as ReferrerPolicyValue, type network_RobotsGroup as RobotsGroup, type network_RobotsIssue as RobotsIssue, type network_RobotsRule as RobotsRule, type network_RobotsValidationResult as RobotsValidationResult, network_STATUS_CODES as STATUS_CODES, type network_SameSiteValue as SameSiteValue, type network_SitemapIndexEntry as SitemapIndexEntry, type network_SitemapIssue as SitemapIssue, type network_SitemapUrlEntry as SitemapUrlEntry, type network_SitemapValidationResult as SitemapValidationResult, type network_StatusCode as StatusCode, type network_UaDeviceType as UaDeviceType, type network_UserAgentInfo as UserAgentInfo, network_buildCacheControl as buildCacheControl, network_buildDnsQueryUrl as buildDnsQueryUrl, network_buildGeoUrl as buildGeoUrl, network_buildLinkHeader as buildLinkHeader, network_buildMapUrl as buildMapUrl, network_buildReferrerPolicy as buildReferrerPolicy, network_checkSetCookieHeader as checkSetCookieHeader, network_countryCodeToFlag as countryCodeToFlag, network_formatCoordinates as formatCoordinates, network_formatTtl as formatTtl, network_getByCategory as getByCategory, network_getHeader as getHeader, network_getHeadersByCategory as getHeadersByCategory, network_getStatusByCategory as getStatusByCategory, network_getStatusCode as getStatusCode, network_isClientError as isClientError, network_isServerError as isServerError, network_isSuccess as isSuccess, network_isValidIp as isValidIp, network_isValidIpv4 as isValidIpv4, network_isValidIpv6 as isValidIpv6, network_parseDnsResponse as parseDnsResponse, network_parseGeoResponse as parseGeoResponse, network_parseHar as parseHar, network_parseIpv6Address as parseIpv6Address, network_parseUserAgent as parseUserAgent, network_searchHeaders as searchHeaders, network_searchStatusCodes as searchStatusCodes, network_statusCodeToText as statusCodeToText, network_typeNumberToLabel as typeNumberToLabel, network_validateDomain as validateDomain, network_validateHeaderName as validateHeaderName, network_validateHeaderValue as validateHeaderValue, network_validateRobotsTxt as validateRobotsTxt, network_validateSitemap as validateSitemap };
534
+ export { type network_AuthResultEntry as AuthResultEntry, type network_CacheControlDirective as CacheControlDirective, type network_CacheControlOptions as CacheControlOptions, type network_CacheControlResult as CacheControlResult, type network_CookieAttributes as CookieAttributes, type network_CookieCheckResult as CookieCheckResult, network_DNS_RECORD_TYPES as DNS_RECORD_TYPES, type network_DnsRecord as DnsRecord, type network_DnsRecordType as DnsRecordType, type network_DnsResponse as DnsResponse, type network_EmailHeaderAnalysis as EmailHeaderAnalysis, type network_EmailHeaderField as EmailHeaderField, type network_GeoResult as GeoResult, network_HTTP_HEADERS as HTTP_HEADERS, type network_HarEntry as HarEntry, type network_HarParseResult as HarParseResult, type network_HarSummary as HarSummary, type network_HeaderCategory as HeaderCategory, type network_HttpHeader as HttpHeader, type network_Ipv6AddressType as Ipv6AddressType, type network_Ipv6ParseResult as Ipv6ParseResult, network_LINK_REL_VALUES as LINK_REL_VALUES, type network_LinkHeaderEntry as LinkHeaderEntry, type network_LinkHeaderEntryInput as LinkHeaderEntryInput, type network_LinkHeaderResult as LinkHeaderResult, type network_LinkRel as LinkRel, type network_ParsedDnsResult as ParsedDnsResult, type network_ParsedGeoResult as ParsedGeoResult, network_REFERRER_POLICY_VALUES as REFERRER_POLICY_VALUES, type network_ReceivedHop as ReceivedHop, type network_ReferrerPolicyEntry as ReferrerPolicyEntry, type network_ReferrerPolicyResult as ReferrerPolicyResult, type network_ReferrerPolicyValue as ReferrerPolicyValue, type network_RobotsGroup as RobotsGroup, type network_RobotsIssue as RobotsIssue, type network_RobotsRule as RobotsRule, type network_RobotsValidationResult as RobotsValidationResult, network_STATUS_CODES as STATUS_CODES, type network_SameSiteValue as SameSiteValue, type network_SitemapIndexEntry as SitemapIndexEntry, type network_SitemapIssue as SitemapIssue, type network_SitemapUrlEntry as SitemapUrlEntry, type network_SitemapValidationResult as SitemapValidationResult, type network_StatusCode as StatusCode, type network_UaDeviceType as UaDeviceType, type network_UserAgentInfo as UserAgentInfo, network_analyzeEmailHeaders as analyzeEmailHeaders, network_buildCacheControl as buildCacheControl, network_buildDnsQueryUrl as buildDnsQueryUrl, network_buildGeoUrl as buildGeoUrl, network_buildLinkHeader as buildLinkHeader, network_buildMapUrl as buildMapUrl, network_buildReferrerPolicy as buildReferrerPolicy, network_checkSetCookieHeader as checkSetCookieHeader, network_countryCodeToFlag as countryCodeToFlag, network_formatCoordinates as formatCoordinates, network_formatTtl as formatTtl, network_getByCategory as getByCategory, network_getHeader as getHeader, network_getHeadersByCategory as getHeadersByCategory, network_getStatusByCategory as getStatusByCategory, network_getStatusCode as getStatusCode, network_isClientError as isClientError, network_isServerError as isServerError, network_isSuccess as isSuccess, network_isValidIp as isValidIp, network_isValidIpv4 as isValidIpv4, network_isValidIpv6 as isValidIpv6, network_parseDnsResponse as parseDnsResponse, network_parseGeoResponse as parseGeoResponse, network_parseHar as parseHar, network_parseIpv6Address as parseIpv6Address, network_parseUserAgent as parseUserAgent, network_searchHeaders as searchHeaders, network_searchStatusCodes as searchStatusCodes, network_statusCodeToText as statusCodeToText, network_typeNumberToLabel as typeNumberToLabel, network_validateDomain as validateDomain, network_validateHeaderName as validateHeaderName, network_validateHeaderValue as validateHeaderValue, network_validateRobotsTxt as validateRobotsTxt, network_validateSitemap as validateSitemap };
485
535
  }
486
536
 
487
- export { getByCategory as $, type SameSiteValue as A, type SitemapIndexEntry as B, type CacheControlDirective as C, DNS_RECORD_TYPES as D, type SitemapIssue as E, type SitemapUrlEntry as F, type GeoResult as G, HTTP_HEADERS as H, type Ipv6AddressType as I, type SitemapValidationResult as J, type StatusCode as K, LINK_REL_VALUES as L, type UserAgentInfo as M, buildCacheControl as N, buildDnsQueryUrl as O, type ParsedDnsResult as P, buildGeoUrl as Q, REFERRER_POLICY_VALUES as R, STATUS_CODES as S, buildLinkHeader as T, type UaDeviceType as U, buildMapUrl as V, buildReferrerPolicy as W, checkSetCookieHeader as X, countryCodeToFlag as Y, formatCoordinates as Z, formatTtl as _, type CacheControlOptions as a, getHeader as a0, getHeadersByCategory as a1, getStatusByCategory as a2, getStatusCode as a3, isClientError as a4, isServerError as a5, isSuccess as a6, isValidIp as a7, isValidIpv4 as a8, isValidIpv6 as a9, parseDnsResponse as aa, parseGeoResponse as ab, parseHar as ac, parseIpv6Address as ad, parseUserAgent as ae, searchHeaders as af, searchStatusCodes as ag, statusCodeToText as ah, typeNumberToLabel as ai, validateDomain as aj, validateHeaderName as ak, validateHeaderValue as al, validateRobotsTxt as am, validateSitemap as an, type CacheControlResult as b, type CookieAttributes as c, type CookieCheckResult as d, type DnsRecord as e, type DnsRecordType as f, type DnsResponse as g, type HarEntry as h, type HarParseResult as i, type HarSummary as j, type HeaderCategory as k, type HttpHeader as l, type Ipv6ParseResult as m, network as n, type LinkHeaderEntry as o, type LinkHeaderEntryInput as p, type LinkHeaderResult as q, type LinkRel as r, type ParsedGeoResult as s, type ReferrerPolicyEntry as t, type ReferrerPolicyResult as u, type ReferrerPolicyValue as v, type RobotsGroup as w, type RobotsIssue as x, type RobotsRule as y, type RobotsValidationResult as z };
537
+ export { buildReferrerPolicy as $, type AuthResultEntry as A, type RobotsRule as B, type CacheControlDirective as C, DNS_RECORD_TYPES as D, type EmailHeaderAnalysis as E, type RobotsValidationResult as F, type GeoResult as G, HTTP_HEADERS as H, type Ipv6AddressType as I, type SameSiteValue as J, type SitemapIndexEntry as K, LINK_REL_VALUES as L, type SitemapIssue as M, type SitemapUrlEntry as N, type SitemapValidationResult as O, type ParsedDnsResult as P, type StatusCode as Q, REFERRER_POLICY_VALUES as R, STATUS_CODES as S, type UserAgentInfo as T, type UaDeviceType as U, analyzeEmailHeaders as V, buildCacheControl as W, buildDnsQueryUrl as X, buildGeoUrl as Y, buildLinkHeader as Z, buildMapUrl as _, type CacheControlOptions as a, checkSetCookieHeader as a0, countryCodeToFlag as a1, formatCoordinates as a2, formatTtl as a3, getByCategory as a4, getHeader as a5, getHeadersByCategory as a6, getStatusByCategory as a7, getStatusCode as a8, isClientError as a9, isServerError as aa, isSuccess as ab, isValidIp as ac, isValidIpv4 as ad, isValidIpv6 as ae, parseDnsResponse as af, parseGeoResponse as ag, parseHar as ah, parseIpv6Address as ai, parseUserAgent as aj, searchHeaders as ak, searchStatusCodes as al, statusCodeToText as am, typeNumberToLabel as an, validateDomain as ao, validateHeaderName as ap, validateHeaderValue as aq, validateRobotsTxt as ar, validateSitemap as as, type CacheControlResult as b, type CookieAttributes as c, type CookieCheckResult as d, type DnsRecord as e, type DnsRecordType as f, type DnsResponse as g, type EmailHeaderField as h, type HarEntry as i, type HarParseResult as j, type HarSummary as k, type HeaderCategory as l, type HttpHeader as m, network as n, type Ipv6ParseResult as o, type LinkHeaderEntry as p, type LinkHeaderEntryInput as q, type LinkHeaderResult as r, type LinkRel as s, type ParsedGeoResult as t, type ReceivedHop as u, type ReferrerPolicyEntry as v, type ReferrerPolicyResult as w, type ReferrerPolicyValue as x, type RobotsGroup as y, type RobotsIssue as z };
@@ -16,6 +16,7 @@
16
16
  * - ipv6-compressor: parseIpv6Address
17
17
  * - link-header-builder: buildLinkHeader
18
18
  * - same-site-cookie-checker: checkSetCookieHeader
19
+ * - email-header-analyzer: analyzeEmailHeaders
19
20
  */
20
21
  declare const DNS_RECORD_TYPES: readonly ["A", "AAAA", "CNAME", "MX", "TXT", "NS", "SOA", "PTR", "SRV", "CAA"];
21
22
  type DnsRecordType = typeof DNS_RECORD_TYPES[number];
@@ -402,7 +403,52 @@ interface CookieCheckResult {
402
403
  declare function checkSetCookieHeader(header: string): CookieCheckResult | {
403
404
  error: string;
404
405
  };
406
+ interface EmailHeaderField {
407
+ name: string;
408
+ value: string;
409
+ }
410
+ interface ReceivedHop {
411
+ index: number;
412
+ raw: string;
413
+ from: string | null;
414
+ by: string | null;
415
+ date: string | null;
416
+ }
417
+ interface AuthResultEntry {
418
+ mechanism: string;
419
+ result: string;
420
+ }
421
+ interface EmailHeaderAnalysis {
422
+ headers: EmailHeaderField[];
423
+ from: string | null;
424
+ to: string | null;
425
+ subject: string | null;
426
+ date: string | null;
427
+ messageId: string | null;
428
+ returnPath: string | null;
429
+ replyTo: string | null;
430
+ receivedHops: ReceivedHop[];
431
+ hopCount: number;
432
+ authResults: AuthResultEntry[];
433
+ spf: string | null;
434
+ dkim: string | null;
435
+ dmarc: string | null;
436
+ warnings: string[];
437
+ }
438
+ /**
439
+ * Parse a raw email header block (e.g. Gmail's "Show original", or the
440
+ * headers from a .eml file) into structured fields, the Received hop chain
441
+ * in the order they appear (top = most recently added, i.e. closest to the
442
+ * final destination), and any SPF/DKIM/DMARC verdicts found in an
443
+ * Authentication-Results header. Header folding (continuation lines starting
444
+ * with whitespace) is unfolded before parsing. This never performs a live
445
+ * DNS/SPF/DKIM check — it only reports what the headers already claim.
446
+ */
447
+ declare function analyzeEmailHeaders(raw: string): EmailHeaderAnalysis | {
448
+ error: string;
449
+ };
405
450
 
451
+ type network_AuthResultEntry = AuthResultEntry;
406
452
  type network_CacheControlDirective = CacheControlDirective;
407
453
  type network_CacheControlOptions = CacheControlOptions;
408
454
  type network_CacheControlResult = CacheControlResult;
@@ -412,6 +458,8 @@ declare const network_DNS_RECORD_TYPES: typeof DNS_RECORD_TYPES;
412
458
  type network_DnsRecord = DnsRecord;
413
459
  type network_DnsRecordType = DnsRecordType;
414
460
  type network_DnsResponse = DnsResponse;
461
+ type network_EmailHeaderAnalysis = EmailHeaderAnalysis;
462
+ type network_EmailHeaderField = EmailHeaderField;
415
463
  type network_GeoResult = GeoResult;
416
464
  declare const network_HTTP_HEADERS: typeof HTTP_HEADERS;
417
465
  type network_HarEntry = HarEntry;
@@ -429,6 +477,7 @@ type network_LinkRel = LinkRel;
429
477
  type network_ParsedDnsResult = ParsedDnsResult;
430
478
  type network_ParsedGeoResult = ParsedGeoResult;
431
479
  declare const network_REFERRER_POLICY_VALUES: typeof REFERRER_POLICY_VALUES;
480
+ type network_ReceivedHop = ReceivedHop;
432
481
  type network_ReferrerPolicyEntry = ReferrerPolicyEntry;
433
482
  type network_ReferrerPolicyResult = ReferrerPolicyResult;
434
483
  type network_ReferrerPolicyValue = ReferrerPolicyValue;
@@ -445,6 +494,7 @@ type network_SitemapValidationResult = SitemapValidationResult;
445
494
  type network_StatusCode = StatusCode;
446
495
  type network_UaDeviceType = UaDeviceType;
447
496
  type network_UserAgentInfo = UserAgentInfo;
497
+ declare const network_analyzeEmailHeaders: typeof analyzeEmailHeaders;
448
498
  declare const network_buildCacheControl: typeof buildCacheControl;
449
499
  declare const network_buildDnsQueryUrl: typeof buildDnsQueryUrl;
450
500
  declare const network_buildGeoUrl: typeof buildGeoUrl;
@@ -481,7 +531,7 @@ declare const network_validateHeaderValue: typeof validateHeaderValue;
481
531
  declare const network_validateRobotsTxt: typeof validateRobotsTxt;
482
532
  declare const network_validateSitemap: typeof validateSitemap;
483
533
  declare namespace network {
484
- export { type network_CacheControlDirective as CacheControlDirective, type network_CacheControlOptions as CacheControlOptions, type network_CacheControlResult as CacheControlResult, type network_CookieAttributes as CookieAttributes, type network_CookieCheckResult as CookieCheckResult, network_DNS_RECORD_TYPES as DNS_RECORD_TYPES, type network_DnsRecord as DnsRecord, type network_DnsRecordType as DnsRecordType, type network_DnsResponse as DnsResponse, type network_GeoResult as GeoResult, network_HTTP_HEADERS as HTTP_HEADERS, type network_HarEntry as HarEntry, type network_HarParseResult as HarParseResult, type network_HarSummary as HarSummary, type network_HeaderCategory as HeaderCategory, type network_HttpHeader as HttpHeader, type network_Ipv6AddressType as Ipv6AddressType, type network_Ipv6ParseResult as Ipv6ParseResult, network_LINK_REL_VALUES as LINK_REL_VALUES, type network_LinkHeaderEntry as LinkHeaderEntry, type network_LinkHeaderEntryInput as LinkHeaderEntryInput, type network_LinkHeaderResult as LinkHeaderResult, type network_LinkRel as LinkRel, type network_ParsedDnsResult as ParsedDnsResult, type network_ParsedGeoResult as ParsedGeoResult, network_REFERRER_POLICY_VALUES as REFERRER_POLICY_VALUES, type network_ReferrerPolicyEntry as ReferrerPolicyEntry, type network_ReferrerPolicyResult as ReferrerPolicyResult, type network_ReferrerPolicyValue as ReferrerPolicyValue, type network_RobotsGroup as RobotsGroup, type network_RobotsIssue as RobotsIssue, type network_RobotsRule as RobotsRule, type network_RobotsValidationResult as RobotsValidationResult, network_STATUS_CODES as STATUS_CODES, type network_SameSiteValue as SameSiteValue, type network_SitemapIndexEntry as SitemapIndexEntry, type network_SitemapIssue as SitemapIssue, type network_SitemapUrlEntry as SitemapUrlEntry, type network_SitemapValidationResult as SitemapValidationResult, type network_StatusCode as StatusCode, type network_UaDeviceType as UaDeviceType, type network_UserAgentInfo as UserAgentInfo, network_buildCacheControl as buildCacheControl, network_buildDnsQueryUrl as buildDnsQueryUrl, network_buildGeoUrl as buildGeoUrl, network_buildLinkHeader as buildLinkHeader, network_buildMapUrl as buildMapUrl, network_buildReferrerPolicy as buildReferrerPolicy, network_checkSetCookieHeader as checkSetCookieHeader, network_countryCodeToFlag as countryCodeToFlag, network_formatCoordinates as formatCoordinates, network_formatTtl as formatTtl, network_getByCategory as getByCategory, network_getHeader as getHeader, network_getHeadersByCategory as getHeadersByCategory, network_getStatusByCategory as getStatusByCategory, network_getStatusCode as getStatusCode, network_isClientError as isClientError, network_isServerError as isServerError, network_isSuccess as isSuccess, network_isValidIp as isValidIp, network_isValidIpv4 as isValidIpv4, network_isValidIpv6 as isValidIpv6, network_parseDnsResponse as parseDnsResponse, network_parseGeoResponse as parseGeoResponse, network_parseHar as parseHar, network_parseIpv6Address as parseIpv6Address, network_parseUserAgent as parseUserAgent, network_searchHeaders as searchHeaders, network_searchStatusCodes as searchStatusCodes, network_statusCodeToText as statusCodeToText, network_typeNumberToLabel as typeNumberToLabel, network_validateDomain as validateDomain, network_validateHeaderName as validateHeaderName, network_validateHeaderValue as validateHeaderValue, network_validateRobotsTxt as validateRobotsTxt, network_validateSitemap as validateSitemap };
534
+ export { type network_AuthResultEntry as AuthResultEntry, type network_CacheControlDirective as CacheControlDirective, type network_CacheControlOptions as CacheControlOptions, type network_CacheControlResult as CacheControlResult, type network_CookieAttributes as CookieAttributes, type network_CookieCheckResult as CookieCheckResult, network_DNS_RECORD_TYPES as DNS_RECORD_TYPES, type network_DnsRecord as DnsRecord, type network_DnsRecordType as DnsRecordType, type network_DnsResponse as DnsResponse, type network_EmailHeaderAnalysis as EmailHeaderAnalysis, type network_EmailHeaderField as EmailHeaderField, type network_GeoResult as GeoResult, network_HTTP_HEADERS as HTTP_HEADERS, type network_HarEntry as HarEntry, type network_HarParseResult as HarParseResult, type network_HarSummary as HarSummary, type network_HeaderCategory as HeaderCategory, type network_HttpHeader as HttpHeader, type network_Ipv6AddressType as Ipv6AddressType, type network_Ipv6ParseResult as Ipv6ParseResult, network_LINK_REL_VALUES as LINK_REL_VALUES, type network_LinkHeaderEntry as LinkHeaderEntry, type network_LinkHeaderEntryInput as LinkHeaderEntryInput, type network_LinkHeaderResult as LinkHeaderResult, type network_LinkRel as LinkRel, type network_ParsedDnsResult as ParsedDnsResult, type network_ParsedGeoResult as ParsedGeoResult, network_REFERRER_POLICY_VALUES as REFERRER_POLICY_VALUES, type network_ReceivedHop as ReceivedHop, type network_ReferrerPolicyEntry as ReferrerPolicyEntry, type network_ReferrerPolicyResult as ReferrerPolicyResult, type network_ReferrerPolicyValue as ReferrerPolicyValue, type network_RobotsGroup as RobotsGroup, type network_RobotsIssue as RobotsIssue, type network_RobotsRule as RobotsRule, type network_RobotsValidationResult as RobotsValidationResult, network_STATUS_CODES as STATUS_CODES, type network_SameSiteValue as SameSiteValue, type network_SitemapIndexEntry as SitemapIndexEntry, type network_SitemapIssue as SitemapIssue, type network_SitemapUrlEntry as SitemapUrlEntry, type network_SitemapValidationResult as SitemapValidationResult, type network_StatusCode as StatusCode, type network_UaDeviceType as UaDeviceType, type network_UserAgentInfo as UserAgentInfo, network_analyzeEmailHeaders as analyzeEmailHeaders, network_buildCacheControl as buildCacheControl, network_buildDnsQueryUrl as buildDnsQueryUrl, network_buildGeoUrl as buildGeoUrl, network_buildLinkHeader as buildLinkHeader, network_buildMapUrl as buildMapUrl, network_buildReferrerPolicy as buildReferrerPolicy, network_checkSetCookieHeader as checkSetCookieHeader, network_countryCodeToFlag as countryCodeToFlag, network_formatCoordinates as formatCoordinates, network_formatTtl as formatTtl, network_getByCategory as getByCategory, network_getHeader as getHeader, network_getHeadersByCategory as getHeadersByCategory, network_getStatusByCategory as getStatusByCategory, network_getStatusCode as getStatusCode, network_isClientError as isClientError, network_isServerError as isServerError, network_isSuccess as isSuccess, network_isValidIp as isValidIp, network_isValidIpv4 as isValidIpv4, network_isValidIpv6 as isValidIpv6, network_parseDnsResponse as parseDnsResponse, network_parseGeoResponse as parseGeoResponse, network_parseHar as parseHar, network_parseIpv6Address as parseIpv6Address, network_parseUserAgent as parseUserAgent, network_searchHeaders as searchHeaders, network_searchStatusCodes as searchStatusCodes, network_statusCodeToText as statusCodeToText, network_typeNumberToLabel as typeNumberToLabel, network_validateDomain as validateDomain, network_validateHeaderName as validateHeaderName, network_validateHeaderValue as validateHeaderValue, network_validateRobotsTxt as validateRobotsTxt, network_validateSitemap as validateSitemap };
485
535
  }
486
536
 
487
- export { getByCategory as $, type SameSiteValue as A, type SitemapIndexEntry as B, type CacheControlDirective as C, DNS_RECORD_TYPES as D, type SitemapIssue as E, type SitemapUrlEntry as F, type GeoResult as G, HTTP_HEADERS as H, type Ipv6AddressType as I, type SitemapValidationResult as J, type StatusCode as K, LINK_REL_VALUES as L, type UserAgentInfo as M, buildCacheControl as N, buildDnsQueryUrl as O, type ParsedDnsResult as P, buildGeoUrl as Q, REFERRER_POLICY_VALUES as R, STATUS_CODES as S, buildLinkHeader as T, type UaDeviceType as U, buildMapUrl as V, buildReferrerPolicy as W, checkSetCookieHeader as X, countryCodeToFlag as Y, formatCoordinates as Z, formatTtl as _, type CacheControlOptions as a, getHeader as a0, getHeadersByCategory as a1, getStatusByCategory as a2, getStatusCode as a3, isClientError as a4, isServerError as a5, isSuccess as a6, isValidIp as a7, isValidIpv4 as a8, isValidIpv6 as a9, parseDnsResponse as aa, parseGeoResponse as ab, parseHar as ac, parseIpv6Address as ad, parseUserAgent as ae, searchHeaders as af, searchStatusCodes as ag, statusCodeToText as ah, typeNumberToLabel as ai, validateDomain as aj, validateHeaderName as ak, validateHeaderValue as al, validateRobotsTxt as am, validateSitemap as an, type CacheControlResult as b, type CookieAttributes as c, type CookieCheckResult as d, type DnsRecord as e, type DnsRecordType as f, type DnsResponse as g, type HarEntry as h, type HarParseResult as i, type HarSummary as j, type HeaderCategory as k, type HttpHeader as l, type Ipv6ParseResult as m, network as n, type LinkHeaderEntry as o, type LinkHeaderEntryInput as p, type LinkHeaderResult as q, type LinkRel as r, type ParsedGeoResult as s, type ReferrerPolicyEntry as t, type ReferrerPolicyResult as u, type ReferrerPolicyValue as v, type RobotsGroup as w, type RobotsIssue as x, type RobotsRule as y, type RobotsValidationResult as z };
537
+ export { buildReferrerPolicy as $, type AuthResultEntry as A, type RobotsRule as B, type CacheControlDirective as C, DNS_RECORD_TYPES as D, type EmailHeaderAnalysis as E, type RobotsValidationResult as F, type GeoResult as G, HTTP_HEADERS as H, type Ipv6AddressType as I, type SameSiteValue as J, type SitemapIndexEntry as K, LINK_REL_VALUES as L, type SitemapIssue as M, type SitemapUrlEntry as N, type SitemapValidationResult as O, type ParsedDnsResult as P, type StatusCode as Q, REFERRER_POLICY_VALUES as R, STATUS_CODES as S, type UserAgentInfo as T, type UaDeviceType as U, analyzeEmailHeaders as V, buildCacheControl as W, buildDnsQueryUrl as X, buildGeoUrl as Y, buildLinkHeader as Z, buildMapUrl as _, type CacheControlOptions as a, checkSetCookieHeader as a0, countryCodeToFlag as a1, formatCoordinates as a2, formatTtl as a3, getByCategory as a4, getHeader as a5, getHeadersByCategory as a6, getStatusByCategory as a7, getStatusCode as a8, isClientError as a9, isServerError as aa, isSuccess as ab, isValidIp as ac, isValidIpv4 as ad, isValidIpv6 as ae, parseDnsResponse as af, parseGeoResponse as ag, parseHar as ah, parseIpv6Address as ai, parseUserAgent as aj, searchHeaders as ak, searchStatusCodes as al, statusCodeToText as am, typeNumberToLabel as an, validateDomain as ao, validateHeaderName as ap, validateHeaderValue as aq, validateRobotsTxt as ar, validateSitemap as as, type CacheControlResult as b, type CookieAttributes as c, type CookieCheckResult as d, type DnsRecord as e, type DnsRecordType as f, type DnsResponse as g, type EmailHeaderField as h, type HarEntry as i, type HarParseResult as j, type HarSummary as k, type HeaderCategory as l, type HttpHeader as m, network as n, type Ipv6ParseResult as o, type LinkHeaderEntry as p, type LinkHeaderEntryInput as q, type LinkHeaderResult as r, type LinkRel as s, type ParsedGeoResult as t, type ReceivedHop as u, type ReferrerPolicyEntry as v, type ReferrerPolicyResult as w, type ReferrerPolicyValue as x, type RobotsGroup as y, type RobotsIssue as z };
@@ -233,16 +233,41 @@ function generateHtpasswdFile(entries) {
233
233
  function validateUsername(username) {
234
234
  return /^[^\s:]{1,255}$/.test(username);
235
235
  }
236
+ var SRI_ALGORITHMS = ["SHA-256", "SHA-384", "SHA-512"];
237
+ var SRI_NODE_ALG_MAP = {
238
+ "SHA-256": "sha256",
239
+ "SHA-384": "sha384",
240
+ "SHA-512": "sha512"
241
+ };
242
+ function generateSri(content, algorithm = "SHA-384") {
243
+ if (typeof content !== "string" || content.length === 0) {
244
+ return { error: "Content is required" };
245
+ }
246
+ if (!SRI_ALGORITHMS.includes(algorithm)) {
247
+ return { error: `Unknown algorithm: ${algorithm}. Must be one of ${SRI_ALGORITHMS.join(", ")}` };
248
+ }
249
+ const base64 = crypto.createHash(SRI_NODE_ALG_MAP[algorithm]).update(content, "utf8").digest("base64");
250
+ return { algorithm, base64, integrity: `${SRI_NODE_ALG_MAP[algorithm]}-${base64}` };
251
+ }
252
+ function generateSriAll(content) {
253
+ if (typeof content !== "string" || content.length === 0) {
254
+ return { error: "Content is required" };
255
+ }
256
+ return SRI_ALGORITHMS.map((alg) => generateSri(content, alg));
257
+ }
236
258
 
237
259
  exports.HASH_ALGORITHMS = HASH_ALGORITHMS;
238
260
  exports.HASH_BITS = HASH_BITS;
239
261
  exports.ROUND_OPTIONS = ROUND_OPTIONS;
262
+ exports.SRI_ALGORITHMS = SRI_ALGORITHMS;
240
263
  exports.createEntry = createEntry;
241
264
  exports.generateBcryptHash = generateBcryptHash;
242
265
  exports.generateHtpasswdFile = generateHtpasswdFile;
243
266
  exports.generateMd5Hash = generateMd5Hash;
244
267
  exports.generatePlain = generatePlain;
245
268
  exports.generateSha1Hash = generateSha1Hash;
269
+ exports.generateSri = generateSri;
270
+ exports.generateSriAll = generateSriAll;
246
271
  exports.hashAll = hashAll;
247
272
  exports.hashOne = hashOne;
248
273
  exports.hashPassword = hashPassword;
@@ -1 +1 @@
1
- export { B as BcryptResult, H as HASH_ALGORITHMS, a as HASH_BITS, b as HashAlgorithm, c as HashResult, d as HtpasswdAlgorithm, e as HtpasswdEntry, R as ROUND_OPTIONS, f as createEntry, g as generateBcryptHash, i as generateHtpasswdFile, j as generateMd5Hash, k as generatePlain, l as generateSha1Hash, m as hashAll, n as hashOne, o as hashPassword, p as hashWithTiming, q as parseHtpasswdFile, v as validateRounds, r as validateUsername, s as verifyPassword } from '../hashing-CnetQFD_.cjs';
1
+ export { B as BcryptResult, H as HASH_ALGORITHMS, a as HASH_BITS, b as HashAlgorithm, c as HashResult, d as HtpasswdAlgorithm, e as HtpasswdEntry, R as ROUND_OPTIONS, S as SRI_ALGORITHMS, f as SriAlgorithm, g as SriResult, i as createEntry, j as generateBcryptHash, k as generateHtpasswdFile, l as generateMd5Hash, m as generatePlain, n as generateSha1Hash, o as generateSri, p as generateSriAll, q as hashAll, r as hashOne, s as hashPassword, t as hashWithTiming, u as parseHtpasswdFile, v as validateRounds, w as validateUsername, x as verifyPassword } from '../hashing-Dnj0IAZf.cjs';
@@ -1 +1 @@
1
- export { B as BcryptResult, H as HASH_ALGORITHMS, a as HASH_BITS, b as HashAlgorithm, c as HashResult, d as HtpasswdAlgorithm, e as HtpasswdEntry, R as ROUND_OPTIONS, f as createEntry, g as generateBcryptHash, i as generateHtpasswdFile, j as generateMd5Hash, k as generatePlain, l as generateSha1Hash, m as hashAll, n as hashOne, o as hashPassword, p as hashWithTiming, q as parseHtpasswdFile, v as validateRounds, r as validateUsername, s as verifyPassword } from '../hashing-CnetQFD_.js';
1
+ export { B as BcryptResult, H as HASH_ALGORITHMS, a as HASH_BITS, b as HashAlgorithm, c as HashResult, d as HtpasswdAlgorithm, e as HtpasswdEntry, R as ROUND_OPTIONS, S as SRI_ALGORITHMS, f as SriAlgorithm, g as SriResult, i as createEntry, j as generateBcryptHash, k as generateHtpasswdFile, l as generateMd5Hash, m as generatePlain, n as generateSha1Hash, o as generateSri, p as generateSriAll, q as hashAll, r as hashOne, s as hashPassword, t as hashWithTiming, u as parseHtpasswdFile, v as validateRounds, w as validateUsername, x as verifyPassword } from '../hashing-Dnj0IAZf.js';
@@ -1,2 +1,2 @@
1
- export { HASH_ALGORITHMS, HASH_BITS, ROUND_OPTIONS, createEntry, generateBcryptHash, generateHtpasswdFile, generateMd5Hash, generatePlain, generateSha1Hash, hashAll, hashOne, hashPassword, hashWithTiming, parseHtpasswdFile, validateRounds, validateUsername, verifyPassword } from '../chunk-GEFVMGZR.js';
1
+ export { HASH_ALGORITHMS, HASH_BITS, ROUND_OPTIONS, SRI_ALGORITHMS, createEntry, generateBcryptHash, generateHtpasswdFile, generateMd5Hash, generatePlain, generateSha1Hash, generateSri, generateSriAll, hashAll, hashOne, hashPassword, hashWithTiming, parseHtpasswdFile, validateRounds, validateUsername, verifyPassword } from '../chunk-VEVNIGJ6.js';
2
2
  import '../chunk-MLKGABMK.js';
@@ -2087,12 +2087,91 @@ function checkSetCookieHeader(header) {
2087
2087
  }
2088
2088
  return { cookie, issues, warnings, valid: issues.length === 0 };
2089
2089
  }
2090
+ function analyzeEmailHeaders(raw) {
2091
+ if (typeof raw !== "string" || !raw.trim()) {
2092
+ return { error: "Raw email header text is required" };
2093
+ }
2094
+ const normalized = raw.replace(/\r\n/g, "\n");
2095
+ const blockEnd = normalized.indexOf("\n\n");
2096
+ const headerBlock = blockEnd === -1 ? normalized : normalized.slice(0, blockEnd);
2097
+ const rawLines = headerBlock.split("\n");
2098
+ const unfolded = [];
2099
+ for (const line of rawLines) {
2100
+ if (/^[ \t]/.test(line) && unfolded.length > 0) {
2101
+ unfolded[unfolded.length - 1] += " " + line.trim();
2102
+ } else if (line.trim() !== "") {
2103
+ unfolded.push(line);
2104
+ }
2105
+ }
2106
+ const headers = [];
2107
+ for (const line of unfolded) {
2108
+ const colonIdx = line.indexOf(":");
2109
+ if (colonIdx === -1) continue;
2110
+ const name = line.slice(0, colonIdx).trim();
2111
+ const value = line.slice(colonIdx + 1).trim();
2112
+ if (!name) continue;
2113
+ headers.push({ name, value });
2114
+ }
2115
+ if (headers.length === 0) {
2116
+ return { error: 'No parseable headers found \u2014 expected lines like "From: ..." or "Received: ..."' };
2117
+ }
2118
+ const findFirst = (name) => headers.find((h) => h.name.toLowerCase() === name.toLowerCase())?.value ?? null;
2119
+ const findAll = (name) => headers.filter((h) => h.name.toLowerCase() === name.toLowerCase());
2120
+ const receivedHops = findAll("received").map((h, i) => {
2121
+ const fromMatch = h.value.match(/from\s+([^\s;]+(?:\s*\([^)]*\))?)/i);
2122
+ const byMatch = h.value.match(/\bby\s+([^\s;]+)/i);
2123
+ const segments = h.value.split(";");
2124
+ const date = segments.length > 1 ? segments[segments.length - 1].trim() : null;
2125
+ return {
2126
+ index: i + 1,
2127
+ raw: h.value,
2128
+ from: fromMatch ? fromMatch[1].trim() : null,
2129
+ by: byMatch ? byMatch[1].trim() : null,
2130
+ date: date || null
2131
+ };
2132
+ });
2133
+ const authResultsHeader = findFirst("authentication-results");
2134
+ const authResults = [];
2135
+ if (authResultsHeader) {
2136
+ const re = /\b(spf|dkim|dmarc)=(\w+)/gi;
2137
+ let m;
2138
+ while ((m = re.exec(authResultsHeader)) !== null) {
2139
+ authResults.push({ mechanism: m[1].toLowerCase(), result: m[2].toLowerCase() });
2140
+ }
2141
+ }
2142
+ const findAuth = (mechanism) => authResults.find((a) => a.mechanism === mechanism)?.result ?? null;
2143
+ const warnings = [];
2144
+ if (receivedHops.length === 0) {
2145
+ warnings.push("No Received headers found \u2014 this may be a partial header block rather than a full raw source.");
2146
+ }
2147
+ if (!authResultsHeader) {
2148
+ warnings.push("No Authentication-Results header found \u2014 SPF/DKIM/DMARC cannot be determined from this header block alone.");
2149
+ }
2150
+ return {
2151
+ headers,
2152
+ from: findFirst("from"),
2153
+ to: findFirst("to"),
2154
+ subject: findFirst("subject"),
2155
+ date: findFirst("date"),
2156
+ messageId: findFirst("message-id"),
2157
+ returnPath: findFirst("return-path"),
2158
+ replyTo: findFirst("reply-to"),
2159
+ receivedHops,
2160
+ hopCount: receivedHops.length,
2161
+ authResults,
2162
+ spf: findAuth("spf"),
2163
+ dkim: findAuth("dkim"),
2164
+ dmarc: findAuth("dmarc"),
2165
+ warnings
2166
+ };
2167
+ }
2090
2168
 
2091
2169
  exports.DNS_RECORD_TYPES = DNS_RECORD_TYPES;
2092
2170
  exports.HTTP_HEADERS = HTTP_HEADERS;
2093
2171
  exports.LINK_REL_VALUES = LINK_REL_VALUES;
2094
2172
  exports.REFERRER_POLICY_VALUES = REFERRER_POLICY_VALUES;
2095
2173
  exports.STATUS_CODES = STATUS_CODES;
2174
+ exports.analyzeEmailHeaders = analyzeEmailHeaders;
2096
2175
  exports.buildCacheControl = buildCacheControl;
2097
2176
  exports.buildDnsQueryUrl = buildDnsQueryUrl;
2098
2177
  exports.buildGeoUrl = buildGeoUrl;
@@ -1 +1 @@
1
- export { C as CacheControlDirective, a as CacheControlOptions, b as CacheControlResult, c as CookieAttributes, d as CookieCheckResult, D as DNS_RECORD_TYPES, e as DnsRecord, f as DnsRecordType, g as DnsResponse, G as GeoResult, H as HTTP_HEADERS, h as HarEntry, i as HarParseResult, j as HarSummary, k as HeaderCategory, l as HttpHeader, I as Ipv6AddressType, m as Ipv6ParseResult, L as LINK_REL_VALUES, o as LinkHeaderEntry, p as LinkHeaderEntryInput, q as LinkHeaderResult, r as LinkRel, P as ParsedDnsResult, s as ParsedGeoResult, R as REFERRER_POLICY_VALUES, t as ReferrerPolicyEntry, u as ReferrerPolicyResult, v as ReferrerPolicyValue, w as RobotsGroup, x as RobotsIssue, y as RobotsRule, z as RobotsValidationResult, S as STATUS_CODES, A as SameSiteValue, B as SitemapIndexEntry, E as SitemapIssue, F as SitemapUrlEntry, J as SitemapValidationResult, K as StatusCode, U as UaDeviceType, M as UserAgentInfo, N as buildCacheControl, O as buildDnsQueryUrl, Q as buildGeoUrl, T as buildLinkHeader, V as buildMapUrl, W as buildReferrerPolicy, X as checkSetCookieHeader, Y as countryCodeToFlag, Z as formatCoordinates, _ as formatTtl, $ as getByCategory, a0 as getHeader, a1 as getHeadersByCategory, a2 as getStatusByCategory, a3 as getStatusCode, a4 as isClientError, a5 as isServerError, a6 as isSuccess, a7 as isValidIp, a8 as isValidIpv4, a9 as isValidIpv6, aa as parseDnsResponse, ab as parseGeoResponse, ac as parseHar, ad as parseIpv6Address, ae as parseUserAgent, af as searchHeaders, ag as searchStatusCodes, ah as statusCodeToText, ai as typeNumberToLabel, aj as validateDomain, ak as validateHeaderName, al as validateHeaderValue, am as validateRobotsTxt, an as validateSitemap } from '../network-CnKUQT4g.cjs';
1
+ export { A as AuthResultEntry, C as CacheControlDirective, a as CacheControlOptions, b as CacheControlResult, c as CookieAttributes, d as CookieCheckResult, D as DNS_RECORD_TYPES, e as DnsRecord, f as DnsRecordType, g as DnsResponse, E as EmailHeaderAnalysis, h as EmailHeaderField, G as GeoResult, H as HTTP_HEADERS, i as HarEntry, j as HarParseResult, k as HarSummary, l as HeaderCategory, m as HttpHeader, I as Ipv6AddressType, o as Ipv6ParseResult, L as LINK_REL_VALUES, p as LinkHeaderEntry, q as LinkHeaderEntryInput, r as LinkHeaderResult, s as LinkRel, P as ParsedDnsResult, t as ParsedGeoResult, R as REFERRER_POLICY_VALUES, u as ReceivedHop, v as ReferrerPolicyEntry, w as ReferrerPolicyResult, x as ReferrerPolicyValue, y as RobotsGroup, z as RobotsIssue, B as RobotsRule, F as RobotsValidationResult, S as STATUS_CODES, J as SameSiteValue, K as SitemapIndexEntry, M as SitemapIssue, N as SitemapUrlEntry, O as SitemapValidationResult, Q as StatusCode, U as UaDeviceType, T as UserAgentInfo, V as analyzeEmailHeaders, W as buildCacheControl, X as buildDnsQueryUrl, Y as buildGeoUrl, Z as buildLinkHeader, _ as buildMapUrl, $ as buildReferrerPolicy, a0 as checkSetCookieHeader, a1 as countryCodeToFlag, a2 as formatCoordinates, a3 as formatTtl, a4 as getByCategory, a5 as getHeader, a6 as getHeadersByCategory, a7 as getStatusByCategory, a8 as getStatusCode, a9 as isClientError, aa as isServerError, ab as isSuccess, ac as isValidIp, ad as isValidIpv4, ae as isValidIpv6, af as parseDnsResponse, ag as parseGeoResponse, ah as parseHar, ai as parseIpv6Address, aj as parseUserAgent, ak as searchHeaders, al as searchStatusCodes, am as statusCodeToText, an as typeNumberToLabel, ao as validateDomain, ap as validateHeaderName, aq as validateHeaderValue, ar as validateRobotsTxt, as as validateSitemap } from '../network-CKPoesdD.cjs';
@@ -1 +1 @@
1
- export { C as CacheControlDirective, a as CacheControlOptions, b as CacheControlResult, c as CookieAttributes, d as CookieCheckResult, D as DNS_RECORD_TYPES, e as DnsRecord, f as DnsRecordType, g as DnsResponse, G as GeoResult, H as HTTP_HEADERS, h as HarEntry, i as HarParseResult, j as HarSummary, k as HeaderCategory, l as HttpHeader, I as Ipv6AddressType, m as Ipv6ParseResult, L as LINK_REL_VALUES, o as LinkHeaderEntry, p as LinkHeaderEntryInput, q as LinkHeaderResult, r as LinkRel, P as ParsedDnsResult, s as ParsedGeoResult, R as REFERRER_POLICY_VALUES, t as ReferrerPolicyEntry, u as ReferrerPolicyResult, v as ReferrerPolicyValue, w as RobotsGroup, x as RobotsIssue, y as RobotsRule, z as RobotsValidationResult, S as STATUS_CODES, A as SameSiteValue, B as SitemapIndexEntry, E as SitemapIssue, F as SitemapUrlEntry, J as SitemapValidationResult, K as StatusCode, U as UaDeviceType, M as UserAgentInfo, N as buildCacheControl, O as buildDnsQueryUrl, Q as buildGeoUrl, T as buildLinkHeader, V as buildMapUrl, W as buildReferrerPolicy, X as checkSetCookieHeader, Y as countryCodeToFlag, Z as formatCoordinates, _ as formatTtl, $ as getByCategory, a0 as getHeader, a1 as getHeadersByCategory, a2 as getStatusByCategory, a3 as getStatusCode, a4 as isClientError, a5 as isServerError, a6 as isSuccess, a7 as isValidIp, a8 as isValidIpv4, a9 as isValidIpv6, aa as parseDnsResponse, ab as parseGeoResponse, ac as parseHar, ad as parseIpv6Address, ae as parseUserAgent, af as searchHeaders, ag as searchStatusCodes, ah as statusCodeToText, ai as typeNumberToLabel, aj as validateDomain, ak as validateHeaderName, al as validateHeaderValue, am as validateRobotsTxt, an as validateSitemap } from '../network-CnKUQT4g.js';
1
+ export { A as AuthResultEntry, C as CacheControlDirective, a as CacheControlOptions, b as CacheControlResult, c as CookieAttributes, d as CookieCheckResult, D as DNS_RECORD_TYPES, e as DnsRecord, f as DnsRecordType, g as DnsResponse, E as EmailHeaderAnalysis, h as EmailHeaderField, G as GeoResult, H as HTTP_HEADERS, i as HarEntry, j as HarParseResult, k as HarSummary, l as HeaderCategory, m as HttpHeader, I as Ipv6AddressType, o as Ipv6ParseResult, L as LINK_REL_VALUES, p as LinkHeaderEntry, q as LinkHeaderEntryInput, r as LinkHeaderResult, s as LinkRel, P as ParsedDnsResult, t as ParsedGeoResult, R as REFERRER_POLICY_VALUES, u as ReceivedHop, v as ReferrerPolicyEntry, w as ReferrerPolicyResult, x as ReferrerPolicyValue, y as RobotsGroup, z as RobotsIssue, B as RobotsRule, F as RobotsValidationResult, S as STATUS_CODES, J as SameSiteValue, K as SitemapIndexEntry, M as SitemapIssue, N as SitemapUrlEntry, O as SitemapValidationResult, Q as StatusCode, U as UaDeviceType, T as UserAgentInfo, V as analyzeEmailHeaders, W as buildCacheControl, X as buildDnsQueryUrl, Y as buildGeoUrl, Z as buildLinkHeader, _ as buildMapUrl, $ as buildReferrerPolicy, a0 as checkSetCookieHeader, a1 as countryCodeToFlag, a2 as formatCoordinates, a3 as formatTtl, a4 as getByCategory, a5 as getHeader, a6 as getHeadersByCategory, a7 as getStatusByCategory, a8 as getStatusCode, a9 as isClientError, aa as isServerError, ab as isSuccess, ac as isValidIp, ad as isValidIpv4, ae as isValidIpv6, af as parseDnsResponse, ag as parseGeoResponse, ah as parseHar, ai as parseIpv6Address, aj as parseUserAgent, ak as searchHeaders, al as searchStatusCodes, am as statusCodeToText, an as typeNumberToLabel, ao as validateDomain, ap as validateHeaderName, aq as validateHeaderValue, ar as validateRobotsTxt, as as validateSitemap } from '../network-CKPoesdD.js';
@@ -1,2 +1,2 @@
1
- export { DNS_RECORD_TYPES, HTTP_HEADERS, LINK_REL_VALUES, REFERRER_POLICY_VALUES, STATUS_CODES, buildCacheControl, buildDnsQueryUrl, buildGeoUrl, buildLinkHeader, buildMapUrl, buildReferrerPolicy, checkSetCookieHeader, countryCodeToFlag, formatCoordinates, formatTtl, getByCategory, getHeader, getHeadersByCategory, getStatusByCategory, getStatusCode, isClientError, isServerError, isSuccess, isValidIp, isValidIpv4, isValidIpv6, parseDnsResponse, parseGeoResponse, parseHar, parseIpv6Address, parseUserAgent, searchHeaders, searchStatusCodes, statusCodeToText, typeNumberToLabel, validateDomain, validateHeaderName, validateHeaderValue, validateRobotsTxt, validateSitemap } from '../chunk-DBNTO3YO.js';
1
+ export { DNS_RECORD_TYPES, HTTP_HEADERS, LINK_REL_VALUES, REFERRER_POLICY_VALUES, STATUS_CODES, analyzeEmailHeaders, buildCacheControl, buildDnsQueryUrl, buildGeoUrl, buildLinkHeader, buildMapUrl, buildReferrerPolicy, checkSetCookieHeader, countryCodeToFlag, formatCoordinates, formatTtl, getByCategory, getHeader, getHeadersByCategory, getStatusByCategory, getStatusCode, isClientError, isServerError, isSuccess, isValidIp, isValidIpv4, isValidIpv6, parseDnsResponse, parseGeoResponse, parseHar, parseIpv6Address, parseUserAgent, searchHeaders, searchStatusCodes, statusCodeToText, typeNumberToLabel, validateDomain, validateHeaderName, validateHeaderValue, validateRobotsTxt, validateSitemap } from '../chunk-Y4BVU76A.js';
2
2
  import '../chunk-MLKGABMK.js';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@utilix-tech/sdk",
3
- "version": "0.38.0",
3
+ "version": "0.39.0",
4
4
  "description": "154+ developer utility tools for Node.js: JSON, encoding, hashing, color, CSS, network and more. Runs locally, no API key required.",
5
5
  "author": "Utilix <hello@utilix.tech>",
6
6
  "license": "MIT",