blob: 91f0c8ba111a6109a7cc81883c8f0e2f0ce2f4ba [file] [log] [blame]
/****************************************************************
* 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.jmap.draft.methods;
import java.util.Map;
import java.util.NoSuchElementException;
import java.util.Optional;
import jakarta.inject.Inject;
import jakarta.mail.Flags;
import org.apache.james.mailbox.MailboxManager;
import org.apache.james.mailbox.MailboxSession;
import org.apache.james.mailbox.MessageIdManager;
import org.apache.james.mailbox.MessageManager.FlagsUpdateMode;
import org.apache.james.mailbox.exception.MailboxException;
import org.apache.james.mailbox.model.Header;
import org.apache.james.mailbox.model.Headers;
import org.apache.james.mailbox.model.MessageId;
import org.apache.james.mailbox.model.MultimailboxesSearchQuery;
import org.apache.james.mailbox.model.SearchQuery;
import org.apache.james.util.streams.Iterators;
import org.apache.mailet.base.RFC2822Headers;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.github.fge.lambdas.Throwing;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.Iterables;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;
public class ReferenceUpdater {
public static final String X_FORWARDED_ID_HEADER = "X-Forwarded-Message-Id";
public static final Flags FORWARDED_FLAG = new Flags("$Forwarded");
private static final Logger logger = LoggerFactory.getLogger(ReferenceUpdater.class);
private final MessageIdManager messageIdManager;
private final MailboxManager mailboxManager;
@Inject
public ReferenceUpdater(MessageIdManager messageIdManager, MailboxManager mailboxManager) {
this.messageIdManager = messageIdManager;
this.mailboxManager = mailboxManager;
}
public Mono<Void> updateReferences(Headers headers, MailboxSession session) throws MailboxException {
Map<String, String> headersAsMap = Iterators.toStream(headers.headers())
.collect(ImmutableMap.toImmutableMap(Header::getName, Header::getValue));
return updateReferences(headersAsMap, session);
}
public Mono<Void> updateReferences(Map<String, String> headers, MailboxSession session) throws MailboxException {
Optional<String> inReplyToId = Optional.ofNullable(headers.get(RFC2822Headers.IN_REPLY_TO));
Optional<String> forwardedId = Optional.ofNullable(headers.get(X_FORWARDED_ID_HEADER));
return inReplyToId.map(Throwing.function((String id) -> updateAnswered(id, session)).sneakyThrow()).orElse(Mono.empty())
.then(forwardedId.map((Throwing.function((String id) -> updateForwarded(id, session)).sneakyThrow())).orElse(Mono.empty()));
}
private Mono<Void> updateAnswered(String messageId, MailboxSession session) throws MailboxException {
return updateFlag(messageId, session, new Flags(Flags.Flag.ANSWERED));
}
private Mono<Void> updateForwarded(String messageId, MailboxSession session) throws MailboxException {
return updateFlag(messageId, session, FORWARDED_FLAG);
}
private Mono<Void> updateFlag(String messageId, MailboxSession session, Flags flag) throws MailboxException {
int limit = 2;
MultimailboxesSearchQuery searchByRFC822MessageId = MultimailboxesSearchQuery
.from(SearchQuery.of(SearchQuery.mimeMessageID(messageId)))
.build();
return Flux.from(mailboxManager.search(searchByRFC822MessageId, session, limit))
.collectList()
.flatMap(references -> {
MessageId reference = Iterables.getOnlyElement(references);
return Flux.from(messageIdManager.messageMetadata(reference, session))
.map(metaData -> metaData.getComposedMessageId().getMailboxId())
.collect(ImmutableList.toImmutableList())
.flatMap(mailboxIds -> Mono.from(messageIdManager.setFlagsReactive(flag, FlagsUpdateMode.ADD, reference, mailboxIds, session)));
})
.onErrorResume(NoSuchElementException.class, e -> {
logger.info("Unable to find a message with this Mime Message Id: " + messageId);
return Mono.empty();
})
.onErrorResume(IllegalArgumentException.class, e -> {
logger.info("Too many messages are matching this Mime Message Id: " + messageId);
return Mono.empty();
});
}
}