2006-06-15 21:34:10 +02:00
|
|
|
/*
|
|
|
|
Copyright (C) 2004-2005 SKYRIX Software AG
|
2009-03-13 20:48:15 +01:00
|
|
|
Copyright (C) 2007-2009 Inverse inc.
|
2006-06-15 21:34:10 +02:00
|
|
|
|
2009-03-13 20:48:15 +01:00
|
|
|
This file is part of SOGo.
|
2006-06-15 21:34:10 +02:00
|
|
|
|
2009-03-13 20:48:15 +01:00
|
|
|
SOGo is free software; you can redistribute it and/or modify it under
|
2006-06-15 21:34:10 +02:00
|
|
|
the terms of the GNU Lesser General Public License as published by the
|
|
|
|
Free Software Foundation; either version 2, or (at your option) any
|
|
|
|
later version.
|
|
|
|
|
2009-03-13 20:48:15 +01:00
|
|
|
SOGo is distributed in the hope that it will be useful, but WITHOUT ANY
|
2006-06-15 21:34:10 +02:00
|
|
|
WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
|
|
|
FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
|
|
|
|
License for more details.
|
|
|
|
|
|
|
|
You should have received a copy of the GNU Lesser General Public
|
2009-10-09 23:01:54 +02:00
|
|
|
License along with SOGo; see the file COPYING. If not, write to the
|
2006-06-15 21:34:10 +02:00
|
|
|
Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA
|
|
|
|
02111-1307, USA.
|
|
|
|
*/
|
|
|
|
|
2007-08-01 20:32:00 +02:00
|
|
|
#import <Foundation/NSArray.h>
|
|
|
|
#import <Foundation/NSURL.h>
|
|
|
|
#import <Foundation/NSString.h>
|
|
|
|
#import <Foundation/NSUserDefaults.h>
|
|
|
|
|
|
|
|
#import <NGObjWeb/NSException+HTTP.h>
|
|
|
|
#import <NGObjWeb/SoHTTPAuthenticator.h>
|
|
|
|
#import <NGObjWeb/WORequest.h>
|
|
|
|
#import <NGObjWeb/WOContext+SoObjects.h>
|
2009-10-09 23:01:54 +02:00
|
|
|
#import <NGStreams/NGInternetSocketAddress.h>
|
2007-08-01 20:32:00 +02:00
|
|
|
#import <NGExtensions/NSNull+misc.h>
|
2008-02-08 00:09:12 +01:00
|
|
|
#import <NGExtensions/NSObject+Logs.h>
|
|
|
|
#import <NGExtensions/NSString+misc.h>
|
2007-08-01 20:32:00 +02:00
|
|
|
#import <NGImap4/NGImap4Connection.h>
|
2008-02-01 17:28:53 +01:00
|
|
|
#import <NGImap4/NGImap4Client.h>
|
|
|
|
#import <NGImap4/NGImap4Context.h>
|
2009-10-09 23:01:54 +02:00
|
|
|
#import <NGImap4/NGSieveClient.h>
|
2007-08-01 20:32:00 +02:00
|
|
|
|
2007-10-31 16:55:47 +01:00
|
|
|
#import <SoObjects/SOGo/NSArray+Utilities.h>
|
2007-10-17 23:03:39 +02:00
|
|
|
#import <SoObjects/SOGo/SOGoUser.h>
|
|
|
|
|
2007-11-01 13:48:19 +01:00
|
|
|
#import "SOGoDraftsFolder.h"
|
2007-08-01 20:32:00 +02:00
|
|
|
#import "SOGoMailFolder.h"
|
|
|
|
#import "SOGoMailManager.h"
|
2007-11-01 13:48:19 +01:00
|
|
|
#import "SOGoSentFolder.h"
|
|
|
|
#import "SOGoTrashFolder.h"
|
2007-08-01 20:32:00 +02:00
|
|
|
|
|
|
|
#import "SOGoMailAccount.h"
|
2006-06-15 21:34:10 +02:00
|
|
|
|
|
|
|
@implementation SOGoMailAccount
|
|
|
|
|
2007-08-15 22:22:24 +02:00
|
|
|
static NSArray *rootFolderNames = nil;
|
|
|
|
static NSString *inboxFolderName = @"INBOX";
|
|
|
|
static NSString *draftsFolderName = @"Drafts";
|
2007-07-30 20:01:25 +02:00
|
|
|
static NSString *sentFolderName = nil;
|
|
|
|
static NSString *trashFolderName = nil;
|
2009-10-09 23:01:54 +02:00
|
|
|
static NSString *sharedFolderName = @""; // TODO: add English default
|
2006-06-15 21:34:10 +02:00
|
|
|
static NSString *otherUsersFolderName = @""; // TODO: add English default
|
2009-10-09 23:01:54 +02:00
|
|
|
static NSString *sieveScriptName = @"sogo";
|
|
|
|
|
2009-05-20 01:31:51 +02:00
|
|
|
static BOOL defaultShowSubscribedFoldersOnly = NO;
|
2008-09-01 19:31:40 +02:00
|
|
|
// this is temporary, until we allow users to manage their own accounts
|
|
|
|
static NSString *fallbackIMAP4Server = nil;
|
|
|
|
|
2007-08-15 22:22:24 +02:00
|
|
|
+ (void) initialize
|
|
|
|
{
|
2006-06-15 21:34:10 +02:00
|
|
|
NSUserDefaults *ud = [NSUserDefaults standardUserDefaults];
|
2006-11-21 21:32:44 +01:00
|
|
|
NSString *cfgDraftsFolderName;
|
2006-06-15 21:34:10 +02:00
|
|
|
|
2007-07-30 20:01:25 +02:00
|
|
|
sharedFolderName = [ud stringForKey:@"SOGoSharedFolderName"];
|
2006-06-15 21:34:10 +02:00
|
|
|
otherUsersFolderName = [ud stringForKey:@"SOGoOtherUsersFolderName"];
|
2006-11-21 21:32:44 +01:00
|
|
|
cfgDraftsFolderName = [ud stringForKey:@"SOGoDraftsFolderName"];
|
2007-07-30 20:01:25 +02:00
|
|
|
if (!sentFolderName)
|
|
|
|
{
|
|
|
|
sentFolderName = [ud stringForKey: @"SOGoSentFolderName"];
|
|
|
|
if (!sentFolderName)
|
|
|
|
sentFolderName = @"Sent";
|
|
|
|
[sentFolderName retain];
|
|
|
|
}
|
|
|
|
if (!trashFolderName)
|
|
|
|
{
|
|
|
|
trashFolderName = [ud stringForKey: @"SOGoTrashFolderName"];
|
|
|
|
if (!trashFolderName)
|
|
|
|
trashFolderName = @"Trash";
|
|
|
|
[trashFolderName retain];
|
|
|
|
}
|
2006-11-21 21:32:44 +01:00
|
|
|
if ([cfgDraftsFolderName length] > 0)
|
|
|
|
{
|
|
|
|
ASSIGN (draftsFolderName, cfgDraftsFolderName);
|
|
|
|
NSLog(@"Note: using drafts folder named: '%@'", draftsFolderName);
|
|
|
|
}
|
|
|
|
|
2006-06-15 21:34:10 +02:00
|
|
|
NSLog(@"Note: using shared-folders name: '%@'", sharedFolderName);
|
|
|
|
NSLog(@"Note: using other-users-folders name: '%@'", otherUsersFolderName);
|
2009-10-09 23:01:54 +02:00
|
|
|
|
|
|
|
rootFolderNames = [[NSArray alloc] initWithObjects:
|
|
|
|
draftsFolderName,
|
|
|
|
nil];
|
2008-09-01 19:31:40 +02:00
|
|
|
|
|
|
|
if (!fallbackIMAP4Server)
|
|
|
|
{
|
|
|
|
fallbackIMAP4Server = [ud stringForKey: @"SOGoFallbackIMAP4Server"];
|
|
|
|
if (fallbackIMAP4Server)
|
|
|
|
[fallbackIMAP4Server retain];
|
|
|
|
else
|
|
|
|
fallbackIMAP4Server = @"localhost";
|
|
|
|
}
|
2009-05-20 01:31:51 +02:00
|
|
|
|
|
|
|
defaultShowSubscribedFoldersOnly = [ud boolForKey: @"SOGoMailShowSubscribedFoldersOnly"];
|
2007-08-15 22:22:24 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
- (id) init
|
|
|
|
{
|
|
|
|
if ((self = [super init]))
|
|
|
|
{
|
|
|
|
inboxFolder = nil;
|
|
|
|
draftsFolder = nil;
|
|
|
|
sentFolder = nil;
|
|
|
|
trashFolder = nil;
|
2009-09-29 22:13:36 +02:00
|
|
|
accountName = nil;
|
2007-08-15 22:22:24 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
return self;
|
|
|
|
}
|
|
|
|
|
|
|
|
- (void) dealloc
|
|
|
|
{
|
|
|
|
[inboxFolder release];
|
|
|
|
[draftsFolder release];
|
|
|
|
[sentFolder release];
|
|
|
|
[trashFolder release];
|
2009-09-29 22:13:36 +02:00
|
|
|
[accountName release];
|
2007-08-15 22:22:24 +02:00
|
|
|
[super dealloc];
|
2006-06-15 21:34:10 +02:00
|
|
|
}
|
|
|
|
|
2009-09-29 22:13:36 +02:00
|
|
|
- (void) setAccountName: (NSString *) newAccountName
|
|
|
|
{
|
|
|
|
ASSIGN (accountName, newAccountName);
|
|
|
|
}
|
|
|
|
|
2006-06-15 21:34:10 +02:00
|
|
|
/* shared accounts */
|
|
|
|
|
2007-08-15 22:22:24 +02:00
|
|
|
- (BOOL) isSharedAccount
|
|
|
|
{
|
2006-06-15 21:34:10 +02:00
|
|
|
NSString *s;
|
|
|
|
NSRange r;
|
|
|
|
|
2009-09-29 22:13:36 +02:00
|
|
|
s = accountName;
|
2006-06-15 21:34:10 +02:00
|
|
|
r = [s rangeOfString:@"@"];
|
|
|
|
if (r.length == 0) /* regular HTTP logins are never a shared mailbox */
|
|
|
|
return NO;
|
|
|
|
|
|
|
|
s = [s substringToIndex:r.location];
|
|
|
|
return [s rangeOfString:@".-."].length > 0 ? YES : NO;
|
|
|
|
}
|
|
|
|
|
2007-08-15 22:22:24 +02:00
|
|
|
- (NSString *) sharedAccountName
|
|
|
|
{
|
2006-06-15 21:34:10 +02:00
|
|
|
return nil;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* listing the available folders */
|
|
|
|
|
2007-08-15 22:22:24 +02:00
|
|
|
- (NSArray *) additionalRootFolderNames
|
|
|
|
{
|
2006-06-15 21:34:10 +02:00
|
|
|
return rootFolderNames;
|
|
|
|
}
|
|
|
|
|
2007-08-15 22:22:24 +02:00
|
|
|
- (BOOL) isInDraftsFolder
|
|
|
|
{
|
|
|
|
return NO;
|
|
|
|
}
|
|
|
|
|
2007-03-30 17:25:20 +02:00
|
|
|
- (NSArray *) toManyRelationshipKeys
|
|
|
|
{
|
|
|
|
NSMutableArray *folders;
|
|
|
|
NSArray *imapFolders, *additionalFolders;
|
|
|
|
|
2007-08-15 22:22:24 +02:00
|
|
|
folders = [NSMutableArray array];
|
2007-03-30 17:25:20 +02:00
|
|
|
|
|
|
|
imapFolders = [[self imap4Connection] subfoldersForURL: [self imap4URL]];
|
|
|
|
additionalFolders = [self additionalRootFolderNames];
|
|
|
|
if ([imapFolders count] > 0)
|
|
|
|
[folders addObjectsFromArray: imapFolders];
|
|
|
|
if ([additionalFolders count] > 0)
|
|
|
|
{
|
|
|
|
[folders removeObjectsInArray: additionalFolders];
|
|
|
|
[folders addObjectsFromArray: additionalFolders];
|
|
|
|
}
|
2007-10-31 16:55:47 +01:00
|
|
|
|
2009-09-28 23:42:11 +02:00
|
|
|
return [folders stringsWithFormat: @"folder%@"];
|
2006-06-15 21:34:10 +02:00
|
|
|
}
|
|
|
|
|
2008-02-01 17:28:53 +01:00
|
|
|
- (BOOL) supportsQuotas
|
|
|
|
{
|
|
|
|
NGImap4Client *imapClient;
|
2008-02-06 16:48:52 +01:00
|
|
|
NSArray *capability;
|
2008-02-01 17:28:53 +01:00
|
|
|
|
|
|
|
imapClient = [[self imap4Connection] client];
|
2008-02-06 16:48:52 +01:00
|
|
|
capability = [[imapClient capability] objectForKey: @"capability"];
|
2008-02-01 17:28:53 +01:00
|
|
|
|
2008-02-06 16:48:52 +01:00
|
|
|
return [capability containsObject: @"quota"];
|
2008-02-01 17:28:53 +01:00
|
|
|
}
|
|
|
|
|
2009-10-09 23:01:54 +02:00
|
|
|
- (BOOL) updateFilters
|
|
|
|
{
|
|
|
|
NSMutableString *header, *script;
|
|
|
|
NGInternetSocketAddress *address;
|
|
|
|
NSDictionary *result, *values;
|
|
|
|
NSUserDefaults *ud;
|
|
|
|
NGSieveClient *client;
|
|
|
|
NSString *v;
|
|
|
|
BOOL b;
|
|
|
|
|
|
|
|
if (![[NSUserDefaults standardUserDefaults] boolForKey: @"SOGoVacationEnabled"] &&
|
|
|
|
![[NSUserDefaults standardUserDefaults] boolForKey: @"SOGoForwardEnabled"])
|
|
|
|
return YES;
|
|
|
|
|
|
|
|
ud = [[context activeUser] userDefaults];
|
|
|
|
b = NO;
|
|
|
|
|
|
|
|
header = [NSMutableString stringWithString: @"require ["];
|
|
|
|
script = [NSMutableString string];
|
|
|
|
|
|
|
|
// Right now, we handle Sieve filters here and only for vacation
|
|
|
|
// and forwards. Traditional filters support (for fileinto, for
|
|
|
|
// example) will be added later.
|
|
|
|
values = [ud objectForKey: @"Vacation"];
|
|
|
|
|
|
|
|
// We handle vacation messages.
|
|
|
|
// See http://ietfreport.isoc.org/idref/draft-ietf-sieve-vacation/
|
|
|
|
if (values && [[values objectForKey: @"enabled"] boolValue])
|
|
|
|
{
|
|
|
|
NSArray *addresses;
|
|
|
|
NSString *text;
|
|
|
|
BOOL ignore;
|
|
|
|
int days, i;
|
|
|
|
|
|
|
|
days = [[values objectForKey: @"daysBetweenResponse"] intValue];
|
|
|
|
addresses = [values objectForKey: @"autoReplyEmailAddresses"];
|
|
|
|
ignore = [[values objectForKey: @"ignoreLists"] boolValue];
|
|
|
|
text = [values objectForKey: @"autoReplyText"];
|
|
|
|
b = YES;
|
|
|
|
|
|
|
|
if (days == 0)
|
|
|
|
days = 7;
|
|
|
|
|
|
|
|
[header appendString: @"\"vacation\""];
|
|
|
|
|
|
|
|
// Skip mailing lists
|
|
|
|
if (ignore)
|
|
|
|
[script appendString: @"if allof ( not exists [\"list-help\", \"list-unsubscribe\", \"list-subscribe\", \"list-owner\", \"list-post\", \"list-archive\", \"list-id\", \"Mailing-List\"], not header :comparator \"i;ascii-casemap\" :is \"Precedence\" [\"list\", \"bulk\", \"junk\"], not header :comparator \"i;ascii-casemap\" :matches \"To\" \"Multiple recipients of*\" ) {"];
|
|
|
|
|
|
|
|
[script appendFormat: @"vacation :days %d :addresses [", days];
|
|
|
|
|
|
|
|
for (i = 0; i < [addresses count]; i++)
|
|
|
|
{
|
|
|
|
[script appendFormat: @"\"%@\"", [addresses objectAtIndex: i]];
|
|
|
|
|
|
|
|
if (i == [addresses count]-1)
|
|
|
|
[script appendString: @"] "];
|
|
|
|
else
|
|
|
|
[script appendString: @", "];
|
|
|
|
}
|
|
|
|
|
|
|
|
[script appendFormat: @"text:\r\n%@\r\n.\r\n;\r\n", text];
|
|
|
|
|
|
|
|
if (ignore)
|
|
|
|
[script appendString: @"}\r\n"];
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// We handle mail forward
|
|
|
|
values = [ud objectForKey: @"Forward"];
|
|
|
|
|
|
|
|
if (values && [[values objectForKey: @"enabled"] boolValue])
|
|
|
|
{
|
|
|
|
b = YES;
|
|
|
|
|
|
|
|
v = [values objectForKey: @"forwardAddress"];
|
|
|
|
|
|
|
|
if (v && [v length] > 0)
|
|
|
|
[script appendFormat: @"redirect \"%@\";\r\n", v];
|
|
|
|
|
|
|
|
if ([[values objectForKey: @"keepCopy"] boolValue])
|
|
|
|
[script appendString: @"keep;\r\n"];
|
|
|
|
}
|
|
|
|
|
|
|
|
if ([header compare: @"require ["] != NSOrderedSame)
|
|
|
|
{
|
|
|
|
[header appendString: @"];\r\n"];
|
|
|
|
[script insertString: header atIndex: 0];
|
|
|
|
}
|
|
|
|
|
|
|
|
// We connect to our Sieve server and upload the script
|
|
|
|
address = [NGInternetSocketAddress addressWithPort: 2000
|
|
|
|
onHost: [[self imap4URL] host]];
|
|
|
|
|
|
|
|
client = [NGSieveClient clientWithAddress: address];
|
|
|
|
|
|
|
|
if (!client) {
|
|
|
|
[self errorWithFormat: @"Sieve connection failed on %@", [address description]];
|
|
|
|
return NO;
|
|
|
|
}
|
|
|
|
|
|
|
|
result = [client login: [[self imap4URL] user] password:[self imap4Password]];
|
|
|
|
|
|
|
|
if (![[result valueForKey:@"result"] boolValue]) {
|
|
|
|
[self errorWithFormat: @"Could not login '%@' (%@) on Sieve server: %@: %@",
|
|
|
|
[[self imap4URL] user], [self imap4Password], client, result];
|
|
|
|
[client closeConnection];
|
|
|
|
return NO;
|
|
|
|
}
|
|
|
|
|
|
|
|
// We delete the existing Sieve script
|
|
|
|
result = [client deleteScript: sieveScriptName];
|
|
|
|
|
|
|
|
if (![[result valueForKey:@"result"] boolValue]) {
|
|
|
|
[self logWithFormat:@"WARNING: Could not delete Sieve script - continuing...: %@", result];
|
|
|
|
}
|
|
|
|
|
|
|
|
// We put and activate the script only if we actually have a script
|
|
|
|
// that does something...
|
|
|
|
if (b)
|
|
|
|
{
|
|
|
|
result = [client putScript: sieveScriptName script: script];
|
|
|
|
|
|
|
|
if (![[result valueForKey:@"result"] boolValue]) {
|
|
|
|
[self errorWithFormat:@"Could not upload Sieve script: %@", result];
|
|
|
|
[client closeConnection];
|
|
|
|
return NO;
|
|
|
|
}
|
|
|
|
|
|
|
|
result = [client setActiveScript: sieveScriptName];
|
|
|
|
if (![[result valueForKey:@"result"] boolValue]) {
|
|
|
|
[self errorWithFormat:@"Could not enable Sieve script: %@", result];
|
|
|
|
[client closeConnection];
|
|
|
|
return NO;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return YES;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2006-06-15 21:34:10 +02:00
|
|
|
/* hierarchy */
|
|
|
|
|
2007-08-15 22:22:24 +02:00
|
|
|
- (SOGoMailAccount *) mailAccountFolder
|
|
|
|
{
|
2006-06-15 21:34:10 +02:00
|
|
|
return self;
|
|
|
|
}
|
|
|
|
|
2007-05-28 21:06:13 +02:00
|
|
|
- (NSArray *) allFolderPaths
|
|
|
|
{
|
2007-11-01 13:48:19 +01:00
|
|
|
NSMutableArray *folderPaths;
|
2007-05-28 21:06:13 +02:00
|
|
|
NSArray *rawFolders, *mainFolders;
|
2009-05-15 22:26:25 +02:00
|
|
|
NSUserDefaults *ud;
|
2009-05-20 01:31:51 +02:00
|
|
|
NSString *showSubscribedFoldersOnly;
|
2007-05-28 21:06:13 +02:00
|
|
|
|
2009-05-15 22:26:25 +02:00
|
|
|
ud = [[context activeUser] userDefaults];
|
2009-05-20 01:31:51 +02:00
|
|
|
showSubscribedFoldersOnly = [ud stringForKey: @"showSubscribedFoldersOnly"];
|
|
|
|
if (showSubscribedFoldersOnly)
|
|
|
|
rawFolders = [[self imap4Connection] allFoldersForURL: [self imap4URL]
|
|
|
|
onlySubscribedFolders: [showSubscribedFoldersOnly boolValue]];
|
|
|
|
else
|
|
|
|
rawFolders = [[self imap4Connection] allFoldersForURL: [self imap4URL]
|
|
|
|
onlySubscribedFolders: defaultShowSubscribedFoldersOnly];
|
2007-05-28 21:06:13 +02:00
|
|
|
|
2007-11-01 13:48:19 +01:00
|
|
|
mainFolders = [[NSArray arrayWithObjects:
|
|
|
|
[self inboxFolderNameInContext: context],
|
|
|
|
[self draftsFolderNameInContext: context],
|
|
|
|
[self sentFolderNameInContext: context],
|
|
|
|
[self trashFolderNameInContext: context],
|
|
|
|
nil] stringsWithFormat: @"/%@"];
|
|
|
|
folderPaths = [NSMutableArray arrayWithArray: rawFolders];
|
|
|
|
[folderPaths removeObjectsInArray: mainFolders];
|
|
|
|
[folderPaths
|
|
|
|
sortUsingSelector: @selector (localizedCaseInsensitiveCompare:)];
|
|
|
|
[folderPaths replaceObjectsInRange: NSMakeRange (0, 0)
|
|
|
|
withObjectsFromArray: mainFolders];
|
|
|
|
|
|
|
|
return folderPaths;
|
2006-06-15 21:34:10 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/* IMAP4 */
|
|
|
|
|
2007-08-15 22:22:24 +02:00
|
|
|
- (BOOL) useSSL
|
|
|
|
{
|
2006-06-15 21:34:10 +02:00
|
|
|
return NO;
|
|
|
|
}
|
|
|
|
|
2007-08-15 22:22:24 +02:00
|
|
|
- (NSString *) imap4LoginFromHTTP
|
|
|
|
{
|
2006-06-15 21:34:10 +02:00
|
|
|
WORequest *rq;
|
|
|
|
NSString *s;
|
|
|
|
NSArray *creds;
|
|
|
|
|
2007-04-11 21:17:20 +02:00
|
|
|
rq = [context request];
|
2006-06-15 21:34:10 +02:00
|
|
|
|
|
|
|
s = [rq headerForKey:@"x-webobjects-remote-user"];
|
|
|
|
if ([s length] > 0)
|
|
|
|
return s;
|
|
|
|
|
|
|
|
if ((s = [rq headerForKey:@"authorization"]) == nil) {
|
|
|
|
/* no basic auth */
|
|
|
|
return nil;
|
|
|
|
}
|
|
|
|
|
|
|
|
creds = [SoHTTPAuthenticator parseCredentials:s];
|
|
|
|
if ([creds count] < 2)
|
|
|
|
/* somehow invalid */
|
|
|
|
return nil;
|
|
|
|
|
|
|
|
return [creds objectAtIndex:0]; /* the user */
|
|
|
|
}
|
|
|
|
|
2008-02-08 00:09:12 +01:00
|
|
|
- (NSString *) _urlHostString
|
|
|
|
{
|
|
|
|
NSDictionary *mailAccount;
|
|
|
|
NSString *username, *escUsername, *hostString;
|
|
|
|
|
2009-09-29 22:13:36 +02:00
|
|
|
mailAccount = [[context activeUser] accountWithName: accountName];
|
2008-02-08 00:09:12 +01:00
|
|
|
if (mailAccount)
|
|
|
|
{
|
|
|
|
username = [mailAccount objectForKey: @"userName"];
|
|
|
|
escUsername
|
2008-02-08 17:20:29 +01:00
|
|
|
= [[username stringByEscapingURL] stringByReplacingString: @"@"
|
|
|
|
withString: @"%40"];
|
2009-05-12 21:56:39 +02:00
|
|
|
#if 1
|
2008-09-01 19:31:40 +02:00
|
|
|
// see comment about fallbackIMAP4Server above
|
2008-02-08 00:09:12 +01:00
|
|
|
hostString = [NSString stringWithFormat: @"%@@%@", escUsername,
|
|
|
|
[mailAccount objectForKey: @"serverName"]];
|
2008-09-01 19:31:40 +02:00
|
|
|
#else
|
|
|
|
hostString = [NSString stringWithFormat: @"%@@%@", escUsername,
|
|
|
|
fallbackIMAP4Server];
|
|
|
|
#endif
|
2008-02-08 00:09:12 +01:00
|
|
|
}
|
|
|
|
else
|
|
|
|
hostString = @"localhost";
|
|
|
|
|
|
|
|
return hostString;
|
|
|
|
}
|
|
|
|
|
2007-07-10 21:23:39 +02:00
|
|
|
- (NSMutableString *) imap4URLString
|
|
|
|
{
|
2006-06-15 21:34:10 +02:00
|
|
|
/* private, overridden by SOGoSharedMailAccount */
|
2007-07-10 21:23:39 +02:00
|
|
|
NSMutableString *urlString;
|
|
|
|
NSString *host;
|
2006-06-15 21:34:10 +02:00
|
|
|
|
2007-07-10 21:23:39 +02:00
|
|
|
urlString = [NSMutableString string];
|
|
|
|
|
|
|
|
if ([self useSSL])
|
|
|
|
[urlString appendString: @"imaps://"];
|
|
|
|
else
|
|
|
|
[urlString appendString: @"imap://"];
|
|
|
|
|
2008-02-08 00:09:12 +01:00
|
|
|
host = [self _urlHostString];
|
2007-07-10 21:23:39 +02:00
|
|
|
if (![host rangeOfString: @"@"].length)
|
|
|
|
[urlString appendFormat: @"%@@", [self imap4LoginFromHTTP]];
|
|
|
|
[urlString appendFormat: @"%@/", host];
|
|
|
|
|
|
|
|
return urlString;
|
2006-06-15 21:34:10 +02:00
|
|
|
}
|
|
|
|
|
2007-10-31 16:55:47 +01:00
|
|
|
- (NSMutableString *) traversalFromMailAccount
|
|
|
|
{
|
|
|
|
return [NSMutableString string];
|
|
|
|
}
|
|
|
|
|
2007-07-10 21:23:39 +02:00
|
|
|
- (NSString *) imap4Login
|
|
|
|
{
|
2006-06-15 21:34:10 +02:00
|
|
|
return [[self imap4URL] user];
|
|
|
|
}
|
|
|
|
|
|
|
|
/* name lookup */
|
|
|
|
|
2007-07-30 17:55:28 +02:00
|
|
|
- (id) lookupName: (NSString *) _key
|
|
|
|
inContext: (id)_ctx
|
|
|
|
acquire: (BOOL) _flag
|
|
|
|
{
|
2007-11-01 13:48:19 +01:00
|
|
|
NSString *folderName;
|
|
|
|
Class klazz;
|
2006-06-15 21:34:10 +02:00
|
|
|
id obj;
|
2007-07-30 17:55:28 +02:00
|
|
|
|
|
|
|
if ([_key hasPrefix: @"folder"])
|
|
|
|
{
|
2007-11-01 13:48:19 +01:00
|
|
|
folderName = [_key substringFromIndex: 6];
|
|
|
|
if ([folderName
|
|
|
|
isEqualToString: [self sentFolderNameInContext: _ctx]])
|
|
|
|
klazz = [SOGoSentFolder class];
|
|
|
|
else if ([folderName
|
|
|
|
isEqualToString: [self draftsFolderNameInContext: _ctx]])
|
|
|
|
klazz = [SOGoDraftsFolder class];
|
|
|
|
else if ([folderName
|
|
|
|
isEqualToString: [self trashFolderNameInContext: _ctx]])
|
|
|
|
klazz = [SOGoTrashFolder class];
|
2007-07-30 17:55:28 +02:00
|
|
|
else
|
2007-11-01 13:48:19 +01:00
|
|
|
klazz = [SOGoMailFolder class];
|
|
|
|
|
|
|
|
obj = [klazz objectWithName: _key inContainer: self];
|
2007-07-30 17:55:28 +02:00
|
|
|
}
|
|
|
|
else
|
|
|
|
obj = [super lookupName: _key inContext: _ctx acquire: NO];
|
2006-06-15 21:34:10 +02:00
|
|
|
|
|
|
|
/* return 404 to stop acquisition */
|
2007-07-30 17:55:28 +02:00
|
|
|
if (!obj)
|
|
|
|
obj = [NSException exceptionWithHTTPStatus: 404 /* Not Found */];
|
|
|
|
|
|
|
|
return obj;
|
2006-06-15 21:34:10 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/* special folders */
|
|
|
|
|
2007-07-30 20:01:25 +02:00
|
|
|
- (NSString *) inboxFolderNameInContext: (id)_ctx
|
|
|
|
{
|
2007-08-01 20:32:00 +02:00
|
|
|
/* cannot be changed in Cyrus ? */
|
2007-11-01 13:48:19 +01:00
|
|
|
return inboxFolderName;
|
2006-06-15 21:34:10 +02:00
|
|
|
}
|
2007-07-30 20:01:25 +02:00
|
|
|
|
2007-10-17 23:03:39 +02:00
|
|
|
- (NSString *) _userFolderNameWithPurpose: (NSString *) purpose
|
|
|
|
{
|
|
|
|
NSUserDefaults *ud;
|
|
|
|
NSMutableDictionary *mailSettings;
|
|
|
|
NSString *folderName;
|
|
|
|
|
|
|
|
folderName = nil;
|
|
|
|
ud = [[context activeUser] userSettings];
|
|
|
|
mailSettings = [ud objectForKey: @"Mail"];
|
|
|
|
if (mailSettings)
|
|
|
|
folderName
|
|
|
|
= [mailSettings objectForKey: [NSString stringWithFormat: @"%@Folder",
|
|
|
|
purpose]];
|
|
|
|
|
|
|
|
return folderName;
|
|
|
|
}
|
|
|
|
|
2007-07-30 20:01:25 +02:00
|
|
|
- (NSString *) draftsFolderNameInContext: (id) _ctx
|
|
|
|
{
|
2007-10-17 23:03:39 +02:00
|
|
|
NSString *folderName;
|
|
|
|
|
|
|
|
folderName = [self _userFolderNameWithPurpose: @"Drafts"];
|
|
|
|
if (!folderName)
|
|
|
|
folderName = draftsFolderName;
|
|
|
|
|
2007-11-01 13:48:19 +01:00
|
|
|
return folderName;
|
2006-06-15 21:34:10 +02:00
|
|
|
}
|
2007-07-30 20:01:25 +02:00
|
|
|
|
2007-08-01 20:32:00 +02:00
|
|
|
- (NSString *) sentFolderNameInContext: (id)_ctx
|
2007-07-30 20:01:25 +02:00
|
|
|
{
|
2007-10-17 23:03:39 +02:00
|
|
|
NSString *folderName;
|
|
|
|
|
|
|
|
folderName = [self _userFolderNameWithPurpose: @"Sent"];
|
|
|
|
if (!folderName)
|
|
|
|
folderName = sentFolderName;
|
|
|
|
|
2007-11-01 13:48:19 +01:00
|
|
|
return folderName;
|
2006-06-15 21:34:10 +02:00
|
|
|
}
|
2007-07-30 20:01:25 +02:00
|
|
|
|
2007-08-01 20:32:00 +02:00
|
|
|
- (NSString *) trashFolderNameInContext: (id)_ctx
|
2007-07-30 20:01:25 +02:00
|
|
|
{
|
2007-10-17 23:03:39 +02:00
|
|
|
NSString *folderName;
|
|
|
|
|
|
|
|
folderName = [self _userFolderNameWithPurpose: @"Trash"];
|
|
|
|
if (!folderName)
|
|
|
|
folderName = trashFolderName;
|
|
|
|
|
2007-11-01 13:48:19 +01:00
|
|
|
return folderName;
|
|
|
|
}
|
|
|
|
|
|
|
|
- (id) folderWithTraversal: (NSString *) traversal
|
|
|
|
andClassName: (NSString *) className
|
|
|
|
{
|
|
|
|
NSArray *paths;
|
|
|
|
NSString *currentName;
|
|
|
|
id currentContainer;
|
|
|
|
unsigned int count, max;
|
|
|
|
Class clazz;
|
|
|
|
|
|
|
|
currentContainer = self;
|
|
|
|
paths = [traversal componentsSeparatedByString: @"/"];
|
|
|
|
|
|
|
|
if (!className)
|
|
|
|
clazz = [SOGoMailFolder class];
|
|
|
|
else
|
|
|
|
clazz = NSClassFromString (className);
|
|
|
|
|
|
|
|
max = [paths count];
|
|
|
|
for (count = 0; count < max - 1; count++)
|
|
|
|
{
|
|
|
|
currentName = [NSString stringWithFormat: @"folder%@",
|
|
|
|
[paths objectAtIndex: count]];
|
|
|
|
currentContainer = [SOGoMailFolder objectWithName: currentName
|
|
|
|
inContainer: currentContainer];
|
|
|
|
}
|
|
|
|
currentName = [NSString stringWithFormat: @"folder%@",
|
|
|
|
[paths objectAtIndex: max - 1]];
|
|
|
|
|
|
|
|
return [clazz objectWithName: currentName inContainer: currentContainer];
|
2006-06-15 21:34:10 +02:00
|
|
|
}
|
|
|
|
|
2007-07-30 20:01:25 +02:00
|
|
|
- (SOGoMailFolder *) inboxFolderInContext: (id) _ctx
|
|
|
|
{
|
2006-06-15 21:34:10 +02:00
|
|
|
// TODO: use some profile to determine real location, use a -traverse lookup
|
2007-07-30 20:01:25 +02:00
|
|
|
if (!inboxFolder)
|
|
|
|
{
|
2007-11-01 13:48:19 +01:00
|
|
|
inboxFolder
|
|
|
|
= [self folderWithTraversal: [self inboxFolderNameInContext: _ctx]
|
|
|
|
andClassName: nil];
|
2007-07-30 20:01:25 +02:00
|
|
|
[inboxFolder retain];
|
|
|
|
}
|
|
|
|
|
|
|
|
return inboxFolder;
|
2006-06-15 21:34:10 +02:00
|
|
|
}
|
|
|
|
|
2007-08-15 22:22:24 +02:00
|
|
|
- (SOGoDraftsFolder *) draftsFolderInContext: (id) _ctx
|
|
|
|
{
|
|
|
|
// TODO: use some profile to determine real location, use a -traverse lookup
|
|
|
|
|
|
|
|
if (!draftsFolder)
|
|
|
|
{
|
2007-10-23 19:46:08 +02:00
|
|
|
draftsFolder
|
2007-11-01 13:48:19 +01:00
|
|
|
= [self folderWithTraversal: [self draftsFolderNameInContext: _ctx]
|
|
|
|
andClassName: @"SOGoDraftsFolder"];
|
2007-08-15 22:22:24 +02:00
|
|
|
[draftsFolder retain];
|
|
|
|
}
|
|
|
|
|
|
|
|
return draftsFolder;
|
|
|
|
}
|
|
|
|
|
2007-11-01 13:48:19 +01:00
|
|
|
- (SOGoSentFolder *) sentFolderInContext: (id) _ctx
|
2007-07-30 20:01:25 +02:00
|
|
|
{
|
2006-06-15 21:34:10 +02:00
|
|
|
// TODO: use some profile to determine real location, use a -traverse lookup
|
2007-07-30 20:01:25 +02:00
|
|
|
|
|
|
|
if (!sentFolder)
|
|
|
|
{
|
2007-11-01 13:48:19 +01:00
|
|
|
sentFolder
|
|
|
|
= [self folderWithTraversal: [self sentFolderNameInContext: _ctx]
|
|
|
|
andClassName: @"SOGoSentFolder"];
|
2007-07-30 20:01:25 +02:00
|
|
|
[sentFolder retain];
|
|
|
|
}
|
|
|
|
|
|
|
|
return sentFolder;
|
2006-06-15 21:34:10 +02:00
|
|
|
}
|
|
|
|
|
2007-11-01 13:48:19 +01:00
|
|
|
- (SOGoTrashFolder *) trashFolderInContext: (id) _ctx
|
2007-07-30 20:01:25 +02:00
|
|
|
{
|
|
|
|
if (!trashFolder)
|
|
|
|
{
|
2007-11-01 13:48:19 +01:00
|
|
|
trashFolder
|
|
|
|
= [self folderWithTraversal: [self trashFolderNameInContext: _ctx]
|
|
|
|
andClassName: @"SOGoTrashFolder"];
|
2007-07-30 20:01:25 +02:00
|
|
|
[trashFolder retain];
|
|
|
|
}
|
|
|
|
|
|
|
|
return trashFolder;
|
2006-06-15 21:34:10 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/* WebDAV */
|
|
|
|
|
2007-06-01 07:45:12 +02:00
|
|
|
- (NSString *) davContentType
|
|
|
|
{
|
|
|
|
return @"httpd/unix-directory";
|
|
|
|
}
|
|
|
|
|
|
|
|
- (BOOL) davIsCollection
|
|
|
|
{
|
2006-06-15 21:34:10 +02:00
|
|
|
return YES;
|
|
|
|
}
|
|
|
|
|
2007-06-01 07:45:12 +02:00
|
|
|
- (NSException *) davCreateCollection: (NSString *) _name
|
|
|
|
inContext: (id) _ctx
|
|
|
|
{
|
2006-06-15 21:34:10 +02:00
|
|
|
return [[self imap4Connection] createMailbox:_name atURL:[self imap4URL]];
|
|
|
|
}
|
|
|
|
|
2007-06-01 07:45:12 +02:00
|
|
|
- (NSString *) shortTitle
|
|
|
|
{
|
2009-09-29 22:13:36 +02:00
|
|
|
NSString *login, *host;
|
2006-06-15 21:34:10 +02:00
|
|
|
NSRange r;
|
|
|
|
|
2009-09-29 22:13:36 +02:00
|
|
|
r = [accountName rangeOfString:@"@"];
|
2007-11-07 16:59:01 +01:00
|
|
|
if (r.length > 0)
|
|
|
|
{
|
2009-09-29 22:13:36 +02:00
|
|
|
login = [accountName substringToIndex:r.location];
|
|
|
|
host = [accountName substringFromIndex:(r.location + r.length)];
|
2007-11-07 16:59:01 +01:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
login = nil;
|
2009-09-29 22:13:36 +02:00
|
|
|
host = accountName;
|
2007-11-07 16:59:01 +01:00
|
|
|
}
|
2006-06-15 21:34:10 +02:00
|
|
|
|
|
|
|
r = [host rangeOfString:@"."];
|
|
|
|
if (r.length > 0)
|
|
|
|
host = [host substringToIndex:r.location];
|
|
|
|
|
|
|
|
if ([login length] == 0)
|
|
|
|
return host;
|
|
|
|
|
|
|
|
r = [login rangeOfString:@"."];
|
|
|
|
if (r.length > 0)
|
|
|
|
login = [login substringToIndex:r.location];
|
|
|
|
|
|
|
|
return [NSString stringWithFormat:@"%@@%@", login, host];
|
|
|
|
}
|
|
|
|
|
2007-06-01 07:45:12 +02:00
|
|
|
- (NSString *) davDisplayName
|
|
|
|
{
|
2006-06-15 21:34:10 +02:00
|
|
|
return [self shortTitle];
|
|
|
|
}
|
|
|
|
|
2007-05-25 23:20:31 +02:00
|
|
|
- (NSString *) sharedFolderName
|
|
|
|
{
|
|
|
|
return sharedFolderName;
|
|
|
|
}
|
|
|
|
|
|
|
|
- (NSString *) otherUsersFolderName
|
|
|
|
{
|
|
|
|
return otherUsersFolderName;
|
|
|
|
}
|
|
|
|
|
2006-06-15 21:34:10 +02:00
|
|
|
@end /* SOGoMailAccount */
|