(fix) properly encode MIME parts with embedded images in HTML parts (fixes #4150)

Conflicts:
	SoObjects/Mailer/NSString+Mail.m
	SoObjects/Mailer/SOGoDraftObject.m
This commit is contained in:
Ludovic Marcotte
2017-08-23 16:05:33 -04:00
parent c915bc7c95
commit 7d190e537e
2 changed files with 69 additions and 36 deletions
+27 -5
View File
@@ -302,7 +302,7 @@
NSData *data;
id body;
int i, j, k;
int i, j, k, len;
i = [value indexOf: ';'];
j = [value indexOf: ';' fromIndex: i+1];
@@ -333,17 +333,39 @@
encoding = @"base64";
data = [[value substringFromIndex: k+1] dataUsingEncoding: NSASCIIStringEncoding];
len = [data length];
if ([encoding isEqualToString: @"base64"] && len > 72)
{
NSMutableData *folded_data;
unsigned char *bytes, c;
folded_data = [NSMutableData data];
bytes = (unsigned char *)[data bytes];
for (i = 0; i < len; i++)
{
if (i > 0 && i % 72 == 0)
{
c = '\n';
[folded_data appendBytes: &c length: 1];
}
c = *bytes; bytes++;
[folded_data appendBytes: &c length: 1];
}
data = folded_data;
}
uniqueId = [SOGoObject globallyUniqueObjectId];
map = [[[NGMutableHashMap alloc] initWithCapacity:5] autorelease];
map = [[[NGMutableHashMap alloc] initWithCapacity: 5] autorelease];
[map setObject: encoding forKey: @"content-transfer-encoding"];
[map setObject:[NSNumber numberWithInt:[data length]] forKey: @"content-length"];
[map setObject:[NSNumber numberWithInt: [data length]] forKey: @"content-length"];
[map setObject: [NSString stringWithFormat: @"inline; filename=\"%@\"", uniqueId] forKey: @"content-disposition"];
[map setObject: [NSString stringWithFormat: @"%@; name=\"%@\"", mimeType, uniqueId] forKey: @"content-type"];
[map setObject: [NSString stringWithFormat: @"<%@>", uniqueId] forKey: @"content-id"];
body = [[NGMimeFileData alloc] initWithBytes: [data bytes] length: [data length]];
bodyPart = [[[NGMimeBodyPart alloc] initWithHeader:map] autorelease];
+42 -31
View File
@@ -1489,7 +1489,7 @@ static NSString *userAgent = nil;
//
//
//
- (NGMimeBodyPart *) mimeMultipartAlternative
- (NGMimeBodyPart *) mimeMultipartAlternative: (NSArray *) extractedBodyParts
{
NGMimeMultipartBody *textParts;
NGMutableHashMap *header;
@@ -1505,8 +1505,35 @@ static NSString *userAgent = nil;
// Get the text part from it and add it
[textParts addBodyPart: [self plainTextBodyPartForText]];
// Add the HTML part
[textParts addBodyPart: [self bodyPartForText]];
if ([extractedBodyParts count])
{
// Create a multipart/related part and add this.
// We have inline image to avoid Thunderbird bug #61815 (https://bugzilla.mozilla.org/show_bug.cgi?id=61815)
NGMutableHashMap *relatedHeader;
NGMimeBodyPart *relatedPart;
NGMimeMultipartBody *relatedParts;
int i;
relatedHeader = [NGMutableHashMap hashMap];
[relatedHeader addObject: MultiRelatedType forKey: @"content-type"];
relatedPart = [NGMimeBodyPart bodyPartWithHeader: relatedHeader];
relatedParts = [[NGMimeMultipartBody alloc] initWithPart: relatedPart];
[relatedParts addBodyPart: [self bodyPartForText]];
for (i = 0; i < [extractedBodyParts count]; i++)
{
[relatedParts addBodyPart: [extractedBodyParts objectAtIndex: i]];
}
[relatedPart setBody: relatedParts];
[textParts addBodyPart: relatedPart];
}
else
{
// Add the HTML part
[textParts addBodyPart: [self bodyPartForText]];
}
[part setBody: textParts];
RELEASE(textParts);
@@ -1518,7 +1545,8 @@ static NSString *userAgent = nil;
//
//
- (NGMimeMessage *) mimeMultiPartMessageWithHeaderMap: (NGMutableHashMap *) map
andBodyParts: (NSArray *) _bodyParts
extractedBodyParts: (NSArray *) extractedBodyParts
andBodyParts: (NSArray *) _bodyParts
{
NGMimeMessage *message;
NGMimeMultipartBody *mBody;
@@ -1534,7 +1562,7 @@ static NSString *userAgent = nil;
if (!isHTML)
part = [self bodyPartForText];
else
part = [self mimeMultipartAlternative];
part = [self mimeMultipartAlternative: extractedBodyParts];
[mBody addBodyPart: part];
@@ -1734,26 +1762,20 @@ static NSString *userAgent = nil;
excluding: (NSArray *) _exclude
extractingImages: (BOOL) _extractImages
{
NSMutableArray *bodyParts;
NSMutableArray *extractedBodyParts;
NGMimeMessage *message;
NSArray *allBodyParts;
NGMutableHashMap *map;
NSString *newText;
BOOL has_inline_images;
message = nil;
has_inline_images = NO;
bodyParts = [NSMutableArray array];
extractedBodyParts = [NSMutableArray array];
if (_extractImages)
{
newText = [text htmlByExtractingImages: bodyParts];
if ([bodyParts count])
{
[self setText: newText];
has_inline_images = YES;
}
newText = [text htmlByExtractingImages: extractedBodyParts];
if ([extractedBodyParts count])
[self setText: newText];
}
map = [self mimeHeaderMapWithHeaders: _headers
@@ -1766,26 +1788,15 @@ static NSString *userAgent = nil;
if (!allBodyParts)
return nil;
[bodyParts addObjectsFromArray: allBodyParts];
//[self debugWithFormat: @"attachments: %@", bodyParts];
if ([bodyParts count] == 0)
if ([extractedBodyParts count] == 0 && [allBodyParts count] == 0)
/* no attachments */
message = [self mimeMessageForContentWithHeaderMap: map];
else
{
// attachments, create multipart/mixed or multipart/related if
// we have inline image to avoid Thunderbird bug #61815 (https://bugzilla.mozilla.org/show_bug.cgi?id=61815)
if (has_inline_images)
{
[map removeAllObjectsForKey: @"content-type"];
[map addObject: MultiRelatedType forKey: @"content-type"];
}
message = [self mimeMultiPartMessageWithHeaderMap: map
andBodyParts: bodyParts];
message = [self mimeMultiPartMessageWithHeaderMap: map
extractedBodyParts: extractedBodyParts
andBodyParts: allBodyParts];
//[self debugWithFormat: @"message: %@", message];
}
}