diff --git a/SoObjects/Mailer/SOGoMailFolder.h b/SoObjects/Mailer/SOGoMailFolder.h index a1ea8cd813..59ba1ef1eb 100644 --- a/SoObjects/Mailer/SOGoMailFolder.h +++ b/SoObjects/Mailer/SOGoMailFolder.h @@ -1,5 +1,5 @@ /* - Copyright (C) 2009-2014 Inverse inc. + Copyright (C) 2009-2021 Inverse inc. Copyright (C) 2004-2005 SKYRIX Software AG This file is part of SOGo @@ -91,6 +91,8 @@ - (BOOL) ensureTrashFolder; +- (NSException *) unsubscribe; + - (NSException *) expunge; - (NSException *) renameTo: (NSString *) newName; diff --git a/SoObjects/Mailer/SOGoMailFolder.m b/SoObjects/Mailer/SOGoMailFolder.m index 280f127059..2fab6935fa 100644 --- a/SoObjects/Mailer/SOGoMailFolder.m +++ b/SoObjects/Mailer/SOGoMailFolder.m @@ -1,5 +1,5 @@ /* - Copyright (C) 2009-2019 Inverse inc. + Copyright (C) 2009-2021 Inverse inc. Copyright (C) 2004-2005 SKYRIX Software AG This file is part of SOGo. @@ -1221,6 +1221,20 @@ - (NSException *) delete return error; } +- (NSException *) unsubscribe +{ + NSException *error = nil; + + if ([self imap4Connection]) + [[imap4 client] unsubscribe: [[self imap4URL] path]]; + else + error = [NSException exceptionWithName: @"SOGoMailException" + reason: @"IMAP connection is invalid" + userInfo: nil]; + + return error; +} + - (NSException *) davMoveToTargetObject: (id) _target newName: (NSString *) _name inContext: (id)_ctx diff --git a/UI/MailerUI/UIxMailFolderActions.m b/UI/MailerUI/UIxMailFolderActions.m index c002b1efb1..5e9e0b8772 100644 --- a/UI/MailerUI/UIxMailFolderActions.m +++ b/UI/MailerUI/UIxMailFolderActions.m @@ -298,8 +298,7 @@ - (NSURL *) _trashedURLOfFolder: (NSURL *) srcURL connection = [co imap4Connection]; folderName = [[srcURL path] lastPathComponent]; - trashFolderName - = [[co mailAccountFolder] trashFolderNameInContext: context]; + trashFolderName = [[co mailAccountFolder] trashFolderNameInContext: context]; path = [NSString stringWithFormat: @"/%@/%@", trashFolderName, folderName]; testPath = path; @@ -326,17 +325,15 @@ - (NSURL *) _trashedURLOfFolder: (NSURL *) srcURL return destURL; } -- (void) _removeFolder +- (void) _removeFolderAtURL: (NSURL *) srcURL { NGImap4Connection *connection; NSMutableDictionary *moduleSettings, *threadsCollapsed;; NSString *keyForMsgUIDs, *currentMailbox, *currentAccount; - NSURL *srcURL; SOGoMailFolder *co; SOGoUserSettings *us; co = [self clientObject]; - srcURL = [co imap4URL]; connection = [co imap4Connection]; // Unsubscribe from mailbox @@ -346,7 +343,6 @@ - (void) _removeFolder us = [[context activeUser] userSettings]; moduleSettings = [us objectForKey: @"Mail"]; threadsCollapsed = [moduleSettings objectForKey: @"threadsCollapsed"]; - if (threadsCollapsed) { currentMailbox = [co nameInContainer]; @@ -363,26 +359,30 @@ - (void) _removeFolder - (WOResponse *) deleteAction { NSDictionary *jsonRequest, *jsonResponse; + NSEnumerator *subURLs; NGImap4Connection *connection; SOGoMailFolder *co, *inbox; - NSURL *srcURL, *destURL; + NSURL *srcURL, *destURL, *currentURL; WORequest *request; WOResponse *response; NSException *error; + NSInteger count; BOOL moved, withTrash; request = [context request]; co = [self clientObject]; + connection = [co imap4Connection]; srcURL = [co imap4URL]; + subURLs = [[co allFolderURLs] objectEnumerator]; jsonRequest = [[request contentAsString] objectFromJSONString]; withTrash = ![[jsonRequest objectForKey: @"withoutTrash"] boolValue]; + error = nil; moved = YES; if (withTrash) { if ([co ensureTrashFolder]) { - connection = [co imap4Connection]; destURL = [self _trashedURLOfFolder: srcURL withObject: co]; inbox = [[co mailAccountFolder] inboxFolderInContext: context]; [[connection client] select: [inbox absoluteImap4Name]]; @@ -397,7 +397,9 @@ - (WOResponse *) deleteAction moved = NO; } else - error = [connection moveMailboxAtURL: srcURL toURL: destURL]; + { + error = [connection moveMailboxAtURL: srcURL toURL: destURL]; + } if (error) { jsonResponse = [NSDictionary dictionaryWithObject: [self labelForKey: @"Unable to move/delete folder." inContext: context] @@ -407,9 +409,30 @@ - (WOResponse *) deleteAction else { // We unsubscribe to the old one, and subscribe back to the new one + [self _removeFolderAtURL: srcURL]; if (moved) [[connection client] subscribe: [destURL path]]; - [self _removeFolder]; + + // We do the same for all subfolders + count = [[srcURL pathComponents] count]; + while (!error && (currentURL = [subURLs nextObject])) + { + [self _removeFolderAtURL: currentURL]; + if (moved) + { + NSArray *currentComponents; + NSMutableArray *destComponents; + NSInteger currentCount; + + destComponents = [NSMutableArray arrayWithArray: [destURL pathComponents]]; + [destComponents removeObjectAtIndex: 0]; // remove leading forward slash + currentCount = [[currentURL pathComponents] count]; + currentComponents = [[currentURL pathComponents] subarrayWithRange: NSMakeRange(count, currentCount - count)]; + [destComponents addObjectsFromArray: currentComponents]; + + [[connection client] subscribe: [NSString stringWithFormat: @"/%@", [destComponents componentsJoinedByString: @"/"]]]; + } + } response = [self responseWith204]; } } @@ -433,7 +456,12 @@ - (WOResponse *) deleteAction } else { - [self _removeFolder]; + // Cleanup all references to mailbox and submailboxes + [self _removeFolderAtURL: srcURL]; + while (!error && (currentURL = [subURLs nextObject])) + { + [self _removeFolderAtURL: currentURL]; + } response = [self responseWith204]; } } diff --git a/UI/MailerUI/UIxMailListActions.m b/UI/MailerUI/UIxMailListActions.m index 3fcda8919a..cc4d3eda05 100644 --- a/UI/MailerUI/UIxMailListActions.m +++ b/UI/MailerUI/UIxMailListActions.m @@ -655,7 +655,10 @@ - (NSDictionary *) getUIDsInFolder: (SOGoMailFolder *) folder // Retrieve messages UIDs using form parameters "sort" and "asc" uids = [self getSortedUIDsInFolder: folder]; if (uids == nil) - return nil; + { + [folder unsubscribe]; // Mailbox is possibly missing -- cleanup subscriptions + return nil; + } // Get rid of the extra parenthesis // uids = [[[[uids stringValue] stringByReplacingOccurrencesOfString:@"(" withString:@""] stringByReplacingOccurrencesOfString:@")" withString:@""] componentsSeparatedByString:@","];