+2007-10-25 Wolfgang Sourdeau <wsourdeau@inverse.ca>
+
+ * SoObjects/Mailer/NSData+Mail.m ([NSData
+ -bodyDataFromEncoding:encoding]): new utility method that decodes
+ the NSData instance properly depending on the encoding string
+ passed as parameter.
+
+ * SoObjects/Mailer/SOGoMailObject+Draft.m ([SOGoMailObject
+ -fetchFileAttachmentKeys]): fetch the attachment encoding as well.
+
+ * SoObjects/Mailer/SOGoMailObject.m ([SOGoMailObject
+ -stringForData:_datapartInfo:_info]): simplified by invoking
+ -bodyDataFromEncoding: from our new NSData category methods.
+
+ * SoObjects/Mailer/SOGoDraftObject.m ([SOGoDraftObject
+ -fetchMailForEditing:sourceMail]): work-around a bug in SOPE-mime
+ where only the body part of the first of the keys fetched was
+ returned. Also decodes the body parts properly following their
+ encoding.
+
+ * SoObjects/Mailer/NSData+Mail.[hm]: new extension module that
+ extends the NSData class with utility methods useful for handling
+ mail.
+
2007-10-23 Wolfgang Sourdeau <wsourdeau@inverse.ca>
* SoObjects/SOGo/NSArray+Utilities.m
SOGoDraftsFolder.m \
SOGoDraftObject.m \
\
- SOGoMailForward.m
+ SOGoMailForward.m \
+ \
+ NSData+Mail.m
Mailer_RESOURCE_FILES += \
Version \
--- /dev/null
+/* NSData+Mail.h - this file is part of SOGo
+ *
+ * Copyright (C) 2007 Inverse groupe conseil
+ *
+ * Author: Wolfgang Sourdeau <wsourdeau@inverse.ca>
+ *
+ * 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 NSDATA_MAIL_H
+#define NSDATA_MAIL_H
+
+#import <Foundation/NSData.h>
+
+@class NSString;
+
+@interface NSData (SOGoMailUtilities)
+
+- (NSData *) bodyDataFromEncoding: (NSString *) encoding;
+
+@end
+
+#endif /* NSDATA_MAIL_H */
--- /dev/null
+/* NSData+Mail.m - this file is part of SOGo
+ *
+ * Copyright (C) 2007 Inverse groupe conseil
+ *
+ * Author: Wolfgang Sourdeau <wsourdeau@inverse.ca>
+ *
+ * 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 <Foundation/NSString.h>
+
+#import <NGExtensions/NGBase64Coding.h>
+#import <NGExtensions/NGQuotedPrintableCoding.h>
+
+#import "NSData+Mail.h"
+
+@implementation NSData (SOGoMailUtilities)
+
+- (NSData *) bodyDataFromEncoding: (NSString *) encoding
+{
+ NSString *realEncoding;
+ NSData *decodedData;
+
+ realEncoding = [encoding lowercaseString];
+
+ if ([realEncoding isEqualToString: @"7bit"]
+ || [realEncoding isEqualToString: @"8bit"])
+ decodedData = self;
+ else if ([realEncoding isEqualToString: @"base64"])
+ decodedData = [self dataByDecodingBase64];
+ else if ([realEncoding isEqualToString: @"quoted-printable"])
+ decodedData = [self dataByDecodingQuotedPrintable];
+ else
+ {
+ decodedData = nil;
+ NSLog (@"encoding '%@' unknown, returning nil data", realEncoding);
+ }
+
+ return decodedData;
+}
+
+@end
#import <SoObjects/SOGo/NSString+Utilities.h>
#import <SoObjects/SOGo/SOGoMailer.h>
#import <SoObjects/SOGo/SOGoUser.h>
+
+#import "NSData+Mail.h"
#import "SOGoMailAccount.h"
#import "SOGoMailFolder.h"
#import "SOGoMailObject.h"
}
}
+- (NSArray *) _attachmentBodiesFromPaths: (NSArray *) paths
+ fromResponseFetch: (NSDictionary *) fetch;
+{
+ NSEnumerator *attachmentKeys;
+ NSMutableArray *bodies;
+ NSString *currentKey;
+ NSDictionary *body;
+
+ bodies = [NSMutableArray array];
+
+ attachmentKeys = [paths objectEnumerator];
+ while ((currentKey = [attachmentKeys nextObject]))
+ {
+ body = [fetch objectForKey: [currentKey lowercaseString]];
+ [bodies addObject: [body objectForKey: @"data"]];
+ }
+
+ return bodies;
+}
+
- (void) _fetchAttachments: (NSArray *) parts
fromMail: (SOGoMailObject *) sourceMail
{
unsigned int count, max;
- NSDictionary *currentPart, *attachment, *body;
- NSArray *paths, *result;
+ NSArray *paths, *bodies;
+ NSData *body;
+ NSDictionary *currentInfo;
+ NGHashMap *response;
max = [parts count];
if (max > 0)
{
paths = [parts keysWithFormat: @"BODY[%{path}]"];
- result = [[sourceMail fetchParts: paths] objectForKey: @"fetch"];
+ response = [[sourceMail fetchParts: paths] objectForKey: @"RawResponse"];
+ bodies = [self _attachmentBodiesFromPaths: paths
+ fromResponseFetch: [response objectForKey: @"fetch"]];
for (count = 0; count < max; count++)
{
- currentPart = [parts objectAtIndex: count];
- body = [[result objectAtIndex: count] objectForKey: @"body"];
- attachment = [NSDictionary dictionaryWithObjectsAndKeys:
- [currentPart objectForKey: @"filename"],
- @"filename",
- [currentPart objectForKey: @"mimetype"],
- @"mime-type",
- nil];
- [self saveAttachment: [body objectForKey: @"data"]
- withMetadata: attachment];
+ currentInfo = [parts objectAtIndex: count];
+ body = [[bodies objectAtIndex: count]
+ bodyDataFromEncoding: [currentInfo
+ objectForKey: @"encoding"]];
+ [self saveAttachment: body withMetadata: currentInfo];
}
}
}
// error = [newDraft saveAttachment:content withName:@"forward.mail"];
attachment = [NSDictionary dictionaryWithObjectsAndKeys:
[sourceMail filenameForForward], @"filename",
- @"message/rfc822", @"mime-type",
+ @"message/rfc822", @"mimetype",
nil];
[self saveAttachment: [sourceMail content]
withMetadata: attachment];
reason: @"Could not write attachment to draft!"];
}
- mimeType = [metadata objectForKey: @"mime-type"];
+ mimeType = [metadata objectForKey: @"mimetype"];
if ([mimeType length] > 0)
{
p = [self pathToAttachmentWithName:
intoArray: (NSMutableArray *) keys
withPath: (NSString *) path
{
- NSDictionary *parameters, *currentFile;
+ NSDictionary *disposition, *currentFile;
NSString *filename, *mimeType;
- parameters = [[part objectForKey: @"disposition"]
- objectForKey: @"parameterList"];
- if (parameters)
+ disposition = [part objectForKey: @"disposition"];
+ filename = [[disposition objectForKey: @"parameterList"]
+ objectForKey: @"filename"];
+ if (filename)
{
- filename = [parameters objectForKey: @"filename"];
mimeType = [NSString stringWithFormat: @"%@/%@",
[part objectForKey: @"type"],
[part objectForKey: @"subtype"]];
currentFile = [NSDictionary dictionaryWithObjectsAndKeys:
filename, @"filename",
[mimeType lowercaseString], @"mimetype",
+ [part
+ objectForKey: @"encoding"], @"encoding",
path, @"path", nil];
[keys addObject: currentFile];
}
#import <NGObjWeb/WOContext+SoObjects.h>
#import <NGObjWeb/WOResponse.h>
#import <NGObjWeb/NSException+HTTP.h>
-#import <NGExtensions/NGBase64Coding.h>
#import <NGExtensions/NSNull+misc.h>
#import <NGExtensions/NSObject+Logs.h>
-#import <NGExtensions/NGQuotedPrintableCoding.h>
#import <NGExtensions/NSString+Encoding.h>
#import <NGExtensions/NSString+misc.h>
#import <NGImap4/NGImap4Connection.h>
#import <SoObjects/SOGo/SOGoPermissions.h>
#import <SoObjects/SOGo/SOGoUser.h>
+
+#import "NSData+Mail.h"
#import "SOGoMailFolder.h"
#import "SOGoMailAccount.h"
#import "SOGoMailManager.h"
}
/* convert parts to strings */
-
- (NSString *) stringForData: (NSData *) _data
partInfo: (NSDictionary *) _info
{
- NSString *charset, *encoding, *s;
+ NSString *charset, *s;
NSData *mailData;
- if (![_data isNotNull])
- return nil;
-
- s = nil;
-
- encoding = [[_info objectForKey: @"encoding"] lowercaseString];
-
- if ([encoding isEqualToString: @"7bit"]
- || [encoding isEqualToString: @"8bit"])
- mailData = _data;
- else if ([encoding isEqualToString: @"base64"])
- mailData = [_data dataByDecodingBase64];
- else if ([encoding isEqualToString: @"quoted-printable"])
- mailData = [_data dataByDecodingQuotedPrintable];
-
- charset = [[_info valueForKey: @"parameterList"] valueForKey: @"charset"];
- if (![charset length])
+ if ([_data isNotNull])
{
- s = [[NSString alloc] initWithData:mailData encoding:NSUTF8StringEncoding];
- [s autorelease];
+ mailData
+ = [_data bodyDataFromEncoding: [_info objectForKey: @"encoding"]];
+
+ charset = [[_info valueForKey: @"parameterList"] valueForKey: @"charset"];
+ if (![charset length])
+ {
+ s = [[NSString alloc] initWithData: mailData encoding: NSUTF8StringEncoding];
+ [s autorelease];
+ }
+ else
+ s = [NSString stringWithData: mailData
+ usingEncodingNamed: charset];
}
else
- s = [NSString stringWithData: mailData
- usingEncodingNamed: charset];
+ s = nil;
return s;
}
for (count = 0; count < max; count++)
{
part = [parts objectAtIndex: count];
- header = (NGMimeContentDispositionHeaderField *) [part headerForKey: @"content-disposition"];
- mimeType = [(NGMimeType *) [part headerForKey: @"content-type"] stringValue];
+ header = (NGMimeContentDispositionHeaderField *)
+ [part headerForKey: @"content-disposition"];
+ mimeType = [(NGMimeType *)
+ [part headerForKey: @"content-type"] stringValue];
attachment = [NSDictionary dictionaryWithObjectsAndKeys:
[header filename], @"filename",
- mimeType, @"mime-type", nil];
- [filenames setObject: attachment
- forKey: [header name]];
+ mimeType, @"mimetype", nil];
+ [filenames setObject: attachment forKey: [header name]];
}
return filenames;
return [calendars componentsJoinedByString: @","];
}
-- (NSString *) componentCalendar
+- (SOGoAppointmentFolder *) componentCalendar
{
SOGoAppointmentFolder *calendar;
calendar = [[self clientObject] container];
- return [calendar nameInContainer];
+ return calendar;
}
/* priorities */