@primitivedotdev/sdk 0.2.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/README.md ADDED
@@ -0,0 +1,227 @@
1
+ # `@primitivedotdev/sdk`
2
+
3
+ Official Primitive Node.js SDK.
4
+
5
+ This package ships three Node.js modules:
6
+
7
+ - `@primitivedotdev/sdk` for the webhook module
8
+ - `@primitivedotdev/sdk/contract` for the contract module
9
+ - `@primitivedotdev/sdk/parser` for the parser module
10
+
11
+ `contract` and `parser` are only available in the Node SDK. The Go and Python SDKs expose the webhook surface only.
12
+
13
+ ## Requirements
14
+
15
+ - Node.js `>=20`
16
+
17
+ ## Installation
18
+
19
+ ```bash
20
+ npm install @primitivedotdev/sdk
21
+ ```
22
+
23
+ ## Modules
24
+
25
+ ### Webhook
26
+
27
+ The root entrypoint remains webhook-focused.
28
+
29
+ ```ts
30
+ import { handleWebhook, PrimitiveWebhookError } from "@primitivedotdev/sdk";
31
+
32
+ app.post("/webhooks/email", express.raw({ type: "application/json" }), (req, res) => {
33
+ try {
34
+ const event = handleWebhook({
35
+ body: req.body,
36
+ headers: req.headers,
37
+ secret: process.env.PRIMITIVE_WEBHOOK_SECRET!,
38
+ });
39
+
40
+ console.log("Email from:", event.email.headers.from);
41
+ console.log("Subject:", event.email.headers.subject);
42
+
43
+ res.json({ received: true });
44
+ } catch (error) {
45
+ if (error instanceof PrimitiveWebhookError) {
46
+ return res.status(400).json({ error: error.code, message: error.message });
47
+ }
48
+
49
+ throw error;
50
+ }
51
+ });
52
+ ```
53
+
54
+ The same API is also available from `@primitivedotdev/sdk/webhook`.
55
+
56
+ Webhook exports include:
57
+
58
+ - `handleWebhook(options)`
59
+ - `parseWebhookEvent(input)`
60
+ - `validateEmailReceivedEvent(input)`
61
+ - `safeValidateEmailReceivedEvent(input)`
62
+ - `verifyWebhookSignature(options)`
63
+ - `validateEmailAuth(auth)`
64
+ - `emailReceivedEventJsonSchema`
65
+ - `WEBHOOK_VERSION`
66
+ - webhook error classes and webhook types
67
+
68
+ ### Contract
69
+
70
+ Use the contract module when constructing canonical Primitive webhook payloads on the producer side.
71
+
72
+ ```ts
73
+ import { buildEmailReceivedEvent, signWebhookPayload } from "@primitivedotdev/sdk/contract";
74
+
75
+ const event = buildEmailReceivedEvent({
76
+ email_id: "email-123",
77
+ endpoint_id: "endpoint-456",
78
+ message_id: "<msg@example.com>",
79
+ sender: "from@example.com",
80
+ recipient: "to@example.com",
81
+ subject: "Hello",
82
+ received_at: "2025-01-01T00:00:00Z",
83
+ smtp_helo: "mail.example.com",
84
+ smtp_mail_from: "from@example.com",
85
+ smtp_rcpt_to: ["to@example.com"],
86
+ raw_bytes: Buffer.from("hello"),
87
+ raw_sha256: "a".repeat(64),
88
+ raw_size_bytes: 5,
89
+ attempt_count: 1,
90
+ date_header: null,
91
+ download_url: "https://example.com/raw",
92
+ download_expires_at: "2025-01-02T00:00:00Z",
93
+ attachments_download_url: null,
94
+ auth: {
95
+ spf: "pass",
96
+ dmarc: "pass",
97
+ dmarcPolicy: "reject",
98
+ dmarcFromDomain: "example.com",
99
+ dmarcSpfAligned: true,
100
+ dmarcDkimAligned: true,
101
+ dmarcSpfStrict: false,
102
+ dmarcDkimStrict: false,
103
+ dkimSignatures: [],
104
+ },
105
+ analysis: {},
106
+ });
107
+
108
+ const signature = signWebhookPayload(JSON.stringify(event), "whsec_test");
109
+ ```
110
+
111
+ Contract exports include:
112
+
113
+ - `buildEmailReceivedEvent(input, options?)`
114
+ - `generateEventId(endpointId, emailId)`
115
+ - `RAW_EMAIL_INLINE_THRESHOLD`
116
+ - `signWebhookPayload(rawBody, secret, timestamp?)`
117
+ - `WEBHOOK_VERSION`
118
+ - contract input and payload helper types
119
+
120
+ ### Parser
121
+
122
+ Use the parser module for raw `.eml` parsing and attachment extraction.
123
+
124
+ ```ts
125
+ import {
126
+ bundleAttachments,
127
+ parseEmail,
128
+ parseEmailWithAttachments,
129
+ toParsedDataComplete,
130
+ } from "@primitivedotdev/sdk/parser";
131
+
132
+ const parsed = await parseEmailWithAttachments(emlBuffer);
133
+ const archive = await bundleAttachments(parsed.attachments);
134
+ const webhookParsed = toParsedDataComplete(parsed, null);
135
+
136
+ await parseEmail(emlBuffer.toString("utf8"));
137
+ ```
138
+
139
+ Parser exports include:
140
+
141
+ - `parseEmail(emlRaw)`
142
+ - `parseEmailWithAttachments(emlBuffer, options?)`
143
+ - `bundleAttachments(attachments)`
144
+ - `extractAttachmentMetadata(attachments)`
145
+ - `getAttachmentsStorageKey(emailId, sha256)`
146
+ - `toParsedDataComplete(parsed, attachmentsDownloadUrl)`
147
+ - `toWebhookAttachments(attachments)`
148
+ - `attachmentMetadataToWebhookAttachments(metadata)`
149
+ - `toCanonicalHeaders(parsed)`
150
+ - parser attachment and bundle types
151
+
152
+ ## Shared Schema
153
+
154
+ The webhook payload contract is defined by the canonical JSON schema in the repository and is exported by this package as `emailReceivedEventJsonSchema`.
155
+
156
+ The SDK uses that schema to generate:
157
+
158
+ - TypeScript types
159
+ - runtime validators
160
+ - the published schema export
161
+
162
+ ## Error Handling
163
+
164
+ All SDK-specific runtime errors extend `PrimitiveWebhookError` and include a stable error `code`.
165
+
166
+ ```ts
167
+ import { PrimitiveWebhookError } from "@primitivedotdev/sdk";
168
+
169
+ try {
170
+ // ...
171
+ } catch (error) {
172
+ if (error instanceof PrimitiveWebhookError) {
173
+ console.error(error.code, error.message);
174
+ }
175
+ }
176
+ ```
177
+
178
+ ## Development
179
+
180
+ From `sdks/sdk-node`:
181
+
182
+ ```bash
183
+ pnpm install
184
+ pnpm generate
185
+ pnpm typecheck
186
+ pnpm test
187
+ pnpm build
188
+ ```
189
+
190
+ Or from repo root `sdks/`:
191
+
192
+ ```bash
193
+ make node-install
194
+ make node-check
195
+ make node-build
196
+ ```
197
+
198
+ ## Package Layout
199
+
200
+ ```text
201
+ sdk-node/
202
+ src/
203
+ contract/
204
+ contract.ts
205
+ index.ts
206
+ parser/
207
+ attachment-bundler.ts
208
+ attachment-parser.ts
209
+ email-parser.ts
210
+ index.ts
211
+ mapping.ts
212
+ webhook/
213
+ auth.ts
214
+ encoding.ts
215
+ errors.ts
216
+ index.ts
217
+ parsing.ts
218
+ signing.ts
219
+ version.ts
220
+ generated/
221
+ email-received-event.validator.generated.ts
222
+ index.ts
223
+ schema.generated.ts
224
+ types.generated.ts
225
+ types.ts
226
+ validation.ts
227
+ ```
@@ -0,0 +1,150 @@
1
+ import { EmailAddress, EmailAnalysis, EmailAuth, EmailReceivedEvent, ParsedDataComplete, ParsedDataFailed, ParsedError, RawContentDownloadOnly, RawContentInline, WebhookAttachment } from "../types-C6M6oCRS.js";
2
+ import { SignResult, WEBHOOK_VERSION$1 as WEBHOOK_VERSION, signWebhookPayload$1 as signWebhookPayload } from "../index-C9pON-wY.js";
3
+
4
+ //#region src/contract/contract.d.ts
5
+ /** Maximum raw email size for inline inclusion (256 KB). */
6
+
7
+ /** Maximum raw email size for inline inclusion (256 KB). */
8
+ declare const RAW_EMAIL_INLINE_THRESHOLD = 262144;
9
+ /** Parsed content input when parsing succeeded. */
10
+ interface ParsedInputComplete {
11
+ status: "complete";
12
+ body_text: string | null;
13
+ body_html: string | null;
14
+ /** Parsed Reply-To header addresses. Defaults to `null` when omitted. */
15
+ reply_to?: EmailAddress[] | null;
16
+ /** Parsed CC header addresses. Defaults to `null` when omitted. */
17
+ cc?: EmailAddress[] | null;
18
+ /** Parsed BCC header addresses. Defaults to `null` when omitted. */
19
+ bcc?: EmailAddress[] | null;
20
+ /** In-Reply-To header values. Defaults to `null` when omitted. */
21
+ in_reply_to?: string[] | null;
22
+ /** References header values. Defaults to `null` when omitted. */
23
+ references?: string[] | null;
24
+ attachments: WebhookAttachment[];
25
+ /** Storage key for the attachments tarball, if attachments were persisted. Ignored by the canonical payload builder. */
26
+ attachments_storage_key?: string | null;
27
+ }
28
+ /** Parsed content input when parsing failed. */
29
+ interface ParsedInputFailed {
30
+ status: "failed";
31
+ error: ParsedError;
32
+ }
33
+ /** Parsed content input (discriminated union on `status`). */
34
+ type ParsedInput = ParsedInputComplete | ParsedInputFailed;
35
+ /**
36
+ * Input for building an `EmailReceivedEvent`.
37
+ *
38
+ * This is the strict producer-side shape required to construct a canonical
39
+ * Primitive `email.received` webhook payload.
40
+ */
41
+ interface EmailReceivedEventInput {
42
+ /** Unique email ID in Primitive. */
43
+ email_id: string;
44
+ /** ID of the webhook endpoint receiving this event. */
45
+ endpoint_id: string;
46
+ /** Message-ID header value, if present. */
47
+ message_id: string | null;
48
+ /** From header value. */
49
+ sender: string;
50
+ /** To header value. */
51
+ recipient: string;
52
+ /** Subject header value, if present. */
53
+ subject: string | null;
54
+ /** ISO 8601 timestamp when Primitive received the email. */
55
+ received_at: string;
56
+ /** HELO/EHLO hostname from the sending server. */
57
+ smtp_helo: string | null;
58
+ /** SMTP envelope sender (MAIL FROM). */
59
+ smtp_mail_from: string;
60
+ /** SMTP envelope recipients (RCPT TO). Must contain at least one recipient. */
61
+ smtp_rcpt_to: [string, ...string[]];
62
+ /** Raw email bytes. These are base64 encoded when inlined into the payload. */
63
+ raw_bytes: Buffer;
64
+ /** SHA-256 hash of the raw email as a 64-character hex string. */
65
+ raw_sha256: string;
66
+ /** Size of the raw email in bytes. */
67
+ raw_size_bytes: number;
68
+ /** Delivery attempt number, starting at 1. */
69
+ attempt_count: number;
70
+ /** Date header parsed from the raw email, if present. */
71
+ date_header: string | null;
72
+ /** HTTPS download URL for the raw email. */
73
+ download_url: string;
74
+ /** ISO 8601 timestamp when the raw-email download URL expires. */
75
+ download_expires_at: string;
76
+ /** HTTPS download URL for the attachments tarball, if one exists. */
77
+ attachments_download_url: string | null;
78
+ /** Parsed email content. Defaults to a failed parse state when omitted. */
79
+ parsed?: ParsedInput;
80
+ /** Email authentication results (SPF, DKIM, DMARC). */
81
+ auth: EmailAuth;
82
+ /** Email analysis results. */
83
+ analysis: EmailAnalysis;
84
+ }
85
+ /**
86
+ * Generate a stable event ID for webhook deduplication.
87
+ *
88
+ * Format: `evt_{sha256_hex}` where the hash is deterministic based on the
89
+ * event type, endpoint ID, and email ID. The same email sent
90
+ * to the same endpoint will always get the same event ID.
91
+ *
92
+ * @param endpoint_id - Webhook endpoint ID.
93
+ * @param email_id - Primitive email ID.
94
+ * @returns Stable event ID with `evt_` prefix.
95
+ */
96
+ declare function generateEventId(endpoint_id: string, email_id: string): string;
97
+ /**
98
+ * Build an `EmailReceivedEvent` from producer-side input.
99
+ *
100
+ * This is the contract package's primary builder. It assembles the canonical
101
+ * payload shape, applies inline/download raw-content rules, and validates the
102
+ * result against the generated JSON Schema before returning.
103
+ *
104
+ * @param input - Producer-side data for the webhook payload.
105
+ * @param options - Optional overrides for event ID and attempted-at timestamp.
106
+ * @returns A fully constructed, schema-valid `EmailReceivedEvent`.
107
+ *
108
+ * @example
109
+ * ```typescript
110
+ * import { buildEmailReceivedEvent } from "@primitivedotdev/sdk/contract";
111
+ *
112
+ * const event = buildEmailReceivedEvent({
113
+ * email_id: "email-123",
114
+ * endpoint_id: "endpoint-456",
115
+ * message_id: "<msg@example.com>",
116
+ * sender: "from@example.com",
117
+ * recipient: "to@example.com",
118
+ * subject: "Hello",
119
+ * received_at: "2025-01-01T00:00:00Z",
120
+ * smtp_helo: "mail.example.com",
121
+ * smtp_mail_from: "from@example.com",
122
+ * smtp_rcpt_to: ["to@example.com"],
123
+ * raw_bytes: Buffer.from("..."),
124
+ * raw_sha256: "a".repeat(64),
125
+ * raw_size_bytes: 1234,
126
+ * attempt_count: 1,
127
+ * date_header: "Mon, 1 Jan 2025 00:00:00 +0000",
128
+ * download_url: "https://example.com/download/email-123",
129
+ * download_expires_at: "2025-01-02T00:00:00Z",
130
+ * attachments_download_url: null,
131
+ * auth: {
132
+ * spf: "pass",
133
+ * dmarc: "pass",
134
+ * dmarcPolicy: "reject",
135
+ * dmarcFromDomain: "example.com",
136
+ * dmarcSpfStrict: false,
137
+ * dmarcDkimStrict: false,
138
+ * dkimSignatures: [],
139
+ * },
140
+ * analysis: {},
141
+ * });
142
+ * ```
143
+ */
144
+ declare function buildEmailReceivedEvent(input: EmailReceivedEventInput, options?: {
145
+ /** Override the generated event ID, typically for tests. */
146
+ event_id?: string;
147
+ /** Override the attempted-at timestamp, typically for tests. */
148
+ attempted_at?: string;
149
+ }): EmailReceivedEvent; //#endregion
150
+ export { EmailAddress, EmailAnalysis, EmailAuth, EmailReceivedEvent, EmailReceivedEventInput, ParsedDataComplete, ParsedDataFailed, ParsedError, ParsedInput, ParsedInputComplete, ParsedInputFailed, RAW_EMAIL_INLINE_THRESHOLD, RawContentDownloadOnly, RawContentInline, SignResult, WEBHOOK_VERSION, WebhookAttachment, buildEmailReceivedEvent, generateEventId, signWebhookPayload };
@@ -0,0 +1,199 @@
1
+ import { WEBHOOK_VERSION, signWebhookPayload, validateEmailReceivedEvent } from "../webhook-h24dbQEE.js";
2
+ import { createHash } from "node:crypto";
3
+
4
+ //#region src/contract/contract.ts
5
+ /** Maximum raw email size for inline inclusion (256 KB). */
6
+ const RAW_EMAIL_INLINE_THRESHOLD = 262144;
7
+ /**
8
+ * ISO 8601 timestamp pattern.
9
+ *
10
+ * Matches RFC 3339 date-time strings with either `Z` or an explicit UTC offset,
11
+ * but rejects loose formats like `Tuesday` that `Date.parse()` would otherwise accept.
12
+ */
13
+ const ISO_8601_PATTERN = /^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}(?:\.\d{1,9})?(?:Z|[+-]\d{2}:\d{2})$/;
14
+ /**
15
+ * Validate that a timestamp is a valid RFC 3339 date-time string.
16
+ *
17
+ * The original string is preserved so callers retain their chosen precision.
18
+ *
19
+ * @param timestamp - Timestamp string to validate.
20
+ * @param fieldName - Logical field name used in error messages.
21
+ * @returns The validated timestamp, unchanged.
22
+ * @throws Error if the timestamp is not a valid RFC 3339 date-time string.
23
+ */
24
+ function validateTimestamp(timestamp, fieldName) {
25
+ if (!ISO_8601_PATTERN.test(timestamp)) throw new Error(`[@primitivedotdev/sdk/contract] Invalid ${fieldName}: "${timestamp}". Expected RFC 3339 date-time format (e.g., "2025-01-15T10:30:00.000Z" or "2025-01-15T10:30:00+00:00")`);
26
+ const date = new Date(timestamp);
27
+ if (Number.isNaN(date.getTime())) throw new Error(`[@primitivedotdev/sdk/contract] Invalid ${fieldName}: "${timestamp}" is not a valid date`);
28
+ return timestamp;
29
+ }
30
+ /**
31
+ * Generate a stable event ID for webhook deduplication.
32
+ *
33
+ * Format: `evt_{sha256_hex}` where the hash is deterministic based on the
34
+ * event type, endpoint ID, and email ID. The same email sent
35
+ * to the same endpoint will always get the same event ID.
36
+ *
37
+ * @param endpoint_id - Webhook endpoint ID.
38
+ * @param email_id - Primitive email ID.
39
+ * @returns Stable event ID with `evt_` prefix.
40
+ */
41
+ function generateEventId(endpoint_id, email_id) {
42
+ const hashInput = `email.received:${endpoint_id}:${email_id}`;
43
+ const hash = createHash("sha256").update(hashInput).digest("hex");
44
+ return `evt_${hash}`;
45
+ }
46
+ /**
47
+ * Build an `EmailReceivedEvent` from producer-side input.
48
+ *
49
+ * This is the contract package's primary builder. It assembles the canonical
50
+ * payload shape, applies inline/download raw-content rules, and validates the
51
+ * result against the generated JSON Schema before returning.
52
+ *
53
+ * @param input - Producer-side data for the webhook payload.
54
+ * @param options - Optional overrides for event ID and attempted-at timestamp.
55
+ * @returns A fully constructed, schema-valid `EmailReceivedEvent`.
56
+ *
57
+ * @example
58
+ * ```typescript
59
+ * import { buildEmailReceivedEvent } from "@primitivedotdev/sdk/contract";
60
+ *
61
+ * const event = buildEmailReceivedEvent({
62
+ * email_id: "email-123",
63
+ * endpoint_id: "endpoint-456",
64
+ * message_id: "<msg@example.com>",
65
+ * sender: "from@example.com",
66
+ * recipient: "to@example.com",
67
+ * subject: "Hello",
68
+ * received_at: "2025-01-01T00:00:00Z",
69
+ * smtp_helo: "mail.example.com",
70
+ * smtp_mail_from: "from@example.com",
71
+ * smtp_rcpt_to: ["to@example.com"],
72
+ * raw_bytes: Buffer.from("..."),
73
+ * raw_sha256: "a".repeat(64),
74
+ * raw_size_bytes: 1234,
75
+ * attempt_count: 1,
76
+ * date_header: "Mon, 1 Jan 2025 00:00:00 +0000",
77
+ * download_url: "https://example.com/download/email-123",
78
+ * download_expires_at: "2025-01-02T00:00:00Z",
79
+ * attachments_download_url: null,
80
+ * auth: {
81
+ * spf: "pass",
82
+ * dmarc: "pass",
83
+ * dmarcPolicy: "reject",
84
+ * dmarcFromDomain: "example.com",
85
+ * dmarcSpfStrict: false,
86
+ * dmarcDkimStrict: false,
87
+ * dkimSignatures: [],
88
+ * },
89
+ * analysis: {},
90
+ * });
91
+ * ```
92
+ */
93
+ function buildEmailReceivedEvent(input, options) {
94
+ const event_id = options?.event_id ?? generateEventId(input.endpoint_id, input.email_id);
95
+ const attempted_at = options?.attempted_at ? validateTimestamp(options.attempted_at, "attempted_at") : new Date().toISOString();
96
+ const raw_size_bytes = input.raw_bytes.length;
97
+ if (input.raw_size_bytes !== raw_size_bytes) throw new Error(`[@primitivedotdev/sdk/contract] Invalid raw_size_bytes: ${input.raw_size_bytes}. Expected ${raw_size_bytes} based on raw_bytes length`);
98
+ const raw_sha256 = createHash("sha256").update(input.raw_bytes).digest("hex");
99
+ if (input.raw_sha256 !== raw_sha256) throw new Error(`[@primitivedotdev/sdk/contract] Invalid raw_sha256: "${input.raw_sha256}". Expected ${raw_sha256} based on raw_bytes`);
100
+ const shouldInline = raw_size_bytes <= RAW_EMAIL_INLINE_THRESHOLD;
101
+ const rawContent = shouldInline ? {
102
+ included: true,
103
+ encoding: "base64",
104
+ max_inline_bytes: RAW_EMAIL_INLINE_THRESHOLD,
105
+ size_bytes: raw_size_bytes,
106
+ sha256: raw_sha256,
107
+ data: input.raw_bytes.toString("base64")
108
+ } : {
109
+ included: false,
110
+ reason_code: "size_exceeded",
111
+ max_inline_bytes: RAW_EMAIL_INLINE_THRESHOLD,
112
+ size_bytes: raw_size_bytes,
113
+ sha256: raw_sha256
114
+ };
115
+ let parsedData;
116
+ if (input.parsed?.status === "complete") parsedData = {
117
+ status: "complete",
118
+ error: null,
119
+ body_text: input.parsed.body_text,
120
+ body_html: input.parsed.body_html,
121
+ reply_to: input.parsed.reply_to ?? null,
122
+ cc: input.parsed.cc ?? null,
123
+ bcc: input.parsed.bcc ?? null,
124
+ in_reply_to: input.parsed.in_reply_to ?? null,
125
+ references: input.parsed.references ?? null,
126
+ attachments: input.parsed.attachments,
127
+ attachments_download_url: input.parsed.attachments.length === 0 ? null : input.attachments_download_url
128
+ };
129
+ else if (input.parsed?.status === "failed") parsedData = {
130
+ status: "failed",
131
+ error: input.parsed.error,
132
+ body_text: null,
133
+ body_html: null,
134
+ reply_to: null,
135
+ cc: null,
136
+ bcc: null,
137
+ in_reply_to: null,
138
+ references: null,
139
+ attachments: [],
140
+ attachments_download_url: null
141
+ };
142
+ else parsedData = {
143
+ status: "failed",
144
+ error: {
145
+ code: "PARSE_FAILED",
146
+ message: "Parsing not attempted",
147
+ retryable: false
148
+ },
149
+ body_text: null,
150
+ body_html: null,
151
+ reply_to: null,
152
+ cc: null,
153
+ bcc: null,
154
+ in_reply_to: null,
155
+ references: null,
156
+ attachments: [],
157
+ attachments_download_url: null
158
+ };
159
+ const event = {
160
+ id: event_id,
161
+ event: "email.received",
162
+ version: WEBHOOK_VERSION,
163
+ delivery: {
164
+ endpoint_id: input.endpoint_id,
165
+ attempt: input.attempt_count,
166
+ attempted_at
167
+ },
168
+ email: {
169
+ id: input.email_id,
170
+ received_at: validateTimestamp(input.received_at, "received_at"),
171
+ smtp: {
172
+ helo: input.smtp_helo,
173
+ mail_from: input.smtp_mail_from,
174
+ rcpt_to: input.smtp_rcpt_to
175
+ },
176
+ headers: {
177
+ message_id: input.message_id,
178
+ subject: input.subject,
179
+ from: input.sender,
180
+ to: input.recipient,
181
+ date: input.date_header
182
+ },
183
+ content: {
184
+ raw: rawContent,
185
+ download: {
186
+ url: input.download_url,
187
+ expires_at: validateTimestamp(input.download_expires_at, "download_expires_at")
188
+ }
189
+ },
190
+ parsed: parsedData,
191
+ analysis: input.analysis,
192
+ auth: input.auth
193
+ }
194
+ };
195
+ return validateEmailReceivedEvent(event);
196
+ }
197
+
198
+ //#endregion
199
+ export { RAW_EMAIL_INLINE_THRESHOLD, WEBHOOK_VERSION, buildEmailReceivedEvent, generateEventId, signWebhookPayload };