// // BPMailAppData.m // Piles3 // // Created by Bea on 13/07/05. // Copyright 2005 __MyCompanyName__. All rights reserved. // // Thanks to Mark 'bdash' Rowe @ http://bdash.net.nz for the PyObjC code on his // blog that showed how to access the mailbox! #import "BPMailAppData.h" #import "BPUtil.h" #import "BPPerson.h" #import "BPAttachment.h" #import "BPEmailDocument.h" #import "BPFetchMailIndicator.h" #import #import @implementation BPAccount - (id)initWithAccount:(MailAccount *)anAccount { [super init]; [anAccount retain]; account = anAccount; mailboxes = [account mailboxes]; // MailboxUid objects mailboxNames = [[NSMutableArray alloc] initWithCapacity:[mailboxes count]]; int i; for (i=0; i<[mailboxes count]; i++) { [mailboxNames addObject:[[mailboxes objectAtIndex:i] name]]; } return self; } - (NSString *)name { //return [NSString stringWithFormat:@"%@ (%@)", // [account accountName], [account accountTypeString]]; return [NSString stringWithFormat:@"%@", [account accountName]]; } - (MailAccount *)account { return account; } - (NSArray *)mailboxes { return mailboxes; } - (NSArray *)mailboxNames { return mailboxNames; } - (NSArray *)emailAddresses { return [account emailAddresses]; } - (NSString *)description { return [NSString stringWithFormat:@"BPAccount for %@", account]; } - (void)dealloc { NSLog(@"dealloc %@", self); [account release]; [mailboxNames release]; [super dealloc]; } @end @implementation BPMailAppData + (void)initialize { // load Mail.app stuff into user defaults NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults]; [defaults addSuiteNamed:@"com.apple.mail"]; } - (void)refreshAccountData { NSArray *mailAccounts = [MailAccount readAccountsUsingDefaultsKey:@"MailAccounts"]; // populate allAccounts if (allAccounts != nil) [allAccounts removeAllObjects]; [allAccounts release]; allAccounts = [[NSMutableArray alloc] initWithCapacity:[mailAccounts count]]; BPAccount *newAccount; int i; for (i=0; i<[mailAccounts count]; i++) { newAccount = [[BPAccount alloc] initWithAccount:[mailAccounts objectAtIndex:i]]; [allAccounts addObject:newAccount]; } // populate accountNames if (accountNames != nil) [accountNames removeAllObjects]; [accountNames release]; accountNames = [[NSMutableArray alloc] initWithCapacity:[allAccounts count]]; for (i=0; i<[allAccounts count]; i++) { NSString *name = [[allAccounts objectAtIndex:i] name]; [accountNames addObject:name]; } [accountNames sortUsingSelector:@selector(compare:)]; } // return string array of names of all accounts - (NSArray *)mailAccounts { if (accountNames == nil) [self refreshAccountData]; //return accountNames; return allAccounts; } - (NSArray *)mailAccountsAddresses { if (allAccounts == nil) [self refreshAccountData]; NSMutableArray *addresses = [NSMutableArray arrayWithCapacity:5]; int i; BPAccount *account; for (i=0; i<[allAccounts count]; i++) { account = [allAccounts objectAtIndex:i]; [addresses addObjectsFromArray:[account emailAddresses]]; } return addresses; } // return string array of names of all mailbox in the specified account - (NSArray *)mailboxesForAccount:(int)accountIndex { if (accountIndex < 0 || accountIndex > [allAccounts count]) { NSLog(@"mailboxesForAccount: error. accountIndex '%d' invalid", accountIndex); return [NSArray array]; } BPAccount *account = [allAccounts objectAtIndex:accountIndex]; return [account mailboxNames]; } - (MailboxUid *)mailboxUidForAccount:(int)accountIndex mailbox:(int)mailboxIndex { MailAccount *account = [[allAccounts objectAtIndex:accountIndex] account]; return [[account mailboxes] objectAtIndex:mailboxIndex]; } - (void)stopImport { doImportMail = NO; } - (void)importWithDetails:(NSDictionary *)details { MailboxUid *mailboxUid = [details objectForKey:@"mailboxUid"]; int numToImport = [[details objectForKey:@"numToImport"] intValue]; id callbackTarget = [details objectForKey:@"callbackTarget"]; SEL callbackSelector = NSSelectorFromString([details objectForKey:@"callbackSelector"]); if (![callbackTarget respondsToSelector:callbackSelector]) return; if (numToImport == 0) [callbackTarget performSelector:callbackSelector withObject:[NSArray array]]; doImportMail = YES; [fetchMailIndicator startWithCancelTarget:self cancelAction:@selector(stopImport)]; // open the message store to get the email messages MessageStore *msgStore = [[mailboxUid account] storeForMailboxUid:mailboxUid]; [fetchMailIndicator openingMessageStoreForMailbox:[mailboxUid name]]; if (![msgStore isOpened]) [msgStore openSynchronously]; NSArray *allMsgs = [msgStore copyOfAllMessages]; //NSLog(@"%@ email count: %d", [account accountName], [allMsgs count]); NSMutableArray *emailDocuments = [[[NSMutableArray alloc] initWithCapacity:100] autorelease]; BPEmailDocument *emailDoc; Message *currentMsg; if (numToImport > [allMsgs count]) numToImport = [allMsgs count]; [fetchMailIndicator setFetchCount:numToImport]; // do '[emailDocuments count] < numToImport' condition and work from // newer back to older msgs, cos there may be junk/deleted msgs that we don't want, // but we want to import at least the numToImport NSEnumerator *enumerator; if ([[NSUserDefaults standardUserDefaults] boolForKey:@"MailStacker_reverseImports"]) enumerator = [allMsgs objectEnumerator]; // for Mail mailboxes where user reversed the chronological order else enumerator = [allMsgs reverseObjectEnumerator]; // newest -> oldest while ((currentMsg = [enumerator nextObject]) != nil && [emailDocuments count] < numToImport) { if (!doImportMail) break; //currentMsg = [allMsgs objectAtIndex:i]; //NSLog(@"New msg: %@", [currentMsg subject]); if (![currentMsg isJunk] && ![currentMsg isDeleted]) { [fetchMailIndicator parsingMessageWithSubject:[currentMsg subject]]; emailDoc = [BPEmailDocument emailDocumentWithMessage:currentMsg]; [emailDocuments addObject:emailDoc]; } } [fetchMailIndicator stopIndicator]; [callbackTarget performSelector:callbackSelector withObject:[BPUtil reversedArray:emailDocuments]]; } // generates BPEmailDocuments into array representing the emails in the specified mailbox - (void)importEmailDocumentsForMailInAccount:(int)accountIndex mailbox:(int)mailboxIndex mailCount:(int)numToImport target:(id)callbackTarget action:(SEL)callbackSelector { // get the specified account & mailbox MailAccount *account = [[allAccounts objectAtIndex:accountIndex] account]; MailboxUid *mailboxUid = [[account mailboxes] objectAtIndex:mailboxIndex]; // use account email address as email address for "me" [BPPerson setMyEmail:[account firstEmailAddress]]; if (mailboxUid == nil || callbackTarget == nil || callbackSelector == nil) { NSLog(@"importEmailDocumentsForMailInAccount Error: argument is nil, import terminated."); return; } NSDictionary *details = [NSDictionary dictionaryWithObjectsAndKeys: mailboxUid, @"mailboxUid", [NSNumber numberWithInt:numToImport], @"numToImport", callbackTarget, @"callbackTarget", NSStringFromSelector(callbackSelector), @"callbackSelector", nil]; [NSApplication detachDrawingThread:@selector(importWithDetails:) toTarget:self withObject:details]; } // turns MessageAddressee array into BPPerson array + (NSArray *)personsFromAddressees:(NSArray *)addressees { if ([addressees count] == 0) return [[NSArray alloc] initWithArray:[NSArray array]]; BPPerson *p; MessageAddressee *addressee; NSMutableArray *persons = [[[NSMutableArray alloc] initWithCapacity:[addressees count]] autorelease]; int i; for (i=0; i<[addressees count]; i++) { addressee = (MessageAddressee *)[addressees objectAtIndex:i]; NSString *addr = [addressee address]; p = [BPPerson personWithName:[addressee displayName] address:addr]; [persons addObject:p]; } return persons; } // turns NSTextAttachment array into BPAttachments array + (NSArray *)attachmentsFromNSTextAttachments:(NSArray *)originalAttachments { if ([originalAttachments count] == 0) return [[NSArray alloc] initWithArray:[NSArray array]]; BPAttachment *attachment; NSTextAttachment *originalAttachment; NSMutableArray *attachments = [[[NSMutableArray alloc] initWithCapacity:[originalAttachments count]] autorelease]; int i; for (i=0; i<[originalAttachments count]; i++) { originalAttachment = [originalAttachments objectAtIndex:i]; attachment = [BPAttachment attachmentWithMimePart:[originalAttachment mimePart]]; [attachments addObject:attachment]; } return attachments; } @end