imapflow 1.0.177 → 1.0.178

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 CHANGED
@@ -1,4 +1,4 @@
1
1
  module.exports = {
2
2
  upgrade: true,
3
- reject: ['jsdoc', 'eslint', 'grunt-eslint']
3
+ reject: ['jsdoc', 'eslint', 'grunt-eslint', 'eslint-config-prettier']
4
4
  };
package/CHANGELOG.md CHANGED
@@ -1,5 +1,12 @@
1
1
  # Changelog
2
2
 
3
+ ## [1.0.178](https://github.com/postalsys/imapflow/compare/v1.0.177...v1.0.178) (2025-01-23)
4
+
5
+
6
+ ### Bug Fixes
7
+
8
+ * **bodystructure:** Handle unicode filenames for servers that do not know how to use parameter continuations ([2b4b240](https://github.com/postalsys/imapflow/commit/2b4b2408bf19a337958888f5f2bcdd9af86424c1))
9
+
3
10
  ## [1.0.177](https://github.com/postalsys/imapflow/compare/v1.0.176...v1.0.177) (2025-01-17)
4
11
 
5
12
 
@@ -0,0 +1,283 @@
1
+ 'use strict';
2
+
3
+ const CHARACTER_SETS = [
4
+ 'US-ASCII',
5
+ 'ISO-8859-1',
6
+ 'ISO-8859-2',
7
+ 'ISO-8859-3',
8
+ 'ISO-8859-4',
9
+ 'ISO-8859-5',
10
+ 'ISO-8859-6',
11
+ 'ISO-8859-7',
12
+ 'ISO-8859-8',
13
+ 'ISO-8859-9',
14
+ 'ISO-8859-10',
15
+ 'ISO_6937-2-add',
16
+ 'JIS_X0201',
17
+ 'JIS_Encoding',
18
+ 'Shift_JIS',
19
+ 'EUC-JP',
20
+ 'Extended_UNIX_Code_Fixed_Width_for_Japanese',
21
+ 'BS_4730',
22
+ 'SEN_850200_C',
23
+ 'IT',
24
+ 'ES',
25
+ 'DIN_66003',
26
+ 'NS_4551-1',
27
+ 'NF_Z_62-010',
28
+ 'ISO-10646-UTF-1',
29
+ 'ISO_646.basic:1983',
30
+ 'INVARIANT',
31
+ 'ISO_646.irv:1983',
32
+ 'NATS-SEFI',
33
+ 'NATS-SEFI-ADD',
34
+ 'NATS-DANO',
35
+ 'NATS-DANO-ADD',
36
+ 'SEN_850200_B',
37
+ 'KS_C_5601-1987',
38
+ 'ISO-2022-KR',
39
+ 'EUC-KR',
40
+ 'ISO-2022-JP',
41
+ 'ISO-2022-JP-2',
42
+ 'JIS_C6220-1969-jp',
43
+ 'JIS_C6220-1969-ro',
44
+ 'PT',
45
+ 'greek7-old',
46
+ 'latin-greek',
47
+ 'NF_Z_62-010_(1973)',
48
+ 'Latin-greek-1',
49
+ 'ISO_5427',
50
+ 'JIS_C6226-1978',
51
+ 'BS_viewdata',
52
+ 'INIS',
53
+ 'INIS-8',
54
+ 'INIS-cyrillic',
55
+ 'ISO_5427:1981',
56
+ 'ISO_5428:1980',
57
+ 'GB_1988-80',
58
+ 'GB_2312-80',
59
+ 'NS_4551-2',
60
+ 'videotex-suppl',
61
+ 'PT2',
62
+ 'ES2',
63
+ 'MSZ_7795.3',
64
+ 'JIS_C6226-1983',
65
+ 'greek7',
66
+ 'ASMO_449',
67
+ 'iso-ir-90',
68
+ 'JIS_C6229-1984-a',
69
+ 'JIS_C6229-1984-b',
70
+ 'JIS_C6229-1984-b-add',
71
+ 'JIS_C6229-1984-hand',
72
+ 'JIS_C6229-1984-hand-add',
73
+ 'JIS_C6229-1984-kana',
74
+ 'ISO_2033-1983',
75
+ 'ANSI_X3.110-1983',
76
+ 'T.61-7bit',
77
+ 'T.61-8bit',
78
+ 'ECMA-cyrillic',
79
+ 'CSA_Z243.4-1985-1',
80
+ 'CSA_Z243.4-1985-2',
81
+ 'CSA_Z243.4-1985-gr',
82
+ 'ISO-8859-6-E',
83
+ 'ISO-8859-6-I',
84
+ 'T.101-G2',
85
+ 'ISO-8859-8-E',
86
+ 'ISO-8859-8-I',
87
+ 'CSN_369103',
88
+ 'JUS_I.B1.002',
89
+ 'IEC_P27-1',
90
+ 'JUS_I.B1.003-serb',
91
+ 'JUS_I.B1.003-mac',
92
+ 'greek-ccitt',
93
+ 'NC_NC00-10:81',
94
+ 'ISO_6937-2-25',
95
+ 'GOST_19768-74',
96
+ 'ISO_8859-supp',
97
+ 'ISO_10367-box',
98
+ 'latin-lap',
99
+ 'JIS_X0212-1990',
100
+ 'DS_2089',
101
+ 'us-dk',
102
+ 'dk-us',
103
+ 'KSC5636',
104
+ 'UNICODE-1-1-UTF-7',
105
+ 'ISO-2022-CN',
106
+ 'ISO-2022-CN-EXT',
107
+ 'UTF-8',
108
+ 'ISO-8859-13',
109
+ 'ISO-8859-14',
110
+ 'ISO-8859-15',
111
+ 'ISO-8859-16',
112
+ 'GBK',
113
+ 'GB18030',
114
+ 'OSD_EBCDIC_DF04_15',
115
+ 'OSD_EBCDIC_DF03_IRV',
116
+ 'OSD_EBCDIC_DF04_1',
117
+ 'ISO-11548-1',
118
+ 'KZ-1048',
119
+ 'ISO-10646-UCS-2',
120
+ 'ISO-10646-UCS-4',
121
+ 'ISO-10646-UCS-Basic',
122
+ 'ISO-10646-Unicode-Latin1',
123
+ 'ISO-10646-J-1',
124
+ 'ISO-Unicode-IBM-1261',
125
+ 'ISO-Unicode-IBM-1268',
126
+ 'ISO-Unicode-IBM-1276',
127
+ 'ISO-Unicode-IBM-1264',
128
+ 'ISO-Unicode-IBM-1265',
129
+ 'UNICODE-1-1',
130
+ 'SCSU',
131
+ 'UTF-7',
132
+ 'UTF-16BE',
133
+ 'UTF-16LE',
134
+ 'UTF-16',
135
+ 'CESU-8',
136
+ 'UTF-32',
137
+ 'UTF-32BE',
138
+ 'UTF-32LE',
139
+ 'BOCU-1',
140
+ 'ISO-8859-1-Windows-3.0-Latin-1',
141
+ 'ISO-8859-1-Windows-3.1-Latin-1',
142
+ 'ISO-8859-2-Windows-Latin-2',
143
+ 'ISO-8859-9-Windows-Latin-5',
144
+ 'hp-roman8',
145
+ 'Adobe-Standard-Encoding',
146
+ 'Ventura-US',
147
+ 'Ventura-International',
148
+ 'DEC-MCS',
149
+ 'IBM850',
150
+ 'PC8-Danish-Norwegian',
151
+ 'IBM862',
152
+ 'PC8-Turkish',
153
+ 'IBM-Symbols',
154
+ 'IBM-Thai',
155
+ 'HP-Legal',
156
+ 'HP-Pi-font',
157
+ 'HP-Math8',
158
+ 'Adobe-Symbol-Encoding',
159
+ 'HP-DeskTop',
160
+ 'Ventura-Math',
161
+ 'Microsoft-Publishing',
162
+ 'Windows-31J',
163
+ 'GB2312',
164
+ 'Big5',
165
+ 'macintosh',
166
+ 'IBM037',
167
+ 'IBM038',
168
+ 'IBM273',
169
+ 'IBM274',
170
+ 'IBM275',
171
+ 'IBM277',
172
+ 'IBM278',
173
+ 'IBM280',
174
+ 'IBM281',
175
+ 'IBM284',
176
+ 'IBM285',
177
+ 'IBM290',
178
+ 'IBM297',
179
+ 'IBM420',
180
+ 'IBM423',
181
+ 'IBM424',
182
+ 'IBM437',
183
+ 'IBM500',
184
+ 'IBM851',
185
+ 'IBM852',
186
+ 'IBM855',
187
+ 'IBM857',
188
+ 'IBM860',
189
+ 'IBM861',
190
+ 'IBM863',
191
+ 'IBM864',
192
+ 'IBM865',
193
+ 'IBM868',
194
+ 'IBM869',
195
+ 'IBM870',
196
+ 'IBM871',
197
+ 'IBM880',
198
+ 'IBM891',
199
+ 'IBM903',
200
+ 'IBM904',
201
+ 'IBM905',
202
+ 'IBM918',
203
+ 'IBM1026',
204
+ 'EBCDIC-AT-DE',
205
+ 'EBCDIC-AT-DE-A',
206
+ 'EBCDIC-CA-FR',
207
+ 'EBCDIC-DK-NO',
208
+ 'EBCDIC-DK-NO-A',
209
+ 'EBCDIC-FI-SE',
210
+ 'EBCDIC-FI-SE-A',
211
+ 'EBCDIC-FR',
212
+ 'EBCDIC-IT',
213
+ 'EBCDIC-PT',
214
+ 'EBCDIC-ES',
215
+ 'EBCDIC-ES-A',
216
+ 'EBCDIC-ES-S',
217
+ 'EBCDIC-UK',
218
+ 'EBCDIC-US',
219
+ 'UNKNOWN-8BIT',
220
+ 'MNEMONIC',
221
+ 'MNEM',
222
+ 'VISCII',
223
+ 'VIQR',
224
+ 'KOI8-R',
225
+ 'HZ-GB-2312',
226
+ 'IBM866',
227
+ 'IBM775',
228
+ 'KOI8-U',
229
+ 'IBM00858',
230
+ 'IBM00924',
231
+ 'IBM01140',
232
+ 'IBM01141',
233
+ 'IBM01142',
234
+ 'IBM01143',
235
+ 'IBM01144',
236
+ 'IBM01145',
237
+ 'IBM01146',
238
+ 'IBM01147',
239
+ 'IBM01148',
240
+ 'IBM01149',
241
+ 'Big5-HKSCS',
242
+ 'IBM1047',
243
+ 'PTCP154',
244
+ 'Amiga-1251',
245
+ 'KOI7-switched',
246
+ 'BRF',
247
+ 'TSCII',
248
+ 'CP51932',
249
+ 'windows-874',
250
+ 'windows-1250',
251
+ 'windows-1251',
252
+ 'windows-1252',
253
+ 'windows-1253',
254
+ 'windows-1254',
255
+ 'windows-1255',
256
+ 'windows-1256',
257
+ 'windows-1257',
258
+ 'windows-1258',
259
+ 'TIS-620',
260
+ 'CP50220'
261
+ ];
262
+
263
+ const CHARSET_MAP = new Map();
264
+
265
+ CHARACTER_SETS.forEach(entry => {
266
+ let key = entry.replace(/[_-\s]/g, '').toLowerCase();
267
+ let modifiedKey = key
268
+ .replace(/^windows/, 'win')
269
+ .replace(/^usascii/, 'ascii')
270
+ .replace(/^iso8859/, 'latin');
271
+ CHARSET_MAP.set(key, entry);
272
+ if (!CHARSET_MAP.has(modifiedKey)) {
273
+ CHARSET_MAP.set(modifiedKey, entry);
274
+ }
275
+ });
276
+
277
+ module.exports.resolveCharset = charset => {
278
+ let key = charset.replace(/[_-\s]/g, '').toLowerCase();
279
+ if (CHARSET_MAP.has(key)) {
280
+ return CHARSET_MAP.get(key);
281
+ }
282
+ return null;
283
+ };
package/lib/tools.js CHANGED
@@ -3,6 +3,7 @@
3
3
  'use strict';
4
4
 
5
5
  const libmime = require('libmime');
6
+ const { resolveCharset } = require('./charsets');
6
7
  const { compiler } = require('./handler/imap-handler');
7
8
  const { createHash } = require('crypto');
8
9
  const { JPDecoder } = require('./jp-decoder');
@@ -507,6 +508,14 @@ const tools = {
507
508
  }
508
509
  });
509
510
 
511
+ if (params.filename && !params['filename*'] && /^[a-z\-_0-9]+'[a-z]*'[^'\x00-\x08\x0b\x0c\x0e-\x1f\u0080-\uFFFF]+/.test(params.filename)) {
512
+ // seems like encoded value
513
+ let [encoding, , encodedValue] = params.filename.split("'");
514
+ if (resolveCharset(encoding)) {
515
+ params['filename*'] = `${encoding}''${encodedValue}`;
516
+ }
517
+ }
518
+
510
519
  // preprocess values
511
520
  Object.keys(params).forEach(key => {
512
521
  let actualKey;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "imapflow",
3
- "version": "1.0.177",
3
+ "version": "1.0.178",
4
4
  "description": "IMAP Client for Node",
5
5
  "main": "./lib/imap-flow.js",
6
6
  "scripts": {
@@ -28,11 +28,11 @@
28
28
  },
29
29
  "homepage": "https://imapflow.com/",
30
30
  "devDependencies": {
31
- "@babel/eslint-parser": "7.25.9",
31
+ "@babel/eslint-parser": "7.26.5",
32
32
  "@babel/eslint-plugin": "7.25.9",
33
33
  "@babel/plugin-syntax-class-properties": "7.12.13",
34
34
  "@babel/preset-env": "7.26.0",
35
- "@types/node": "22.10.5",
35
+ "@types/node": "22.10.8",
36
36
  "eslint": "8.57.0",
37
37
  "eslint-config-nodemailer": "1.2.0",
38
38
  "eslint-config-prettier": "9.1.0",
@@ -52,7 +52,7 @@
52
52
  "libmime": "5.3.6",
53
53
  "libqp": "2.1.1",
54
54
  "mailsplit": "5.4.2",
55
- "nodemailer": "6.9.16",
55
+ "nodemailer": "6.10.0",
56
56
  "pino": "9.6.0",
57
57
  "socks": "2.8.3"
58
58
  }
@@ -992,3 +992,141 @@ module.exports['Process invalid TEXT without line count'] = test => {
992
992
  });
993
993
  test.done();
994
994
  };
995
+
996
+ module.exports['Process non-standard unicode filename property'] = test => {
997
+ let attribute = [
998
+ [
999
+ [
1000
+ { type: 'STRING', value: 'text' },
1001
+ { type: 'STRING', value: 'plain' },
1002
+ [
1003
+ { type: 'STRING', value: 'charset' },
1004
+ { type: 'STRING', value: 'utf-8' }
1005
+ ],
1006
+ null,
1007
+ null,
1008
+ { type: 'STRING', value: 'quoted-printable' },
1009
+ { type: 'ATOM', value: '275385' },
1010
+ { type: 'ATOM', value: '3531' },
1011
+ null,
1012
+ null,
1013
+ null,
1014
+ null
1015
+ ],
1016
+ [
1017
+ [
1018
+ { type: 'STRING', value: 'text' },
1019
+ { type: 'STRING', value: 'html' },
1020
+ [
1021
+ { type: 'STRING', value: 'charset' },
1022
+ { type: 'STRING', value: 'utf-8' }
1023
+ ],
1024
+ null,
1025
+ null,
1026
+ { type: 'STRING', value: 'quoted-printable' },
1027
+ { type: 'ATOM', value: '333' },
1028
+ { type: 'ATOM', value: '6' },
1029
+ null,
1030
+ null,
1031
+ null,
1032
+ null
1033
+ ],
1034
+ [
1035
+ { type: 'STRING', value: 'image' },
1036
+ { type: 'STRING', value: 'png' },
1037
+ [
1038
+ { type: 'STRING', value: 'name' },
1039
+ { type: 'STRING', value: 'image-1.png' }
1040
+ ],
1041
+ {
1042
+ type: 'STRING',
1043
+ value: '<7e1703a0-b8b7-4d00-9193-989506afb76e@emailengine>'
1044
+ },
1045
+ null,
1046
+ { type: 'STRING', value: 'base64' },
1047
+ { type: 'ATOM', value: '271540' },
1048
+ null,
1049
+ [
1050
+ { type: 'STRING', value: 'inline' },
1051
+ [
1052
+ { type: 'STRING', value: 'filename' },
1053
+ { type: 'STRING', value: 'image-1.png' }
1054
+ ]
1055
+ ],
1056
+ null,
1057
+ null
1058
+ ],
1059
+ { type: 'STRING', value: 'related' },
1060
+ [
1061
+ { type: 'STRING', value: 'type' },
1062
+ { type: 'STRING', value: 'text/html' },
1063
+ { type: 'STRING', value: 'boundary' },
1064
+ {
1065
+ type: 'STRING',
1066
+ value: '----=_Part-GUieKCU_ZWVAMi40OS43_nvE0TCtGsQo-Part_4'
1067
+ }
1068
+ ],
1069
+ null,
1070
+ null
1071
+ ],
1072
+ { type: 'STRING', value: 'alternative' },
1073
+ [
1074
+ { type: 'STRING', value: 'boundary' },
1075
+ {
1076
+ type: 'STRING',
1077
+ value: '----=_Part-GUieKCU_ZWVAMi40OS43_nvE0TCtGsQo-Part_2'
1078
+ }
1079
+ ],
1080
+ null,
1081
+ null
1082
+ ],
1083
+ [
1084
+ { type: 'STRING', value: 'application' },
1085
+ {
1086
+ type: 'STRING',
1087
+ value: 'vnd.openxmlformats-officedocument.spreadsheetml.sheet'
1088
+ },
1089
+ [
1090
+ { type: 'STRING', value: 'name' },
1091
+ {
1092
+ type: 'STRING',
1093
+ value: '=?UTF-8?Q?Trang=5Fghi=5F=C3=A2m_=288=29_=281=29=2E?= =?UTF-8?Q?xlsx?='
1094
+ }
1095
+ ],
1096
+ null,
1097
+ null,
1098
+ { type: 'STRING', value: 'base64' },
1099
+ { type: 'ATOM', value: '532006' },
1100
+ null,
1101
+ [
1102
+ { type: 'STRING', value: 'attachment' },
1103
+ [
1104
+ { type: 'STRING', value: 'filename' },
1105
+ {
1106
+ type: 'STRING',
1107
+ value: "utf-8''Trang_ghi_%C3%A2m%20%288%29%20%281%29.xlsx"
1108
+ }
1109
+ ]
1110
+ ],
1111
+ null,
1112
+ null
1113
+ ],
1114
+ { type: 'STRING', value: 'mixed' },
1115
+ [
1116
+ { type: 'STRING', value: 'boundary' },
1117
+ {
1118
+ type: 'STRING',
1119
+ value: '----=_Part-GUieKCU_ZWVAMi40OS43_nvE0TCtGsQo-Part_1'
1120
+ }
1121
+ ],
1122
+ null,
1123
+ null
1124
+ ];
1125
+
1126
+ let bodyStruct = parseBodystructure(attribute);
1127
+
1128
+ console.log(JSON.stringify(bodyStruct, false, 2));
1129
+
1130
+ test.deepEqual(bodyStruct.childNodes[1].dispositionParameters.filename, 'Trang_ghi_âm (8) (1).xlsx');
1131
+ test.done();
1132
+ };