@@ -27,13 +27,6 @@ const mail = JMAP.mail;
27
27
28
28
// ---
29
29
30
- const bodyType = {
31
- 'text/plain' : 'text' ,
32
- 'text/enriched' : 'text' ,
33
- 'text/richtext' : 'text' ,
34
- 'text/html' : 'html' ,
35
- } ;
36
-
37
30
const parseStructure = function ( parts , multipartType , inAlternative ,
38
31
htmlParts , textParts , fileParts ) {
39
32
@@ -45,13 +38,13 @@ const parseStructure = function ( parts, multipartType, inAlternative,
45
38
for ( i = 0 ; i < parts . length ; i += 1 ) {
46
39
var part = parts [ i ] ;
47
40
var type = part . type ;
48
- var isTextOrHTML = false ;
41
+ var isText = false ;
49
42
var isMultipart = false ;
50
43
var isImage = false ;
51
44
var isInline , subMultiType ;
52
45
53
- if ( bodyType [ type ] ) {
54
- isTextOrHTML = true ;
46
+ if ( type . startsWith ( 'text/' ) ) {
47
+ isText = true ;
55
48
} else if ( type . startsWith ( 'multipart/' ) ) {
56
49
isMultipart = true ;
57
50
} else if ( type . startsWith ( 'image/' ) ) {
@@ -61,7 +54,7 @@ const parseStructure = function ( parts, multipartType, inAlternative,
61
54
// Is this a body part rather than an attachment
62
55
isInline =
63
56
// Must be one of the allowed body types
64
- ( isTextOrHTML || isImage ) &&
57
+ ( isText || isImage ) && type !== 'text/calendar' &&
65
58
// Must not be explicitly marked as an attachment
66
59
part . disposition !== 'attachment' &&
67
60
// If multipart/related, only the first part can be inline
@@ -77,26 +70,26 @@ const parseStructure = function ( parts, multipartType, inAlternative,
77
70
htmlParts , textParts , fileParts ) ;
78
71
} else if ( isInline ) {
79
72
if ( multipartType === 'alternative' ) {
80
- switch ( bodyType [ type ] ) {
81
- case 'text' :
82
- textParts . push ( part ) ;
83
- break ;
84
- case 'html' :
73
+ if ( type === 'text/html' ) {
85
74
htmlParts . push ( part ) ;
86
- break ;
87
- default :
75
+ } else if ( isText && textParts . length === textLength ) {
76
+ textParts . push ( part ) ;
77
+ } else if ( type === 'text/plain' ) {
78
+ // We've found a text/plain but already chose a text part.
79
+ // Replace it and move the other part to files instead.
80
+ fileParts . push ( textParts . pop ( ) ) ;
81
+ textParts . push ( part ) ;
82
+ } else {
88
83
fileParts . push ( part ) ;
89
- break ;
90
84
}
91
85
continue ;
92
86
} else if ( inAlternative ) {
93
- switch ( bodyType [ type ] ) {
94
- case 'text' :
95
- htmlParts = null ;
96
- break ;
97
- case 'html' :
98
- textParts = null ;
99
- break ;
87
+ if ( isText ) {
88
+ if ( type === 'text/html' ) {
89
+ textParts = null ;
90
+ } else {
91
+ htmlParts = null ;
92
+ }
100
93
}
101
94
}
102
95
if ( textParts ) {
@@ -163,6 +156,7 @@ const Message = Class({
163
156
recordType : Mailbox ,
164
157
key : 'mailboxIds' ,
165
158
Type : Object ,
159
+ isNullable : false ,
166
160
} ) ,
167
161
168
162
keywords : attr ( Object , {
@@ -358,7 +352,8 @@ const Message = Class({
358
352
359
353
hasTextBody : function ( ) {
360
354
return this . get ( 'bodyParts' ) . text . some ( function ( part ) {
361
- return bodyType [ part . type ] === 'text' ;
355
+ const type = part . type ;
356
+ return type . startsWith ( 'text/' ) && type !== 'text/html' ;
362
357
} ) ;
363
358
} . property ( 'bodyParts' ) ,
364
359
0 commit comments