postal-mime 2.3.0 → 2.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +21 -0
- package/LICENSE.txt +1 -1
- package/README.md +96 -89
- package/package.json +1 -1
- package/postal-mime.d.ts +5 -2
- package/src/base64-encoder.js +69 -0
- package/src/postal-mime.js +39 -0
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,26 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## [2.4.0](https://github.com/postalsys/postal-mime/compare/v2.3.2...v2.4.0) (2025-01-05)
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
### Features
|
|
7
|
+
|
|
8
|
+
* **attachments:** Added new option 'attachmentEncoding' to return attachment content as a string, not arraybuffer ([0f7e9df](https://github.com/postalsys/postal-mime/commit/0f7e9df855c9c8f99ed0b7c517d6653169c53405))
|
|
9
|
+
|
|
10
|
+
## [2.3.2](https://github.com/postalsys/postal-mime/compare/v2.3.1...v2.3.2) (2024-09-23)
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
### Bug Fixes
|
|
14
|
+
|
|
15
|
+
* Modified README to trigger a new release (previous npm publish failed) ([f975ef4](https://github.com/postalsys/postal-mime/commit/f975ef4bc8403af72d8cd25ee2d4b3a12cdf82e4))
|
|
16
|
+
|
|
17
|
+
## [2.3.1](https://github.com/postalsys/postal-mime/compare/v2.3.0...v2.3.1) (2024-09-23)
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
### Bug Fixes
|
|
21
|
+
|
|
22
|
+
* **message/rfc822:** Added option 'forceRfc822Attachments' to handle all message/rfc822 nodes as attachments instead of inline content ([bf47621](https://github.com/postalsys/postal-mime/commit/bf47621da7c55a31acb39fb505f415b1ed4ce5e2))
|
|
23
|
+
|
|
3
24
|
## [2.3.0](https://github.com/postalsys/postal-mime/compare/v2.2.9...v2.3.0) (2024-09-23)
|
|
4
25
|
|
|
5
26
|
|
package/LICENSE.txt
CHANGED
package/README.md
CHANGED
|
@@ -1,11 +1,27 @@
|
|
|
1
1
|
# postal-mime
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
**postal-mime** is an email parsing library that runs in browser environments (including Web Workers) and serverless functions (like Cloudflare Email Workers). It takes in a raw email message (RFC822 format) and outputs a structured object containing headers, recipients, attachments, and more.
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
> **Tip**
|
|
6
|
+
> 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 provides a REST API for IMAP and SMTP servers and sends webhooks whenever something changes in registered accounts.
|
|
6
7
|
|
|
7
|
-
|
|
8
|
-
|
|
8
|
+
## Table of Contents
|
|
9
|
+
|
|
10
|
+
- [Source](#source)
|
|
11
|
+
- [Demo](#demo)
|
|
12
|
+
- [Installation](#installation)
|
|
13
|
+
- [Usage](#usage)
|
|
14
|
+
- [Browser](#browser)
|
|
15
|
+
- [Node.js](#nodejs)
|
|
16
|
+
- [Cloudflare Email Workers](#cloudflare-email-workers)
|
|
17
|
+
- [API](#api)
|
|
18
|
+
- [PostalMime.parse()](#postalmimeparse)
|
|
19
|
+
- [Utility Functions](#utility-functions)
|
|
20
|
+
- [addressParser()](#addressparser)
|
|
21
|
+
- [decodeWords()](#decodewords)
|
|
22
|
+
- [License](#license)
|
|
23
|
+
|
|
24
|
+
---
|
|
9
25
|
|
|
10
26
|
## Source
|
|
11
27
|
|
|
@@ -13,33 +29,23 @@ The source code is available on [GitHub](https://github.com/postalsys/postal-mim
|
|
|
13
29
|
|
|
14
30
|
## Demo
|
|
15
31
|
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
## Usage
|
|
32
|
+
Try out a live demo using the [example page](https://kreata.ee/postal-mime/example/).
|
|
19
33
|
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
```
|
|
23
|
-
$ npm install postal-mime
|
|
24
|
-
```
|
|
34
|
+
## Installation
|
|
25
35
|
|
|
26
|
-
|
|
36
|
+
Install the module from npm:
|
|
27
37
|
|
|
28
|
-
```
|
|
29
|
-
|
|
38
|
+
```bash
|
|
39
|
+
npm install postal-mime
|
|
30
40
|
```
|
|
31
41
|
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
```js
|
|
35
|
-
import PostalMime from 'postal-mime';
|
|
36
|
-
```
|
|
42
|
+
## Usage
|
|
37
43
|
|
|
38
|
-
|
|
44
|
+
You can import the `PostalMime` class differently depending on your environment:
|
|
39
45
|
|
|
40
|
-
|
|
46
|
+
### Browser
|
|
41
47
|
|
|
42
|
-
|
|
48
|
+
To use PostalMime in the browser (including Web Workers), import it from the `src` folder:
|
|
43
49
|
|
|
44
50
|
```js
|
|
45
51
|
import PostalMime from './node_modules/postal-mime/src/postal-mime.js';
|
|
@@ -49,12 +55,12 @@ Content-Type: text/html; charset=utf-8
|
|
|
49
55
|
|
|
50
56
|
<p>Hello world 😵💫</p>`);
|
|
51
57
|
|
|
52
|
-
console.log(email.subject);
|
|
58
|
+
console.log(email.subject); // "My awesome email 🤓"
|
|
53
59
|
```
|
|
54
60
|
|
|
55
|
-
|
|
61
|
+
### Node.js
|
|
56
62
|
|
|
57
|
-
|
|
63
|
+
In Node.js (including serverless functions), import it directly from `postal-mime`:
|
|
58
64
|
|
|
59
65
|
```js
|
|
60
66
|
import PostalMime from 'postal-mime';
|
|
@@ -65,12 +71,13 @@ Content-Type: text/html; charset=utf-8
|
|
|
65
71
|
|
|
66
72
|
<p>Hello world 😵💫</p>`);
|
|
67
73
|
|
|
74
|
+
// Use 'util.inspect' for pretty-printing
|
|
68
75
|
console.log(util.inspect(email, false, 22, true));
|
|
69
76
|
```
|
|
70
77
|
|
|
71
|
-
|
|
78
|
+
### Cloudflare Email Workers
|
|
72
79
|
|
|
73
|
-
|
|
80
|
+
Use the `message.raw` as the raw email data for parsing:
|
|
74
81
|
|
|
75
82
|
```js
|
|
76
83
|
import PostalMime from 'postal-mime';
|
|
@@ -79,106 +86,106 @@ export default {
|
|
|
79
86
|
async email(message, env, ctx) {
|
|
80
87
|
const email = await PostalMime.parse(message.raw);
|
|
81
88
|
|
|
82
|
-
console.log('Subject:
|
|
83
|
-
console.log('HTML:
|
|
84
|
-
console.log('Text:
|
|
89
|
+
console.log('Subject:', email.subject);
|
|
90
|
+
console.log('HTML:', email.html);
|
|
91
|
+
console.log('Text:', email.text);
|
|
85
92
|
}
|
|
86
93
|
};
|
|
87
94
|
```
|
|
88
95
|
|
|
89
|
-
|
|
96
|
+
---
|
|
90
97
|
|
|
91
|
-
|
|
98
|
+
## API
|
|
99
|
+
|
|
100
|
+
### PostalMime.parse()
|
|
92
101
|
|
|
93
102
|
```js
|
|
94
|
-
PostalMime.parse(email, options) -> Promise
|
|
103
|
+
PostalMime.parse(email, options) -> Promise<ParsedEmail>
|
|
95
104
|
```
|
|
96
105
|
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
- **
|
|
100
|
-
- **
|
|
101
|
-
- **
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
- **
|
|
109
|
-
-
|
|
110
|
-
-
|
|
111
|
-
- **
|
|
112
|
-
-
|
|
113
|
-
-
|
|
114
|
-
|
|
115
|
-
- **
|
|
116
|
-
- **
|
|
117
|
-
- **
|
|
118
|
-
- **
|
|
119
|
-
- **
|
|
120
|
-
- **
|
|
121
|
-
|
|
122
|
-
-
|
|
123
|
-
-
|
|
124
|
-
-
|
|
125
|
-
-
|
|
126
|
-
-
|
|
106
|
+
- **email**: An RFC822 formatted email. This can be a `string`, `ArrayBuffer/Uint8Array`, `Blob` (browser only), `Buffer` (Node.js), or a [ReadableStream](https://developer.mozilla.org/en-US/docs/Web/API/ReadableStream).
|
|
107
|
+
- **options**: Optional configuration object:
|
|
108
|
+
- **rfc822Attachments** (boolean, default: `false`): Treat `message/rfc822` attachments without a Content-Disposition as attachments.
|
|
109
|
+
- **forceRfc822Attachments** (boolean, default: `false`): Treat _all_ `message/rfc822` parts as attachments.
|
|
110
|
+
- **attachmentEncoding** (string): Determines how attachment content is decoded in the parsed email:
|
|
111
|
+
- `"base64"`
|
|
112
|
+
- `"utf8"`
|
|
113
|
+
- `"arraybuffer"` (no decoding, returns `ArrayBuffer`)
|
|
114
|
+
|
|
115
|
+
**Returns**: A Promise that resolves to a structured object with the following properties:
|
|
116
|
+
|
|
117
|
+
- **headers**: An array of header objects, each containing:
|
|
118
|
+
- `key`: Lowercase header name (e.g., `"dkim-signature"`).
|
|
119
|
+
- `value`: Unprocessed header value as a string.
|
|
120
|
+
- **from**, **sender**: Processed address objects:
|
|
121
|
+
- `name`: Decoded display name, or an empty string if not set.
|
|
122
|
+
- `address`: Email address.
|
|
123
|
+
- **deliveredTo**, **returnPath**: Single email addresses as strings.
|
|
124
|
+
- **to**, **cc**, **bcc**, **replyTo**: Arrays of processed address objects (same structure as `from`).
|
|
125
|
+
- **subject**: Subject line of the email.
|
|
126
|
+
- **messageId**, **inReplyTo**, **references**: Values from their corresponding headers.
|
|
127
|
+
- **date**: The email’s sending time in ISO 8601 format (or the original string if parsing fails).
|
|
128
|
+
- **html**: String containing the HTML content of the email.
|
|
129
|
+
- **text**: String containing the plain text content of the email.
|
|
130
|
+
- **attachments**: Array of attachment objects:
|
|
131
|
+
- `filename`
|
|
132
|
+
- `mimeType`
|
|
133
|
+
- `disposition` (e.g., `"attachment"`, `"inline"`, or `null`)
|
|
134
|
+
- `related` (boolean, `true` if it’s an inline image)
|
|
135
|
+
- `contentId`
|
|
136
|
+
- `content` (array buffer or string, depending on `attachmentEncoding`)
|
|
137
|
+
- `encoding` (e.g., `"base64"`)
|
|
138
|
+
|
|
139
|
+
---
|
|
127
140
|
|
|
128
141
|
### Utility Functions
|
|
129
142
|
|
|
130
|
-
#### addressParser
|
|
131
|
-
|
|
132
|
-
Parse email address strings.
|
|
143
|
+
#### addressParser()
|
|
133
144
|
|
|
134
145
|
```js
|
|
146
|
+
import { addressParser } from 'postal-mime';
|
|
147
|
+
|
|
135
148
|
addressParser(addressStr, opts) -> Array
|
|
136
149
|
```
|
|
137
150
|
|
|
138
|
-
|
|
151
|
+
- **addressStr**: A raw address header string.
|
|
152
|
+
- **opts**: Optional configuration:
|
|
153
|
+
- **flatten** (boolean, default: `false`): If `true`, ignores address groups and returns a flat array of addresses.
|
|
139
154
|
|
|
140
|
-
|
|
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.
|
|
155
|
+
**Returns**: An array of address objects, which can be nested if address groups are present.
|
|
143
156
|
|
|
144
|
-
|
|
145
|
-
|
|
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.
|
|
157
|
+
**Example**:
|
|
149
158
|
|
|
150
159
|
```js
|
|
151
|
-
import { addressParser } from 'postal-mime';
|
|
152
|
-
|
|
153
160
|
const addressStr = '=?utf-8?B?44Ko44Od44K544Kr44O844OJ?= <support@example.com>';
|
|
154
161
|
console.log(addressParser(addressStr));
|
|
155
162
|
// [ { name: 'エポスカード', address: 'support@example.com' } ]
|
|
156
163
|
```
|
|
157
164
|
|
|
158
|
-
#### decodeWords
|
|
159
|
-
|
|
160
|
-
Decode MIME encoded-words.
|
|
165
|
+
#### decodeWords()
|
|
161
166
|
|
|
162
167
|
```js
|
|
163
|
-
decodeWords
|
|
168
|
+
import { decodeWords } from 'postal-mime';
|
|
169
|
+
|
|
170
|
+
decodeWords(encodedStr) -> string
|
|
164
171
|
```
|
|
165
172
|
|
|
166
|
-
|
|
173
|
+
- **encodedStr**: A string that may contain MIME encoded-words.
|
|
167
174
|
|
|
168
|
-
|
|
175
|
+
**Returns**: A Unicode string with all encoded-words decoded.
|
|
169
176
|
|
|
170
|
-
|
|
177
|
+
**Example**:
|
|
171
178
|
|
|
172
179
|
```js
|
|
173
|
-
import { decodeWords } from 'postal-mime';
|
|
174
|
-
|
|
175
180
|
const encodedStr = 'Hello, =?utf-8?B?44Ko44Od44K544Kr44O844OJ?=';
|
|
176
181
|
console.log(decodeWords(encodedStr));
|
|
177
182
|
// Hello, エポスカード
|
|
178
183
|
```
|
|
179
184
|
|
|
185
|
+
---
|
|
186
|
+
|
|
180
187
|
## License
|
|
181
188
|
|
|
182
|
-
© 2021
|
|
189
|
+
© 2021–2025 Andris Reinman
|
|
183
190
|
|
|
184
|
-
`postal-mime` is licensed under the **MIT No Attribution license
|
|
191
|
+
`postal-mime` is licensed under the **MIT No Attribution license**.
|
package/package.json
CHANGED
package/postal-mime.d.ts
CHANGED
|
@@ -16,7 +16,8 @@ export type Attachment = {
|
|
|
16
16
|
description?: string;
|
|
17
17
|
contentId?: string;
|
|
18
18
|
method?: string;
|
|
19
|
-
content: ArrayBuffer;
|
|
19
|
+
content: ArrayBuffer | string;
|
|
20
|
+
encoding?: "base64" | "utf8";
|
|
20
21
|
};
|
|
21
22
|
|
|
22
23
|
export type Email = {
|
|
@@ -53,7 +54,9 @@ declare function decodeWords (
|
|
|
53
54
|
): string;
|
|
54
55
|
|
|
55
56
|
declare type PostalMimeOptions = {
|
|
56
|
-
rfc822Attachments?: boolean
|
|
57
|
+
rfc822Attachments?: boolean,
|
|
58
|
+
forceRfc822Attachments?: boolean,
|
|
59
|
+
attachmentEncoding?: "base64" | "utf8"
|
|
57
60
|
}
|
|
58
61
|
|
|
59
62
|
declare class PostalMime {
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
// Code from: https://gist.githubusercontent.com/jonleighton/958841/raw/fb05a8632efb75d85d43deb593df04367ce48371/base64ArrayBuffer.js
|
|
2
|
+
|
|
3
|
+
// Converts an ArrayBuffer directly to base64, without any intermediate 'convert to string then
|
|
4
|
+
// use window.btoa' step. According to my tests, this appears to be a faster approach:
|
|
5
|
+
// http://jsperf.com/encoding-xhr-image-data/5
|
|
6
|
+
|
|
7
|
+
/*
|
|
8
|
+
MIT LICENSE
|
|
9
|
+
|
|
10
|
+
Copyright 2011 Jon Leighton
|
|
11
|
+
|
|
12
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
|
13
|
+
|
|
14
|
+
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
|
|
15
|
+
|
|
16
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
17
|
+
*/
|
|
18
|
+
|
|
19
|
+
export function base64ArrayBuffer(arrayBuffer) {
|
|
20
|
+
var base64 = '';
|
|
21
|
+
var encodings = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/';
|
|
22
|
+
|
|
23
|
+
var bytes = new Uint8Array(arrayBuffer);
|
|
24
|
+
var byteLength = bytes.byteLength;
|
|
25
|
+
var byteRemainder = byteLength % 3;
|
|
26
|
+
var mainLength = byteLength - byteRemainder;
|
|
27
|
+
|
|
28
|
+
var a, b, c, d;
|
|
29
|
+
var chunk;
|
|
30
|
+
|
|
31
|
+
// Main loop deals with bytes in chunks of 3
|
|
32
|
+
for (var i = 0; i < mainLength; i = i + 3) {
|
|
33
|
+
// Combine the three bytes into a single integer
|
|
34
|
+
chunk = (bytes[i] << 16) | (bytes[i + 1] << 8) | bytes[i + 2];
|
|
35
|
+
|
|
36
|
+
// Use bitmasks to extract 6-bit segments from the triplet
|
|
37
|
+
a = (chunk & 16515072) >> 18; // 16515072 = (2^6 - 1) << 18
|
|
38
|
+
b = (chunk & 258048) >> 12; // 258048 = (2^6 - 1) << 12
|
|
39
|
+
c = (chunk & 4032) >> 6; // 4032 = (2^6 - 1) << 6
|
|
40
|
+
d = chunk & 63; // 63 = 2^6 - 1
|
|
41
|
+
|
|
42
|
+
// Convert the raw binary segments to the appropriate ASCII encoding
|
|
43
|
+
base64 += encodings[a] + encodings[b] + encodings[c] + encodings[d];
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
// Deal with the remaining bytes and padding
|
|
47
|
+
if (byteRemainder == 1) {
|
|
48
|
+
chunk = bytes[mainLength];
|
|
49
|
+
|
|
50
|
+
a = (chunk & 252) >> 2; // 252 = (2^6 - 1) << 2
|
|
51
|
+
|
|
52
|
+
// Set the 4 least significant bits to zero
|
|
53
|
+
b = (chunk & 3) << 4; // 3 = 2^2 - 1
|
|
54
|
+
|
|
55
|
+
base64 += encodings[a] + encodings[b] + '==';
|
|
56
|
+
} else if (byteRemainder == 2) {
|
|
57
|
+
chunk = (bytes[mainLength] << 8) | bytes[mainLength + 1];
|
|
58
|
+
|
|
59
|
+
a = (chunk & 64512) >> 10; // 64512 = (2^6 - 1) << 10
|
|
60
|
+
b = (chunk & 1008) >> 4; // 1008 = (2^6 - 1) << 4
|
|
61
|
+
|
|
62
|
+
// Set the 2 least significant bits to zero
|
|
63
|
+
c = (chunk & 15) << 2; // 15 = 2^4 - 1
|
|
64
|
+
|
|
65
|
+
base64 += encodings[a] + encodings[b] + encodings[c] + '=';
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
return base64;
|
|
69
|
+
}
|
package/src/postal-mime.js
CHANGED
|
@@ -2,6 +2,7 @@ import MimeNode from './mime-node.js';
|
|
|
2
2
|
import { textToHtml, htmlToText, formatTextHeader, formatHtmlHeader } from './text-format.js';
|
|
3
3
|
import addressParser from './address-parser.js';
|
|
4
4
|
import { decodeWords, textEncoder, blobToArrayBuffer } from './decode-strings.js';
|
|
5
|
+
import { base64ArrayBuffer } from './base64-encoder.js';
|
|
5
6
|
|
|
6
7
|
export { addressParser, decodeWords };
|
|
7
8
|
|
|
@@ -22,6 +23,13 @@ export default class PostalMime {
|
|
|
22
23
|
this.textContent = {};
|
|
23
24
|
this.attachments = [];
|
|
24
25
|
|
|
26
|
+
this.attachmentEncoding =
|
|
27
|
+
(this.options.attachmentEncoding || '')
|
|
28
|
+
.toString()
|
|
29
|
+
.replace(/[-_\s]/g, '')
|
|
30
|
+
.trim()
|
|
31
|
+
.toLowerCase() || 'arraybuffer';
|
|
32
|
+
|
|
25
33
|
this.started = false;
|
|
26
34
|
}
|
|
27
35
|
|
|
@@ -339,6 +347,10 @@ export default class PostalMime {
|
|
|
339
347
|
|
|
340
348
|
// Check if this is a specially crafted report email where message/rfc822 content should not be inlined
|
|
341
349
|
forceRfc822Attachments() {
|
|
350
|
+
if (this.options.forceRfc822Attachments) {
|
|
351
|
+
return true;
|
|
352
|
+
}
|
|
353
|
+
|
|
342
354
|
let forceRfc822Attachments = false;
|
|
343
355
|
let walk = node => {
|
|
344
356
|
if (!node.contentType.multipart) {
|
|
@@ -491,6 +503,33 @@ export default class PostalMime {
|
|
|
491
503
|
|
|
492
504
|
message.attachments = this.attachments;
|
|
493
505
|
|
|
506
|
+
switch (this.attachmentEncoding) {
|
|
507
|
+
case 'arraybuffer':
|
|
508
|
+
break;
|
|
509
|
+
|
|
510
|
+
case 'base64':
|
|
511
|
+
for (let attachment of message.attachments || []) {
|
|
512
|
+
if (attachment?.content) {
|
|
513
|
+
attachment.content = base64ArrayBuffer(attachment.content);
|
|
514
|
+
attachment.encoding = 'base64';
|
|
515
|
+
}
|
|
516
|
+
}
|
|
517
|
+
break;
|
|
518
|
+
|
|
519
|
+
case 'utf8':
|
|
520
|
+
let attachmentDecoder = new TextDecoder('utf8');
|
|
521
|
+
for (let attachment of message.attachments || []) {
|
|
522
|
+
if (attachment?.content) {
|
|
523
|
+
attachment.content = attachmentDecoder.decode(attachment.content);
|
|
524
|
+
attachment.encoding = 'utf8';
|
|
525
|
+
}
|
|
526
|
+
}
|
|
527
|
+
break;
|
|
528
|
+
|
|
529
|
+
default:
|
|
530
|
+
throw new Error('Unknwon attachment encoding');
|
|
531
|
+
}
|
|
532
|
+
|
|
494
533
|
return message;
|
|
495
534
|
}
|
|
496
535
|
}
|