| /**************************************************************** |
| * Licensed to the Apache Software Foundation (ASF) under one * |
| * or more contributor license agreements. See the NOTICE file * |
| * distributed with this work for additional information * |
| * regarding copyright ownership. The ASF licenses this file * |
| * to you under the Apache License, Version 2.0 (the * |
| * "License"); you may not use this file except in compliance * |
| * with the License. You may obtain a copy of the License at * |
| * * |
| * http://www.apache.org/licenses/LICENSE-2.0 * |
| * * |
| * Unless required by applicable law or agreed to in writing, * |
| * software distributed under the License is distributed on an * |
| * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * |
| * KIND, either express or implied. See the License for the * |
| * specific language governing permissions and limitations * |
| * under the License. * |
| ****************************************************************/ |
| |
| package org.apache.james.mailbox; |
| |
| import java.util.EnumSet; |
| import java.util.List; |
| import java.util.Objects; |
| import java.util.Optional; |
| |
| import org.apache.james.mailbox.exception.MailboxException; |
| import org.apache.james.mailbox.exception.MailboxExistsException; |
| import org.apache.james.mailbox.exception.MailboxNotFoundException; |
| import org.apache.james.mailbox.model.Mailbox; |
| import org.apache.james.mailbox.model.MailboxId; |
| import org.apache.james.mailbox.model.MailboxMetaData; |
| import org.apache.james.mailbox.model.MailboxPath; |
| import org.apache.james.mailbox.model.MessageId; |
| import org.apache.james.mailbox.model.MessageRange; |
| import org.apache.james.mailbox.model.MultimailboxesSearchQuery; |
| import org.apache.james.mailbox.model.ThreadId; |
| import org.apache.james.mailbox.model.search.MailboxQuery; |
| import org.reactivestreams.Publisher; |
| |
| import reactor.core.publisher.Flux; |
| |
| /** |
| * <p> |
| * Central MailboxManager which creates, lists, provides, renames and deletes |
| * Mailboxes |
| * </p> |
| * <p> |
| * An important goal is to be JavaMail feature compatible. That means JavaMail |
| * could be used in both directions: As a backend for e.g. accessing a Maildir |
| * JavaMail store or as a frontend to access a JDBC MailboxManager through |
| * JavaMail. This should be possible by not too complicated wrapper classes. Due |
| * to the complexity of JavaMail it might be impossible to avoid some |
| * limitations. |
| * </p> |
| * <p> |
| * Internally MailboxManager deals with named repositories that could have |
| * different implementations. E.g. JDBC connections to different hosts or |
| * Maildir / Mbox like stores. These repositories are identified by their names |
| * and maybe are configured in config.xml. The names of the mailboxes have to be |
| * mapped to the corresponding repository name. For user mailboxes this could be |
| * done by a "User.getRepositoryName()" property. It is imaginable that |
| * repositories lookup further properties from the user object like a path name |
| * for a file based storage method. Until Milestone 6 there is only one named |
| * repository: "default". |
| * </p> |
| * <p> |
| * The only operation that requires dealing with the named repositories directly |
| * is the quota management. It is probably really difficult to implement a quota |
| * system that spans multiple repository implementations. That is why quotas are |
| * created for a specific repository. To be able to administer, repositories and |
| * theier belonging mailboxes can be listet. |
| * </p> |
| */ |
| |
| public interface MailboxManager extends RequestAware, RightManager, MailboxAnnotationManager, SessionProvider { |
| |
| int MAX_MAILBOX_NAME_LENGTH = 200; |
| |
| enum MailboxCapabilities { |
| Annotation, |
| Move, |
| Namespace, |
| UserFlag, |
| ACL, |
| Quota |
| } |
| |
| EnumSet<MailboxCapabilities> getSupportedMailboxCapabilities(); |
| |
| boolean hasCapability(MailboxCapabilities capability); |
| |
| enum MessageCapabilities { |
| UniqueID |
| } |
| |
| EnumSet<MessageCapabilities> getSupportedMessageCapabilities(); |
| |
| enum SearchCapabilities { |
| MultimailboxSearch, |
| PartialEmailMatch, |
| /** |
| * The implementation supporting this capability should |
| * provide an index on the fields: |
| * From, To, Cc, Bcc, Subjects, textBody & htmlBody |
| */ |
| Text, |
| FullText, |
| Attachment, |
| AttachmentFileName |
| } |
| |
| EnumSet<SearchCapabilities> getSupportedSearchCapabilities(); |
| |
| /** |
| * Gets an object managing the given mailbox. |
| * |
| * @param mailboxPath |
| * the Path of the mailbox, not null |
| * @param session |
| * the context for this call, not null |
| * @throws MailboxException |
| * when the mailbox cannot be opened |
| * @throws MailboxNotFoundException |
| * when the given mailbox does not exist |
| */ |
| MessageManager getMailbox(MailboxPath mailboxPath, MailboxSession session) throws MailboxException; |
| |
| /** |
| * Gets an object managing the given mailbox. |
| * |
| * @param mailboxId |
| * the Id of the mailbox, not null |
| * @param session |
| * the context for this call, not null |
| * @throws MailboxException |
| * when the mailbox cannot be opened |
| * @throws MailboxNotFoundException |
| * when the given mailbox does not exist |
| */ |
| MessageManager getMailbox(MailboxId mailboxId, MailboxSession session) throws MailboxException; |
| |
| Publisher<MessageManager> getMailboxReactive(MailboxId mailboxId, MailboxSession session); |
| |
| Publisher<MessageManager> getMailboxReactive(MailboxPath mailboxPath, MailboxSession session); |
| |
| /** |
| * Creates a new mailbox. Any intermediary mailboxes missing from the |
| * hierarchy should be created. |
| * |
| * @param mailboxSession |
| * the context for this call, not null |
| * @throws MailboxException |
| * when creation fails |
| * @return Empty optional when the mailbox name is empty. If mailbox is created, the id of the mailboxPath specified as |
| * parameter is returned (and potential mailboxIds of parent mailboxes created in the process will be omitted) |
| */ |
| Optional<MailboxId> createMailbox(MailboxPath mailboxPath, MailboxSession mailboxSession) throws MailboxException; |
| |
| /** |
| * Delete the mailbox with the name |
| */ |
| void deleteMailbox(MailboxPath mailboxPath, MailboxSession session) throws MailboxException; |
| |
| /** |
| * Delete the mailbox with the given id |
| * |
| * @return the Mailbox when deleted |
| */ |
| Mailbox deleteMailbox(MailboxId mailboxId, MailboxSession session) throws MailboxException; |
| |
| class MailboxRenamedResult { |
| private final MailboxId mailboxId; |
| private final MailboxPath originPath; |
| private final MailboxPath destinationPath; |
| |
| public MailboxRenamedResult(MailboxId mailboxId, MailboxPath originPath, MailboxPath destinationPath) { |
| this.mailboxId = mailboxId; |
| this.originPath = originPath; |
| this.destinationPath = destinationPath; |
| } |
| |
| public MailboxId getMailboxId() { |
| return mailboxId; |
| } |
| |
| public MailboxPath getOriginPath() { |
| return originPath; |
| } |
| |
| public MailboxPath getDestinationPath() { |
| return destinationPath; |
| } |
| |
| @Override |
| public final boolean equals(Object o) { |
| if (o instanceof MailboxRenamedResult) { |
| MailboxRenamedResult that = (MailboxRenamedResult) o; |
| |
| return Objects.equals(this.mailboxId, that.mailboxId) |
| && Objects.equals(this.originPath, that.originPath) |
| && Objects.equals(this.destinationPath, that.destinationPath); |
| } |
| return false; |
| } |
| |
| @Override |
| public final int hashCode() { |
| return Objects.hash(mailboxId, originPath, destinationPath); |
| } |
| } |
| |
| enum RenameOption { |
| NONE, RENAME_SUBSCRIPTIONS |
| } |
| |
| /** |
| * Renames a mailbox. |
| * |
| * @param from |
| * original mailbox path |
| * @param to |
| * new mailbox path |
| * @param session |
| * the context for this call, not null |
| * @throws MailboxException |
| * upon unexpected failure |
| * @throws MailboxExistsException |
| * when the <code>to</code> mailbox exists |
| * @throws MailboxNotFoundException |
| * when the <code>from</code> mailbox does not exist |
| */ |
| List<MailboxRenamedResult> renameMailbox(MailboxPath from, MailboxPath to, RenameOption option, MailboxSession session) throws MailboxException; |
| |
| default List<MailboxRenamedResult> renameMailbox(MailboxPath from, MailboxPath to, MailboxSession session) throws MailboxException { |
| return renameMailbox(from, to, RenameOption.NONE, session); |
| } |
| |
| /** |
| * Renames a mailbox. |
| * |
| * @param mailboxId |
| * original mailbox |
| * @param newMailboxPath |
| * new mailbox path |
| * @param session |
| * the context for this call, not null |
| * @throws MailboxException |
| * upon unexpected failure |
| * @throws MailboxExistsException |
| * when the <code>newMailboxPath</code> mailbox exists |
| * @throws MailboxNotFoundException |
| * when the <code>mailboxId</code> original mailbox does not exist |
| */ |
| List<MailboxRenamedResult> renameMailbox(MailboxId mailboxId, MailboxPath newMailboxPath, RenameOption option, MailboxSession session) throws MailboxException; |
| |
| default List<MailboxRenamedResult> renameMailbox(MailboxId mailboxId, MailboxPath newMailboxPath, MailboxSession session) throws MailboxException { |
| return renameMailbox(mailboxId, newMailboxPath, RenameOption.NONE, session); |
| } |
| |
| /** |
| * Copy the given {@link MessageRange} from one Mailbox to the other. |
| * |
| * Be aware that the copied Messages MUST get the \RECENT flag set! |
| * |
| * @param set |
| * messages to copy |
| * @param from |
| * name of the source mailbox |
| * @param to |
| * name of the destination mailbox |
| * @param session |
| * <code>MailboxSession</code>, not null |
| * @return a list of MessageRange - uids assigned to copied messages |
| */ |
| List<MessageRange> copyMessages(MessageRange set, MailboxPath from, MailboxPath to, MailboxSession session) throws MailboxException; |
| |
| List<MessageRange> copyMessages(MessageRange set, MailboxId from, MailboxId to, MailboxSession session) throws MailboxException; |
| |
| /** |
| * Move the given {@link MessageRange} from one Mailbox to the other. |
| * |
| * Be aware that the moved Messages MUST get the \RECENT flag set! |
| * |
| * @param set |
| * messages to move |
| * @param from |
| * name of the source mailbox |
| * @param to |
| * name of the destination mailbox |
| * @param session |
| * <code>MailboxSession</code>, not null |
| * @return a list of MessageRange - uids assigned to moved messages |
| */ |
| List<MessageRange> moveMessages(MessageRange set, MailboxPath from, MailboxPath to, MailboxSession session) throws MailboxException; |
| |
| List<MessageRange> moveMessages(MessageRange set, MailboxId from, MailboxId to, MailboxSession session) throws MailboxException; |
| |
| enum MailboxSearchFetchType { |
| Minimal, |
| Counters |
| } |
| |
| /** |
| * Searches for mailboxes matching the given query. |
| * |
| * @param expression |
| * not null |
| * @param session |
| * the context for this call, not null |
| */ |
| default Flux<MailboxMetaData> search(MailboxQuery expression, MailboxSession session) { |
| return search(expression, MailboxSearchFetchType.Counters, session); |
| } |
| |
| Flux<MailboxMetaData> search(MailboxQuery expression, MailboxSearchFetchType fetchType, MailboxSession session); |
| |
| /** |
| * Searches for messages matching the given query. |
| * |
| * @param expression |
| * not null |
| * @param session |
| * the context for this call, not null |
| */ |
| Publisher<MessageId> search(MultimailboxesSearchQuery expression, MailboxSession session, long limit); |
| |
| /** |
| * Returns the list of MessageId of messages belonging to that Thread |
| * |
| * @param threadId |
| * target Thread |
| * @param session |
| * the context for this call, not null |
| * @return the list of MessageId of messages belonging to that Thread |
| */ |
| Publisher<MessageId> getThread(ThreadId threadId, MailboxSession session); |
| |
| /** |
| * Does the given mailbox exist? |
| * |
| * @param mailboxPath |
| * not null |
| * @param session |
| * the context for this call, not null |
| * @return A publisher holding true when the mailbox exists and is accessible for the given |
| * user, false otherwise |
| */ |
| Publisher<Boolean> mailboxExists(MailboxPath mailboxPath, MailboxSession session) throws MailboxException; |
| |
| /** |
| * Does the user INBOX exist? |
| * |
| * @param session |
| * the context for this call, not null |
| * @return true when the INBOX exists and is accessible for the given |
| * user, false otherwise |
| */ |
| default Publisher<Boolean> hasInbox(MailboxSession session) throws MailboxException { |
| return mailboxExists(MailboxPath.inbox(session), session); |
| } |
| |
| /** |
| * Return a unmodifiable {@link List} of {@link MailboxPath} objects |
| */ |
| List<MailboxPath> list(MailboxSession session) throws MailboxException; |
| |
| boolean hasChildren(MailboxPath mailboxPath, MailboxSession session) throws MailboxException; |
| } |