@ultimat3/mail 24.0.0 → 25.1.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/CLAUDE.md +57 -7
- package/README.md +78 -11
- package/package.json +9 -8
- package/src/catalog.ts +3 -12
- package/src/delivery-event-errors.ts +148 -0
- package/src/delivery-event-ses.ts +101 -0
- package/src/delivery-event.ts +103 -0
- package/src/driver-env.ts +92 -19
- package/src/driver-resend.ts +2 -2
- package/src/driver-ses.ts +205 -0
- package/src/driver-smtp.ts +12 -5
- package/src/driver.ts +10 -4
- package/src/errors.ts +13 -6
- package/src/events.ts +28 -0
- package/src/html.ts +1 -1
- package/src/index.ts +20 -9
- package/src/layout.ts +2 -2
- package/src/render.ts +7 -6
- package/src/resend-event-receiver.ts +111 -0
- package/src/resend-signature.ts +93 -0
- package/src/retain-mime.ts +142 -0
- package/src/ses-event-receiver.ts +141 -0
- package/src/ses-failure.ts +114 -0
- package/src/smtp-client.ts +3 -3
- package/src/smtp-socket.ts +1 -1
- package/src/sns-certificate-cache.ts +111 -0
- package/src/sns-signature.ts +187 -0
- package/src/transform.ts +13 -3
- package/src/x509-spki.ts +67 -0
package/src/x509-spki.ts
ADDED
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
// Single responsibility: the public key out of a PEM X.509 certificate, as the SubjectPublicKeyInfo
|
|
2
|
+
// bytes Web Crypto imports (`importKey('spki', …)`). Web Crypto takes no certificate, so this walks
|
|
3
|
+
// just enough DER to find the seventh field of `tbsCertificate` (RFC 5280 §4.1). Malformed input is
|
|
4
|
+
// `undefined`, never a throw: the bytes came off a network.
|
|
5
|
+
|
|
6
|
+
interface Tlv {
|
|
7
|
+
readonly tag: number;
|
|
8
|
+
/** Offset of the tag byte. */
|
|
9
|
+
readonly start: number;
|
|
10
|
+
/** Offset of the first content byte. */
|
|
11
|
+
readonly body: number;
|
|
12
|
+
/** Offset one past the last content byte. */
|
|
13
|
+
readonly end: number;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
const SEQUENCE = 0x30;
|
|
17
|
+
const VERSION = 0xa0;
|
|
18
|
+
/** `serialNumber`, `signature`, `issuer`, `validity`, `subject` — skipped to reach the key. */
|
|
19
|
+
const FIELDS_BEFORE_KEY = 5;
|
|
20
|
+
|
|
21
|
+
/** One DER tag-length-value at `at`, bounded by `limit`. Definite lengths only, as DER requires. */
|
|
22
|
+
function readTlv(bytes: Uint8Array, at: number, limit: number): Tlv | undefined {
|
|
23
|
+
if (at + 2 > limit) return undefined;
|
|
24
|
+
const tag = bytes[at] ?? 0;
|
|
25
|
+
const first = bytes[at + 1] ?? 0;
|
|
26
|
+
let body = at + 2;
|
|
27
|
+
let length = first;
|
|
28
|
+
if (first & 0x80) {
|
|
29
|
+
const count = first & 0x7f;
|
|
30
|
+
if (count === 0 || count > 4 || body + count > limit) return undefined;
|
|
31
|
+
length = 0;
|
|
32
|
+
for (let index = 0; index < count; index += 1)
|
|
33
|
+
length = length * 256 + (bytes[body + index] ?? 0);
|
|
34
|
+
body += count;
|
|
35
|
+
}
|
|
36
|
+
const end = body + length;
|
|
37
|
+
return end > limit ? undefined : { tag, start: at, body, end };
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
/** The DER inside the first `CERTIFICATE` block, or `undefined` for anything else. */
|
|
41
|
+
export function pemCertificateDer(pem: string): Uint8Array | undefined {
|
|
42
|
+
const match = /-----BEGIN CERTIFICATE-----([A-Za-z0-9+/=\s]+)-----END CERTIFICATE-----/.exec(pem);
|
|
43
|
+
if (match === null) return undefined;
|
|
44
|
+
try {
|
|
45
|
+
const binary = atob((match[1] ?? '').replace(/\s+/g, ''));
|
|
46
|
+
return Uint8Array.from(binary, (char) => char.charCodeAt(0));
|
|
47
|
+
} catch {
|
|
48
|
+
return undefined;
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
/** `Certificate → tbsCertificate → subjectPublicKeyInfo`, the whole element, tag included. */
|
|
53
|
+
export function certificateSpki(der: Uint8Array): Uint8Array | undefined {
|
|
54
|
+
const certificate = readTlv(der, 0, der.byteLength);
|
|
55
|
+
if (certificate?.tag !== SEQUENCE) return undefined;
|
|
56
|
+
const tbs = readTlv(der, certificate.body, certificate.end);
|
|
57
|
+
if (tbs?.tag !== SEQUENCE) return undefined;
|
|
58
|
+
let field = readTlv(der, tbs.body, tbs.end);
|
|
59
|
+
// `[0] EXPLICIT version` is absent on a v1 certificate and present on every v3 one.
|
|
60
|
+
if (field?.tag === VERSION) field = readTlv(der, field.end, tbs.end);
|
|
61
|
+
for (let skipped = 0; skipped < FIELDS_BEFORE_KEY; skipped += 1) {
|
|
62
|
+
if (field === undefined) return undefined;
|
|
63
|
+
field = readTlv(der, field.end, tbs.end);
|
|
64
|
+
}
|
|
65
|
+
if (field?.tag !== SEQUENCE) return undefined;
|
|
66
|
+
return der.slice(field.start, field.end);
|
|
67
|
+
}
|