public void setInMailboxesNoCheck(MessageId messageId, MailboxId targetMailboxId, MailboxSession mailboxSession) throws MailboxException { MessageIdMapper messageIdMapper = mailboxSessionMapperFactory.getMessageIdMapper(mailboxSession); List<MailboxMessage> currentMailboxMessages = messageIdMapper.find(ImmutableList.of(messageId), MessageMapper.FetchType.Full); MessageMoves messageMoves = MessageMoves.builder() .previousMailboxIds(toMailboxIds(currentMailboxMessages)) .targetMailboxIds(targetMailboxId) .build(); if (messageMoves.isChange()) { applyMessageMoveNoMailboxChecks(mailboxSession, currentMailboxMessages, messageMoves); } }
public Stream<MailboxId> impactedMailboxIds() { return Stream.concat( addedMailboxIds().stream(), removedMailboxIds().stream()); }
public MessageMoves build() { return new MessageMoves(previousMailboxIds.build(), targetMailboxIds.build()); } }
private SortedMap<MessageUid, MessageMetaData> copy(MessageRange set, StoreMessageManager to, MailboxSession session) throws MailboxException { IteratorWrapper<MailboxMessage> originalRows = new IteratorWrapper<>(retrieveOriginalRows(set, session)); SortedMap<MessageUid, MessageMetaData> copiedUids = collectMetadata(to.copy(originalRows, session)); ImmutableMap.Builder<MessageUid, MailboxMessage> messagesMap = ImmutableMap.builder(); for (MailboxMessage message : originalRows.getEntriesSeen()) { messagesMap.put(message.getUid(), immutableMailboxMessageFactory.from(to.getMailboxEntity().getMailboxId(), message)); } dispatcher.added(session, copiedUids, to.getMailboxEntity(), messagesMap.build()); dispatcher.moved(session, MessageMoves.builder() .previousMailboxIds(getMailboxEntity().getMailboxId()) .targetMailboxIds(to.getMailboxEntity().getMailboxId(), getMailboxEntity().getMailboxId()) .build(), messagesMap.build()); return copiedUids; }
private void assertValidUpdate(List<MessageResult> messagesToBeUpdated, UpdateMessagePatch updateMessagePatch, MailboxSession session) throws MailboxException { List<MailboxId> outboxMailboxes = mailboxIdFor(Role.OUTBOX, session); ImmutableList<MailboxId> previousMailboxes = messagesToBeUpdated.stream() .map(MessageResult::getMailboxId) .collect(Guavate.toImmutableList()); List<MailboxId> targetMailboxes = getTargetedMailboxes(previousMailboxes, updateMessagePatch); boolean isDraft = messagesToBeUpdated.stream() .map(MessageResult::getFlags) .map(Keywords.factory().filterImapNonExposedKeywords()::fromFlags) .reduce(new KeywordsCombiner()) .orElse(Keywords.DEFAULT_VALUE) .contains(Keyword.DRAFT); MessageMoves messageMoves = MessageMoves.builder() .previousMailboxIds(previousMailboxes) .targetMailboxIds(targetMailboxes) .build(); boolean targetContainsOutbox = messageMoves.addedMailboxIds().stream().anyMatch(outboxMailboxes::contains); boolean targetIsOnlyOutbox = targetMailboxes.stream().allMatch(outboxMailboxes::contains); assertOutboxMoveTargetsOnlyOutBox(targetContainsOutbox, targetIsOnlyOutbox); assertOutboxMoveOriginallyHasDraftKeywordSet(targetContainsOutbox, isDraft); }
public boolean isMoveTo(MailboxId mailboxId) { return messageMoves.addedMailboxIds() .contains(mailboxId); }
public boolean isMoveFrom(MailboxId mailboxId) { return messageMoves.removedMailboxIds() .contains(mailboxId); } }
private SortedMap<MessageUid, MessageMetaData> move(MessageRange set, StoreMessageManager to, MailboxSession session) throws MailboxException { IteratorWrapper<MailboxMessage> originalRows = new IteratorWrapper<>(retrieveOriginalRows(set, session)); MoveResult moveResult = to.move(originalRows, session); SortedMap<MessageUid, MessageMetaData> moveUids = collectMetadata(moveResult.getMovedMessages()); ImmutableMap.Builder<MessageUid, MailboxMessage> messagesMap = ImmutableMap.builder(); for (MailboxMessage message : originalRows.getEntriesSeen()) { messagesMap.put(message.getUid(), immutableMailboxMessageFactory.from(to.getMailboxEntity().getMailboxId(), message)); } dispatcher.added(session, moveUids, to.getMailboxEntity(), messagesMap.build()); dispatcher.expunged(session, collectMetadata(moveResult.getOriginalMessages()), getMailboxEntity()); dispatcher.moved(session, MessageMoves.builder() .previousMailboxIds(getMailboxEntity().getMailboxId()) .targetMailboxIds(to.getMailboxEntity().getMailboxId()) .build(), messagesMap.build()); return moveUids; }
public boolean isMoveTo(MailboxId mailboxId) { return messageMoves.addedMailboxIds() .contains(mailboxId); }
public boolean isMoveFrom(MailboxId mailboxId) { return messageMoves.removedMailboxIds() .contains(mailboxId); }
@Test public void eventShouldCallSpamAssassinSpamLearningWhenTheEventMatches() { MessageMoveEvent messageMoveEvent = MessageMoveEvent.builder() .session(MAILBOX_SESSION) .messageMoves(MessageMoves.builder() .previousMailboxIds(mailboxId1) .targetMailboxIds(spamMailboxId) .build()) .messages(ImmutableMap.of(MessageUid.of(45), createMessage(mailboxId1))) .build(); listener.event(messageMoveEvent); verify(spamAssassin).learnSpam(any(), any()); }
private Map<QuotaRoot, Integer> buildMapQuotaRoot(MessageMoves messageMoves, MailboxMapper mailboxMapper) throws MailboxException { Map<QuotaRoot, Integer> messageCountByQuotaRoot = new HashMap<>(); for (MailboxId mailboxId : messageMoves.addedMailboxIds()) { QuotaRoot quotaRoot = retrieveQuotaRoot(mailboxMapper, mailboxId); int currentCount = Optional.ofNullable(messageCountByQuotaRoot.get(quotaRoot)) .orElse(0); messageCountByQuotaRoot.put(quotaRoot, currentCount + 1); } for (MailboxId mailboxId : messageMoves.removedMailboxIds()) { QuotaRoot quotaRoot = retrieveQuotaRoot(mailboxMapper, mailboxId); int currentCount = Optional.ofNullable(messageCountByQuotaRoot.get(quotaRoot)) .orElse(0); messageCountByQuotaRoot.put(quotaRoot, currentCount - 1); } return messageCountByQuotaRoot; }
@Override public void setInMailboxes(MessageId messageId, Collection<MailboxId> targetMailboxIds, MailboxSession mailboxSession) throws MailboxException { assertRightsOnMailboxes(targetMailboxIds, mailboxSession, Right.Read); List<MailboxMessage> currentMailboxMessages = findRelatedMailboxMessages(messageId, mailboxSession); if (currentMailboxMessages.isEmpty()) { LOGGER.info("Tried to access {} not accessible for {}", messageId, mailboxSession.getUser().getUserName()); return; } MessageMoves messageMoves = MessageMoves.builder() .targetMailboxIds(targetMailboxIds) .previousMailboxIds(toMailboxIds(currentMailboxMessages)) .build(); if (messageMoves.isChange()) { applyMessageMoves(mailboxSession, currentMailboxMessages, messageMoves); } }
@Test public void isEventOnSpamMailboxShouldReturnTrueWhenMailboxIsSpam() { MessageMoveEvent messageMoveEvent = MessageMoveEvent.builder() .session(MAILBOX_SESSION) .messageMoves(MessageMoves.builder() .previousMailboxIds(mailboxId1) .targetMailboxIds(spamMailboxId) .build()) .messages(ImmutableMap.of(MessageUid.of(45), createMessage(mailboxId1))) .build(); assertThat(listener.isMessageMovedToSpamMailbox(messageMoveEvent)).isTrue(); }
private void applyMessageMoves(MailboxSession mailboxSession, List<MailboxMessage> currentMailboxMessages, MessageMoves messageMoves) throws MailboxException { assertRightsOnMailboxes(messageMoves.addedMailboxIds(), mailboxSession, Right.Insert); assertRightsOnMailboxes(messageMoves.removedMailboxIds(), mailboxSession, Right.DeleteMessages); applyMessageMoveNoMailboxChecks(mailboxSession, currentMailboxMessages, messageMoves); }
@Test public void isEventOnSpamMailboxShouldReturnFalseWhenMailboxIsSpamOtherCase() { MessageMoveEvent messageMoveEvent = MessageMoveEvent.builder() .session(MAILBOX_SESSION) .messageMoves(MessageMoves.builder() .previousMailboxIds(mailboxId1) .targetMailboxIds(spamCapitalMailboxId) .build()) .messages(ImmutableMap.of(MessageUid.of(45), createMessage(mailboxId1))) .build(); assertThat(listener.isMessageMovedToSpamMailbox(messageMoveEvent)).isFalse(); }
private void applyMessageMoveNoMailboxChecks(MailboxSession mailboxSession, List<MailboxMessage> currentMailboxMessages, MessageMoves messageMoves) throws MailboxException { MailboxMessage mailboxMessage = currentMailboxMessages.stream().findAny().orElseThrow(() -> new MailboxNotFoundException("can't load message")); validateQuota(messageMoves, mailboxSession, mailboxMessage); addMessageToMailboxes(mailboxMessage, messageMoves.addedMailboxIds(), mailboxSession); removeMessageFromMailboxes(mailboxMessage, messageMoves.removedMailboxIds(), mailboxSession); dispatcher.moved(mailboxSession, messageMoves, ImmutableMap.of(mailboxMessage.getUid(), mailboxMessage)); }
@Test public void eventShouldCallSpamAssassinHamLearningWhenTheEventMatches() { MessageMoveEvent messageMoveEvent = MessageMoveEvent.builder() .session(MAILBOX_SESSION) .messageMoves(MessageMoves.builder() .previousMailboxIds(spamMailboxId) .targetMailboxIds(mailboxId1) .build()) .messages(ImmutableMap.of(MessageUid.of(45), createMessage(mailboxId1))) .build(); listener.event(messageMoveEvent); verify(spamAssassin).learnHam(any(), any()); }
@Test public void isMessageMovedOutOfSpamMailboxShouldReturnTrueWhenMessageMovedOutOfSpamMailbox() { MessageMoveEvent messageMoveEvent = MessageMoveEvent.builder() .session(MAILBOX_SESSION) .messageMoves(MessageMoves.builder() .previousMailboxIds(spamMailboxId) .targetMailboxIds(mailboxId2) .build()) .messages(ImmutableMap.of(MessageUid.of(45), createMessage(mailboxId2))) .build(); assertThat(listener.isMessageMovedOutOfSpamMailbox(messageMoveEvent)).isTrue(); }
@Test public void isEventOnSpamMailboxShouldReturnFalseWhenMessageIsMovedToANonSpamMailbox() { MessageMoveEvent messageMoveEvent = MessageMoveEvent.builder() .session(MAILBOX_SESSION) .messageMoves(MessageMoves.builder() .previousMailboxIds(mailboxId1) .targetMailboxIds(mailboxId2) .build()) .messages(ImmutableMap.of(MessageUid.of(45), createMessage(mailboxId2))) .build(); assertThat(listener.isMessageMovedToSpamMailbox(messageMoveEvent)).isFalse(); }