Files
MailCore/Source/CTCoreMessage.m
T

743 lines
23 KiB
Objective-C

/*
* MailCore
*
* Copyright (C) 2007 - Matt Ronge
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the MailCore project nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#import "CTCoreMessage.h"
#import "CTCoreFolder.h"
#import "MailCoreTypes.h"
#import "CTCoreAddress.h"
#import "CTMIMEFactory.h"
#import "CTMIME_MessagePart.h"
#import "CTMIME_TextPart.h"
#import "CTMIME_MultiPart.h"
#import "CTMIME_SinglePart.h"
#import "CTBareAttachment.h"
#import "CTMIME_HtmlPart.h"
@interface CTCoreMessage (Private)
- (CTCoreAddress *)_addressFromMailbox:(struct mailimf_mailbox *)mailbox;
- (NSSet *)_addressListFromMailboxList:(struct mailimf_mailbox_list *)mailboxList;
- (struct mailimf_mailbox_list *)_mailboxListFromAddressList:(NSSet *)addresses;
- (NSSet *)_addressListFromIMFAddressList:(struct mailimf_address_list *)imfList;
- (struct mailimf_address_list *)_IMFAddressListFromAddresssList:(NSSet *)addresses;
- (void)_buildUpBodyText:(CTMIME *)mime result:(NSMutableString *)result;
- (void)_buildUpHtmlBodyText:(CTMIME *)mime result:(NSMutableString *)result;
- (NSString *)_decodeMIMEPhrase:(char *)data;
@end
//TODO Add encode of subjects/from/to
//TODO Add decode of to/from ...
/*
char * etpan_encode_mime_header(char * phrase)
{
return
etpan_make_quoted_printable(DEFAULT_DISPLAY_CHARSET,
phrase);
}
*/
@implementation CTCoreMessage
@synthesize mime=myParsedMIME;
- (id)init {
[super init];
if (self) {
struct mailimf_fields *fields = mailimf_fields_new_empty();
myFields = mailimf_single_fields_new(fields);
mailimf_fields_free(fields);
}
return self;
}
- (id)initWithMessageStruct:(struct mailmessage *)message {
self = [super init];
if (self) {
assert(message != NULL);
myMessage = message;
myFields = mailimf_single_fields_new(message->msg_fields);
}
return self;
}
- (id)initWithFileAtPath:(NSString *)path {
return [self initWithString:[NSString stringWithContentsOfFile:path encoding:NSUTF8StringEncoding error:NULL]];
}
- (id)initWithString:(NSString *)msgData {
struct mailmessage *msg = data_message_init((char *)[msgData cStringUsingEncoding:NSUTF8StringEncoding],
[msgData lengthOfBytesUsingEncoding:NSUTF8StringEncoding]);
int err;
struct mailmime *dummyMime;
/* mailmessage_get_bodystructure will fill the mailmessage struct for us */
err = mailmessage_get_bodystructure(msg, &dummyMime);
assert(err == 0);
return [self initWithMessageStruct:msg];
}
- (void)dealloc {
if (myMessage != NULL) {
mailmessage_flush(myMessage);
mailmessage_free(myMessage);
}
if (myFields != NULL) {
mailimf_single_fields_free(myFields);
}
[myParsedMIME release];
[super dealloc];
}
- (int)fetchBody {
int err;
struct mailmime *dummyMime;
//Retrieve message mime and message field
err = mailmessage_get_bodystructure(myMessage, &dummyMime);
if(err != 0) { // added by gabor
return err;
}
myParsedMIME = [[CTMIMEFactory createMIMEWithMIMEStruct:[self messageStruct]->msg_mime
forMessage:[self messageStruct]] retain];
return 0;
}
- (NSString *)body {
NSMutableString *result = [NSMutableString string];
[self _buildUpBodyText:myParsedMIME result:result];
return result;
}
- (NSString *)htmlBody {
// added by Gabor
NSMutableString *result = [NSMutableString string];
[self _buildUpHtmlBodyText:myParsedMIME result:result];
return result;
}
- (NSString *)editableHtmlBody{
//added by KK
NSMutableString *result = [NSMutableString string];
[self _buildUpHtmlBodyText:myParsedMIME result:result];
NSString *str = [NSString stringWithFormat:@"<div id = 'myDiv' contentEditable>"];
str = [str stringByAppendingFormat:@"%@",[NSString stringWithString:result]];
str = [str stringByAppendingString:@"</div>"];
//Used For Getting changed content
str = [str stringByAppendingString:@"<script type = 'text/javascript'> function getHtmlContent() { return document.getElementById('myDiv').innerHTML;}</script>"];
return str;
}
- (NSString *)bodyPreferringPlainText {
NSString *body = [self body];
if ([body length] == 0) {
body = [self htmlBody];
}
return body;
}
- (void)_buildUpBodyText:(CTMIME *)mime result:(NSMutableString *)result {
if (mime == nil)
return;
if ([mime isKindOfClass:[CTMIME_MessagePart class]]) {
[self _buildUpBodyText:[mime content] result:result];
}
else if ([mime isKindOfClass:[CTMIME_TextPart class]]) {
if ([mime.contentType isEqualToString:@"text/plain"]) {
[(CTMIME_TextPart *)mime fetchPart];
NSString* y = [mime content];
if(y != nil) {
[result appendString:y];
}
}
}
else if ([mime isKindOfClass:[CTMIME_MultiPart class]]) {
//TODO need to take into account the different kinds of multipart
NSEnumerator *enumer = [[mime content] objectEnumerator];
CTMIME *subpart;
while ((subpart = [enumer nextObject])) {
[self _buildUpBodyText:subpart result:result];
}
}
}
- (void)_buildUpHtmlBodyText:(CTMIME *)mime result:(NSMutableString *)result {
if (mime == nil)
return;
if ([mime isKindOfClass:[CTMIME_MessagePart class]]) {
[self _buildUpHtmlBodyText:[mime content] result:result];
}
else if ([mime isKindOfClass:[CTMIME_TextPart class]]) {
if ([mime.contentType isEqualToString:@"text/html"]) {
[(CTMIME_TextPart *)mime fetchPart];
NSString* y = [mime content];
if(y != nil) {
[result appendString:y];
}
}
}
else if ([mime isKindOfClass:[CTMIME_MultiPart class]]) {
//TODO need to take into account the different kinds of multipart
NSEnumerator *enumer = [[mime content] objectEnumerator];
CTMIME *subpart;
while ((subpart = [enumer nextObject])) {
[self _buildUpHtmlBodyText:subpart result:result];
}
}
}
- (void)setBody:(NSString *)body {
CTMIME *oldMIME = myParsedMIME;
CTMIME_TextPart *text = [CTMIME_TextPart mimeTextPartWithString:body];
// If myParsedMIME is already a multi-part mime, just add it. otherwise replace it.
//TODO: If setBody is called multiple times it will add text parts multiple times. Instead
// it should find the existing text part (if there is one) and replace it
if ([myParsedMIME isKindOfClass:[CTMIME_MultiPart class]]) {
[(CTMIME_MultiPart *)myParsedMIME addMIMEPart:text];
} else {
CTMIME_MessagePart *messagePart = [CTMIME_MessagePart mimeMessagePartWithContent:text];
myParsedMIME = [messagePart retain];
[oldMIME release];
}
}
- (void) setHTMLBody:(NSString *)body{
CTMIME *oldMIME = myParsedMIME;
CTMIME_HtmlPart *text = [CTMIME_HtmlPart mimeTextPartWithString:body];
CTMIME_MessagePart *messagePart = [CTMIME_MessagePart mimeMessagePartWithContent:text];
myParsedMIME = [messagePart retain];
[oldMIME release];
}
- (NSArray *)attachments {
NSMutableArray *attachments = [NSMutableArray array];
CTMIME_Enumerator *enumerator = [myParsedMIME mimeEnumerator];
CTMIME *mime;
while ((mime = [enumerator nextObject])) {
if ([mime isKindOfClass:[CTMIME_SinglePart class]]) {
CTMIME_SinglePart *singlePart = (CTMIME_SinglePart *)mime;
if (singlePart.attached) {
CTBareAttachment *attach = [[CTBareAttachment alloc]
initWithMIMESinglePart:singlePart];
[attachments addObject:attach];
[attach release];
}
}
}
return attachments;
}
- (void)addAttachment:(CTCoreAttachment *)attachment {
CTMIME_MultiPart *multi;
CTMIME_MessagePart *msg;
if ([myParsedMIME isKindOfClass:[CTMIME_MessagePart class]]) {
msg = (CTMIME_MessagePart *)myParsedMIME;
CTMIME *sub = [msg content];
// Creat new multimime part if needed
if ([sub isKindOfClass:[CTMIME_MultiPart class]]) {
multi = (CTMIME_MultiPart *)sub;
} else {
multi = [CTMIME_MultiPart mimeMultiPart];
[multi addMIMEPart:sub];
[msg setContent:multi];
}
// add new SinglePart which encodes the attachment in base64
CTMIME_SinglePart *attpart = [CTMIME_SinglePart mimeSinglePartWithData:[attachment data]];
attpart.contentType = [attachment contentType];
attpart.filename = [attachment filename];
[multi addMIMEPart:attpart];
}
}
- (NSString *)subject {
if (myFields->fld_subject == NULL)
return @"";
NSString *decodedSubject = [self _decodeMIMEPhrase:myFields->fld_subject->sbj_value];
if (decodedSubject == nil)
return @"";
return decodedSubject;
}
- (void)setSubject:(NSString *)subject {
struct mailimf_subject *subjectStruct;
subjectStruct = mailimf_subject_new(strdup([subject cStringUsingEncoding:NSUTF8StringEncoding]));
if (myFields->fld_subject != NULL)
mailimf_subject_free(myFields->fld_subject);
myFields->fld_subject = subjectStruct;
}
- (struct mailimf_date_time*)libetpanDateTime {
if(!myFields || !myFields->fld_orig_date || !myFields->fld_orig_date->dt_date_time)
return NULL;
return myFields->fld_orig_date->dt_date_time;
}
- (NSTimeZone*)senderTimeZone {
struct mailimf_date_time *d;
if((d = [self libetpanDateTime]) == NULL)
return nil;
NSInteger timezoneOffsetInSeconds = 3600*d->dt_zone/100;
return [NSTimeZone timeZoneForSecondsFromGMT:timezoneOffsetInSeconds];
}
- (NSDate *)senderDate {
if ( myFields->fld_orig_date == NULL) {
return [NSDate distantPast];
}
else {
struct mailimf_date_time *d;
if((d = [self libetpanDateTime]) == NULL)
return nil;
NSCalendar *calendar = [[NSCalendar alloc] initWithCalendarIdentifier:NSGregorianCalendar];
NSDateComponents *comps = [[NSDateComponents alloc] init];
[comps setYear:d->dt_year];
[comps setMonth:d->dt_month];
[comps setDay:d->dt_day];
[comps setHour:d->dt_hour];
[comps setMinute:d->dt_min];
[comps setSecond:d->dt_sec];
NSDate *messageDateNoTimezone = [calendar dateFromComponents:comps];
[comps release];
[calendar release];
// no timezone applied
return messageDateNoTimezone;
}
}
- (NSDate *)sentDateGMT {
struct mailimf_date_time *d;
if((d = [self libetpanDateTime]) == NULL)
return nil;
NSInteger timezoneOffsetInSeconds = 3600*d->dt_zone/100;
NSDate *date = [self senderDate];
return [date addTimeInterval:timezoneOffsetInSeconds * -1];
}
- (NSDate*)sentDateLocalTimeZone {
return [[self sentDateGMT] addTimeInterval:[[NSTimeZone localTimeZone] secondsFromGMT]];
}
- (BOOL)isUnread {
struct mail_flags *flags = myMessage->msg_flags;
if (flags != NULL) {
BOOL flag_seen = (flags->fl_flags & MAIL_FLAG_SEEN);
return !flag_seen;
}
return NO;
}
- (BOOL)isNew {
struct mail_flags *flags = myMessage->msg_flags;
if (flags != NULL) {
BOOL flag_seen = (flags->fl_flags & MAIL_FLAG_SEEN);
BOOL flag_new = (flags->fl_flags & MAIL_FLAG_NEW);
return !flag_seen && flag_new;
}
return NO;
}
- (NSString *)messageId {
if (myFields->fld_message_id != NULL) {
char *value = myFields->fld_message_id->mid_value;
return [NSString stringWithCString:value encoding:NSUTF8StringEncoding];
}
return nil;
}
- (NSString *)uid {
return [NSString stringWithCString:myMessage->msg_uid encoding:NSUTF8StringEncoding];
}
- (NSUInteger)messageSize {
return [self messageStruct]->msg_size;
}
- (NSUInteger)sequenceNumber {
return mySequenceNumber;
}
- (void)setSequenceNumber:(NSUInteger)sequenceNumber {
mySequenceNumber = sequenceNumber;
}
- (NSSet *)from {
if (myFields->fld_from == NULL)
return [NSSet set]; //Return just an empty set
return [self _addressListFromMailboxList:myFields->fld_from->frm_mb_list];
}
- (void)setFrom:(NSSet *)addresses {
struct mailimf_mailbox_list *imf = [self _mailboxListFromAddressList:addresses];
if (myFields->fld_from != NULL)
mailimf_from_free(myFields->fld_from);
myFields->fld_from = mailimf_from_new(imf);
}
- (CTCoreAddress *)sender {
if (myFields->fld_sender == NULL)
return [CTCoreAddress address];
return [self _addressFromMailbox:myFields->fld_sender->snd_mb];
}
- (NSSet *)to {
if (myFields->fld_to == NULL)
return [NSSet set];
else
return [self _addressListFromIMFAddressList:myFields->fld_to->to_addr_list];
}
- (void)setTo:(NSSet *)addresses {
struct mailimf_address_list *imf = [self _IMFAddressListFromAddresssList:addresses];
if (myFields->fld_to != NULL) {
mailimf_address_list_free(myFields->fld_to->to_addr_list);
myFields->fld_to->to_addr_list = imf;
}
else
myFields->fld_to = mailimf_to_new(imf);
}
- (NSSet *)cc {
if (myFields->fld_cc == NULL)
return [NSSet set];
else
return [self _addressListFromIMFAddressList:myFields->fld_cc->cc_addr_list];
}
- (void)setCc:(NSSet *)addresses {
struct mailimf_address_list *imf = [self _IMFAddressListFromAddresssList:addresses];
if (myFields->fld_cc != NULL) {
mailimf_address_list_free(myFields->fld_cc->cc_addr_list);
myFields->fld_cc->cc_addr_list = imf;
}
else
myFields->fld_cc = mailimf_cc_new(imf);
}
- (NSSet *)bcc {
if (myFields->fld_bcc == NULL)
return [NSSet set];
else
return [self _addressListFromIMFAddressList:myFields->fld_bcc->bcc_addr_list];
}
- (void)setBcc:(NSSet *)addresses {
struct mailimf_address_list *imf = [self _IMFAddressListFromAddresssList:addresses];
if (myFields->fld_bcc != NULL) {
mailimf_address_list_free(myFields->fld_bcc->bcc_addr_list);
myFields->fld_bcc->bcc_addr_list = imf;
}
else
myFields->fld_bcc = mailimf_bcc_new(imf);
}
- (NSSet *)replyTo {
if (myFields->fld_reply_to == NULL)
return [NSSet set];
else
return [self _addressListFromIMFAddressList:myFields->fld_reply_to->rt_addr_list];
}
- (void)setReplyTo:(NSSet *)addresses {
struct mailimf_address_list *imf = [self _IMFAddressListFromAddresssList:addresses];
if (myFields->fld_reply_to != NULL) {
mailimf_address_list_free(myFields->fld_reply_to->rt_addr_list);
myFields->fld_reply_to->rt_addr_list = imf;
}
else
myFields->fld_reply_to = mailimf_reply_to_new(imf);
}
- (NSString *)render {
CTMIME *msgPart = myParsedMIME;
if ([myParsedMIME isKindOfClass:[CTMIME_MessagePart class]]) {
/* It's a message part, so let's set it's fields */
struct mailimf_fields *fields;
struct mailimf_mailbox *sender = (myFields->fld_sender != NULL) ? (myFields->fld_sender->snd_mb) : NULL;
struct mailimf_mailbox_list *from = (myFields->fld_from != NULL) ? (myFields->fld_from->frm_mb_list) : NULL;
struct mailimf_address_list *replyTo = (myFields->fld_reply_to != NULL) ? (myFields->fld_reply_to->rt_addr_list) : NULL;
struct mailimf_address_list *to = (myFields->fld_to != NULL) ? (myFields->fld_to->to_addr_list) : NULL;
struct mailimf_address_list *cc = (myFields->fld_cc != NULL) ? (myFields->fld_cc->cc_addr_list) : NULL;
struct mailimf_address_list *bcc = (myFields->fld_bcc != NULL) ? (myFields->fld_bcc->bcc_addr_list) : NULL;
clist *inReplyTo = (myFields->fld_in_reply_to != NULL) ? (myFields->fld_in_reply_to->mid_list) : NULL;
clist *references = (myFields->fld_references != NULL) ? (myFields->fld_references->mid_list) : NULL;
char *subject = (myFields->fld_subject != NULL) ? (myFields->fld_subject->sbj_value) : NULL;
//TODO uh oh, when this get freed it frees stuff in the CTCoreMessage
//TODO Need to make sure that fields gets freed somewhere
fields = mailimf_fields_new_with_data(from, sender, replyTo, to, cc, bcc, inReplyTo, references, subject);
[(CTMIME_MessagePart *)msgPart setIMFFields:fields];
}
return [myParsedMIME render];
}
- (NSData *)messageAsEmlx {
NSString *msgContent = [[self rfc822] stringByReplacingOccurrencesOfString:@"\r\n" withString:@"\n"];
NSData *msgContentAsData = [msgContent dataUsingEncoding:NSUTF8StringEncoding];
NSMutableData *emlx = [NSMutableData data];
[emlx appendData:[[NSString stringWithFormat:@"%-10d\n", msgContentAsData.length] dataUsingEncoding:NSUTF8StringEncoding]];
[emlx appendData:msgContentAsData];
struct mail_flags *flagsStruct = myMessage->msg_flags;
long long flags = 0;
if (flagsStruct != NULL) {
BOOL seen = (flagsStruct->fl_flags & CTFlagSeen) > 0;
flags |= seen << 0;
BOOL answered = (flagsStruct->fl_flags & CTFlagAnswered) > 0;
flags |= answered << 2;
BOOL flagged = (flagsStruct->fl_flags & CTFlagFlagged) > 0;
flags |= flagged << 4;
BOOL forwarded = (flagsStruct->fl_flags & CTFlagForwarded) > 0;
flags |= forwarded << 8;
}
NSMutableDictionary *dictionary = [NSMutableDictionary dictionary];
[dictionary setValue:[NSNumber numberWithDouble:[[self senderDate] timeIntervalSince1970]] forKey:@"date-sent"];
[dictionary setValue:[NSNumber numberWithUnsignedLongLong:flags] forKey:@"flags"];
[dictionary setValue:[self subject] forKey:@"subject"];
NSError *error;
NSData *propertyList = [NSPropertyListSerialization dataWithPropertyList:dictionary
format:NSPropertyListXMLFormat_v1_0
options:0
error:&error];
[emlx appendData:propertyList];
return emlx;
}
- (NSString *)rfc822 {
char *result = NULL;
NSString *nsresult;
int r = mailimap_fetch_rfc822([self imapSession], [self sequenceNumber], &result);
if (r == 0) {
nsresult = [[NSString alloc] initWithCString:result encoding:NSUTF8StringEncoding];
} else {
NSException *exception = [NSException
exceptionWithName:CTUnknownError
reason:[NSString stringWithFormat:@"Error number: %d",r]
userInfo:nil];
[exception raise];
}
mailimap_msg_att_rfc822_free(result);
return [nsresult autorelease];
}
- (struct mailmessage *)messageStruct {
return myMessage;
}
- (mailimap *)imapSession; {
struct imap_cached_session_state_data * cached_data;
struct imap_session_state_data * data;
mailsession *session = [self messageStruct]->msg_session;
if (strcasecmp(session->sess_driver->sess_name, "imap-cached") == 0) {
cached_data = session->sess_data;
session = cached_data->imap_ancestor;
}
data = session->sess_data;
return data->imap_session;
}
/*********************************** myprivates ***********************************/
- (CTCoreAddress *)_addressFromMailbox:(struct mailimf_mailbox *)mailbox; {
CTCoreAddress *address = [CTCoreAddress address];
if (mailbox == NULL) {
return address;
}
if (mailbox->mb_display_name != NULL) {
NSString *decodedName = [self _decodeMIMEPhrase:mailbox->mb_display_name];
if (decodedName == nil) {
decodedName = @"";
}
[address setName:decodedName];
}
if (mailbox->mb_addr_spec != NULL) {
[address setEmail:[NSString stringWithCString:mailbox->mb_addr_spec encoding:NSUTF8StringEncoding]];
}
return address;
}
- (NSSet *)_addressListFromMailboxList:(struct mailimf_mailbox_list *)mailboxList; {
clist *list;
clistiter * iter;
struct mailimf_mailbox *address;
NSMutableSet *addressSet = [NSMutableSet set];
if (mailboxList == NULL)
return addressSet;
list = mailboxList->mb_list;
for(iter = clist_begin(list); iter != NULL; iter = clist_next(iter)) {
address = clist_content(iter);
[addressSet addObject:[self _addressFromMailbox:address]];
}
return addressSet;
}
- (struct mailimf_mailbox_list *)_mailboxListFromAddressList:(NSSet *)addresses {
struct mailimf_mailbox_list *imfList = mailimf_mailbox_list_new_empty();
NSEnumerator *objEnum = [addresses objectEnumerator];
CTCoreAddress *address;
int err;
const char *addressName;
const char *addressEmail;
while(address = [objEnum nextObject]) {
addressName = [[address name] cStringUsingEncoding:NSUTF8StringEncoding];
addressEmail = [[address email] cStringUsingEncoding:NSUTF8StringEncoding];
err = mailimf_mailbox_list_add_mb(imfList, strdup(addressName), strdup(addressEmail));
assert(err == 0);
}
return imfList;
}
- (NSSet *)_addressListFromIMFAddressList:(struct mailimf_address_list *)imfList {
clist *list;
clistiter * iter;
struct mailimf_address *address;
NSMutableSet *addressSet = [NSMutableSet set];
if (imfList == NULL)
return addressSet;
list = imfList->ad_list;
for(iter = clist_begin(list); iter != NULL; iter = clist_next(iter)) {
address = clist_content(iter);
/* Check to see if it's a solo address a group */
if (address->ad_type == MAILIMF_ADDRESS_MAILBOX) {
[addressSet addObject:[self _addressFromMailbox:address->ad_data.ad_mailbox]];
}
else {
if (address->ad_data.ad_group->grp_mb_list != NULL)
[addressSet unionSet:[self _addressListFromMailboxList:address->ad_data.ad_group->grp_mb_list]];
}
}
return addressSet;
}
- (struct mailimf_address_list *)_IMFAddressListFromAddresssList:(NSSet *)addresses {
struct mailimf_address_list *imfList = mailimf_address_list_new_empty();
NSEnumerator *objEnum = [addresses objectEnumerator];
CTCoreAddress *address;
int err;
const char *addressName;
const char *addressEmail;
while(address = [objEnum nextObject]) {
addressName = [[address name] cStringUsingEncoding:NSUTF8StringEncoding];
addressEmail = [[address email] cStringUsingEncoding:NSUTF8StringEncoding];
err = mailimf_address_list_add_mb(imfList, strdup(addressName), strdup(addressEmail));
assert(err == 0);
}
return imfList;
}
- (NSString *)_decodeMIMEPhrase:(char *)data {
int err;
size_t currToken = 0;
char *decodedSubject;
NSString *result;
if (*data != '\0') {
err = mailmime_encoded_phrase_parse(DEST_CHARSET, data, strlen(data),
&currToken, DEST_CHARSET, &decodedSubject);
if (err != MAILIMF_NO_ERROR) {
if (decodedSubject == NULL)
free(decodedSubject);
return nil;
}
}
else {
return @"";
}
result = [NSString stringWithCString:decodedSubject encoding:NSUTF8StringEncoding];
free(decodedSubject);
return result;
}
@end