View Issue Details
ID | Project | Category | View Status | Date Submitted | Last Update |
---|---|---|---|---|---|
0002024 | SOGo | Apple Calendar (Mac OS X) | public | 2012-10-12 13:46 | 2012-11-20 20:41 |
Reporter | gyurco | Assigned To | |||
Priority | normal | Severity | minor | Reproducibility | always |
Status | closed | Resolution | fixed | ||
Target Version | 2.0.3 | Fixed in Version | 2.0.3 | ||
Summary | 0002024: Certain mails don't have From: in Outlook | ||||
Description | During Outlook synchronization, certain types of mails don't have the From: address. The web interface shows it correctly. Attached an example. | ||||
Tags | No tags attached. | ||||
2012-10-12 13:46
|
|
Which versions are you using of SOGo and OpenChange? |
|
I'm using the latest nightly build |
|
I have the same (or similar) issue. It looks like mine can be narrowed down to the following: The from field is blank in Outlook when the mail was sent from Outlook. When you then click Reply, the To... field is blank and you have to select the user. BUT: In the message body part of Outlook where it quotes the original message it will show: <b>From</b> [mailto:email@example.com] In the web interface it appears fine. When the mail was sent from the web interface the from field is not blank in outlook. Hope this help you guys to find the problem. |
|
2012-11-14 15:28
|
|
2012-11-14 15:28
|
|
The issue is still there with latest nightly. Uploaded two screenshots which shows the problem: no sender in Outlook2007 with certain mails. |
|
With further invetigation, I think this problem can be seen as two problems actually:
I hope it is clear enough, please let me know if I can provide any more info. |
|
The problem causing this issue seems to be in FillMessageHeadersFromProperties. It seems that the block dealing with the recipients somehow overwrites the "from" assigned before. Moving the line '[headers setObject: QuoteSpecials (from) forKey: @"from"];' as described shown in following example "fixes" the problem and the sender is correctly displayed in outlook. I sure that this is just a hack but maybe it might help someone how really understand the code to fix the issue. static inline void activeUser from = [NSString stringWithFormat: @"%@ <%@>", / save the recipients /
else // moved following line from above =============================================<<<<<<<<<<<<<<<<<<<<<<<<< subject = [NSMutableString stringWithCapacity: 128]; |
|
Do you see the "recipient not generated from record" message in your logs? |
|
No this message is not repored in my logs. |
|
2012-11-19 19:14
|
MAPIStoreMailVolatileMessage.m.txt (30,453 bytes)
/* MAPIStoreMailVolatileMessage.m - this file is part of SOGo * * Copyright (C) 2011-2012 Inverse inc * * 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 3, 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. */ /* TODO: - calendar invitations - merge some code in a common module with SOGoDraftObject */ #import <Foundation/NSArray.h> #import <Foundation/NSData.h> #import <Foundation/NSDictionary.h> #import <Foundation/NSString.h> #import <Foundation/NSTimeZone.h> #import <Foundation/NSValue.h> #import <NGExtensions/NGHashMap.h> #import <NGExtensions/NSObject+Logs.h> #import <NGExtensions/NSString+Encoding.h> #import <NGMime/NGMimeBodyPart.h> #import <NGMime/NGMimeMultipartBody.h> #import <NGMail/NGMimeMessage.h> #import <NGMail/NGMimeMessageGenerator.h> #import <NGImap4/NGImap4Client.h> #import <NGImap4/NGImap4Connection.h> #import <SOGo/NSArray+Utilities.h> #import <SOGo/NSCalendarDate+SOGo.h> #import <SOGo/NSString+Utilities.h> #import <SOGo/SOGoDomainDefaults.h> #import <SOGo/SOGoMailer.h> #import <SOGo/SOGoUser.h> #import <SOGo/SOGoUserManager.h> #import <Mailer/SOGoMailFolder.h> #import <Mailer/NSString+Mail.h> #import "MAPIStoreAttachment.h" #import "MAPIStoreAttachmentTable.h" #import "MAPIStoreContext.h" #import "MAPIStoreMailFolder.h" #import "MAPIStoreMIME.h" #import "MAPIStoreMapping.h" #import "MAPIStoreSamDBUtils.h" #import "MAPIStoreTypes.h" #import "MAPIStoreUserContext.h" #import "NSData+MAPIStore.h" #import "NSObject+MAPIStore.h" #import "NSString+MAPIStore.h" #import "SOGoMAPIObject.h" #import "MAPIStoreMailVolatileMessage.h" #undef DEBUG #include <mapistore/mapistore.h> #include <mapistore/mapistore_errors.h> static Class NSNumberK = Nil; static NSString *recTypes[] = { @"orig", @"to", @"cc", @"bcc" }; // // Useful extension that comes from Pantomime which is also // released under the LGPL. We should eventually merge // this with the same category found in SOPE's NGSmtpClient.m // or simply drop sope-mime in favor of Pantomime // @interface NSMutableData (DataCleanupExtension) - (NSRange) rangeOfCString: (const char *) theCString; - (NSRange) rangeOfCString: (const char *) theCString options: (unsigned int) theOptions range: (NSRange) theRange; @end @implementation NSMutableData (DataCleanupExtension) - (NSRange) rangeOfCString: (const char *) theCString { return [self rangeOfCString: theCString options: 0 range: NSMakeRange(0,[self length])]; } -(NSRange) rangeOfCString: (const char *) theCString options: (unsigned int) theOptions range: (NSRange) theRange { const char *b, *bytes; int i, len, slen; if (!theCString) { return NSMakeRange(NSNotFound,0); } bytes = [self bytes]; len = [self length]; slen = strlen(theCString); b = bytes; if (len > theRange.location + theRange.length) { len = theRange.location + theRange.length; } if (theOptions == NSCaseInsensitiveSearch) { i = theRange.location; b += i; for (; i <= len-slen; i++, b++) { if (!strncasecmp(theCString,b,slen)) { return NSMakeRange(i,slen); } } } else { i = theRange.location; b += i; for (; i <= len-slen; i++, b++) { if (!memcmp(theCString,b,slen)) { return NSMakeRange(i,slen); } } } return NSMakeRange(NSNotFound,0); } @end @interface MAPIStoreAttachment (MAPIStoreMIME) - (BOOL) hasContentId; - (NGMimeBodyPart *) asMIMEBodyPart; @end @implementation MAPIStoreAttachment (MAPIStoreMIME) - (BOOL) hasContentId { return ([properties objectForKey: MAPIPropertyKey (PR_ATTACH_CONTENT_ID_UNICODE)] != nil); } - (NGMimeBodyPart *) asMIMEBodyPart { NGMimeBodyPart *bodyPart = nil; NSString *filename, *mimeType, *baseDisposition, *contentType, *contentDisposition, *contentId; NSData *content; struct mapistore_connection_info *connInfo; SOGoDomainDefaults *dd; SOGoUser *activeUser; NGMutableHashMap *map; content = [properties objectForKey: MAPIPropertyKey (PR_ATTACH_DATA_BIN)]; if (content) { filename = [properties objectForKey: MAPIPropertyKey (PR_ATTACH_LONG_FILENAME_UNICODE)]; if (![filename length]) filename = [properties objectForKey: MAPIPropertyKey (PR_ATTACH_FILENAME_UNICODE)]; mimeType = [properties objectForKey: MAPIPropertyKey (PR_ATTACH_MIME_TAG_UNICODE)]; if (!mimeType && [filename length]) mimeType = [[MAPIStoreMIME sharedMAPIStoreMIME] mimeTypeForExtension: [filename pathExtension]]; if (!mimeType) mimeType = @"application/octet-stream"; if ([mimeType hasPrefix: @"text/"]) { connInfo = [[self context] connectionInfo]; activeUser = [SOGoUser userWithLogin: [NSString stringWithUTF8String: connInfo->username]]; dd = [activeUser domainDefaults]; baseDisposition = ([dd mailAttachTextDocumentsInline] ? @"inline" : @"attachment"); } else if ([mimeType hasPrefix: @"image/"] || [mimeType hasPrefix: @"message"]) baseDisposition = @"inline"; else baseDisposition = @"attachment"; if ([filename length] > 0) { contentType = [NSString stringWithFormat: @"%@; name=\"%@\"", mimeType, filename]; contentDisposition = [NSString stringWithFormat: @"%@; filename=\"%@\"", baseDisposition, filename]; } else { contentType = mimeType; contentDisposition = baseDisposition; } map = [[NGMutableHashMap alloc] initWithCapacity: 16]; [map addObject: contentType forKey: @"content-type"]; [map addObject: contentDisposition forKey: @"content-disposition"]; contentId = [properties objectForKey: MAPIPropertyKey (PR_ATTACH_CONTENT_ID_UNICODE)]; if (contentId) [map setObject: [NSString stringWithFormat: @"<%@>", contentId] forKey: @"content-id"]; bodyPart = [NGMimeBodyPart bodyPartWithHeader: map]; [bodyPart setBody: content]; [map release]; } else [self errorWithFormat: @"no content for attachment"]; return bodyPart; } @end @implementation MAPIStoreMailVolatileMessage + (void) initialize { NSNumberK = [NSNumber class]; } - (id) initWithSOGoObject: (id) newSOGoObject inContainer: (MAPIStoreObject *) newContainer { if ((self = [super initWithSOGoObject: newSOGoObject inContainer: newContainer])) { ASSIGN (properties, [sogoObject properties]); } return self; } - (void) addProperties: (NSDictionary *) newProperties { [super addProperties: newProperties]; [sogoObject adjustLastModified]; } - (BOOL) canGetProperty: (enum MAPITAGS) propTag { return ([super canGetProperty: propTag] || [properties objectForKey: MAPIPropertyKey (propTag)] != nil); } - (uint64_t) objectVersion { NSNumber *version; version = [properties objectForKey: @"version"]; return (version ? exchange_globcnt ([version unsignedLongLongValue]) : ULLONG_MAX); } - (int) getPidTagMessageClass: (void **) data inMemCtx: (TALLOC_CTX *) memCtx { *data = [@"IPM.Note" asUnicodeInMemCtx: memCtx]; return MAPISTORE_SUCCESS; } - (int) getPidTagChangeKey: (void **) data inMemCtx: (TALLOC_CTX *) memCtx { NSData *changeKey; int rc; changeKey = [properties objectForKey: MAPIPropertyKey (PR_CHANGE_KEY)]; if (changeKey) { *data = [changeKey asBinaryInMemCtx: memCtx]; rc = MAPISTORE_SUCCESS; } else rc = [super getPidTagChangeKey: data inMemCtx: memCtx]; return rc; } - (NSDate *) creationTime { return [sogoObject creationDate]; } - (NSDate *) lastModificationTime { return [sogoObject lastModified]; } - (id) lookupAttachment: (NSString *) childKey { return [attachmentParts objectForKey: childKey]; } - (void) getMessageData: (struct mapistore_message **) dataPtr inMemCtx: (TALLOC_CTX *) memCtx { NSArray *recipients; NSUInteger count, max, recipientsMax, p, current; NSString *username, *cn, *email; NSData *entryId; NSDictionary *allRecipients, *dict, *contactInfos; SOGoUserManager *mgr; struct ldb_context *samCtx; struct mapistore_message *msgData; struct mapistore_message_recipient *recipient; enum ulRecipClass type; samCtx = [[self context] connectionInfo]->sam_ctx; // [super getMessageData: &msgData inMemCtx: memCtx]; msgData = talloc_zero (memCtx, struct mapistore_message); allRecipients = [properties objectForKey: @"recipients"]; msgData->columns = set_SPropTagArray (msgData, 9, PR_OBJECT_TYPE, PR_DISPLAY_TYPE, PR_7BIT_DISPLAY_NAME_UNICODE, PR_SMTP_ADDRESS_UNICODE, PR_SEND_INTERNET_ENCODING, PR_RECIPIENT_DISPLAY_NAME_UNICODE, PR_RECIPIENT_FLAGS, PR_RECIPIENT_ENTRYID, PR_RECIPIENT_TRACKSTATUS); /* Retrieve recipients from the message */ max = ([[allRecipients objectForKey: @"orig"] count] + [[allRecipients objectForKey: @"to"] count] + [[allRecipients objectForKey: @"cc"] count] + [[allRecipients objectForKey: @"bcc"] count]); mgr = [SOGoUserManager sharedUserManager]; msgData->recipients_count = max; msgData->recipients = talloc_array (msgData, struct mapistore_message_recipient, max); current = 0; for (type = 0; type < 4; type++) { recipients = [allRecipients objectForKey: recTypes[type]]; recipientsMax = [recipients count]; for (count = 0; count < recipientsMax; count++) { recipient = msgData->recipients + current; recipient->type = type; dict = [recipients objectAtIndex: count]; cn = [dict objectForKey: @"fullName"]; email = [dict objectForKey: @"email"]; contactInfos = [mgr contactInfosForUserWithUIDorEmail: email]; if (contactInfos) { username = [contactInfos objectForKey: @"c_uid"]; recipient->username = [username asUnicodeInMemCtx: msgData]; entryId = MAPIStoreInternalEntryId (samCtx, username); } else { recipient->username = NULL; entryId = MAPIStoreExternalEntryId (cn, email); } /* properties */ p = 0; recipient->data = talloc_array (msgData, void *, msgData->columns->cValues); memset (recipient->data, 0, msgData->columns->cValues * sizeof (void *)); // PR_OBJECT_TYPE = MAPI_MAILUSER (see MAPI_OBJTYPE) recipient->data[p] = MAPILongValue (msgData, MAPI_MAILUSER); p++; // PR_DISPLAY_TYPE = DT_MAILUSER (see MS-NSPI) recipient->data[p] = MAPILongValue (msgData, 0); p++; // PR_7BIT_DISPLAY_NAME_UNICODE recipient->data[p] = [cn asUnicodeInMemCtx: msgData]; p++; // PR_SMTP_ADDRESS_UNICODE recipient->data[p] = [email asUnicodeInMemCtx: msgData]; p++; // PR_SEND_INTERNET_ENCODING = 0x00060000 (plain text, see OXCMAIL) recipient->data[p] = MAPILongValue (msgData, 0x00060000); p++; // PR_RECIPIENT_DISPLAY_NAME_UNICODE recipient->data[p] = [cn asUnicodeInMemCtx: msgData]; p++; // PR_RECIPIENT_FLAGS recipient->data[p] = MAPILongValue (msgData, 0x01); p++; // PR_RECIPIENT_ENTRYID recipient->data[p] = [entryId asBinaryInMemCtx: msgData]; p++; // PR_RECIPIENT_TRACKSTATUS recipient->data[p] = MAPILongValue (msgData, 0x00); p++; current++; } } *dataPtr = msgData; } static inline NSString * MakeRecipientString (NSDictionary *recipient) { NSString *fullName, *email, *fullEmail; fullName = [recipient objectForKey: @"fullName"]; NSLog (@"tfu fullName %@", fullName); email = [recipient objectForKey: @"email"]; NSLog (@"tfu email %@", email); if ([email length] > 0) { if ([fullName length] > 0) fullEmail = [NSString stringWithFormat: @"%@ <%@>", fullName, email]; else fullEmail = email; } else { NSLog (@"recipient not generated from record: %@", recipient); fullEmail = nil; } NSLog (@"tfu fullEmail %@", fullEmail); return fullEmail; } static inline NSArray * MakeRecipientsList (NSArray *recipients) { NSMutableArray *list; NSUInteger count, max; NSString *recipient; max = [recipients count]; list = [NSMutableArray arrayWithCapacity: max]; for (count = 0; count < max; count++) { recipient = MakeRecipientString ([recipients objectAtIndex: count]); NSLog (@"tfu rv recipient: %@", recipient); if (recipient) [list addObject: recipient]; } return list; } static NSString * QuoteSpecials (NSString *address) { NSString *result, *part, *s2; int i, len; // We want to correctly send mails to recipients such as : // foo.bar // foo (bar) <foo@zot.com> // bar, foo <foo@zot.com> if ([address indexOf: '('] >= 0 || [address indexOf: ')'] >= 0 || [address indexOf: '<'] >= 0 || [address indexOf: '>'] >= 0 || [address indexOf: '@'] >= 0 || [address indexOf: ','] >= 0 || [address indexOf: ';'] >= 0 || [address indexOf: ':'] >= 0 || [address indexOf: '\\'] >= 0 || [address indexOf: '"'] >= 0 || [address indexOf: '.'] >= 0 || [address indexOf: '['] >= 0 || [address indexOf: ']'] >= 0) { // We search for the first instance of < from the end // and we quote what was before if we need to len = [address length]; i = -1; while (len--) if ([address characterAtIndex: len] == '<') { i = len; break; } if (i > 0) { part = [address substringToIndex: i - 1]; s2 = [[part stringByReplacingString: @"\\" withString: @"\\\\"] stringByReplacingString: @"\"" withString: @"\\\""]; result = [NSString stringWithFormat: @"\"%@\" %@", s2, [address substringFromIndex: i]]; } else { s2 = [[address stringByReplacingString: @"\\" withString: @"\\\\"] stringByReplacingString: @"\"" withString: @"\\\""]; result = [NSString stringWithFormat: @"\"%@\"", s2]; } } else result = address; NSLog (@"from string: %@", result); return result; } static inline void FillMessageHeadersFromProperties (NGMutableHashMap *headers, NSDictionary *mailProperties, BOOL withBcc, struct mapistore_connection_info *connInfo) { NSMutableString *subject; NSString *from, *recId, *messageId, *subjectData; NSArray *list; NSCalendarDate *date; NSDictionary *recipients; NSUInteger type, bccLimit; SOGoUser *activeUser; activeUser = [SOGoUser userWithLogin: [NSString stringWithUTF8String: connInfo->username]]; from = [NSString stringWithFormat: @"%@ <%@>", [activeUser cn], [[activeUser allEmails] objectAtIndex: 0]]; NSLog (@"from header: %@", from); [headers setObject: QuoteSpecials (from) forKey: @"from"]; /* save the recipients */ recipients = [mailProperties objectForKey: @"recipients"]; if (recipients) { if (withBcc) bccLimit = MAPI_BCC; else bccLimit = MAPI_CC; bccLimit++; for (type = MAPI_TO; type < bccLimit; type++) { recId = recTypes[type]; NSLog (@"tfu type: %@", recId); list = MakeRecipientsList ([recipients objectForKey: recId]); [headers setObjects: list forKey: recId]; } NSLog (@"fromxx recipients: %@", recipients); list = MakeRecipientsList ([recipients objectForKey: @"orig"]); NSLog (@"from tfutfutfu2: %@", list); if (list) [headers setObjects: list forKey: @"from"]; } else NSLog (@"message without recipients"); //tfu [headers setObject: QuoteSpecials (from) forKey: @"from"]; subject = [NSMutableString stringWithCapacity: 128]; subjectData = [mailProperties objectForKey: MAPIPropertyKey (PR_SUBJECT_PREFIX_UNICODE)]; if (subjectData) [subject appendString: subjectData]; subjectData = [mailProperties objectForKey: MAPIPropertyKey (PR_NORMALIZED_SUBJECT_UNICODE)]; if (subjectData) [subject appendString: subjectData]; [headers setObject: [subject asQPSubjectString: @"utf-8"] forKey: @"subject"]; messageId = [mailProperties objectForKey: MAPIPropertyKey (PR_INTERNET_MESSAGE_ID_UNICODE)]; if ([messageId length]) [headers setObject: messageId forKey: @"message-id"]; date = [mailProperties objectForKey: MAPIPropertyKey (PR_CLIENT_SUBMIT_TIME)]; NSLog (@"from subject: %@", subject); NSLog (@"from date: %@", date); if (date) { date = [date addYear: 0 month: 0 day: 0 hour: 0 minute: 0 second: [[date timeZone] secondsFromGMT]]; [headers addObject: [date rfc822DateString] forKey: @"date"]; } NSLog (@"from headerxx: %@", headers); [headers addObject: @"1.0" forKey: @"MIME-Version"]; } static NSArray * MakeAttachmentParts (NSDictionary *attachmentParts, BOOL withContentId) { NSMutableArray *attachmentMimeParts; NSArray *keys; MAPIStoreAttachment *attachment; NSUInteger count, max; NGMimeBodyPart *mimePart; keys = [attachmentParts allKeys]; max = [keys count]; attachmentMimeParts = [NSMutableArray arrayWithCapacity: max]; for (count = 0; count < max; count++) { attachment = [attachmentParts objectForKey: [keys objectAtIndex: count]]; if ([attachment hasContentId] == withContentId) { mimePart = [attachment asMIMEBodyPart]; if (mimePart) [attachmentMimeParts addObject: mimePart]; } } return attachmentMimeParts; } static inline id MakeTextPlainBody (NSDictionary *mailProperties, NSString **contentType) { id textPlainBody; textPlainBody = [[mailProperties objectForKey: MAPIPropertyKey (PR_BODY_UNICODE)] dataUsingEncoding: NSUTF8StringEncoding]; *contentType = @"text/plain; charset=utf-8"; return textPlainBody; } static inline id MakeTextHtmlBody (NSDictionary *mailProperties, NSDictionary *attachmentParts, NSString **contentType) { id textHtmlBody; NSData *htmlBody; NSString *charset, *htmlContentType; NSArray *parts; NSNumber *codePage; NGMimeBodyPart *htmlBodyPart; NGMutableHashMap *headers; NSUInteger count, max; htmlBody = [mailProperties objectForKey: MAPIPropertyKey (PR_HTML)]; if (htmlBody) { /* charset */ codePage = [mailProperties objectForKey: MAPIPropertyKey (PR_INTERNET_CPID)]; switch ([codePage intValue]) { case 20127: charset = @"us-ascii"; break; case 28605: charset = @"iso-8859-15"; break; case 65001: charset = @"utf-8"; break; case 28591: default: charset = @"iso-8859-1"; } htmlContentType = [NSString stringWithFormat: @"text/html; charset=%@", charset]; parts = MakeAttachmentParts (attachmentParts, YES); max = [parts count]; if (max > 0) { textHtmlBody = [NGMimeMultipartBody new]; [textHtmlBody autorelease]; headers = [[NGMutableHashMap alloc] initWithCapacity: 1]; [headers setObject: htmlContentType forKey: @"content-type"]; htmlBodyPart = [NGMimeBodyPart bodyPartWithHeader: headers]; [htmlBodyPart setBody: htmlBody]; [headers release]; [textHtmlBody addBodyPart: htmlBodyPart]; for (count = 0; count < max; count++) [textHtmlBody addBodyPart: [parts objectAtIndex: count]]; *contentType = @"multipart/related"; } else { textHtmlBody = htmlBody; *contentType = htmlContentType; } } else textHtmlBody = nil; return textHtmlBody; } static inline id MakeTextPartBody (NSDictionary *mailProperties, NSDictionary *attachmentParts, NSString **contentType) { id textBody, textPlainBody, textHtmlBody; NSString *textPlainContentType, *textHtmlContentType; NGMutableHashMap *headers; NGMimeBodyPart *bodyPart; textPlainBody = MakeTextPlainBody (mailProperties, &textPlainContentType); textHtmlBody = MakeTextHtmlBody (mailProperties, attachmentParts, &textHtmlContentType); if (textPlainBody) { if (textHtmlBody) { textBody = [NGMimeMultipartBody new]; [textBody autorelease]; headers = [[NGMutableHashMap alloc] initWithCapacity: 1]; [headers setObject: textHtmlContentType forKey: @"content-type"]; bodyPart = [NGMimeBodyPart bodyPartWithHeader: headers]; [bodyPart setBody: textHtmlBody]; [headers release]; [textBody addBodyPart: bodyPart]; headers = [[NGMutableHashMap alloc] initWithCapacity: 1]; [headers setObject: textPlainContentType forKey: @"content-type"]; bodyPart = [NGMimeBodyPart bodyPartWithHeader: headers]; [bodyPart setBody: textPlainBody]; [headers release]; [textBody addBodyPart: bodyPart]; *contentType = @"multipart/alternative"; } else { textBody = textPlainBody; *contentType = textPlainContentType; } } else { textBody = textHtmlBody; *contentType = textHtmlContentType; } return textBody; } // static id // MakeMessageBody (NSDictionary *mailProperties, NSDictionary *attachmentParts, // NSString **contentType) static id MakeMessageBody (NSDictionary *mailProperties, NSDictionary *attachmentParts, NSString **contentType) { id messageBody, textBody; NSString *textContentType; NSArray *parts; NGMimeBodyPart *textBodyPart; NGMutableHashMap *headers; NSUInteger count, max; textBody = MakeTextPartBody (mailProperties, attachmentParts, &textContentType); parts = MakeAttachmentParts (attachmentParts, NO); max = [parts count]; if (max > 0) { messageBody = [NGMimeMultipartBody new]; [messageBody autorelease]; if (textBody) { headers = [[NGMutableHashMap alloc] initWithCapacity: 1]; [headers setObject: textContentType forKey: @"content-type"]; textBodyPart = [NGMimeBodyPart bodyPartWithHeader: headers]; [textBodyPart setBody: textBody]; [headers release]; [messageBody addBodyPart: textBodyPart]; } for (count = 0; count < max; count++) [messageBody addBodyPart: [parts objectAtIndex: count]]; *contentType = @"multipart/mixed"; } else { messageBody = textBody; *contentType = textContentType; } return messageBody; } - (NGMimeMessage *) _generateMessageWithBcc: (BOOL) withBcc { NSString *contentType; NGMimeMessage *message; NGMutableHashMap *headers; id messageBody; headers = [[NGMutableHashMap alloc] initWithCapacity: 16]; FillMessageHeadersFromProperties (headers, properties, withBcc, [[self context] connectionInfo]); message = [[NGMimeMessage alloc] initWithHeader: headers]; [message autorelease]; [headers release]; messageBody = MakeMessageBody (properties, attachmentParts, &contentType); if (messageBody) { [headers setObject: contentType forKey: @"content-type"]; [message setBody: messageBody]; } return message; } - (NSData *) _generateMailDataWithBcc: (BOOL) withBcc { NGMimeMessage *message; NGMimeMessageGenerator *generator; NSData *messageData; /* mime message generation */ generator = [NGMimeMessageGenerator new]; message = [self _generateMessageWithBcc: withBcc]; messageData = [generator generateMimeFromPart: message]; [generator release]; [messageData writeToFile: @"/tmp/mimegen.eml" atomically: NO]; return messageData; } - (int) submitWithFlags: (enum SubmitFlags) flags { NSDictionary *recipients; NSData *messageData; NSMutableArray *recipientEmails; NSArray *list; NSString *recId, *from, *msgClass; NSUInteger count; SOGoUser *activeUser; SOGoDomainDefaults *dd; NSException *error; WOContext *woContext; id <SOGoAuthenticator> authenticator; msgClass = [properties objectForKey: MAPIPropertyKey (PidTagMessageClass)]; if ([msgClass isEqualToString: @"IPM.Note"]) /* we skip invitation replies */ { /* send mail */ messageData = [self _generateMailDataWithBcc: NO]; recipientEmails = [NSMutableArray arrayWithCapacity: 32]; recipients = [properties objectForKey: @"recipients"]; for (count = 0; count < 3; count++) { recId = recTypes[count]; list = [recipients objectForKey: recId]; [recipientEmails addObjectsFromArray: [list objectsForKey: @"email" notFoundMarker: nil]]; } activeUser = [[self context] activeUser]; dd = [activeUser domainDefaults]; from = [[activeUser allEmails] objectAtIndex: 0]; woContext = [[self userContext] woContext]; authenticator = [sogoObject authenticatorInContext: woContext]; error = [[SOGoMailer mailerWithDomainDefaults: dd] sendMailData: messageData toRecipients: recipientEmails sender: from withAuthenticator: authenticator inContext: woContext]; if (error) [self logWithFormat: @"an error occurred: '%@'", error]; // mapping = [self mapping]; // [mapping unregisterURLWithID: [self objectId]]; // [self setIsNew: NO]; // [properties removeAllObjects]; [(MAPIStoreMailFolder *) [self container] cleanupCaches]; } else [self logWithFormat: @"skipping submit of message with class '%@'", msgClass]; return MAPISTORE_SUCCESS; } - (void) save { NSString *folderName, *flag, *newIdString, *messageKey; NSData *changeKey, *messageData; NGImap4Connection *connection; NGImap4Client *client; SOGoMailFolder *containerFolder; NSDictionary *result, *responseResult; MAPIStoreMapping *mapping; uint64_t mid; messageData = [self _generateMailDataWithBcc: YES]; /* appending to imap folder */ containerFolder = [container sogoObject]; connection = [containerFolder imap4Connection]; client = [connection client]; folderName = [connection imap4FolderNameForURL: [containerFolder imap4URL]]; result = [client append: messageData toFolder: folderName withFlags: [NSArray arrayWithObjects: @"seen", nil]]; if ([[result objectForKey: @"result"] boolValue]) { /* we reregister the new message URL with the id mapper */ responseResult = [[result objectForKey: @"RawResponse"] objectForKey: @"ResponseResult"]; flag = [responseResult objectForKey: @"flag"]; newIdString = [[flag componentsSeparatedByString: @" "] objectAtIndex: 2]; mapping = [self mapping]; mid = [self objectId]; [mapping unregisterURLWithID: mid]; // [sogoObject setNameInContainer: ]; messageKey = [NSString stringWithFormat: @"%@.eml", newIdString]; [sogoObject setNameInContainer: messageKey]; [mapping registerURL: [self url] withID: mid]; /* synchronise the cache and update the change key with the one provided by the client */ [(MAPIStoreMailFolder *) container synchroniseCache]; changeKey = [properties objectForKey: MAPIPropertyKey (PR_CHANGE_KEY)]; if (changeKey) [(MAPIStoreMailFolder *) container setChangeKey: changeKey forMessageWithKey: messageKey]; } } @end |
2012-11-19 19:15
|
|
Please try this patch: --- a/OpenChange/MAPIStoreMailVolatileMessage.m
|
|
Patch works -> sender (from header) is displayed in outlook |
|
Fix pushed: https://github.com/inverse-inc/sogo/commit/cc98664d130d08d9c65c0dde332f334bda6e51e2 Thanks for your excellent feedback on this bug, keep up with the good work! |
|
Date Modified | Username | Field | Change |
---|---|---|---|
2012-10-12 13:46 | gyurco | New Issue | |
2012-10-12 13:46 | gyurco | File Added: 3063.gz | |
2012-10-12 14:02 |
|
Note Added: 0004624 | |
2012-10-12 19:42 | gyurco | Note Added: 0004627 | |
2012-10-25 16:38 | lmo566 | Note Added: 0004706 | |
2012-10-25 21:38 | lmo566 | Note Edited: 0004706 | |
2012-11-14 15:28 | gyurco | File Added: sogo1.jpg | |
2012-11-14 15:28 | gyurco | File Added: sogo2.jpg | |
2012-11-14 15:30 | gyurco | Note Added: 0004847 | |
2012-11-14 16:24 | lmo566 | Note Added: 0004848 | |
2012-11-19 08:46 | tfu | Note Added: 0004903 | |
2012-11-19 18:09 | ludovic | Note Added: 0004914 | |
2012-11-19 19:13 | tfu | Note Added: 0004922 | |
2012-11-19 19:14 | tfu | File Added: MAPIStoreMailVolatileMessage.m.txt | |
2012-11-19 19:15 | tfu | File Added: samba.log | |
2012-11-19 19:16 | tfu | Note Edited: 0004922 | |
2012-11-20 14:17 | ludovic | Note Added: 0004935 | |
2012-11-20 16:52 | ludovic | Relationship added | has duplicate 0002084 |
2012-11-20 20:08 | tfu | Note Added: 0004942 | |
2012-11-20 20:39 | ludovic | Note Added: 0004943 | |
2012-11-20 20:39 | ludovic | Status | new => closed |
2012-11-20 20:39 | ludovic | Resolution | open => fixed |
2012-11-20 20:39 | ludovic | Fixed in Version | => trunk |
2012-11-20 20:40 | ludovic | Project | SOGo Native Outlook Compatibility (obsolete) => SOGo |
2012-11-20 20:41 | ludovic | Category | => Apple iCal.app |
2012-11-20 20:41 | ludovic | Fixed in Version | trunk => 2.0.3 |
2012-11-20 20:41 | ludovic | Target Version | => 2.0.3 |
2014-09-26 18:08 | ludovic | Category | Apple iCal.app => Apple Calendar (Mac OS X) |