mirror of
https://github.com/inverse-inc/sogo.git
synced 2026-02-17 07:33:57 +00:00
fix(mail): Fix images not displayed when forward / reply to a mail. Fixes #3981
This commit is contained in:
@@ -859,7 +859,7 @@ static NSString *userAgent = nil;
|
||||
//
|
||||
//
|
||||
//
|
||||
- (void) _fetchAttachmentsFromMail: (SOGoMailObject *) sourceMail
|
||||
- (void) _fetchAttachmentsFromMail: (SOGoMailObject *) sourceMail onlyImages: (BOOL) onlyImages
|
||||
{
|
||||
NSMutableDictionary *currentInfo;
|
||||
NSArray *attachments;
|
||||
@@ -871,15 +871,19 @@ static NSString *userAgent = nil;
|
||||
for (count = 0; count < max; count++)
|
||||
{
|
||||
currentInfo = [attachments objectAtIndex: count];
|
||||
[self saveAttachment: [currentInfo objectForKey: @"body"]
|
||||
if (!onlyImages
|
||||
|| (onlyImages && [[NGMimeBodyPart imageMimeTypes] containsObject: [currentInfo objectForKey: @"mimetype"]])) {
|
||||
[self saveAttachment: [currentInfo objectForKey: @"body"]
|
||||
withMetadata: currentInfo];
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
//
|
||||
//
|
||||
- (void) _fileAttachmentsFromPart: (id) thePart
|
||||
- (void) _fileAttachmentsFromPart: (id) thePart onlyImages: (BOOL) onlyImages
|
||||
{
|
||||
// Small hack to avoid SOPE's stupid behavior to wrap a multipart
|
||||
// object in a NGMimeBodyPart.
|
||||
@@ -889,10 +893,15 @@ static NSString *userAgent = nil;
|
||||
|
||||
if ([thePart isKindOfClass: [NGMimeBodyPart class]])
|
||||
{
|
||||
NSString *filename, *mimeType;
|
||||
NSString *filename, *mimeType, *bodyId;
|
||||
id body;
|
||||
|
||||
if (onlyImages && ![thePart isImage]) {
|
||||
return;
|
||||
}
|
||||
|
||||
mimeType = [[thePart contentType] stringValue];
|
||||
bodyId = [[thePart contentId] stringValue];
|
||||
body = [thePart body];
|
||||
filename = [(NGMimeContentDispositionHeaderField *)[thePart headerForKey: @"content-disposition"] filename];
|
||||
|
||||
@@ -906,6 +915,7 @@ static NSString *userAgent = nil;
|
||||
currentInfo = [NSMutableDictionary dictionaryWithObjectsAndKeys:
|
||||
filename, @"filename",
|
||||
mimeType, @"mimetype",
|
||||
bodyId, @"bodyid",
|
||||
nil];
|
||||
[self saveAttachment: body
|
||||
withMetadata: currentInfo];
|
||||
@@ -919,7 +929,7 @@ static NSString *userAgent = nil;
|
||||
parts = [thePart parts];
|
||||
for (i = 0; i < [parts count]; i++)
|
||||
{
|
||||
[self _fileAttachmentsFromPart: [parts objectAtIndex: i]];
|
||||
[self _fileAttachmentsFromPart: [parts objectAtIndex: i] onlyImages: onlyImages];
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -928,7 +938,7 @@ static NSString *userAgent = nil;
|
||||
//
|
||||
//
|
||||
//
|
||||
- (void) _fetchAttachmentsFromEncryptedMail: (SOGoMailObject *) sourceMail
|
||||
- (void) _fetchAttachmentsFromEncryptedMail: (SOGoMailObject *) sourceMail onlyImages: (BOOL) onlyImages
|
||||
{
|
||||
NSData *certificate;
|
||||
|
||||
@@ -941,7 +951,7 @@ static NSString *userAgent = nil;
|
||||
NGMimeMessage *m;
|
||||
|
||||
m = [[sourceMail content] messageFromEncryptedDataAndCertificate: certificate];
|
||||
[self _fileAttachmentsFromPart: [m body]];
|
||||
[self _fileAttachmentsFromPart: [m body] onlyImages: onlyImages];
|
||||
}
|
||||
}
|
||||
|
||||
@@ -949,12 +959,12 @@ static NSString *userAgent = nil;
|
||||
//
|
||||
//
|
||||
//
|
||||
- (void) _fetchAttachmentsFromOpaqueSignedMail: (SOGoMailObject *) sourceMail
|
||||
- (void) _fetchAttachmentsFromOpaqueSignedMail: (SOGoMailObject *) sourceMail onlyImages: (BOOL) onlyImages
|
||||
{
|
||||
NGMimeMessage *m;
|
||||
|
||||
m = [[sourceMail content] messageFromOpaqueSignedData];
|
||||
[self _fileAttachmentsFromPart: [m body]];
|
||||
[self _fileAttachmentsFromPart: [m body] onlyImages: onlyImages];
|
||||
}
|
||||
|
||||
|
||||
@@ -973,7 +983,7 @@ static NSString *userAgent = nil;
|
||||
|
||||
[sourceMail fetchCoreInfos];
|
||||
|
||||
[self _fetchAttachmentsFromMail: sourceMail];
|
||||
[self _fetchAttachmentsFromMail: sourceMail onlyImages: NO];
|
||||
info = [NSMutableDictionary dictionaryWithCapacity: 16];
|
||||
subject = [sourceMail subject];
|
||||
if ([subject length] > 0)
|
||||
@@ -1057,6 +1067,22 @@ static NSString *userAgent = nil;
|
||||
[self setSourceIMAP4ID: [[sourceMail nameInContainer] intValue]];
|
||||
[self setSourceFolderWithMailObject: sourceMail];
|
||||
|
||||
|
||||
ud = [[context activeUser] userDefaults];
|
||||
// TODO: Change mailMessageForwarding for reply
|
||||
if ([[ud mailMessageForwarding] isEqualToString: @"inline"])
|
||||
{
|
||||
[self setText: [sourceMail contentForInlineForward]];
|
||||
if ([sourceMail isEncrypted])
|
||||
[self _fetchAttachmentsFromEncryptedMail: sourceMail onlyImages: YES];
|
||||
else if ([sourceMail isOpaqueSigned])
|
||||
[self _fetchAttachmentsFromOpaqueSignedMail: sourceMail onlyImages: YES];
|
||||
else
|
||||
[self _fetchAttachmentsFromMail: sourceMail onlyImages: YES];
|
||||
}
|
||||
|
||||
[self save];
|
||||
|
||||
[self storeInfo];
|
||||
}
|
||||
|
||||
@@ -1090,15 +1116,16 @@ static NSString *userAgent = nil;
|
||||
|
||||
/* attach message */
|
||||
ud = [[context activeUser] userDefaults];
|
||||
|
||||
if ([[ud mailMessageForwarding] isEqualToString: @"inline"])
|
||||
{
|
||||
[self setText: [sourceMail contentForInlineForward]];
|
||||
if ([sourceMail isEncrypted])
|
||||
[self _fetchAttachmentsFromEncryptedMail: sourceMail];
|
||||
[self _fetchAttachmentsFromEncryptedMail: sourceMail onlyImages: NO];
|
||||
else if ([sourceMail isOpaqueSigned])
|
||||
[self _fetchAttachmentsFromOpaqueSignedMail: sourceMail];
|
||||
[self _fetchAttachmentsFromOpaqueSignedMail: sourceMail onlyImages: NO];
|
||||
else
|
||||
[self _fetchAttachmentsFromMail: sourceMail];
|
||||
[self _fetchAttachmentsFromMail: sourceMail onlyImages: NO];
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -1195,7 +1222,7 @@ static NSString *userAgent = nil;
|
||||
withMetadata: (NSMutableDictionary *) metadata
|
||||
{
|
||||
NSFileManager *fm;
|
||||
NSString *p, *pmime, *name, *baseName, *extension, *mimeType;
|
||||
NSString *p, *pmime, *pbodyId, *name, *baseName, *extension, *mimeType, *bodyId;
|
||||
int i;
|
||||
|
||||
if (![_attach isNotNull])
|
||||
@@ -1216,6 +1243,7 @@ static NSString *userAgent = nil;
|
||||
fm = [NSFileManager defaultManager];
|
||||
p = [self pathToAttachmentWithName: name];
|
||||
i = 1;
|
||||
bodyId = nil;
|
||||
|
||||
while ([fm isReadableFileAtPath: p])
|
||||
{
|
||||
@@ -1244,6 +1272,18 @@ static NSString *userAgent = nil;
|
||||
reason: @"Could not write attachment to draft!"];
|
||||
}
|
||||
}
|
||||
|
||||
bodyId = [metadata objectForKey: @"bodyId"];
|
||||
if ([bodyId length] > 0)
|
||||
{
|
||||
pbodyId = [self pathToAttachmentWithName: [NSString stringWithFormat: @".%@.bodyid", name]];
|
||||
if (![[bodyId dataUsingEncoding: NSUTF8StringEncoding] writeToFile: pbodyId atomically: YES])
|
||||
{
|
||||
[[NSFileManager defaultManager] removeFileAtPath: p handler: nil];
|
||||
return [NSException exceptionWithHTTPStatus: 500 /* Server Error */
|
||||
reason: @"Could not write body idattachment to draft!"];
|
||||
}
|
||||
}
|
||||
|
||||
return nil; /* everything OK */
|
||||
}
|
||||
@@ -1381,6 +1421,27 @@ static NSString *userAgent = nil;
|
||||
return s;
|
||||
}
|
||||
|
||||
- (NSString *) bodyIdForAttachmentWithName: (NSString *) _name
|
||||
{
|
||||
NSString *s, *p;
|
||||
NSData *bodyIdData;
|
||||
|
||||
p = [self pathToAttachmentWithName: [NSString stringWithFormat: @".%@.bodyid", _name]];
|
||||
bodyIdData = [NSData dataWithContentsOfFile: p];
|
||||
if (bodyIdData)
|
||||
{
|
||||
s = [[NSString alloc] initWithData: bodyIdData
|
||||
encoding: NSUTF8StringEncoding];
|
||||
[s autorelease];
|
||||
}
|
||||
else
|
||||
{
|
||||
s = nil;
|
||||
}
|
||||
|
||||
return s;
|
||||
}
|
||||
|
||||
- (NSString *) contentDispositionForAttachmentWithName: (NSString *) _name
|
||||
andContentType: (NSString *) _type
|
||||
{
|
||||
@@ -1441,6 +1502,9 @@ static NSString *userAgent = nil;
|
||||
else if ([s hasPrefix: @"message/rfc822"])
|
||||
attachAsRFC822 = YES;
|
||||
}
|
||||
if ((s = [self bodyIdForAttachmentWithName:_name]) != nil) {
|
||||
[map setObject: s forKey: @"content-id"];
|
||||
}
|
||||
if ((s = [self contentDispositionForAttachmentWithName: _name andContentType: s]))
|
||||
{
|
||||
NGMimeContentDispositionHeaderField *o;
|
||||
|
||||
@@ -91,7 +91,9 @@ SOGo_HEADER_FILES = \
|
||||
SOGoTextTemplateFile.h \
|
||||
SOGoZipArchiver.h \
|
||||
\
|
||||
JWT.h
|
||||
JWT.h \
|
||||
\
|
||||
NGMimeBodyPart+SOGo.h
|
||||
|
||||
all::
|
||||
@touch SOGoBuild.m
|
||||
@@ -176,7 +178,9 @@ SOGo_OBJC_FILES = \
|
||||
SOGoTextTemplateFile.m \
|
||||
SOGoZipArchiver.m \
|
||||
\
|
||||
JWT.m
|
||||
JWT.m \
|
||||
\
|
||||
NGMimeBodyPart+SOGo.m
|
||||
|
||||
SOGo_C_FILES += lmhash.c aes.c crypt_blowfish.c pkcs5_pbkdf2.c
|
||||
|
||||
|
||||
35
SoObjects/SOGo/NGMimeBodyPart+SOGo.h
Normal file
35
SoObjects/SOGo/NGMimeBodyPart+SOGo.h
Normal file
@@ -0,0 +1,35 @@
|
||||
/* NGMimeBodyPart+SOGo.h - this file is part of SOGo
|
||||
*
|
||||
* Copyright (C) 2023 Alinto
|
||||
*
|
||||
* Author: Sébastien Mizrahi <smizrahi@alinto.eu>
|
||||
*
|
||||
* This file is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2, or (at your option)
|
||||
* any later version.
|
||||
*
|
||||
* This file is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; see the file COPYING. If not, write to
|
||||
* the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
||||
* Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#ifndef NGMIMEBODYPART_SOGO_H
|
||||
#define NGMIMEBODYPART_SOGO_H
|
||||
|
||||
#import <NGMime/NGMimeBodyPart.h>
|
||||
|
||||
@interface NGMimeBodyPart (SOGoExtensions)
|
||||
|
||||
+ (NSArray *) imageMimeTypes;
|
||||
- (BOOL) isImage;
|
||||
|
||||
@end
|
||||
|
||||
#endif /* NGMIMEBODYPART_SOGO_H */
|
||||
41
SoObjects/SOGo/NGMimeBodyPart+SOGo.m
Normal file
41
SoObjects/SOGo/NGMimeBodyPart+SOGo.m
Normal file
@@ -0,0 +1,41 @@
|
||||
/* NGMimeBodyPart+SOGo.m - this file is part of SOGo
|
||||
*
|
||||
* Copyright (C) 2023 Alinto
|
||||
*
|
||||
* Author: Sébastien Mizrahi <smizrahi@alinto.eu>
|
||||
*
|
||||
* This file is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2, or (at your option)
|
||||
* any later version.
|
||||
*
|
||||
* This file is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; see the file COPYING. If not, write to
|
||||
* the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
||||
* Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#import "NGMimeBodyPart+SOGo.h"
|
||||
|
||||
#import <Foundation/NSString.h>
|
||||
#import <Foundation/NSArray.h>
|
||||
|
||||
@implementation NGMimeBodyPart (SOGoExtensions)
|
||||
|
||||
+ (NSArray *) imageMimeTypes
|
||||
{
|
||||
return [NSArray arrayWithObjects: @"image/png", @"image/gif", @"image/tiff"
|
||||
, @"image/jpeg", @"image/bmp", @"image/svg+xml", @"image/webp", nil];
|
||||
}
|
||||
|
||||
- (BOOL) isImage
|
||||
{
|
||||
return [[NGMimeBodyPart imageMimeTypes] containsObject: [[self contentType] stringValue]];
|
||||
}
|
||||
|
||||
@end
|
||||
@@ -42,6 +42,7 @@
|
||||
#import <SOGo/NSDictionary+Utilities.h>
|
||||
#import <SOGo/NSString+Utilities.h>
|
||||
#import <SOGo/WOResourceManager+SOGo.h>
|
||||
#import <SOGo/NGMimeBodyPart+SOGo.h>
|
||||
#import <SOGoUI/UIxComponent.h>
|
||||
#import <Mailer/SOGoDraftObject.h>
|
||||
#import <Mailer/SOGoMailObject+Draft.h>
|
||||
@@ -702,6 +703,34 @@ static NSArray *infoKeys = nil;
|
||||
return [[self attachmentAttrs] count] > 0 ? YES : NO;
|
||||
}
|
||||
|
||||
/*
|
||||
* This method replace cid images in body with base64 inline image data
|
||||
*/
|
||||
- (void) setBase64ImagesInText:(SOGoDraftObject *) draft
|
||||
{
|
||||
NSString *contentId, *lText;
|
||||
NGMimeBodyPart *mime;
|
||||
|
||||
if ([self isHTML] && [[draft fetchAttachmentAttrs] count] > 0) {
|
||||
for (NSDictionary *draftFileAttachement in [draft fetchAttachmentAttrs]) {
|
||||
mime = [draftFileAttachement objectForKey: @"part"];
|
||||
if ([mime isImage]) {
|
||||
contentId = [mime contentId];
|
||||
contentId = [contentId stringByReplacingOccurrencesOfString: @"<" withString: @"cid:"];
|
||||
contentId = [contentId stringByReplacingOccurrencesOfString: @">" withString: @""];
|
||||
|
||||
if ([[mime encoding] isEqualToString: @"base64"]) {
|
||||
lText = [text stringByReplacingOccurrencesOfString: contentId
|
||||
withString: [NSString stringWithFormat: @"data:%@;base64,%@",
|
||||
[[mime contentType] stringValue],
|
||||
[NSString stringWithUTF8String: [[mime body] bytes]]]];
|
||||
[self setText: lText];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
- (id <WOActionResults>) editAction
|
||||
{
|
||||
id <WOActionResults> response;
|
||||
@@ -720,7 +749,6 @@ static NSArray *infoKeys = nil;
|
||||
data = [NSMutableDictionary dictionaryWithObjectsAndKeys:
|
||||
[self localeCode], @"locale",
|
||||
[NSNumber numberWithBool: [self isHTML]], @"isHTML",
|
||||
text, @"text",
|
||||
nil];
|
||||
if ((value = [self from]))
|
||||
[data setObject: value forKey: @"from"];
|
||||
@@ -737,6 +765,10 @@ static NSArray *infoKeys = nil;
|
||||
if ((value = [self attachmentAttrs]))
|
||||
[data setObject: value forKey: @"attachmentAttrs"];
|
||||
|
||||
[self setBase64ImagesInText: co];
|
||||
[data setObject: text forKey: @"text"];
|
||||
|
||||
|
||||
response = [self responseWithStatus: 200
|
||||
andString: [data jsonRepresentation]];
|
||||
|
||||
|
||||
Reference in New Issue
Block a user