This is an automated email from the ASF dual-hosted git repository. chibenwa pushed a commit to branch 3.9.x in repository https://gitbox.apache.org/repos/asf/james-project.git
commit b687123dbaa9e6fccc4fe0eb5d89e83dbf48ae4a Author: Benoit TELLIER <[email protected]> AuthorDate: Tue Jun 16 17:35:09 2026 +0200 [FIX] User rename: per rename temporary mailbox layout --- .../adapter/mailbox/MailboxUsernameChangeTaskStep.java | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/server/container/mailbox-adapter/src/main/java/org/apache/james/adapter/mailbox/MailboxUsernameChangeTaskStep.java b/server/container/mailbox-adapter/src/main/java/org/apache/james/adapter/mailbox/MailboxUsernameChangeTaskStep.java index 74441266f7..b23334c786 100644 --- a/server/container/mailbox-adapter/src/main/java/org/apache/james/adapter/mailbox/MailboxUsernameChangeTaskStep.java +++ b/server/container/mailbox-adapter/src/main/java/org/apache/james/adapter/mailbox/MailboxUsernameChangeTaskStep.java @@ -19,6 +19,8 @@ package org.apache.james.adapter.mailbox; +import java.util.concurrent.ThreadLocalRandom; + import jakarta.inject.Inject; import org.apache.james.core.Username; @@ -69,22 +71,27 @@ public class MailboxUsernameChangeTaskStep implements UsernameChangeTaskStep { .user(fromSession.getUser()) .build(); + // A single random suffix is generated for the whole rename operation so that temporary + // mailboxes never collide with a leftover from a previous run (we thus do not loose the + // previous content) while staying recognizable. + int renameOperationId = ThreadLocalRandom.current().nextInt(1000); + return mailboxManager.search(queryUser, MailboxManager.MailboxSearchFetchType.Minimal, fromSession) // Only keep top level, rename takes care of sub mailboxes .filter(mailbox -> mailbox.getPath().getHierarchyLevels(fromSession.getPathDelimiter()).size() == 1) - .concatMap(mailbox -> migrateMailbox(fromSession, toSession, mailbox)) + .concatMap(mailbox -> migrateMailbox(fromSession, toSession, mailbox, renameOperationId)) .doFinally(any -> mailboxManager.endProcessingRequest(fromSession)) .doFinally(any -> mailboxManager.endProcessingRequest(toSession)); } - private Mono<Void> migrateMailbox(MailboxSession fromSession, MailboxSession toSession, org.apache.james.mailbox.model.MailboxMetaData mailbox) { + private Mono<Void> migrateMailbox(MailboxSession fromSession, MailboxSession toSession, org.apache.james.mailbox.model.MailboxMetaData mailbox, int renameOperationId) { MailboxPath renamedPath = mailbox.getPath().withUser(toSession.getUser()); return mailboxManager.mailboxExists(renamedPath, toSession) .flatMap(exist -> { if (!exist) { return renameMailboxAndRenameSubscriptionForDelegatee(fromSession, toSession, mailbox, renamedPath); } else { - return moveWhenMailboxExist(fromSession, toSession, mailbox, renamedPath); + return moveWhenMailboxExist(fromSession, toSession, mailbox, renamedPath, renameOperationId); } }); } @@ -100,8 +107,8 @@ public class MailboxUsernameChangeTaskStep implements UsernameChangeTaskStep { // The destination mailbox already exists: bring the source mailbox into the destination // account under a temporary name, MOVE its messages into the destination, then drop the // emptied temporary mailbox. - private Mono<Void> moveWhenMailboxExist(MailboxSession fromSession, MailboxSession toSession, MailboxMetaData mailbox, MailboxPath renamedPath) { - MailboxPath temporaryPath = new MailboxPath(renamedPath.getNamespace(), renamedPath.getUser(), renamedPath.getName() + "tmp"); + private Mono<Void> moveWhenMailboxExist(MailboxSession fromSession, MailboxSession toSession, MailboxMetaData mailbox, MailboxPath renamedPath, int renameOperationId) { + MailboxPath temporaryPath = new MailboxPath(renamedPath.getNamespace(), renamedPath.getUser(), renamedPath.getName() + "-tmp-" + renameOperationId); return mailboxManager.renameMailboxReactive(mailbox.getPath(), temporaryPath, MailboxManager.RenameOption.NONE, fromSession, toSession) .thenMany(mailboxManager.moveMessagesReactive(MessageRange.all(), temporaryPath, renamedPath, toSession)) --------------------------------------------------------------------- To unsubscribe, e-mail: [email protected] For additional commands, e-mail: [email protected]
