@@ -23,6 +23,7 @@ const appendList = require('../../append-list');
23
23
const { mimeHtml } = require ( '@postalsys/email-text-tools' ) ;
24
24
const simpleParser = require ( 'mailparser' ) . simpleParser ;
25
25
const ical = require ( 'ical.js' ) ;
26
+ const addressparser = require ( 'nodemailer/lib/addressparser' ) ;
26
27
const { llmPreProcess } = require ( '../../llm-pre-process' ) ;
27
28
28
29
const { getESClient } = require ( '../../document-store' ) ;
@@ -84,6 +85,8 @@ class Mailbox {
84
85
this . isGmail = connection . isGmail ;
85
86
this . isAllMail = this . isGmail && this . listingEntry . specialUse === '\\All' ;
86
87
88
+ this . isLarkSuite = connection . isLarkSuite ;
89
+
87
90
this . selected = false ;
88
91
// does the mailbox open happen before or after initial syncing
89
92
this . previouslyConnected = false ;
@@ -1343,7 +1346,7 @@ class Mailbox {
1343
1346
isDraft = true ;
1344
1347
}
1345
1348
1346
- // do not expose the \Recent flag as it is session specific
1349
+ // Do not expose the \Recent flag as it is session specific
1347
1350
if ( messageData . flags && messageData . flags . has ( '\\Recent' ) ) {
1348
1351
messageData . flags . delete ( '\\Recent' ) ;
1349
1352
}
@@ -1352,6 +1355,41 @@ class Mailbox {
1352
1355
isDraft = true ;
1353
1356
}
1354
1357
1358
+ let headers ;
1359
+
1360
+ // This section is needed for Lark Mail as some address fields might be missing
1361
+ // from the ENVELOPE section, so fall back to the header instead.
1362
+ // Normally, these headers are not fetched from the server and only ENVELOPE is used
1363
+ let parsedAddresses = { } ;
1364
+ if ( messageData . headers ) {
1365
+ headers = libmime . decodeHeaders ( messageData . headers . toString ( ) . trim ( ) ) ;
1366
+ for ( let key of [ 'from' , 'to' , 'cc' , 'bcc' ] ) {
1367
+ if ( headers [ key ] ?. length ) {
1368
+ try {
1369
+ const addressList = addressparser ( headers [ key ] )
1370
+ . filter ( address => ! ! address . address )
1371
+ . map ( address => {
1372
+ let name = address . name ;
1373
+ try {
1374
+ name = libmime . decodeWords ( name ) ;
1375
+ } catch ( err ) {
1376
+ // ignore
1377
+ }
1378
+ return {
1379
+ name,
1380
+ address : address . address
1381
+ } ;
1382
+ } ) ;
1383
+ if ( addressList ?. length ) {
1384
+ parsedAddresses [ key ] = addressList ;
1385
+ }
1386
+ } catch ( err ) {
1387
+ // just ignore
1388
+ }
1389
+ }
1390
+ }
1391
+ }
1392
+
1355
1393
const result = {
1356
1394
id : packedUid ,
1357
1395
uid : messageData . uid ,
@@ -1374,21 +1412,21 @@ class Mailbox {
1374
1412
1375
1413
size : messageData . size || undefined ,
1376
1414
subject : envelope . subject || undefined ,
1377
- from : envelope . from && envelope . from [ 0 ] ? envelope . from [ 0 ] : undefined ,
1415
+ from : envelope . from ?. [ 0 ] ? envelope . from [ 0 ] : parsedAddresses . from ?. [ 0 ] || undefined ,
1378
1416
1379
1417
replyTo : envelope . replyTo && envelope . replyTo . length ? envelope . replyTo : undefined ,
1380
1418
sender : extended && envelope . sender && envelope . sender [ 0 ] ? envelope . sender [ 0 ] : undefined ,
1381
1419
1382
- to : envelope . to && envelope . to . length ? envelope . to : undefined ,
1383
- cc : envelope . cc && envelope . cc . length ? envelope . cc : undefined ,
1420
+ to : envelope . to ?. length ? envelope . to : parsedAddresses . to || undefined ,
1421
+ cc : envelope . cc ?. length ? envelope . cc : parsedAddresses . cc || undefined ,
1384
1422
1385
1423
bcc : extended && envelope . bcc && envelope . bcc . length ? envelope . bcc : undefined ,
1386
1424
1387
1425
attachments : attachments && attachments . length ? attachments : undefined ,
1388
1426
messageId : ( envelope . messageId && envelope . messageId . toString ( ) . trim ( ) ) || undefined ,
1389
1427
inReplyTo : envelope . inReplyTo || undefined ,
1390
1428
1391
- headers : ( extended && messageData . headers && libmime . decodeHeaders ( messageData . headers . toString ( ) . trim ( ) ) ) || undefined ,
1429
+ headers : ( extended && headers ) || undefined ,
1392
1430
text : textId
1393
1431
? {
1394
1432
id : textId ,
@@ -2072,6 +2110,13 @@ class Mailbox {
2072
2110
2073
2111
fetchHeaders . add ( 'content-type' ) ;
2074
2112
2113
+ if ( this . isLarkSuite ) {
2114
+ // add address headers as a fallback to use if ENVELOPE does not include a specific address field (no idea why it happens)
2115
+ fetchHeaders . add ( 'from' ) ;
2116
+ fetchHeaders . add ( 'to' ) ;
2117
+ fetchHeaders . add ( 'cc' ) ;
2118
+ }
2119
+
2075
2120
messageFetchOptions . fetchHeaders = Array . from ( fetchHeaders ) ;
2076
2121
}
2077
2122
@@ -2904,6 +2949,20 @@ class Mailbox {
2904
2949
labels : true
2905
2950
} ;
2906
2951
2952
+ if ( this . isLarkSuite ) {
2953
+ if ( ! fields . headers && fields . headers !== true ) {
2954
+ fields . headers = [ ] ;
2955
+ }
2956
+ if ( Array . isArray ( fields . headers ) ) {
2957
+ // ensure that the response includes header fiels because Lark Mail ENVELOPE response is unreliable
2958
+ for ( let key of [ 'from' , 'to' , 'cc' ] ) {
2959
+ if ( ! fields . headers . includes ( key ) ) {
2960
+ fields . headers . push ( key ) ;
2961
+ }
2962
+ }
2963
+ }
2964
+ }
2965
+
2907
2966
for await ( let messageData of connectionClient . fetch ( range , fields , opts ) ) {
2908
2967
if ( ! messageData || ! messageData . uid ) {
2909
2968
//TODO: support partial responses
0 commit comments