postal-mime 2.2.5 → 2.2.7
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 +14 -0
- package/README.md +48 -46
- package/package.json +3 -3
- package/postal-mime.d.ts +35 -27
- package/src/postal-mime.js +14 -4
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,19 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## [2.2.7](https://github.com/postalsys/postal-mime/compare/v2.2.6...v2.2.7) (2024-07-31)
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
### Bug Fixes
|
|
7
|
+
|
|
8
|
+
* **rfc822:** Only inline message/rfc822 messages if Content-Disposition is ([53024de](https://github.com/postalsys/postal-mime/commit/53024dec22ea121817913a9cf152bdf60acbdbe7))
|
|
9
|
+
|
|
10
|
+
## [2.2.6](https://github.com/postalsys/postal-mime/compare/v2.2.5...v2.2.6) (2024-07-09)
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
### Bug Fixes
|
|
14
|
+
|
|
15
|
+
* **types:** Updated type for attachment.content to ArrayBuffer ([191524f](https://github.com/postalsys/postal-mime/commit/191524fa32ac550934fb17c074153cf9170622a0))
|
|
16
|
+
|
|
3
17
|
## [2.2.5](https://github.com/postalsys/postal-mime/compare/v2.2.4...v2.2.5) (2024-04-11)
|
|
4
18
|
|
|
5
19
|
|
package/README.md
CHANGED
|
@@ -2,14 +2,14 @@
|
|
|
2
2
|
|
|
3
3
|
Email parser for browser and serverless environments.
|
|
4
4
|
|
|
5
|
-
PostalMime can be run in the main web thread or from Web Workers. It can also used in serverless functions.
|
|
5
|
+
PostalMime can be run in the main web thread or from Web Workers. It can also be used in serverless functions.
|
|
6
6
|
|
|
7
7
|
> [!TIP]
|
|
8
8
|
> PostalMime is developed by the makers of **[EmailEngine](https://emailengine.app/?utm_source=github&utm_campaign=imapflow&utm_medium=readme-link)** – a self-hosted email gateway that allows making **REST requests against IMAP and SMTP servers**. EmailEngine also sends webhooks whenever something changes on the registered accounts.
|
|
9
9
|
|
|
10
10
|
## Source
|
|
11
11
|
|
|
12
|
-
The source code is available
|
|
12
|
+
The source code is available on [GitHub](https://github.com/postalsys/postal-mime).
|
|
13
13
|
|
|
14
14
|
## Demo
|
|
15
15
|
|
|
@@ -23,13 +23,13 @@ First, install the module from npm:
|
|
|
23
23
|
$ npm install postal-mime
|
|
24
24
|
```
|
|
25
25
|
|
|
26
|
-
|
|
26
|
+
Next, import the PostalMime class into your script:
|
|
27
27
|
|
|
28
28
|
```js
|
|
29
29
|
import PostalMime from './node_modules/postal-mime/src/postal-mime.js';
|
|
30
30
|
```
|
|
31
31
|
|
|
32
|
-
|
|
32
|
+
Or when using it from a Node.js app or in a serverless function:
|
|
33
33
|
|
|
34
34
|
```js
|
|
35
35
|
import PostalMime from 'postal-mime';
|
|
@@ -37,7 +37,7 @@ import PostalMime from 'postal-mime';
|
|
|
37
37
|
|
|
38
38
|
### Promises
|
|
39
39
|
|
|
40
|
-
PostalMime methods use Promises, so you need to wait using `await` or
|
|
40
|
+
PostalMime methods use Promises, so you need to wait using `await` or the `then()` method to get the response.
|
|
41
41
|
|
|
42
42
|
#### Browser
|
|
43
43
|
|
|
@@ -88,62 +88,64 @@ export default {
|
|
|
88
88
|
|
|
89
89
|
#### PostalMime.parse()
|
|
90
90
|
|
|
91
|
-
`parse(email)` is a static class method to parse emails
|
|
91
|
+
`parse(email, options)` is a static class method used to parse emails.
|
|
92
92
|
|
|
93
93
|
```js
|
|
94
|
-
PostalMime.parse(email) -> Promise
|
|
94
|
+
PostalMime.parse(email, options) -> Promise
|
|
95
95
|
```
|
|
96
96
|
|
|
97
|
-
Where
|
|
97
|
+
Where:
|
|
98
98
|
|
|
99
|
-
- **email
|
|
99
|
+
- **email**: The RFC822 formatted email. This can be a string, an ArrayBuffer/Uint8Array, a Blob object, a Node.js Buffer, or a [ReadableStream](https://developer.mozilla.org/en-US/docs/Web/API/ReadableStream).
|
|
100
|
+
- **options**: An optional object containing configuration options.
|
|
101
|
+
- **rfc822Attachments**: A boolean (defaults to `false`). If set to `true`, it treats `Message/RFC822` attachments without a Content-Disposition declaration as attachments. By default, these messages are treated as inline values.
|
|
100
102
|
|
|
101
103
|
This method parses an email message into a structured object with the following properties:
|
|
102
104
|
|
|
103
|
-
- **headers
|
|
104
|
-
- **headers[].key
|
|
105
|
-
- **headers[].value
|
|
106
|
-
- **from**, **sender
|
|
107
|
-
- **from.name
|
|
108
|
-
- **from.address
|
|
109
|
-
- **deliveredTo**, **returnPath
|
|
110
|
-
- **to**, **cc**, **bcc**, **replyTo
|
|
111
|
-
- **to[].name
|
|
112
|
-
- **to[].address
|
|
113
|
-
- **subject
|
|
114
|
-
- **messageId**, **inReplyTo**, **references
|
|
115
|
-
- **date
|
|
116
|
-
- **html
|
|
117
|
-
- **text
|
|
118
|
-
- **attachments
|
|
119
|
-
- **
|
|
120
|
-
- **
|
|
121
|
-
- **
|
|
122
|
-
- **
|
|
123
|
-
- **
|
|
124
|
-
- **
|
|
125
|
-
|
|
126
|
-
### Utility
|
|
105
|
+
- **headers**: An array of headers in the order they appear in the message (topmost headers first).
|
|
106
|
+
- **headers[].key**: The lowercase key of the header line, e.g., `"dkim-signature"`.
|
|
107
|
+
- **headers[].value**: The unprocessed value of the header line.
|
|
108
|
+
- **from**, **sender**: Includes a processed object for the corresponding headers.
|
|
109
|
+
- **from.name**: The decoded name (empty string if not set).
|
|
110
|
+
- **from.address**: The email address.
|
|
111
|
+
- **deliveredTo**, **returnPath**: The email address from the corresponding header.
|
|
112
|
+
- **to**, **cc**, **bcc**, **replyTo**: An array of processed objects for the corresponding headers.
|
|
113
|
+
- **to[].name**: The decoded name (empty string if not set).
|
|
114
|
+
- **to[].address**: The email address.
|
|
115
|
+
- **subject**: The email subject line.
|
|
116
|
+
- **messageId**, **inReplyTo**, **references**: The value as found in the corresponding header without any processing.
|
|
117
|
+
- **date**: The email sending time formatted as an ISO date string (unless parsing failed, in which case the original value is used).
|
|
118
|
+
- **html**: The HTML content of the message as a string.
|
|
119
|
+
- **text**: The plaintext content of the message as a string.
|
|
120
|
+
- **attachments**: An array that includes the message attachments.
|
|
121
|
+
- **attachments[].filename**: The file name if provided.
|
|
122
|
+
- **attachments[].mimeType**: The MIME type of the attachment.
|
|
123
|
+
- **attachments[].disposition**: Either "attachment", "inline", or `null` if disposition was not provided.
|
|
124
|
+
- **attachments[].related**: A boolean value indicating if this attachment should be treated as an embedded image.
|
|
125
|
+
- **attachments[].contentId**: The ID from the Content-ID header.
|
|
126
|
+
- **attachments[].content**: A Uint8Array value that contains the attachment file.
|
|
127
|
+
|
|
128
|
+
### Utility Functions
|
|
127
129
|
|
|
128
130
|
#### addressParser
|
|
129
131
|
|
|
130
|
-
Parse email address strings
|
|
132
|
+
Parse email address strings.
|
|
131
133
|
|
|
132
134
|
```js
|
|
133
135
|
addressParser(addressStr, opts) -> Array
|
|
134
136
|
```
|
|
135
137
|
|
|
136
|
-
|
|
138
|
+
Where:
|
|
137
139
|
|
|
138
|
-
- **addressStr
|
|
139
|
-
- **opts
|
|
140
|
-
- **flatten
|
|
140
|
+
- **addressStr**: The header value for an address header.
|
|
141
|
+
- **opts**: An optional object containing configuration options.
|
|
142
|
+
- **flatten**: A boolean value. If set to `true`, it ignores address groups and returns a flat array of addresses. By default (`flatten` is `false`), the result might include nested groups.
|
|
141
143
|
|
|
142
|
-
The result is an array of objects
|
|
144
|
+
The result is an array of objects:
|
|
143
145
|
|
|
144
|
-
- **name
|
|
145
|
-
- **address
|
|
146
|
-
- **group
|
|
146
|
+
- **name**: The name string. An empty string is used if the name value is not set.
|
|
147
|
+
- **address**: The email address value.
|
|
148
|
+
- **group**: An array of nested address objects. This is used when `flatten` is `false` (the default) and the address string contains address group syntax.
|
|
147
149
|
|
|
148
150
|
```js
|
|
149
151
|
import { addressParser } from 'postal-mime';
|
|
@@ -155,17 +157,17 @@ console.log(addressParser(addressStr));
|
|
|
155
157
|
|
|
156
158
|
#### decodeWords
|
|
157
159
|
|
|
158
|
-
Decode MIME encoded-words
|
|
160
|
+
Decode MIME encoded-words.
|
|
159
161
|
|
|
160
162
|
```js
|
|
161
163
|
decodeWords(encodedStr) -> String
|
|
162
164
|
```
|
|
163
165
|
|
|
164
|
-
|
|
166
|
+
Where:
|
|
165
167
|
|
|
166
|
-
- **encodedStr
|
|
168
|
+
- **encodedStr**: A string value that _may_ include MIME encoded-words.
|
|
167
169
|
|
|
168
|
-
The result is a
|
|
170
|
+
The result is a Unicode string.
|
|
169
171
|
|
|
170
172
|
```js
|
|
171
173
|
import { decodeWords } from 'postal-mime';
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "postal-mime",
|
|
3
|
-
"version": "2.2.
|
|
3
|
+
"version": "2.2.7",
|
|
4
4
|
"description": "Email parser for browser environments",
|
|
5
5
|
"main": "./src/postal-mime.js",
|
|
6
6
|
"exports": {
|
|
@@ -27,11 +27,11 @@
|
|
|
27
27
|
"author": "Andris Reinman",
|
|
28
28
|
"license": "MIT-0",
|
|
29
29
|
"devDependencies": {
|
|
30
|
-
"@types/node": "
|
|
30
|
+
"@types/node": "22.0.0",
|
|
31
31
|
"cross-blob": "3.0.2",
|
|
32
32
|
"cross-env": "7.0.3",
|
|
33
33
|
"eslint": "8.57.0",
|
|
34
34
|
"eslint-cli": "1.1.1",
|
|
35
|
-
"iframe-resizer": "4.
|
|
35
|
+
"iframe-resizer": "4.4.5"
|
|
36
36
|
}
|
|
37
37
|
}
|
package/postal-mime.d.ts
CHANGED
|
@@ -3,40 +3,40 @@ export type RawEmail = string | ArrayBuffer | Uint8Array | Blob | Buffer | Reada
|
|
|
3
3
|
export type Header = Record<string, string>;
|
|
4
4
|
|
|
5
5
|
export type Address = {
|
|
6
|
-
|
|
6
|
+
name: string;
|
|
7
7
|
address?: string;
|
|
8
8
|
group?: Address[]
|
|
9
9
|
};
|
|
10
10
|
|
|
11
11
|
export type Attachment = {
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
12
|
+
filename: string | null;
|
|
13
|
+
mimeType: string;
|
|
14
|
+
disposition: "attachment" | "inline" | null;
|
|
15
|
+
related?: boolean;
|
|
16
16
|
description?: string;
|
|
17
|
-
|
|
17
|
+
contentId?: string;
|
|
18
18
|
method?: string;
|
|
19
|
-
|
|
19
|
+
content: ArrayBuffer;
|
|
20
20
|
};
|
|
21
21
|
|
|
22
22
|
export type Email = {
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
23
|
+
headers: Header[];
|
|
24
|
+
from: Address;
|
|
25
|
+
sender?: Address;
|
|
26
|
+
replyTo?: Address[];
|
|
27
|
+
deliveredTo?: string;
|
|
28
|
+
returnPath?: string;
|
|
29
|
+
to?: Address[];
|
|
30
|
+
cc?: Address[];
|
|
31
|
+
bcc?: Address[];
|
|
32
|
+
subject?: string;
|
|
33
|
+
messageId: string;
|
|
34
|
+
inReplyTo?: string;
|
|
35
|
+
references?: string;
|
|
36
|
+
date?: string;
|
|
37
|
+
html?: string;
|
|
38
|
+
text?: string;
|
|
39
|
+
attachments: Attachment[];
|
|
40
40
|
};
|
|
41
41
|
|
|
42
42
|
declare type AddressParserOptions = {
|
|
@@ -45,16 +45,24 @@ declare type AddressParserOptions = {
|
|
|
45
45
|
|
|
46
46
|
declare function addressParser (
|
|
47
47
|
str: string,
|
|
48
|
-
|
|
48
|
+
options?: AddressParserOptions
|
|
49
49
|
): Address[];
|
|
50
50
|
|
|
51
51
|
declare function decodeWords (
|
|
52
52
|
str: string
|
|
53
53
|
): string;
|
|
54
54
|
|
|
55
|
+
declare type PostalMimeOptions = {
|
|
56
|
+
rfc822Attachments?: boolean
|
|
57
|
+
}
|
|
58
|
+
|
|
55
59
|
declare class PostalMime {
|
|
56
|
-
|
|
57
|
-
|
|
60
|
+
constructor(options?: PostalMimeOptions);
|
|
61
|
+
static parse(
|
|
62
|
+
email: RawEmail,
|
|
63
|
+
options?: PostalMimeOptions
|
|
64
|
+
): Promise<Email>;
|
|
65
|
+
parse(email: RawEmail): Promise<Email>;
|
|
58
66
|
}
|
|
59
67
|
|
|
60
68
|
export { addressParser, decodeWords };
|
package/src/postal-mime.js
CHANGED
|
@@ -6,12 +6,14 @@ import { decodeWords, textEncoder, blobToArrayBuffer } from './decode-strings.js
|
|
|
6
6
|
export { addressParser, decodeWords };
|
|
7
7
|
|
|
8
8
|
export default class PostalMime {
|
|
9
|
-
static parse(buf) {
|
|
10
|
-
const parser = new PostalMime();
|
|
9
|
+
static parse(buf, options) {
|
|
10
|
+
const parser = new PostalMime(options);
|
|
11
11
|
return parser.parse(buf);
|
|
12
12
|
}
|
|
13
13
|
|
|
14
|
-
constructor() {
|
|
14
|
+
constructor(options) {
|
|
15
|
+
this.options = options || {};
|
|
16
|
+
|
|
15
17
|
this.root = this.currentNode = new MimeNode({
|
|
16
18
|
postalMime: this
|
|
17
19
|
});
|
|
@@ -129,7 +131,7 @@ export default class PostalMime {
|
|
|
129
131
|
// regular node
|
|
130
132
|
|
|
131
133
|
// is it inline message/rfc822
|
|
132
|
-
if (
|
|
134
|
+
if (this.isInlineMessageRfc822(node)) {
|
|
133
135
|
const subParser = new PostalMime();
|
|
134
136
|
node.subMessage = await subParser.parse(node.content);
|
|
135
137
|
|
|
@@ -339,6 +341,14 @@ export default class PostalMime {
|
|
|
339
341
|
}
|
|
340
342
|
}
|
|
341
343
|
|
|
344
|
+
isInlineMessageRfc822(node) {
|
|
345
|
+
if (node.contentType.parsed.value !== 'message/rfc822') {
|
|
346
|
+
return false;
|
|
347
|
+
}
|
|
348
|
+
let disposition = node.contentDisposition.parsed.value || (this.options.rfc822Attachments ? 'attachment' : 'inline');
|
|
349
|
+
return disposition === 'inline';
|
|
350
|
+
}
|
|
351
|
+
|
|
342
352
|
async resolveStream(stream) {
|
|
343
353
|
let chunkLen = 0;
|
|
344
354
|
let chunks = [];
|