@orkestrel/msg 0.0.1
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/LICENSE +21 -0
- package/README.md +91 -0
- package/dist/src/core/index.cjs +2548 -0
- package/dist/src/core/index.cjs.map +1 -0
- package/dist/src/core/index.d.cts +1350 -0
- package/dist/src/core/index.d.ts +1350 -0
- package/dist/src/core/index.js +2445 -0
- package/dist/src/core/index.js.map +1 -0
- package/package.json +83 -0
|
@@ -0,0 +1,1350 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* CFB-compliant directory name comparator.
|
|
3
|
+
* Compares by UTF-16 length first, then by uppercased code points.
|
|
4
|
+
*
|
|
5
|
+
* @param a - First name
|
|
6
|
+
* @param b - Second name
|
|
7
|
+
* @returns Negative, zero, or positive
|
|
8
|
+
*/
|
|
9
|
+
export declare function compareCFBName(a: string, b: string): number;
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* Create a new email file parser for .eml and .msg input.
|
|
13
|
+
*
|
|
14
|
+
* @param options - Optional parser configuration
|
|
15
|
+
* @returns A working {@link EmailParserInterface}
|
|
16
|
+
*
|
|
17
|
+
* @example
|
|
18
|
+
* ```ts
|
|
19
|
+
* import { createEmailParser, isSuccess } from '@src/core'
|
|
20
|
+
*
|
|
21
|
+
* const parser = createEmailParser()
|
|
22
|
+
* const result = parser.parse({ bytes, name: 'message.eml' })
|
|
23
|
+
* if (isSuccess(result)) {
|
|
24
|
+
* console.log(result.value.messages[0].subject)
|
|
25
|
+
* }
|
|
26
|
+
* ```
|
|
27
|
+
*/
|
|
28
|
+
export declare function createEmailParser(options?: EmailParserOptions): EmailParserInterface;
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* Create a new CFB binary writer for reconstituting .msg files.
|
|
32
|
+
*
|
|
33
|
+
* @returns A working {@link MSGBurnerInterface}
|
|
34
|
+
*
|
|
35
|
+
* @example
|
|
36
|
+
* ```ts
|
|
37
|
+
* import { createMSGBurner } from '@src/core'
|
|
38
|
+
*
|
|
39
|
+
* const burner = createMSGBurner()
|
|
40
|
+
* const binary = burner.burn(entries)
|
|
41
|
+
* ```
|
|
42
|
+
*/
|
|
43
|
+
export declare function createMSGBurner(): MSGBurnerInterface;
|
|
44
|
+
|
|
45
|
+
/**
|
|
46
|
+
* Create a new .msg file reader.
|
|
47
|
+
*
|
|
48
|
+
* @param buffer - Raw .msg file bytes
|
|
49
|
+
* @param options - Optional reader configuration
|
|
50
|
+
* @returns A working {@link MSGReaderInterface}
|
|
51
|
+
*
|
|
52
|
+
* @example
|
|
53
|
+
* ```ts
|
|
54
|
+
* import { createMSGReader } from '@src/core'
|
|
55
|
+
*
|
|
56
|
+
* const reader = createMSGReader(buffer)
|
|
57
|
+
* const data = reader.parse()
|
|
58
|
+
* console.log(data.kind)
|
|
59
|
+
* ```
|
|
60
|
+
*/
|
|
61
|
+
export declare function createMSGReader(buffer: ArrayBuffer | Uint8Array, options?: MSGReaderOptions): MSGReaderInterface;
|
|
62
|
+
|
|
63
|
+
/**
|
|
64
|
+
* Decode a Base64 string into raw bytes without relying on `atob`.
|
|
65
|
+
* Ignores ASCII whitespace and tolerates missing padding.
|
|
66
|
+
*
|
|
67
|
+
* @param text - Base64-encoded string
|
|
68
|
+
* @returns Decoded byte array
|
|
69
|
+
* @throws {@link MSGError} with code `MALFORMED` when the string contains
|
|
70
|
+
* a character outside the Base64 alphabet
|
|
71
|
+
*
|
|
72
|
+
* @example
|
|
73
|
+
* ```ts
|
|
74
|
+
* decodeBase64('SGVsbG8=') // Uint8Array [72, 101, 108, 108, 111]
|
|
75
|
+
* ```
|
|
76
|
+
*/
|
|
77
|
+
export declare function decodeBase64(text: string): Uint8Array;
|
|
78
|
+
|
|
79
|
+
/**
|
|
80
|
+
* Decode Latin-1 (ISO-8859-1) bytes into a string, byte-for-code-point.
|
|
81
|
+
*
|
|
82
|
+
* @param bytes - Latin-1 byte array
|
|
83
|
+
* @returns Decoded string
|
|
84
|
+
*
|
|
85
|
+
* @example
|
|
86
|
+
* ```ts
|
|
87
|
+
* decodeLatin1(new Uint8Array([0xe9])) // 'é'
|
|
88
|
+
* ```
|
|
89
|
+
*/
|
|
90
|
+
export declare function decodeLatin1(bytes: Uint8Array): string;
|
|
91
|
+
|
|
92
|
+
/**
|
|
93
|
+
* Decode a MIME-encoded body string into a raw byte array.
|
|
94
|
+
*
|
|
95
|
+
* @param body - Raw encoded string
|
|
96
|
+
* @param encoding - Encoding type (e.g., 'base64', 'quoted-printable')
|
|
97
|
+
* @returns Decoded byte array
|
|
98
|
+
* @throws {@link MSGError} with code `MALFORMED` when `encoding` is `'base64'`
|
|
99
|
+
* and `body` contains an invalid Base64 character
|
|
100
|
+
*/
|
|
101
|
+
export declare function decodeMIMEEncoding(body: string, encoding: string): Uint8Array;
|
|
102
|
+
|
|
103
|
+
/**
|
|
104
|
+
* Decode a MIME-encoded body into a text string based on an arbitrary
|
|
105
|
+
* charset label, resolved via {@link resolveEncoding}.
|
|
106
|
+
*
|
|
107
|
+
* @param body - Raw encoded string
|
|
108
|
+
* @param encoding - Transfer encoding type
|
|
109
|
+
* @param charset - Character set label (e.g., 'utf-8')
|
|
110
|
+
* @returns Decoded string
|
|
111
|
+
*/
|
|
112
|
+
export declare function decodeMIMEText(body: string, encoding: string, charset: string): string;
|
|
113
|
+
|
|
114
|
+
/**
|
|
115
|
+
* Decode RFC 2047 encoded words in header values.
|
|
116
|
+
* Handles both Base64 (B) and Quoted-Printable (Q) forms.
|
|
117
|
+
*
|
|
118
|
+
* @param text - Header value string potentially containing encoded words
|
|
119
|
+
* @returns Decoded string
|
|
120
|
+
*
|
|
121
|
+
* @example
|
|
122
|
+
* ```ts
|
|
123
|
+
* decodeMIMEWords('=?UTF-8?B?SGVsbG8=?=') // 'Hello'
|
|
124
|
+
* ```
|
|
125
|
+
*/
|
|
126
|
+
export declare function decodeMIMEWords(text: string): string;
|
|
127
|
+
|
|
128
|
+
/**
|
|
129
|
+
* Decode UTF-8 bytes into a string, WHATWG-style: an invalid byte
|
|
130
|
+
* sequence decodes as U+FFFD rather than throwing. Rejects overlong
|
|
131
|
+
* encodings, surrogate code points (0xD800-0xDFFF), and code points
|
|
132
|
+
* beyond 0x10FFFF — each invalid sequence yields exactly one U+FFFD
|
|
133
|
+
* and decoding resumes at the next lead byte.
|
|
134
|
+
*
|
|
135
|
+
* @param bytes - UTF-8 byte array
|
|
136
|
+
* @returns Decoded string
|
|
137
|
+
*
|
|
138
|
+
* @example
|
|
139
|
+
* ```ts
|
|
140
|
+
* decodeUTF8(new Uint8Array([65])) // 'A'
|
|
141
|
+
* decodeUTF8(new Uint8Array([0xff])) // '�'
|
|
142
|
+
* ```
|
|
143
|
+
*/
|
|
144
|
+
export declare function decodeUTF8(bytes: Uint8Array): string;
|
|
145
|
+
|
|
146
|
+
/**
|
|
147
|
+
* Decode Windows-1252 bytes into a string. Identical to {@link decodeLatin1}
|
|
148
|
+
* except for the 0x80-0x9F range, which maps through {@link WINDOWS_1252_HIGH}.
|
|
149
|
+
*
|
|
150
|
+
* @param bytes - Windows-1252 byte array
|
|
151
|
+
* @returns Decoded string
|
|
152
|
+
*
|
|
153
|
+
* @example
|
|
154
|
+
* ```ts
|
|
155
|
+
* decodeWindows1252(new Uint8Array([0x93])) // '“'
|
|
156
|
+
* ```
|
|
157
|
+
*/
|
|
158
|
+
export declare function decodeWindows1252(bytes: Uint8Array): string;
|
|
159
|
+
|
|
160
|
+
/**
|
|
161
|
+
* Derive the EmailFormat from a file name and/or MIME type.
|
|
162
|
+
* Returns undefined when the format cannot be determined.
|
|
163
|
+
*
|
|
164
|
+
* @param name - File name to inspect
|
|
165
|
+
* @param mime - MIME type to inspect
|
|
166
|
+
* @returns Detected format or undefined
|
|
167
|
+
*
|
|
168
|
+
* @example
|
|
169
|
+
* ```ts
|
|
170
|
+
* detectFormat('message.eml', undefined) // 'eml'
|
|
171
|
+
* detectFormat(undefined, 'application/vnd.ms-outlook') // 'msg'
|
|
172
|
+
* ```
|
|
173
|
+
*/
|
|
174
|
+
export declare function detectFormat(name: string | undefined, mime: string | undefined): EmailFormat | undefined;
|
|
175
|
+
|
|
176
|
+
/**
|
|
177
|
+
* Extracted attachment from an email message.
|
|
178
|
+
*
|
|
179
|
+
* @remarks
|
|
180
|
+
* - `name` — attachment file name
|
|
181
|
+
* - `mimeType` — MIME content type
|
|
182
|
+
* - `size` — byte length
|
|
183
|
+
* - `bytes` — raw binary content
|
|
184
|
+
*/
|
|
185
|
+
export declare interface EmailAttachment {
|
|
186
|
+
readonly name: string;
|
|
187
|
+
readonly mimeType: string;
|
|
188
|
+
readonly size: number;
|
|
189
|
+
readonly bytes: Uint8Array;
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
/**
|
|
193
|
+
* Parsed email chain from a single file.
|
|
194
|
+
*
|
|
195
|
+
* @remarks
|
|
196
|
+
* - `format` — detected file format ('eml' or 'msg')
|
|
197
|
+
* - `messages` — extracted messages (always length 1 for single-file formats)
|
|
198
|
+
*/
|
|
199
|
+
export declare interface EmailChain {
|
|
200
|
+
readonly format: EmailFormat;
|
|
201
|
+
readonly messages: readonly EmailMessage[];
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
/**
|
|
205
|
+
* Supported email file format.
|
|
206
|
+
*/
|
|
207
|
+
export declare type EmailFormat = 'eml' | 'msg';
|
|
208
|
+
|
|
209
|
+
/**
|
|
210
|
+
* Raw email input handed to an EmailParser.
|
|
211
|
+
*
|
|
212
|
+
* @remarks
|
|
213
|
+
* - `bytes` — raw file content
|
|
214
|
+
* - `name` — optional file name, used to infer format when `mime` is absent
|
|
215
|
+
* - `mime` — optional MIME type, used to infer format
|
|
216
|
+
*/
|
|
217
|
+
export declare interface EmailInput {
|
|
218
|
+
readonly bytes: Uint8Array;
|
|
219
|
+
readonly name?: string;
|
|
220
|
+
readonly mime?: string;
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
/**
|
|
224
|
+
* Structured email message extracted from a parsed file.
|
|
225
|
+
*
|
|
226
|
+
* @remarks
|
|
227
|
+
* - `from` — sender address string
|
|
228
|
+
* - `to` — recipient addresses
|
|
229
|
+
* - `cc` — carbon copy addresses
|
|
230
|
+
* - `subject` — decoded subject line
|
|
231
|
+
* - `date` — delivery date or undefined when absent/malformed
|
|
232
|
+
* - `text` — plain-text body (includes quoted reply chain)
|
|
233
|
+
* - `html` — HTML body (includes quoted reply chain)
|
|
234
|
+
* - `attachments` — decoded file attachments
|
|
235
|
+
*/
|
|
236
|
+
export declare interface EmailMessage {
|
|
237
|
+
readonly from: string;
|
|
238
|
+
readonly to: readonly string[];
|
|
239
|
+
readonly cc: readonly string[];
|
|
240
|
+
readonly subject: string;
|
|
241
|
+
readonly date: Date | undefined;
|
|
242
|
+
readonly text: string;
|
|
243
|
+
readonly html: string;
|
|
244
|
+
readonly attachments: readonly EmailAttachment[];
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
/**
|
|
248
|
+
* Parses raw .eml or .msg file bytes into a structured {@link EmailChain}.
|
|
249
|
+
* Synchronous and dependency-free: format detection falls back to sniffing
|
|
250
|
+
* the CFB magic header when neither `name` nor `mime` resolves it, and every
|
|
251
|
+
* parse failure is contained into a `Result` rather than thrown.
|
|
252
|
+
*
|
|
253
|
+
* @example
|
|
254
|
+
* ```ts
|
|
255
|
+
* import { createEmailParser, isSuccess } from '@src/core'
|
|
256
|
+
*
|
|
257
|
+
* const parser = createEmailParser()
|
|
258
|
+
* const result = parser.parse({ bytes, name: 'message.eml' })
|
|
259
|
+
* if (isSuccess(result)) {
|
|
260
|
+
* const { messages } = result.value
|
|
261
|
+
* console.log(messages[0].text)
|
|
262
|
+
* console.log(messages[0].attachments)
|
|
263
|
+
* }
|
|
264
|
+
* ```
|
|
265
|
+
*/
|
|
266
|
+
export declare class EmailParser implements EmailParserInterface {
|
|
267
|
+
#private;
|
|
268
|
+
constructor(options?: EmailParserOptions);
|
|
269
|
+
/**
|
|
270
|
+
* Parse raw email bytes into a structured chain.
|
|
271
|
+
*
|
|
272
|
+
* @param input - Raw bytes plus optional name/MIME hints
|
|
273
|
+
* @returns A {@link Success} wrapping the parsed {@link EmailChain}, or a
|
|
274
|
+
* {@link Failure} wrapping an {@link MSGError} (code `UNSUPPORTED` when
|
|
275
|
+
* the format cannot be determined, `MALFORMED` when parsing fails)
|
|
276
|
+
*
|
|
277
|
+
* @example
|
|
278
|
+
* ```ts
|
|
279
|
+
* const result = parser.parse({ bytes, name: 'message.msg' })
|
|
280
|
+
* ```
|
|
281
|
+
*/
|
|
282
|
+
parse(input: EmailInput): Result<EmailChain, MSGError>;
|
|
283
|
+
/**
|
|
284
|
+
* Current parser configuration.
|
|
285
|
+
*
|
|
286
|
+
* @returns A copy of the configured {@link EmailParserOptions} — the
|
|
287
|
+
* internal reference is never leaked
|
|
288
|
+
*/
|
|
289
|
+
get options(): EmailParserOptions;
|
|
290
|
+
}
|
|
291
|
+
|
|
292
|
+
/**
|
|
293
|
+
* Public interface for parsing email files into structured chains.
|
|
294
|
+
*
|
|
295
|
+
* @remarks
|
|
296
|
+
* - `parse` — parse an EmailInput into an EmailChain result
|
|
297
|
+
* - `options` — current parser configuration
|
|
298
|
+
*/
|
|
299
|
+
export declare interface EmailParserInterface {
|
|
300
|
+
/**
|
|
301
|
+
* Parse raw email bytes into a structured chain.
|
|
302
|
+
*
|
|
303
|
+
* @param input - Raw bytes plus optional name/MIME hints
|
|
304
|
+
* @returns A {@link Success} wrapping the parsed {@link EmailChain}, or a
|
|
305
|
+
* {@link Failure} wrapping an {@link MSGError} (code `UNSUPPORTED` when
|
|
306
|
+
* the format cannot be determined, `MALFORMED` when parsing fails)
|
|
307
|
+
*/
|
|
308
|
+
parse(input: EmailInput): Result<EmailChain, MSGError>;
|
|
309
|
+
readonly options: EmailParserOptions;
|
|
310
|
+
}
|
|
311
|
+
|
|
312
|
+
/**
|
|
313
|
+
* Configuration for creating an EmailParser.
|
|
314
|
+
*
|
|
315
|
+
* @remarks
|
|
316
|
+
* - `encoding` — encoding for decoding MIME part bodies (default `'utf-8'`)
|
|
317
|
+
*/
|
|
318
|
+
export declare interface EmailParserOptions {
|
|
319
|
+
readonly encoding?: MSGEncoding;
|
|
320
|
+
}
|
|
321
|
+
|
|
322
|
+
/**
|
|
323
|
+
* File extensions recognized as RFC 2822 / MIME email files.
|
|
324
|
+
*/
|
|
325
|
+
export declare const EML_EXTENSIONS: readonly string[];
|
|
326
|
+
|
|
327
|
+
/**
|
|
328
|
+
* MIME types recognized as RFC 2822 / MIME email files.
|
|
329
|
+
*/
|
|
330
|
+
export declare const EML_MIME_TYPES: readonly string[];
|
|
331
|
+
|
|
332
|
+
/**
|
|
333
|
+
* Encode a string into UTF-8 bytes, handling surrogate pairs.
|
|
334
|
+
* A lone (unpaired) surrogate encodes as U+FFFD.
|
|
335
|
+
*
|
|
336
|
+
* @param text - String to encode
|
|
337
|
+
* @returns UTF-8 byte array
|
|
338
|
+
*
|
|
339
|
+
* @example
|
|
340
|
+
* ```ts
|
|
341
|
+
* encodeUTF8('A') // Uint8Array [65]
|
|
342
|
+
* ```
|
|
343
|
+
*/
|
|
344
|
+
export declare function encodeUTF8(text: string): Uint8Array;
|
|
345
|
+
|
|
346
|
+
/**
|
|
347
|
+
* Extract a single EmailMessage from a top-level MIMEPart.
|
|
348
|
+
* Walks the full MIME tree to collect text, HTML, and attachments.
|
|
349
|
+
*
|
|
350
|
+
* @param part - Root MIMEPart from parseMIMEPart
|
|
351
|
+
* @returns Structured EmailMessage
|
|
352
|
+
*/
|
|
353
|
+
export declare function extractMessage(part: MIMEPart): EmailMessage;
|
|
354
|
+
|
|
355
|
+
/**
|
|
356
|
+
* Extract a single EmailMessage from a parsed MSGReader.
|
|
357
|
+
* Reads field data and attachments from the reader interface.
|
|
358
|
+
*
|
|
359
|
+
* Each attachment is read independently: a corrupt attachment throws
|
|
360
|
+
* from `reader.attachment(i)` is caught and that attachment is skipped
|
|
361
|
+
* so the rest of the message still parses. This containment keeps one
|
|
362
|
+
* damaged attachment stream from failing the entire message extraction.
|
|
363
|
+
*
|
|
364
|
+
* @param reader - A parsed MSGReaderInterface instance
|
|
365
|
+
* @returns Structured EmailMessage
|
|
366
|
+
*/
|
|
367
|
+
export declare function extractMessageFromMSG(reader: MSGReaderInterface): EmailMessage;
|
|
368
|
+
|
|
369
|
+
/**
|
|
370
|
+
* Failed operation result.
|
|
371
|
+
*/
|
|
372
|
+
export declare interface Failure<E> {
|
|
373
|
+
readonly success: false;
|
|
374
|
+
readonly error: E;
|
|
375
|
+
}
|
|
376
|
+
|
|
377
|
+
/**
|
|
378
|
+
* Construct a {@link Failure} wrapping an error.
|
|
379
|
+
*
|
|
380
|
+
* @param error - The error to wrap
|
|
381
|
+
* @returns A `Failure<E>` result
|
|
382
|
+
*
|
|
383
|
+
* @example
|
|
384
|
+
* ```ts
|
|
385
|
+
* const result = failure(new MSGError('MALFORMED', 'bad input'))
|
|
386
|
+
* ```
|
|
387
|
+
*/
|
|
388
|
+
export declare function failure<E>(error: E): Failure<E>;
|
|
389
|
+
|
|
390
|
+
/**
|
|
391
|
+
* Default file name for attachments without an explicit name.
|
|
392
|
+
*/
|
|
393
|
+
export declare const FALLBACK_ATTACHMENT_NAME = "attachment";
|
|
394
|
+
|
|
395
|
+
/**
|
|
396
|
+
* Default charset for decoding MIME part bodies.
|
|
397
|
+
*/
|
|
398
|
+
export declare const FALLBACK_CHARSET = "utf-8";
|
|
399
|
+
|
|
400
|
+
/**
|
|
401
|
+
* Convert a Windows FILETIME (100-ns intervals since 1601-01-01) to a UTC date string.
|
|
402
|
+
* Combines the low/high 32-bit halves with `BigInt` so the 64-bit interval
|
|
403
|
+
* count never loses precision to float64 rounding.
|
|
404
|
+
*
|
|
405
|
+
* @param low - Low 32 bits of FILETIME
|
|
406
|
+
* @param high - High 32 bits of FILETIME
|
|
407
|
+
* @returns UTC date string
|
|
408
|
+
*/
|
|
409
|
+
export declare function fileTimeToUTCString(low: number, high: number): string;
|
|
410
|
+
|
|
411
|
+
/**
|
|
412
|
+
* Format a name and email into a standard composite address.
|
|
413
|
+
*
|
|
414
|
+
* @param name - Display name
|
|
415
|
+
* @param email - Email address
|
|
416
|
+
* @returns Formatted address string
|
|
417
|
+
*/
|
|
418
|
+
export declare function formatEmailAddress(name: string | undefined, email: string | undefined): string;
|
|
419
|
+
|
|
420
|
+
/**
|
|
421
|
+
* Infers the file extension for an attachment based on its filename or MIME type.
|
|
422
|
+
* Returns the extension including the dot (e.g., '.jpg').
|
|
423
|
+
*
|
|
424
|
+
* @param mimeType - MIME type to infer from
|
|
425
|
+
* @param fileName - File name to infer from
|
|
426
|
+
* @returns Inferred extension, or `.bin` when neither hint resolves
|
|
427
|
+
*/
|
|
428
|
+
export declare function inferExtension(mimeType?: string, fileName?: string): string;
|
|
429
|
+
|
|
430
|
+
/**
|
|
431
|
+
* Narrow an unknown value to a valid EmailFormat.
|
|
432
|
+
*
|
|
433
|
+
* @param value - Value to check
|
|
434
|
+
* @returns True when value is 'eml' or 'msg'
|
|
435
|
+
*/
|
|
436
|
+
export declare function isEmailFormat(value: unknown): value is EmailFormat;
|
|
437
|
+
|
|
438
|
+
/**
|
|
439
|
+
* Narrow a Result to Failure.
|
|
440
|
+
*
|
|
441
|
+
* @param result - Result to check
|
|
442
|
+
* @returns True when result is Failure
|
|
443
|
+
*/
|
|
444
|
+
export declare function isFailure<T, E>(result: Result<T, E>): result is Failure<E>;
|
|
445
|
+
|
|
446
|
+
/**
|
|
447
|
+
* Narrow an unknown caught (or `Failure.error`) value to an {@link MSGError}.
|
|
448
|
+
*
|
|
449
|
+
* @param value - The value to test (typically a `catch` binding or a `Result.error`)
|
|
450
|
+
* @returns `true` when `value` is an {@link MSGError}
|
|
451
|
+
*
|
|
452
|
+
* @example
|
|
453
|
+
* ```ts
|
|
454
|
+
* import { isMSGError } from '@src/core'
|
|
455
|
+
*
|
|
456
|
+
* try {
|
|
457
|
+
* reader.parse()
|
|
458
|
+
* } catch (error) {
|
|
459
|
+
* if (isMSGError(error) && error.code === 'MALFORMED') return
|
|
460
|
+
* }
|
|
461
|
+
* ```
|
|
462
|
+
*/
|
|
463
|
+
export declare function isMSGError(value: unknown): value is MSGError;
|
|
464
|
+
|
|
465
|
+
/**
|
|
466
|
+
* Validate that a DataView starts with the CFB magic header.
|
|
467
|
+
*
|
|
468
|
+
* @param view - DataView to check
|
|
469
|
+
* @returns True when the first 8 bytes match the CFB signature
|
|
470
|
+
*/
|
|
471
|
+
export declare function isMSGFile(view: DataView): boolean;
|
|
472
|
+
|
|
473
|
+
/**
|
|
474
|
+
* Narrow an unknown value to a plain record.
|
|
475
|
+
*
|
|
476
|
+
* @param value - Value to check
|
|
477
|
+
* @returns True when value is a non-null, non-array object
|
|
478
|
+
*/
|
|
479
|
+
export declare function isRecord(value: unknown): value is Record<string, unknown>;
|
|
480
|
+
|
|
481
|
+
/**
|
|
482
|
+
* Narrow a Result to Success.
|
|
483
|
+
*
|
|
484
|
+
* @param result - Result to check
|
|
485
|
+
* @returns True when result is Success
|
|
486
|
+
*/
|
|
487
|
+
export declare function isSuccess<T, E>(result: Result<T, E>): result is Success<T>;
|
|
488
|
+
|
|
489
|
+
/**
|
|
490
|
+
* Common MIME types to file extensions mapping.
|
|
491
|
+
* Used for inferring the correct extension during file extraction.
|
|
492
|
+
*/
|
|
493
|
+
export declare const MIME_EXTENSIONS: ReadonlyMap<string, string>;
|
|
494
|
+
|
|
495
|
+
/**
|
|
496
|
+
* Maximum multipart nesting depth accepted by `parseMIMEPart`.
|
|
497
|
+
* Guards against pathological or hostile MIME trees causing
|
|
498
|
+
* unbounded recursion.
|
|
499
|
+
*/
|
|
500
|
+
export declare const MIME_MAX_DEPTH = 50;
|
|
501
|
+
|
|
502
|
+
/**
|
|
503
|
+
* Parsed MIME header with value and parameter map.
|
|
504
|
+
*
|
|
505
|
+
* @remarks
|
|
506
|
+
* - `value` — primary header value (before first semicolon)
|
|
507
|
+
* - `params` — key-value parameter map (e.g. charset, boundary)
|
|
508
|
+
*/
|
|
509
|
+
export declare interface MIMEHeader {
|
|
510
|
+
readonly value: string;
|
|
511
|
+
readonly params: ReadonlyMap<string, string>;
|
|
512
|
+
}
|
|
513
|
+
|
|
514
|
+
/**
|
|
515
|
+
* Recursive MIME part tree node.
|
|
516
|
+
*
|
|
517
|
+
* @remarks
|
|
518
|
+
* - `headers` — parsed header map keyed by lowercase name
|
|
519
|
+
* - `body` — raw body text (empty for multipart containers)
|
|
520
|
+
* - `parts` — child parts for multipart types
|
|
521
|
+
*/
|
|
522
|
+
export declare interface MIMEPart {
|
|
523
|
+
readonly headers: ReadonlyMap<string, MIMEHeader>;
|
|
524
|
+
readonly body: string;
|
|
525
|
+
readonly parts: readonly MIMEPart[];
|
|
526
|
+
}
|
|
527
|
+
|
|
528
|
+
/**
|
|
529
|
+
* Stringify a mixed-endian Microsoft UUID from a byte array.
|
|
530
|
+
*
|
|
531
|
+
* @param data - Byte array containing the UUID
|
|
532
|
+
* @param offset - Byte offset to start reading
|
|
533
|
+
* @returns UUID string in lowercase
|
|
534
|
+
*/
|
|
535
|
+
export declare function msftUUIDStringify(data: Uint8Array, offset: number): string;
|
|
536
|
+
|
|
537
|
+
/**
|
|
538
|
+
* Threshold below which data is stored in the mini-stream.
|
|
539
|
+
*/
|
|
540
|
+
export declare const MSG_BIG_BLOCK_MIN_DOC_SIZE = 4096;
|
|
541
|
+
|
|
542
|
+
/**
|
|
543
|
+
* Maximum DIFAT entries stored in the CFB header (109).
|
|
544
|
+
*/
|
|
545
|
+
export declare const MSG_BURNER_DIFAT_HEADER_SLOTS = 109;
|
|
546
|
+
|
|
547
|
+
/**
|
|
548
|
+
* DIFAT sector marker: this sector holds DIFAT data (-4).
|
|
549
|
+
*/
|
|
550
|
+
export declare const MSG_BURNER_DIFAT_SECTOR_MARKER = -4;
|
|
551
|
+
|
|
552
|
+
/**
|
|
553
|
+
* CFB directory entry size in bytes (128).
|
|
554
|
+
*/
|
|
555
|
+
export declare const MSG_BURNER_DIR_ENTRY_SIZE = 128;
|
|
556
|
+
|
|
557
|
+
/**
|
|
558
|
+
* FAT sector marker: this sector holds FAT data (-3).
|
|
559
|
+
*/
|
|
560
|
+
export declare const MSG_BURNER_FAT_SECTOR_MARKER = -3;
|
|
561
|
+
|
|
562
|
+
/**
|
|
563
|
+
* Number of 32-bit integers per standard sector (128).
|
|
564
|
+
*/
|
|
565
|
+
export declare const MSG_BURNER_INTS_PER_SECTOR: number;
|
|
566
|
+
|
|
567
|
+
/**
|
|
568
|
+
* CFB mini-stream sector size in bytes (64).
|
|
569
|
+
*/
|
|
570
|
+
export declare const MSG_BURNER_MINI_SECTOR_SIZE = 64;
|
|
571
|
+
|
|
572
|
+
/**
|
|
573
|
+
* Threshold below which streams are stored in the mini-stream (4096).
|
|
574
|
+
*/
|
|
575
|
+
export declare const MSG_BURNER_MINI_STREAM_CUTOFF = 4096;
|
|
576
|
+
|
|
577
|
+
/**
|
|
578
|
+
* Maximum UTF-16 code units allowed in a CFB directory entry name (31).
|
|
579
|
+
* The fixed 64-byte name field holds 32 UTF-16 units including the
|
|
580
|
+
* NUL terminator, so the name itself is capped at 31 units.
|
|
581
|
+
*/
|
|
582
|
+
export declare const MSG_BURNER_NAME_MAX = 31;
|
|
583
|
+
|
|
584
|
+
/**
|
|
585
|
+
* Root entry CLSID for MSG compound files.
|
|
586
|
+
*/
|
|
587
|
+
export declare const MSG_BURNER_ROOT_CLSID: Uint8Array<ArrayBuffer>;
|
|
588
|
+
|
|
589
|
+
/**
|
|
590
|
+
* Standard CFB sector size in bytes (512).
|
|
591
|
+
*/
|
|
592
|
+
export declare const MSG_BURNER_SECTOR_SIZE = 512;
|
|
593
|
+
|
|
594
|
+
/**
|
|
595
|
+
* Sentinel for end-of-chain in the FAT.
|
|
596
|
+
*/
|
|
597
|
+
export declare const MSG_END_OF_CHAIN = -2;
|
|
598
|
+
|
|
599
|
+
/**
|
|
600
|
+
* File extensions recognized as Outlook binary email files.
|
|
601
|
+
*/
|
|
602
|
+
export declare const MSG_EXTENSIONS: readonly string[];
|
|
603
|
+
|
|
604
|
+
/**
|
|
605
|
+
* Attachment data class identifier.
|
|
606
|
+
*/
|
|
607
|
+
export declare const MSG_FIELD_CLASS_ATTACHMENT_DATA = "3701";
|
|
608
|
+
|
|
609
|
+
/**
|
|
610
|
+
* Directory field type indicating an embedded MSG.
|
|
611
|
+
*/
|
|
612
|
+
export declare const MSG_FIELD_DIR_TYPE_INNER_MSG = "000d";
|
|
613
|
+
|
|
614
|
+
/**
|
|
615
|
+
* Full 8-char property tag to field name mapping (for compound tags).
|
|
616
|
+
*/
|
|
617
|
+
export declare const MSG_FIELD_FULL_NAME_MAPPING: Readonly<Record<string, string>>;
|
|
618
|
+
|
|
619
|
+
/**
|
|
620
|
+
* MAPI property tag to field name mapping.
|
|
621
|
+
*/
|
|
622
|
+
export declare const MSG_FIELD_NAME_MAPPING: Readonly<Record<string, string>>;
|
|
623
|
+
|
|
624
|
+
/**
|
|
625
|
+
* MAPI property type tag to decode type mapping.
|
|
626
|
+
*/
|
|
627
|
+
export declare const MSG_FIELD_TYPE_MAPPING: Readonly<Record<string, string>>;
|
|
628
|
+
|
|
629
|
+
/**
|
|
630
|
+
* CFB magic header bytes (0xD0CF11E0A1B11AE1).
|
|
631
|
+
*/
|
|
632
|
+
export declare const MSG_FILE_HEADER: Uint8Array<ArrayBuffer>;
|
|
633
|
+
|
|
634
|
+
/**
|
|
635
|
+
* Header offset: BAT sector count.
|
|
636
|
+
*/
|
|
637
|
+
export declare const MSG_HEADER_BAT_COUNT_OFFSET = 44;
|
|
638
|
+
|
|
639
|
+
/**
|
|
640
|
+
* Header offset: BAT sector array start.
|
|
641
|
+
*/
|
|
642
|
+
export declare const MSG_HEADER_BAT_START_OFFSET = 76;
|
|
643
|
+
|
|
644
|
+
/**
|
|
645
|
+
* Header offset: property (directory) start sector.
|
|
646
|
+
*/
|
|
647
|
+
export declare const MSG_HEADER_PROPERTY_START_OFFSET = 48;
|
|
648
|
+
|
|
649
|
+
/**
|
|
650
|
+
* Header offset: SBAT sector count.
|
|
651
|
+
*/
|
|
652
|
+
export declare const MSG_HEADER_SBAT_COUNT_OFFSET = 64;
|
|
653
|
+
|
|
654
|
+
/**
|
|
655
|
+
* Header offset: SBAT start sector.
|
|
656
|
+
*/
|
|
657
|
+
export declare const MSG_HEADER_SBAT_START_OFFSET = 60;
|
|
658
|
+
|
|
659
|
+
/**
|
|
660
|
+
* Header offset: XBAT (DIFAT) sector count.
|
|
661
|
+
*/
|
|
662
|
+
export declare const MSG_HEADER_XBAT_COUNT_OFFSET = 72;
|
|
663
|
+
|
|
664
|
+
/**
|
|
665
|
+
* Header offset: XBAT (DIFAT) start sector.
|
|
666
|
+
*/
|
|
667
|
+
export declare const MSG_HEADER_XBAT_START_OFFSET = 68;
|
|
668
|
+
|
|
669
|
+
/**
|
|
670
|
+
* Large sector size mark in the header (byte at offset 30).
|
|
671
|
+
*/
|
|
672
|
+
export declare const MSG_L_BIG_BLOCK_MARK = 12;
|
|
673
|
+
|
|
674
|
+
/**
|
|
675
|
+
* Large sector size (4096 bytes).
|
|
676
|
+
*/
|
|
677
|
+
export declare const MSG_L_BIG_BLOCK_SIZE = 4096;
|
|
678
|
+
|
|
679
|
+
/**
|
|
680
|
+
* MAPI recipient type: BCC.
|
|
681
|
+
*/
|
|
682
|
+
export declare const MSG_MAPI_RECIPIENT_BCC = 3;
|
|
683
|
+
|
|
684
|
+
/**
|
|
685
|
+
* MAPI recipient type: CC.
|
|
686
|
+
*/
|
|
687
|
+
export declare const MSG_MAPI_RECIPIENT_CC = 2;
|
|
688
|
+
|
|
689
|
+
/**
|
|
690
|
+
* MAPI recipient type: TO.
|
|
691
|
+
*/
|
|
692
|
+
export declare const MSG_MAPI_RECIPIENT_TO = 1;
|
|
693
|
+
|
|
694
|
+
/**
|
|
695
|
+
* Maximum recursion depth accepted by the directory hierarchy builder
|
|
696
|
+
* (`MSGReader#buildHierarchy`). Defense-in-depth against a pathological
|
|
697
|
+
* or hostile directory tree — the sibling-chain and visited-set guards
|
|
698
|
+
* already bound each level, this caps the recursion depth itself.
|
|
699
|
+
*/
|
|
700
|
+
export declare const MSG_MAX_HIERARCHY_DEPTH = 64;
|
|
701
|
+
|
|
702
|
+
/**
|
|
703
|
+
* MIME types recognized as Outlook binary email files.
|
|
704
|
+
*/
|
|
705
|
+
export declare const MSG_MIME_TYPES: readonly string[];
|
|
706
|
+
|
|
707
|
+
/**
|
|
708
|
+
* PidLid property set GUID to LID-to-field-name mapping.
|
|
709
|
+
* Maps well-known MAPI named property sets to their property
|
|
710
|
+
* long IDs and corresponding field names on MSGFieldData.
|
|
711
|
+
*/
|
|
712
|
+
export declare const MSG_PIDLID_MAPPING: Readonly<Record<string, Readonly<Record<number, string>>>>;
|
|
713
|
+
|
|
714
|
+
/**
|
|
715
|
+
* Name prefix for attachment storage entries.
|
|
716
|
+
*/
|
|
717
|
+
export declare const MSG_PREFIX_ATTACHMENT = "__attach_version1.0";
|
|
718
|
+
|
|
719
|
+
/**
|
|
720
|
+
* Name prefix for document (substg) stream entries.
|
|
721
|
+
*/
|
|
722
|
+
export declare const MSG_PREFIX_DOCUMENT = "__substg1.";
|
|
723
|
+
|
|
724
|
+
/**
|
|
725
|
+
* Name prefix for named property mapping storage.
|
|
726
|
+
*/
|
|
727
|
+
export declare const MSG_PREFIX_NAMEID = "__nameid_version1.0";
|
|
728
|
+
|
|
729
|
+
/**
|
|
730
|
+
* Name prefix for recipient storage entries.
|
|
731
|
+
*/
|
|
732
|
+
export declare const MSG_PREFIX_RECIPIENT = "__recip_version1.0";
|
|
733
|
+
|
|
734
|
+
/**
|
|
735
|
+
* Offset within a directory entry: child index.
|
|
736
|
+
*/
|
|
737
|
+
export declare const MSG_PROP_CHILD_PROPERTY_OFFSET = 76;
|
|
738
|
+
|
|
739
|
+
/**
|
|
740
|
+
* Offset within a directory entry: name byte length.
|
|
741
|
+
*/
|
|
742
|
+
export declare const MSG_PROP_NAME_SIZE_OFFSET = 64;
|
|
743
|
+
|
|
744
|
+
/**
|
|
745
|
+
* Offset within a directory entry: right sibling index.
|
|
746
|
+
*/
|
|
747
|
+
export declare const MSG_PROP_NEXT_PROPERTY_OFFSET = 72;
|
|
748
|
+
|
|
749
|
+
/**
|
|
750
|
+
* No child/sibling index sentinel.
|
|
751
|
+
*/
|
|
752
|
+
export declare const MSG_PROP_NO_INDEX = -1;
|
|
753
|
+
|
|
754
|
+
/**
|
|
755
|
+
* Offset within a directory entry: left sibling index.
|
|
756
|
+
*/
|
|
757
|
+
export declare const MSG_PROP_PREVIOUS_PROPERTY_OFFSET = 68;
|
|
758
|
+
|
|
759
|
+
/**
|
|
760
|
+
* Offset within a directory entry: stream byte length.
|
|
761
|
+
*/
|
|
762
|
+
export declare const MSG_PROP_SIZE_OFFSET = 120;
|
|
763
|
+
|
|
764
|
+
/**
|
|
765
|
+
* Offset within a directory entry: start sector of stream data.
|
|
766
|
+
*/
|
|
767
|
+
export declare const MSG_PROP_START_BLOCK_OFFSET = 116;
|
|
768
|
+
|
|
769
|
+
/**
|
|
770
|
+
* Offset within a directory entry: object type byte.
|
|
771
|
+
*/
|
|
772
|
+
export declare const MSG_PROP_TYPE_OFFSET = 66;
|
|
773
|
+
|
|
774
|
+
/**
|
|
775
|
+
* Directory entry size in bytes.
|
|
776
|
+
*/
|
|
777
|
+
export declare const MSG_PROPERTY_SIZE = 128;
|
|
778
|
+
|
|
779
|
+
/**
|
|
780
|
+
* Small sector size mark in the header (byte at offset 30).
|
|
781
|
+
*/
|
|
782
|
+
export declare const MSG_S_BIG_BLOCK_MARK = 9;
|
|
783
|
+
|
|
784
|
+
/**
|
|
785
|
+
* Small sector size (512 bytes).
|
|
786
|
+
*/
|
|
787
|
+
export declare const MSG_S_BIG_BLOCK_SIZE = 512;
|
|
788
|
+
|
|
789
|
+
/**
|
|
790
|
+
* Mini-stream sector size (64 bytes).
|
|
791
|
+
*/
|
|
792
|
+
export declare const MSG_SMALL_BLOCK_SIZE = 64;
|
|
793
|
+
|
|
794
|
+
/**
|
|
795
|
+
* Directory entry type: storage (folder).
|
|
796
|
+
*/
|
|
797
|
+
export declare const MSG_TYPE_DIRECTORY = 1;
|
|
798
|
+
|
|
799
|
+
/**
|
|
800
|
+
* Directory entry type: stream (document).
|
|
801
|
+
*/
|
|
802
|
+
export declare const MSG_TYPE_DOCUMENT = 2;
|
|
803
|
+
|
|
804
|
+
/**
|
|
805
|
+
* Directory entry type: root storage.
|
|
806
|
+
*/
|
|
807
|
+
export declare const MSG_TYPE_ROOT = 5;
|
|
808
|
+
|
|
809
|
+
/**
|
|
810
|
+
* Directory entry type: unallocated.
|
|
811
|
+
*/
|
|
812
|
+
export declare const MSG_TYPE_UNALLOCATED = 0;
|
|
813
|
+
|
|
814
|
+
/**
|
|
815
|
+
* Sentinel for unused blocks in the FAT.
|
|
816
|
+
*/
|
|
817
|
+
export declare const MSG_UNUSED_BLOCK = -1;
|
|
818
|
+
|
|
819
|
+
/**
|
|
820
|
+
* Extracted attachment content from an MSG file.
|
|
821
|
+
*
|
|
822
|
+
* @remarks
|
|
823
|
+
* - `fileName` — the attachment file name
|
|
824
|
+
* - `content` — the raw binary content
|
|
825
|
+
*/
|
|
826
|
+
export declare interface MSGAttachment {
|
|
827
|
+
readonly fileName: string;
|
|
828
|
+
readonly content: Uint8Array;
|
|
829
|
+
}
|
|
830
|
+
|
|
831
|
+
/**
|
|
832
|
+
* Reconstitutes a valid CFB (Compound Binary File) from a flat list of
|
|
833
|
+
* {@link MSGBurnerEntry} descriptors — root storage at index 0, its
|
|
834
|
+
* children reachable through `children` indices.
|
|
835
|
+
*
|
|
836
|
+
* @remarks
|
|
837
|
+
* Builds a red-black directory tree, allocates FAT/mini-FAT/DIFAT
|
|
838
|
+
* sectors, then writes the header, directory entries, and stream data
|
|
839
|
+
* into a single binary. Used to extract embedded `.msg` attachments as
|
|
840
|
+
* standalone CFB files.
|
|
841
|
+
*/
|
|
842
|
+
export declare class MSGBurner implements MSGBurnerInterface {
|
|
843
|
+
#private;
|
|
844
|
+
/**
|
|
845
|
+
* Burn a flat list of CFB entries into a valid compound binary file.
|
|
846
|
+
*
|
|
847
|
+
* @param entries - Flat entry list starting with Root Entry at index 0
|
|
848
|
+
* @returns Complete CFB binary as Uint8Array
|
|
849
|
+
* @throws {@link MSGError} with code `BURN` when an entry name exceeds
|
|
850
|
+
* the {@link MSG_BURNER_NAME_MAX} UTF-16 code unit limit the CFB directory entry format allows
|
|
851
|
+
*/
|
|
852
|
+
burn(entries: readonly MSGBurnerEntry[]): Uint8Array;
|
|
853
|
+
}
|
|
854
|
+
|
|
855
|
+
/**
|
|
856
|
+
* CFB entry descriptor for the MSG burner (CFB binary writer).
|
|
857
|
+
* Entries form a flat list starting with the root storage at index 0.
|
|
858
|
+
*/
|
|
859
|
+
export declare interface MSGBurnerEntry {
|
|
860
|
+
readonly name: string;
|
|
861
|
+
readonly type: number;
|
|
862
|
+
readonly length: number;
|
|
863
|
+
readonly binaryProvider?: () => Uint8Array;
|
|
864
|
+
children?: number[];
|
|
865
|
+
}
|
|
866
|
+
|
|
867
|
+
/**
|
|
868
|
+
* Public interface for the CFB binary writer.
|
|
869
|
+
* Reconstitutes a flat list of entry descriptors into a valid
|
|
870
|
+
* Compound Binary File (CFB) byte stream.
|
|
871
|
+
*
|
|
872
|
+
* @remarks
|
|
873
|
+
* - `burn` — write the entries to a CFB binary
|
|
874
|
+
*/
|
|
875
|
+
export declare interface MSGBurnerInterface {
|
|
876
|
+
/**
|
|
877
|
+
* Write the entries to a CFB binary.
|
|
878
|
+
*
|
|
879
|
+
* @param entries - Flat CFB entry descriptor list, root storage at index 0
|
|
880
|
+
* @returns Complete CFB byte stream
|
|
881
|
+
* @throws {@link MSGError} with code `BURN` when the entry list cannot be
|
|
882
|
+
* reconstituted into a valid CFB structure
|
|
883
|
+
*/
|
|
884
|
+
burn(entries: readonly MSGBurnerEntry[]): Uint8Array;
|
|
885
|
+
}
|
|
886
|
+
|
|
887
|
+
/**
|
|
888
|
+
* Internal lite entry with tree metadata used during CFB burn.
|
|
889
|
+
* Tracks red-black coloring and sector allocation alongside
|
|
890
|
+
* the source MSGBurnerEntry.
|
|
891
|
+
*/
|
|
892
|
+
export declare interface MSGBurnerLiteEntry {
|
|
893
|
+
readonly entry: MSGBurnerEntry;
|
|
894
|
+
left: number;
|
|
895
|
+
right: number;
|
|
896
|
+
child: number;
|
|
897
|
+
firstSector: number;
|
|
898
|
+
readonly mini: boolean;
|
|
899
|
+
red: boolean;
|
|
900
|
+
}
|
|
901
|
+
|
|
902
|
+
/**
|
|
903
|
+
* CFB directory entry describing a storage or stream in the compound file.
|
|
904
|
+
*/
|
|
905
|
+
export declare interface MSGDirectoryEntry {
|
|
906
|
+
readonly type: number;
|
|
907
|
+
readonly name: string;
|
|
908
|
+
readonly previousProperty: number;
|
|
909
|
+
readonly nextProperty: number;
|
|
910
|
+
readonly childProperty: number;
|
|
911
|
+
readonly startBlock: number;
|
|
912
|
+
readonly sizeBlock: number;
|
|
913
|
+
children?: number[];
|
|
914
|
+
}
|
|
915
|
+
|
|
916
|
+
/**
|
|
917
|
+
* Lifecycle type of a directory entry in a CFB compound file.
|
|
918
|
+
*/
|
|
919
|
+
export declare type MSGDirectoryEntryType = 'root' | 'directory' | 'document' | 'unallocated';
|
|
920
|
+
|
|
921
|
+
/**
|
|
922
|
+
* Supported text encoding for decoding non-Unicode MSG strings and
|
|
923
|
+
* MIME part bodies.
|
|
924
|
+
*/
|
|
925
|
+
export declare type MSGEncoding = 'utf-8' | 'utf-16le' | 'windows-1252' | 'latin1';
|
|
926
|
+
|
|
927
|
+
/**
|
|
928
|
+
* An error thrown or returned by the MSG/EML parsing and burning surfaces.
|
|
929
|
+
*
|
|
930
|
+
* @remarks
|
|
931
|
+
* Carries a machine-readable {@link MSGErrorCode} so a `catch` (or a
|
|
932
|
+
* `Failure.error` branch) can dispatch on `error.code` instead of parsing
|
|
933
|
+
* the message text. `context` carries whatever structured detail the
|
|
934
|
+
* throwing site has on hand (e.g. `{ offset, expected }`).
|
|
935
|
+
*/
|
|
936
|
+
export declare class MSGError extends Error {
|
|
937
|
+
readonly code: MSGErrorCode;
|
|
938
|
+
readonly context?: Readonly<Record<string, unknown>>;
|
|
939
|
+
constructor(code: MSGErrorCode, message: string, context?: Readonly<Record<string, unknown>>);
|
|
940
|
+
}
|
|
941
|
+
|
|
942
|
+
/**
|
|
943
|
+
* Machine-readable classification for an {@link MSGError}.
|
|
944
|
+
*
|
|
945
|
+
* @remarks
|
|
946
|
+
* - `UNSUPPORTED` — the input is not a recognized MSG/EML format
|
|
947
|
+
* - `MALFORMED` — the input claims a recognized format but is structurally invalid
|
|
948
|
+
* - `CYCLE` — a directory or MIME structure references itself, forming a cycle
|
|
949
|
+
* - `RANGE` — a computed offset, length, or index falls outside the valid bounds
|
|
950
|
+
* - `BURN` — the CFB binary writer could not reconstitute the entry list
|
|
951
|
+
*/
|
|
952
|
+
export declare type MSGErrorCode = 'UNSUPPORTED' | 'MALFORMED' | 'CYCLE' | 'RANGE' | 'BURN';
|
|
953
|
+
|
|
954
|
+
/**
|
|
955
|
+
* Parsed field data extracted from an MSG file.
|
|
956
|
+
* Represents the root message, an attachment, or a recipient.
|
|
957
|
+
*
|
|
958
|
+
* @remarks
|
|
959
|
+
* - `kind` — discriminator: 'msg', 'attachment', or 'recipient'
|
|
960
|
+
* - `subject` — message subject
|
|
961
|
+
* - `senderName` — display name of the sender
|
|
962
|
+
* - `senderEmail` — email address of the sender
|
|
963
|
+
* - `body` — plain text body
|
|
964
|
+
* - `headers` — transport message headers
|
|
965
|
+
* - `bodyHTML` — HTML body (string)
|
|
966
|
+
* - `html` — HTML body (binary)
|
|
967
|
+
* - `compressedRTF` — compressed RTF body (binary)
|
|
968
|
+
* - `attachments` — child attachment field data
|
|
969
|
+
* - `recipients` — child recipient field data
|
|
970
|
+
* - `innerMSGContent` — true if the attachment is an embedded .msg
|
|
971
|
+
* - `innerMSGContentFields` — parsed fields of the embedded .msg
|
|
972
|
+
* - `dataId` — internal CFBF entry index (for attachment binary access)
|
|
973
|
+
* - `contentLength` — attachment binary length
|
|
974
|
+
* - `folderId` — internal CFBF storage index (for embedded msg)
|
|
975
|
+
* - `recipientRole` — recipient type: 'to', 'cc', or 'bcc'
|
|
976
|
+
*/
|
|
977
|
+
export declare interface MSGFieldData {
|
|
978
|
+
readonly kind: 'msg' | 'attachment' | 'recipient';
|
|
979
|
+
readonly subject?: string;
|
|
980
|
+
readonly senderName?: string;
|
|
981
|
+
readonly senderEmail?: string;
|
|
982
|
+
readonly senderAddressType?: string;
|
|
983
|
+
readonly senderSMTPAddress?: string;
|
|
984
|
+
readonly sentRepresentingSMTPAddress?: string;
|
|
985
|
+
readonly body?: string;
|
|
986
|
+
readonly headers?: string;
|
|
987
|
+
readonly bodyHTML?: string;
|
|
988
|
+
readonly html?: Uint8Array;
|
|
989
|
+
readonly compressedRTF?: Uint8Array;
|
|
990
|
+
readonly messageClass?: string;
|
|
991
|
+
readonly messageFlags?: number;
|
|
992
|
+
readonly messageId?: string;
|
|
993
|
+
readonly internetCodepage?: number;
|
|
994
|
+
readonly messageCodepage?: number;
|
|
995
|
+
readonly messageLocaleId?: number;
|
|
996
|
+
readonly clientSubmitTime?: string;
|
|
997
|
+
readonly messageDeliveryTime?: string;
|
|
998
|
+
readonly creationTime?: string;
|
|
999
|
+
readonly lastModificationTime?: string;
|
|
1000
|
+
readonly lastModifierName?: string;
|
|
1001
|
+
readonly creatorSMTPAddress?: string;
|
|
1002
|
+
readonly lastModifierSMTPAddress?: string;
|
|
1003
|
+
readonly preview?: string;
|
|
1004
|
+
readonly conversationTopic?: string;
|
|
1005
|
+
readonly normalizedSubject?: string;
|
|
1006
|
+
readonly name?: string;
|
|
1007
|
+
readonly email?: string;
|
|
1008
|
+
readonly addressType?: string;
|
|
1009
|
+
readonly smtpAddress?: string;
|
|
1010
|
+
readonly recipientRole?: MSGRecipientRole;
|
|
1011
|
+
readonly extension?: string;
|
|
1012
|
+
readonly fileNameShort?: string;
|
|
1013
|
+
readonly fileName?: string;
|
|
1014
|
+
readonly contentId?: string;
|
|
1015
|
+
readonly attachmentHidden?: boolean;
|
|
1016
|
+
readonly mimeType?: string;
|
|
1017
|
+
readonly contentLength?: number;
|
|
1018
|
+
readonly dataId?: number;
|
|
1019
|
+
readonly folderId?: number;
|
|
1020
|
+
readonly innerMSGContent?: true;
|
|
1021
|
+
readonly innerMSGContentFields?: MSGFieldData;
|
|
1022
|
+
readonly attachments?: readonly MSGFieldData[];
|
|
1023
|
+
readonly recipients?: readonly MSGFieldData[];
|
|
1024
|
+
readonly departmentName?: string;
|
|
1025
|
+
readonly middleName?: string;
|
|
1026
|
+
readonly generation?: string;
|
|
1027
|
+
readonly surname?: string;
|
|
1028
|
+
readonly givenName?: string;
|
|
1029
|
+
readonly companyName?: string;
|
|
1030
|
+
readonly jobTitle?: string;
|
|
1031
|
+
readonly location?: string;
|
|
1032
|
+
readonly postalAddress?: string;
|
|
1033
|
+
readonly streetAddress?: string;
|
|
1034
|
+
readonly postalCode?: string;
|
|
1035
|
+
readonly country?: string;
|
|
1036
|
+
readonly stateOrProvince?: string;
|
|
1037
|
+
readonly homePhone?: string;
|
|
1038
|
+
readonly mobilePhone?: string;
|
|
1039
|
+
readonly businessPhone?: string;
|
|
1040
|
+
readonly businessFax?: string;
|
|
1041
|
+
readonly businessHomePage?: string;
|
|
1042
|
+
readonly namePrefix?: string;
|
|
1043
|
+
readonly homeAddressCity?: string;
|
|
1044
|
+
readonly appointmentStart?: string;
|
|
1045
|
+
readonly appointmentEnd?: string;
|
|
1046
|
+
readonly clipStart?: string;
|
|
1047
|
+
readonly clipEnd?: string;
|
|
1048
|
+
readonly timeZoneDescription?: string;
|
|
1049
|
+
readonly appointmentLocation?: string;
|
|
1050
|
+
readonly appointmentOldLocation?: string;
|
|
1051
|
+
readonly globalAppointmentId?: string;
|
|
1052
|
+
readonly votingResponse?: string;
|
|
1053
|
+
readonly internetAccountName?: string;
|
|
1054
|
+
readonly yomiFirstName?: string;
|
|
1055
|
+
readonly yomiLastName?: string;
|
|
1056
|
+
readonly yomiCompanyName?: string;
|
|
1057
|
+
readonly primaryEmailAddress?: string;
|
|
1058
|
+
readonly primaryEmailDisplayName?: string;
|
|
1059
|
+
readonly primaryEmailOriginalDisplayName?: string;
|
|
1060
|
+
readonly fileUnder?: string;
|
|
1061
|
+
readonly workAddressCity?: string;
|
|
1062
|
+
readonly workAddressStreet?: string;
|
|
1063
|
+
readonly workAddressState?: string;
|
|
1064
|
+
readonly workAddressPostalCode?: string;
|
|
1065
|
+
readonly workAddressCountry?: string;
|
|
1066
|
+
readonly workAddressCountryCode?: string;
|
|
1067
|
+
readonly addressCountryCode?: string;
|
|
1068
|
+
readonly contactWebPage?: string;
|
|
1069
|
+
readonly workAddress?: string;
|
|
1070
|
+
readonly instantMessagingAddress?: string;
|
|
1071
|
+
readonly fax1AddressType?: string;
|
|
1072
|
+
readonly fax1EmailAddress?: string;
|
|
1073
|
+
readonly fax1OriginalDisplayName?: string;
|
|
1074
|
+
readonly fax2AddressType?: string;
|
|
1075
|
+
readonly fax2EmailAddress?: string;
|
|
1076
|
+
readonly fax2OriginalDisplayName?: string;
|
|
1077
|
+
readonly fax3AddressType?: string;
|
|
1078
|
+
readonly fax3EmailAddress?: string;
|
|
1079
|
+
readonly fax3OriginalDisplayName?: string;
|
|
1080
|
+
}
|
|
1081
|
+
|
|
1082
|
+
/**
|
|
1083
|
+
* MAPI property data type tag.
|
|
1084
|
+
*/
|
|
1085
|
+
export declare type MSGFieldType = 'string' | 'unicode' | 'binary' | 'time' | 'integer' | 'boolean';
|
|
1086
|
+
|
|
1087
|
+
/**
|
|
1088
|
+
* Internal mutable accumulator used during MSG field extraction.
|
|
1089
|
+
* Properties are assigned dynamically via index signature and
|
|
1090
|
+
* narrowed to the readonly {@link MSGFieldData} at the public boundary.
|
|
1091
|
+
*/
|
|
1092
|
+
export declare interface MSGMutableFieldData {
|
|
1093
|
+
kind: 'msg' | 'attachment' | 'recipient';
|
|
1094
|
+
attachments?: MSGMutableFieldData[];
|
|
1095
|
+
recipients?: MSGMutableFieldData[];
|
|
1096
|
+
innerMSGContent?: true;
|
|
1097
|
+
innerMSGContentFields?: MSGMutableFieldData;
|
|
1098
|
+
dataId?: number;
|
|
1099
|
+
contentLength?: number;
|
|
1100
|
+
folderId?: number;
|
|
1101
|
+
[key: string]: unknown;
|
|
1102
|
+
}
|
|
1103
|
+
|
|
1104
|
+
/**
|
|
1105
|
+
* Resolved named property entry from the __nameid_version1.0 storage.
|
|
1106
|
+
*/
|
|
1107
|
+
export declare interface MSGNameIdEntry {
|
|
1108
|
+
readonly useName: boolean;
|
|
1109
|
+
readonly name?: string;
|
|
1110
|
+
readonly propertySet?: string;
|
|
1111
|
+
readonly propertyLid?: number;
|
|
1112
|
+
}
|
|
1113
|
+
|
|
1114
|
+
/**
|
|
1115
|
+
* Parses Microsoft Outlook .msg files (CFB/OLE2 compound binary format).
|
|
1116
|
+
* Every parsing step treats the input as untrusted: sector and property
|
|
1117
|
+
* chains are cycle-guarded and length-capped, every raw byte range is
|
|
1118
|
+
* bounds-checked before a view is constructed over it, and every failure
|
|
1119
|
+
* surfaces as a typed {@link MSGError} rather than a raw `RangeError` or
|
|
1120
|
+
* `TypeError`.
|
|
1121
|
+
*/
|
|
1122
|
+
export declare class MSGReader implements MSGReaderInterface {
|
|
1123
|
+
#private;
|
|
1124
|
+
/**
|
|
1125
|
+
* Create a reader over a raw MSG file buffer.
|
|
1126
|
+
*
|
|
1127
|
+
* @param input - Raw MSG file bytes, as an `ArrayBuffer` or a `Uint8Array` view
|
|
1128
|
+
* @param options - Reader configuration
|
|
1129
|
+
*/
|
|
1130
|
+
constructor(input: ArrayBuffer | Uint8Array, options?: MSGReaderOptions);
|
|
1131
|
+
/**
|
|
1132
|
+
* Parse the MSG file and return extracted field data.
|
|
1133
|
+
*
|
|
1134
|
+
* @returns Root message field data with nested attachments and recipients
|
|
1135
|
+
* @throws {@link MSGError} with code `UNSUPPORTED`, `MALFORMED`, `CYCLE`,
|
|
1136
|
+
* or `RANGE` when the compound file cannot be parsed
|
|
1137
|
+
*/
|
|
1138
|
+
parse(): MSGFieldData;
|
|
1139
|
+
/**
|
|
1140
|
+
* Read attachment binary content by index.
|
|
1141
|
+
*
|
|
1142
|
+
* @param index - Zero-based index into the parsed attachment list
|
|
1143
|
+
* @returns File name and raw binary content
|
|
1144
|
+
* @throws {@link MSGError} with code `RANGE` when the index is out of bounds
|
|
1145
|
+
*/
|
|
1146
|
+
attachment(index: number): MSGAttachment;
|
|
1147
|
+
/**
|
|
1148
|
+
* Rebuild the parsed MSG as a standalone CFB/.msg binary.
|
|
1149
|
+
*
|
|
1150
|
+
* @returns Complete CFB byte stream
|
|
1151
|
+
* @throws {@link MSGError} with code `BURN` when the parsed structure
|
|
1152
|
+
* cannot be reconstituted
|
|
1153
|
+
*/
|
|
1154
|
+
burn(): Uint8Array;
|
|
1155
|
+
}
|
|
1156
|
+
|
|
1157
|
+
/**
|
|
1158
|
+
* Public interface for parsing Microsoft Outlook .msg files.
|
|
1159
|
+
*
|
|
1160
|
+
* @remarks
|
|
1161
|
+
* - `parse` — parse the MSG file and return extracted field data
|
|
1162
|
+
* - `attachment` — read attachment binary content by index
|
|
1163
|
+
* - `burn` — rebuild the parsed MSG as a standalone CFB/.msg binary
|
|
1164
|
+
*/
|
|
1165
|
+
export declare interface MSGReaderInterface {
|
|
1166
|
+
/**
|
|
1167
|
+
* Parse the MSG file and return extracted field data.
|
|
1168
|
+
*
|
|
1169
|
+
* @returns Root message field data with nested attachments and recipients
|
|
1170
|
+
* @throws {@link MSGError} with code `UNSUPPORTED`, `MALFORMED`, `CYCLE`,
|
|
1171
|
+
* or `RANGE` when the compound file cannot be parsed
|
|
1172
|
+
*/
|
|
1173
|
+
parse(): MSGFieldData;
|
|
1174
|
+
/**
|
|
1175
|
+
* Read attachment binary content by index.
|
|
1176
|
+
*
|
|
1177
|
+
* @param index - Zero-based index into the parsed attachment list
|
|
1178
|
+
* @returns File name and raw binary content
|
|
1179
|
+
* @throws {@link MSGError} with code `RANGE` when the index is out of bounds
|
|
1180
|
+
*/
|
|
1181
|
+
attachment(index: number): MSGAttachment;
|
|
1182
|
+
/**
|
|
1183
|
+
* Rebuild the parsed MSG as a standalone CFB/.msg binary.
|
|
1184
|
+
*
|
|
1185
|
+
* @returns Complete CFB byte stream
|
|
1186
|
+
* @throws {@link MSGError} with code `BURN` when the parsed structure
|
|
1187
|
+
* cannot be reconstituted
|
|
1188
|
+
*/
|
|
1189
|
+
burn(): Uint8Array;
|
|
1190
|
+
}
|
|
1191
|
+
|
|
1192
|
+
/**
|
|
1193
|
+
* Configuration for creating an MSGReader.
|
|
1194
|
+
*
|
|
1195
|
+
* @remarks
|
|
1196
|
+
* - `encoding` — encoding for non-Unicode (PT_STRING8) strings (default `'windows-1252'`)
|
|
1197
|
+
*/
|
|
1198
|
+
export declare interface MSGReaderOptions {
|
|
1199
|
+
readonly encoding?: MSGEncoding;
|
|
1200
|
+
}
|
|
1201
|
+
|
|
1202
|
+
/**
|
|
1203
|
+
* Recipient role in a message.
|
|
1204
|
+
*/
|
|
1205
|
+
export declare type MSGRecipientRole = 'to' | 'cc' | 'bcc';
|
|
1206
|
+
|
|
1207
|
+
/**
|
|
1208
|
+
* Parse headers from a raw RFC 2822 / MIME header text block.
|
|
1209
|
+
*
|
|
1210
|
+
* @param text - Raw header text
|
|
1211
|
+
* @returns Map of parsed header objects
|
|
1212
|
+
*/
|
|
1213
|
+
export declare function parseMIMEHeaders(text: string): ReadonlyMap<string, MIMEHeader>;
|
|
1214
|
+
|
|
1215
|
+
/**
|
|
1216
|
+
* Parse a raw RFC 2822 / MIME text string into a MIMEPart tree.
|
|
1217
|
+
* Line endings are normalised to \n before processing. Recursion is
|
|
1218
|
+
* capped at {@link MIME_MAX_DEPTH} to guard against a hostile or
|
|
1219
|
+
* pathological multipart nesting cycle.
|
|
1220
|
+
*
|
|
1221
|
+
* @param raw - Raw MIME text
|
|
1222
|
+
* @param depth - Current recursion depth (internal; callers omit this)
|
|
1223
|
+
* @returns Parsed MIMEPart tree
|
|
1224
|
+
* @throws {@link MSGError} with code `CYCLE` when nesting exceeds {@link MIME_MAX_DEPTH}
|
|
1225
|
+
*/
|
|
1226
|
+
export declare function parseMIMEPart(raw: string, depth?: number): MIMEPart;
|
|
1227
|
+
|
|
1228
|
+
/**
|
|
1229
|
+
* Read a non-Unicode (PT_STRING8) string from a byte array using a
|
|
1230
|
+
* pure-ES decoder — no `TextDecoder` dependency, so this stays usable
|
|
1231
|
+
* in the core's DOM/Node-free environment.
|
|
1232
|
+
*
|
|
1233
|
+
* @param data - Binary data
|
|
1234
|
+
* @param encoding - Encoding to decode with (default `'windows-1252'`)
|
|
1235
|
+
* @returns Decoded string
|
|
1236
|
+
*
|
|
1237
|
+
* @example
|
|
1238
|
+
* ```ts
|
|
1239
|
+
* readANSIString(new Uint8Array([0x93, 0x41, 0x94])) // '“A”'
|
|
1240
|
+
* ```
|
|
1241
|
+
*/
|
|
1242
|
+
export declare function readANSIString(data: Uint8Array, encoding?: MSGEncoding): string;
|
|
1243
|
+
|
|
1244
|
+
/**
|
|
1245
|
+
* Read a UTF-16LE string from a DataView.
|
|
1246
|
+
*
|
|
1247
|
+
* @param view - DataView to read from
|
|
1248
|
+
* @param offset - Byte offset to start reading
|
|
1249
|
+
* @param charCount - Number of UTF-16 code units to read
|
|
1250
|
+
* @returns Decoded string
|
|
1251
|
+
* @throws {@link MSGError} with code `MALFORMED` when the requested range
|
|
1252
|
+
* exceeds the view's bounds
|
|
1253
|
+
*/
|
|
1254
|
+
export declare function readUTF16String(view: DataView, offset: number, charCount: number): string;
|
|
1255
|
+
|
|
1256
|
+
/**
|
|
1257
|
+
* Remove trailing null characters from a string.
|
|
1258
|
+
*
|
|
1259
|
+
* @param text - Input string
|
|
1260
|
+
* @returns String with trailing nulls removed
|
|
1261
|
+
*/
|
|
1262
|
+
export declare function removeTrailingNull(text: string): string;
|
|
1263
|
+
|
|
1264
|
+
/**
|
|
1265
|
+
* Resolve a free-form charset label (as seen in a MIME `charset` parameter)
|
|
1266
|
+
* to a supported {@link MSGEncoding}. Unknown or absent labels fall back
|
|
1267
|
+
* to `'utf-8'`.
|
|
1268
|
+
*
|
|
1269
|
+
* @param label - Charset label to resolve (case-insensitive)
|
|
1270
|
+
* @returns Resolved encoding
|
|
1271
|
+
*
|
|
1272
|
+
* @example
|
|
1273
|
+
* ```ts
|
|
1274
|
+
* resolveEncoding('ISO-8859-1') // 'latin1'
|
|
1275
|
+
* resolveEncoding(undefined) // 'utf-8'
|
|
1276
|
+
* ```
|
|
1277
|
+
*/
|
|
1278
|
+
export declare function resolveEncoding(label: string | undefined): MSGEncoding;
|
|
1279
|
+
|
|
1280
|
+
/**
|
|
1281
|
+
* Discriminated union for operations that can succeed or fail safely.
|
|
1282
|
+
*/
|
|
1283
|
+
export declare type Result<T, E = Error> = Success<T> | Failure<E>;
|
|
1284
|
+
|
|
1285
|
+
/**
|
|
1286
|
+
* Round a value up to the nearest multiple of a boundary.
|
|
1287
|
+
*
|
|
1288
|
+
* @param value - Number to round
|
|
1289
|
+
* @param boundary - Must be a power of 2
|
|
1290
|
+
* @returns Rounded value
|
|
1291
|
+
*/
|
|
1292
|
+
export declare function roundUpToMultiple(value: number, boundary: number): number;
|
|
1293
|
+
|
|
1294
|
+
/**
|
|
1295
|
+
* Compute how many sectors are needed to hold a given byte count.
|
|
1296
|
+
*
|
|
1297
|
+
* @param bytes - Total byte count
|
|
1298
|
+
* @param sectorSize - Sector size in bytes
|
|
1299
|
+
* @returns Number of sectors (0 when bytes ≤ 0)
|
|
1300
|
+
*/
|
|
1301
|
+
export declare function sectorsNeeded(bytes: number, sectorSize: number): number;
|
|
1302
|
+
|
|
1303
|
+
/**
|
|
1304
|
+
* Successful operation result.
|
|
1305
|
+
*/
|
|
1306
|
+
export declare interface Success<T> {
|
|
1307
|
+
readonly success: true;
|
|
1308
|
+
readonly value: T;
|
|
1309
|
+
}
|
|
1310
|
+
|
|
1311
|
+
/**
|
|
1312
|
+
* Construct a {@link Success} wrapping a value.
|
|
1313
|
+
*
|
|
1314
|
+
* @param value - The value to wrap
|
|
1315
|
+
* @returns A `Success<T>` result
|
|
1316
|
+
*
|
|
1317
|
+
* @example
|
|
1318
|
+
* ```ts
|
|
1319
|
+
* const result = success(42) // { success: true, value: 42 }
|
|
1320
|
+
* ```
|
|
1321
|
+
*/
|
|
1322
|
+
export declare function success<T>(value: T): Success<T>;
|
|
1323
|
+
|
|
1324
|
+
/**
|
|
1325
|
+
* Convert a number to a lowercase hex string with specified padding.
|
|
1326
|
+
*
|
|
1327
|
+
* @param value - Number to convert
|
|
1328
|
+
* @param length - Minimum hex string length (zero-padded)
|
|
1329
|
+
* @returns Lowercase hex string
|
|
1330
|
+
*/
|
|
1331
|
+
export declare function toHexLower(value: number, length: number): string;
|
|
1332
|
+
|
|
1333
|
+
/**
|
|
1334
|
+
* Minimum valid code point for each UTF-8 sequence length, keyed by the
|
|
1335
|
+
* number of continuation bytes (1, 2, or 3). Enforces the WHATWG
|
|
1336
|
+
* requirement that a sequence encode the shortest possible form — an
|
|
1337
|
+
* overlong encoding (a code point below its sequence's minimum) is
|
|
1338
|
+
* rejected rather than accepted by `decodeUTF8`.
|
|
1339
|
+
*/
|
|
1340
|
+
export declare const UTF8_SEQUENCE_MINIMUM: Readonly<Record<number, number>>;
|
|
1341
|
+
|
|
1342
|
+
/**
|
|
1343
|
+
* Windows-1252 high-byte (0x80-0x9F) to Unicode code point lookup.
|
|
1344
|
+
* Index `n` maps byte `0x80 + n` to its Unicode code point; entries
|
|
1345
|
+
* that Windows-1252 leaves undefined map to the byte's own value
|
|
1346
|
+
* (C1 control code passthrough) per the WHATWG encoding standard.
|
|
1347
|
+
*/
|
|
1348
|
+
export declare const WINDOWS_1252_HIGH: readonly number[];
|
|
1349
|
+
|
|
1350
|
+
export { }
|