postal-mime 2.2.2 → 2.2.3

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/.ncurc.js ADDED
@@ -0,0 +1,7 @@
1
+ module.exports = {
2
+ upgrade: true,
3
+ reject: [
4
+ // api changes, check and fix
5
+ 'eslint'
6
+ ]
7
+ };
package/CHANGELOG.md CHANGED
@@ -1,5 +1,13 @@
1
1
  # Changelog
2
2
 
3
+ ## [2.2.3](https://github.com/postalsys/postal-mime/compare/v2.2.2...v2.2.3) (2024-04-11)
4
+
5
+
6
+ ### Bug Fixes
7
+
8
+ * **attachments:** Added description key from Content-Description attachment header ([6e29de9](https://github.com/postalsys/postal-mime/commit/6e29de97a4dc0043587a59870d52250602801e3c))
9
+ * **calendar-attachments:** treat text/calendar as an attachment ([2196b49](https://github.com/postalsys/postal-mime/commit/2196b497f289697e9dc72011708e4355ee7362cc))
10
+
3
11
  ## [2.2.2](https://github.com/postalsys/postal-mime/compare/v2.2.1...v2.2.2) (2024-04-10)
4
12
 
5
13
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "postal-mime",
3
- "version": "2.2.2",
3
+ "version": "2.2.3",
4
4
  "description": "Email parser for browser environments",
5
5
  "main": "./src/postal-mime.js",
6
6
  "exports": {
@@ -27,7 +27,7 @@
27
27
  "author": "Andris Reinman",
28
28
  "license": "MIT-0",
29
29
  "devDependencies": {
30
- "@types/node": "20.11.30",
30
+ "@types/node": "20.12.7",
31
31
  "cross-blob": "3.0.2",
32
32
  "cross-env": "7.0.3",
33
33
  "eslint": "8.57.0",
package/postal-mime.d.ts CHANGED
@@ -8,11 +8,13 @@ export type Address = {
8
8
  };
9
9
 
10
10
  export type Attachment = {
11
- filename: string;
11
+ filename: string | null;
12
12
  mimeType: string;
13
13
  disposition: "attachment" | "inline" | null;
14
14
  related?: boolean;
15
+ description?: string;
15
16
  contentId?: string;
17
+ method?: string;
16
18
  content: Uint8Array;
17
19
  };
18
20
 
package/src/mime-node.js CHANGED
@@ -226,6 +226,9 @@ export default class MimeNode {
226
226
  case 'content-id':
227
227
  this.contentId = value;
228
228
  break;
229
+ case 'content-description':
230
+ this.contentDescription = value;
231
+ break;
229
232
  }
230
233
  }
231
234
  }
@@ -162,10 +162,7 @@ export default class PostalMime {
162
162
  }
163
163
 
164
164
  // is it text?
165
- else if (
166
- (/^text\//i.test(node.contentType.parsed.value) || node.contentType.parsed.value === 'message/delivery-status') &&
167
- node.contentDisposition.parsed.value !== 'attachment'
168
- ) {
165
+ else if (this.isInlineTextNode(node)) {
169
166
  let textType = node.contentType.parsed.value.substr(node.contentType.parsed.value.indexOf('/') + 1);
170
167
  if (node.contentType.parsed.value === 'message/delivery-status') {
171
168
  textType = 'plain';
@@ -184,9 +181,9 @@ export default class PostalMime {
184
181
 
185
182
  // is it an attachment
186
183
  else if (node.content) {
187
- let filename = node.contentDisposition.parsed.params.filename || node.contentType.parsed.params.name || null;
188
- let attachment = {
189
- filename: decodeWords(filename),
184
+ const filename = node.contentDisposition.parsed.params.filename || node.contentType.parsed.params.name || null;
185
+ const attachment = {
186
+ filename: filename ? decodeWords(filename) : null,
190
187
  mimeType: node.contentType.parsed.value,
191
188
  disposition: node.contentDisposition.parsed.value || null
192
189
  };
@@ -195,11 +192,39 @@ export default class PostalMime {
195
192
  attachment.related = true;
196
193
  }
197
194
 
195
+ if (node.contentDescription) {
196
+ attachment.description = node.contentDescription;
197
+ }
198
+
198
199
  if (node.contentId) {
199
200
  attachment.contentId = node.contentId;
200
201
  }
201
202
 
202
- attachment.content = node.content;
203
+ switch (node.contentType.parsed.value) {
204
+ // Special handling for calendar events
205
+ case 'text/calendar':
206
+ case 'application/ics': {
207
+ if (node.contentType.parsed.params.method) {
208
+ attachment.method = node.contentType.parsed.params.method.toString().toUpperCase().trim();
209
+ }
210
+
211
+ // Enforce into unicode
212
+ const decodedText = node.getTextContent().replace(/\r?\n/g, '\n').replace(/\n*$/, '\n');
213
+ attachment.content = textEncoder.encode(decodedText);
214
+ break;
215
+ }
216
+
217
+ case 'message/delivery-status': {
218
+ // Enforce into unicode
219
+ const decodedText = node.getTextContent().replace(/\r?\n/g, '\n').replace(/\n*$/, '\n');
220
+ attachment.content = textEncoder.encode(decodedText);
221
+ break;
222
+ }
223
+
224
+ // Regular attachments
225
+ default:
226
+ attachment.content = node.content;
227
+ }
203
228
 
204
229
  this.attachments.push(attachment);
205
230
  }
@@ -292,6 +317,26 @@ export default class PostalMime {
292
317
  this.textContent = textContent;
293
318
  }
294
319
 
320
+ isInlineTextNode(node) {
321
+ if (node.contentDisposition.parsed.value === 'attachment') {
322
+ // no matter the type, this is an attachment
323
+ return false;
324
+ }
325
+
326
+ switch (node.contentType.parsed.value) {
327
+ case 'text/html':
328
+ case 'text/plain':
329
+ // message/delivery-status is cast into regular plaintext content
330
+ case 'message/delivery-status':
331
+ return true;
332
+
333
+ case 'text/calendar':
334
+ case 'text/csv':
335
+ default:
336
+ return false;
337
+ }
338
+ }
339
+
295
340
  async resolveStream(stream) {
296
341
  let chunkLen = 0;
297
342
  let chunks = [];
@@ -418,11 +463,11 @@ export default class PostalMime {
418
463
  message.date = date;
419
464
  }
420
465
 
421
- if (this.textContent && this.textContent.html) {
466
+ if (this.textContent?.html) {
422
467
  message.html = this.textContent.html;
423
468
  }
424
469
 
425
- if (this.textContent && this.textContent.plain) {
470
+ if (this.textContent?.plain) {
426
471
  message.text = this.textContent.plain;
427
472
  }
428
473