This is an automated email from the ASF dual-hosted git repository.

btellier pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/james-project.git


The following commit(s) were added to refs/heads/master by this push:
     new 2c786d7d0a JAMES-33775 RSpamDListener (#1095)
2c786d7d0a is described below

commit 2c786d7d0a9ff319fe6c7448d0d3b4de469cd9f2
Author: vttran <[email protected]>
AuthorDate: Wed Aug 10 11:08:24 2022 +0700

    JAMES-33775 RSpamDListener (#1095)
---
 third-party/rspamd/pom.xml                         |   5 +
 .../org/apache/james/rspamd/RSpamDListener.java    | 192 ++++++++++++++
 .../apache/james/rspamd/RSpamDListenerTest.java    | 295 +++++++++++++++++++++
 3 files changed, 492 insertions(+)

diff --git a/third-party/rspamd/pom.xml b/third-party/rspamd/pom.xml
index 51142d3bf6..3b9faea8a5 100644
--- a/third-party/rspamd/pom.xml
+++ b/third-party/rspamd/pom.xml
@@ -118,6 +118,11 @@
             <type>test-jar</type>
             <scope>test</scope>
         </dependency>
+        <dependency>
+            <groupId>${james.groupId}</groupId>
+            <artifactId>metrics-tests</artifactId>
+            <scope>test</scope>
+        </dependency>
         <dependency>
             <groupId>${james.groupId}</groupId>
             <artifactId>testing-base</artifactId>
diff --git 
a/third-party/rspamd/src/main/java/org/apache/james/rspamd/RSpamDListener.java 
b/third-party/rspamd/src/main/java/org/apache/james/rspamd/RSpamDListener.java
new file mode 100644
index 0000000000..5a242f3f2c
--- /dev/null
+++ 
b/third-party/rspamd/src/main/java/org/apache/james/rspamd/RSpamDListener.java
@@ -0,0 +1,192 @@
+/****************************************************************
+ * 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.rspamd;
+
+
+import java.io.InputStream;
+
+import javax.inject.Inject;
+
+import org.apache.commons.lang3.tuple.Pair;
+import org.apache.james.core.Username;
+import org.apache.james.events.Event;
+import org.apache.james.events.EventListener;
+import org.apache.james.events.Group;
+import org.apache.james.mailbox.MailboxManager;
+import org.apache.james.mailbox.MailboxSession;
+import org.apache.james.mailbox.MessageManager;
+import org.apache.james.mailbox.Role;
+import org.apache.james.mailbox.SystemMailboxesProvider;
+import org.apache.james.mailbox.events.MailboxEvents;
+import org.apache.james.mailbox.events.MessageMoveEvent;
+import org.apache.james.mailbox.model.MessageRange;
+import org.apache.james.mailbox.store.MailboxSessionMapperFactory;
+import org.apache.james.mailbox.store.event.SpamEventListener;
+import org.apache.james.mailbox.store.mail.MessageMapper;
+import org.apache.james.mailbox.store.mail.model.MailboxMessage;
+import org.apache.james.rspamd.client.RSpamDHttpClient;
+import org.apache.james.util.FunctionalUtils;
+import org.apache.james.util.ReactorUtils;
+import org.reactivestreams.Publisher;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.github.fge.lambdas.Throwing;
+import com.google.common.annotations.VisibleForTesting;
+
+import reactor.core.publisher.Flux;
+import reactor.core.publisher.Mono;
+
+public class RSpamDListener implements SpamEventListener, 
EventListener.ReactiveGroupEventListener {
+    public static class RSpamDListenerGroup extends Group {
+
+    }
+
+    private static final Logger LOGGER = 
LoggerFactory.getLogger(RSpamDListener.class);
+
+    private static final int LIMIT = 1;
+    private static final Group GROUP = new RSpamDListenerGroup();
+
+    private final RSpamDHttpClient rSpamDHttpClient;
+    private final MailboxManager mailboxManager;
+    private final MailboxSessionMapperFactory mapperFactory;
+    private final SystemMailboxesProvider systemMailboxesProvider;
+
+    @Inject
+    public RSpamDListener(RSpamDHttpClient rSpamDHttpClient, MailboxManager 
mailboxManager, MailboxSessionMapperFactory mapperFactory, 
SystemMailboxesProvider systemMailboxesProvider) {
+        this.rSpamDHttpClient = rSpamDHttpClient;
+        this.mailboxManager = mailboxManager;
+        this.mapperFactory = mapperFactory;
+        this.systemMailboxesProvider = systemMailboxesProvider;
+    }
+
+    @Override
+    public Group getDefaultGroup() {
+        return GROUP;
+    }
+
+    @Override
+    public boolean isHandling(Event event) {
+        return event instanceof MessageMoveEvent || event instanceof 
MailboxEvents.Added;
+    }
+
+    @Override
+    public Publisher<Void> reactiveEvent(Event event) {
+        if (event instanceof MessageMoveEvent) {
+            return handleMessageMoved((MessageMoveEvent) event);
+        } else if (event instanceof MailboxEvents.Added) {
+            return handleMessageAdded((MailboxEvents.Added) event);
+        }
+        return Mono.empty();
+    }
+
+    private Mono<Void> handleMessageAdded(MailboxEvents.Added addedEvent) {
+        return isAppendedToInbox(addedEvent)
+            .filter(FunctionalUtils.identityPredicate())
+            .doOnNext(isHam -> LOGGER.debug("Ham event detected, EventId = 
{}", addedEvent.getEventId().getId()))
+            .flatMap(any -> reportHamWhenAdded(addedEvent, 
mailboxManager.createSystemSession(Username.of(getClass().getCanonicalName()))));
+    }
+
+    private Mono<Void> handleMessageMoved(MessageMoveEvent messageMoveEvent) {
+        return handleMessageMoved(mailboxMessagePublisher(messageMoveEvent), 
messageMoveEvent);
+    }
+
+    private Mono<Void> reportHamWhenAdded(MailboxEvents.Added addedEvent, 
MailboxSession session) {
+        return mapperFactory.getMailboxMapper(session)
+            .findMailboxById(addedEvent.getMailboxId())
+            .map(mailbox -> Pair.of(mailbox, 
mapperFactory.getMessageMapper(session)))
+            .flatMapMany(pair -> 
Flux.fromIterable(MessageRange.toRanges(addedEvent.getUids()))
+                .flatMap(range -> 
pair.getRight().findInMailboxReactive(pair.getLeft(), range, 
MessageMapper.FetchType.FULL, LIMIT)))
+            .map(Throwing.function(MailboxMessage::getFullContent))
+            .flatMap(rSpamDHttpClient::reportAsHam, 
ReactorUtils.DEFAULT_CONCURRENCY)
+            .then();
+    }
+
+    private Flux<InputStream> mailboxMessagePublisher(MessageMoveEvent 
messageMoveEvent) {
+        return Mono.fromCallable(() -> 
mapperFactory.getMessageIdMapper(mailboxManager.createSystemSession(Username.of(getClass().getCanonicalName()))))
+            .flatMapMany(messageIdMapper -> 
messageIdMapper.findReactive(messageMoveEvent.getMessageIds(), 
MessageMapper.FetchType.FULL))
+            .map(Throwing.function(MailboxMessage::getFullContent));
+    }
+
+    private Mono<Void> handleMessageMoved(Flux<InputStream> 
mailboxMessagesPublisher, MessageMoveEvent messageMoveEvent) {
+        Mono<Boolean> reportHamIfNotSpamDetected = 
isMessageMovedOutOfSpamMailbox(messageMoveEvent)
+            .filter(FunctionalUtils.identityPredicate())
+            .doOnNext(isHam -> LOGGER.debug("Ham event detected, EventId = 
{}", messageMoveEvent.getEventId().getId()));
+
+        return isMessageMovedToSpamMailbox(messageMoveEvent)
+            .flatMap(isSpam -> {
+                if (isSpam) {
+                    LOGGER.debug("Spam event detected, EventId = {}", 
messageMoveEvent.getEventId().getId());
+                    return 
mailboxMessagesPublisher.flatMap(rSpamDHttpClient::reportAsSpam, 
ReactorUtils.DEFAULT_CONCURRENCY)
+                        .then();
+                } else {
+                    return reportHamIfNotSpamDetected
+                        .flatMapMany(isHam -> 
mailboxMessagesPublisher.flatMap(rSpamDHttpClient::reportAsHam, 
ReactorUtils.DEFAULT_CONCURRENCY))
+                        .then();
+                }
+            });
+    }
+
+    @VisibleForTesting
+    Mono<Boolean> isMessageMovedToSpamMailbox(MessageMoveEvent event) {
+        return isMessageMovedToMailbox(event, Role.SPAM);
+    }
+
+    @VisibleForTesting
+    Mono<Boolean> isMessageMovedOutOfSpamMailbox(MessageMoveEvent event) {
+        return isMessageMovedOutToMailbox(event, Role.SPAM)
+            .zipWith(isMessageMovedToMailbox(event, Role.TRASH))
+            .map(tuple -> tuple.getT1() && !tuple.getT2());
+    }
+
+    @VisibleForTesting
+    Mono<Boolean> isAppendedToInbox(MailboxEvents.Added addedEvent) {
+        return Flux.from(systemMailboxesProvider.getMailboxByRole(Role.INBOX, 
addedEvent.getUsername()))
+            .next()
+            .map(MessageManager::getId)
+            .map(mailboxId -> mailboxId.equals(addedEvent.getMailboxId()))
+            .onErrorResume(e -> {
+                LOGGER.warn("Could not resolve Inbox mailbox", e);
+                return Mono.just(false);
+            });
+    }
+
+    private Mono<Boolean> isMessageMovedToMailbox(MessageMoveEvent event, Role 
role) {
+        return Flux.from(systemMailboxesProvider.getMailboxByRole(role, 
event.getUsername()))
+            .next()
+            .map(MessageManager::getId)
+            .map(spamMailboxId -> 
event.getMessageMoves().addedMailboxIds().contains(spamMailboxId))
+            .onErrorResume(e -> {
+                LOGGER.warn("Could not resolve {} mailbox", role, e);
+                return Mono.just(false);
+            });
+    }
+
+    private Mono<Boolean> isMessageMovedOutToMailbox(MessageMoveEvent event, 
Role role) {
+        return Flux.from(systemMailboxesProvider.getMailboxByRole(role, 
event.getUsername()))
+            .next()
+            .map(MessageManager::getId)
+            .map(spamMailboxId -> 
event.getMessageMoves().removedMailboxIds().contains(spamMailboxId))
+            .onErrorResume(e -> {
+                LOGGER.warn("Could not resolve {} mailbox", role, e);
+                return Mono.just(false);
+            });
+    }
+}
\ No newline at end of file
diff --git 
a/third-party/rspamd/src/test/java/org/apache/james/rspamd/RSpamDListenerTest.java
 
b/third-party/rspamd/src/test/java/org/apache/james/rspamd/RSpamDListenerTest.java
new file mode 100644
index 0000000000..dd0db4b0ae
--- /dev/null
+++ 
b/third-party/rspamd/src/test/java/org/apache/james/rspamd/RSpamDListenerTest.java
@@ -0,0 +1,295 @@
+/****************************************************************
+ * 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.rspamd;
+
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import java.nio.charset.StandardCharsets;
+import java.util.Date;
+
+import javax.mail.Flags;
+
+import org.apache.james.core.Username;
+import org.apache.james.events.Group;
+import org.apache.james.mailbox.DefaultMailboxes;
+import org.apache.james.mailbox.MailboxSession;
+import org.apache.james.mailbox.MailboxSessionUtil;
+import org.apache.james.mailbox.events.MailboxEvents;
+import org.apache.james.mailbox.events.MessageMoveEvent;
+import org.apache.james.mailbox.exception.MailboxException;
+import org.apache.james.mailbox.inmemory.manager.InMemoryIntegrationResources;
+import org.apache.james.mailbox.model.ByteContent;
+import org.apache.james.mailbox.model.Mailbox;
+import org.apache.james.mailbox.model.MailboxId;
+import org.apache.james.mailbox.model.MailboxPath;
+import org.apache.james.mailbox.model.MessageMetaData;
+import org.apache.james.mailbox.model.MessageMoves;
+import org.apache.james.mailbox.model.TestMessageId;
+import org.apache.james.mailbox.model.ThreadId;
+import org.apache.james.mailbox.model.UidValidity;
+import org.apache.james.mailbox.store.MailboxSessionMapperFactory;
+import org.apache.james.mailbox.store.StoreMailboxManager;
+import org.apache.james.mailbox.store.SystemMailboxesProviderImpl;
+import org.apache.james.mailbox.store.event.EventFactory;
+import org.apache.james.mailbox.store.mail.MailboxMapper;
+import org.apache.james.mailbox.store.mail.model.impl.PropertyBuilder;
+import org.apache.james.mailbox.store.mail.model.impl.SimpleMailboxMessage;
+import org.apache.james.rspamd.client.RSpamDHttpClient;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+
+import reactor.core.publisher.Mono;
+
+public class RSpamDListenerTest {
+    static final Username USER = Username.of("user");
+    static final MailboxSession MAILBOX_SESSION = 
MailboxSessionUtil.create(USER);
+    static final UidValidity UID_VALIDITY = UidValidity.of(43);
+    static final TestMessageId MESSAGE_ID = TestMessageId.of(45);
+    static final ThreadId THREAD_ID = ThreadId.fromBaseMessageId(MESSAGE_ID);
+
+    private RSpamDHttpClient rSpamDHttpClient;
+    private RSpamDListener listener;
+    private MailboxSessionMapperFactory mapperFactory;
+
+    private Mailbox inbox;
+    private Mailbox mailbox1;
+    private Mailbox mailbox2;
+    private MailboxId mailboxId1;
+    private MailboxId mailboxId2;
+    private MailboxId spamMailboxId;
+    private MailboxId spamCapitalMailboxId;
+    private MailboxId trashMailboxId;
+
+    @BeforeEach
+    void setup() {
+        rSpamDHttpClient = mock(RSpamDHttpClient.class);
+
+        when(rSpamDHttpClient.reportAsHam(any())).thenReturn(Mono.empty());
+        when(rSpamDHttpClient.reportAsSpam(any())).thenReturn(Mono.empty());
+
+        StoreMailboxManager mailboxManager = 
spy(InMemoryIntegrationResources.defaultResources().getMailboxManager());
+        SystemMailboxesProviderImpl systemMailboxesProvider = new 
SystemMailboxesProviderImpl(mailboxManager);
+        when(mailboxManager.createSystemSession(USER))
+            .thenReturn(MAILBOX_SESSION);
+        mapperFactory = mailboxManager.getMapperFactory();
+        MailboxMapper mailboxMapper = 
mapperFactory.createMailboxMapper(MAILBOX_SESSION);
+        inbox = mailboxMapper.create(MailboxPath.forUser(USER, 
DefaultMailboxes.INBOX), UID_VALIDITY).block();
+        mailbox1 = mailboxMapper.create(MailboxPath.forUser(USER, "mailbox1"), 
UID_VALIDITY).block();
+        mailbox2 = mailboxMapper.create(MailboxPath.forUser(USER, "mailbox2"), 
UID_VALIDITY).block();
+        mailboxId1 = mailbox1.getMailboxId();
+        mailboxId2 = mailbox2.getMailboxId();
+        spamMailboxId = mailboxMapper.create(MailboxPath.forUser(USER, 
"Spam"), UID_VALIDITY).block().getMailboxId();
+        spamCapitalMailboxId = mailboxMapper.create(MailboxPath.forUser(USER, 
"SPAM"), UID_VALIDITY).block().getMailboxId();
+        trashMailboxId = mailboxMapper.create(MailboxPath.forUser(USER, 
"Trash"), UID_VALIDITY).block().getMailboxId();
+
+        listener = new RSpamDListener(rSpamDHttpClient, mailboxManager, 
mapperFactory, systemMailboxesProvider);
+    }
+
+    @Test
+    void deserializeListenerGroup() throws Exception {
+        
assertThat(Group.deserialize("org.apache.james.rspamd.RSpamDListener$RSpamDListenerGroup"))
+            .isEqualTo(new RSpamDListener.RSpamDListenerGroup());
+    }
+
+    @Test
+    void 
isEventOnSpamMailboxShouldReturnFalseWhenMessageIsMovedToANonSpamMailbox() {
+        MessageMoveEvent messageMoveEvent = MessageMoveEvent.builder()
+            .session(MAILBOX_SESSION)
+            .messageMoves(MessageMoves.builder()
+                .previousMailboxIds(mailboxId1)
+                .targetMailboxIds(mailboxId2)
+                .build())
+            .messageId(MESSAGE_ID)
+            .build();
+
+        
assertThat(listener.isMessageMovedToSpamMailbox(messageMoveEvent).block()).isFalse();
+    }
+
+    @Test
+    void isEventOnSpamMailboxShouldReturnTrueWhenMailboxIsSpam() {
+        MessageMoveEvent messageMoveEvent = MessageMoveEvent.builder()
+            .session(MAILBOX_SESSION)
+            .messageMoves(MessageMoves.builder()
+                .previousMailboxIds(mailboxId1)
+                .targetMailboxIds(spamMailboxId)
+                .build())
+            .messageId(MESSAGE_ID)
+            .build();
+
+        
assertThat(listener.isMessageMovedToSpamMailbox(messageMoveEvent).block()).isTrue();
+    }
+
+    @Test
+    void isEventOnSpamMailboxShouldReturnFalseWhenMailboxIsSpamOtherCase() {
+        MessageMoveEvent messageMoveEvent = MessageMoveEvent.builder()
+            .session(MAILBOX_SESSION)
+            .messageMoves(MessageMoves.builder()
+                .previousMailboxIds(mailboxId1)
+                .targetMailboxIds(spamCapitalMailboxId)
+                .build())
+            .messageId(MESSAGE_ID)
+            .build();
+
+        
assertThat(listener.isMessageMovedToSpamMailbox(messageMoveEvent).block()).isFalse();
+    }
+
+    @Test
+    void 
isMessageMovedOutOfSpamMailboxShouldReturnFalseWhenMessageMovedBetweenNonSpamMailboxes()
 {
+        MessageMoveEvent messageMoveEvent = MessageMoveEvent.builder()
+            .session(MAILBOX_SESSION)
+            .messageMoves(MessageMoves.builder()
+                .previousMailboxIds(mailboxId1)
+                .targetMailboxIds(mailboxId2)
+                .build())
+            .messageId(MESSAGE_ID)
+            .build();
+
+        
assertThat(listener.isMessageMovedOutOfSpamMailbox(messageMoveEvent).block()).isFalse();
+    }
+
+    @Test
+    void 
isMessageMovedOutOfSpamMailboxShouldReturnFalseWhenMessageMovedOutOfCapitalSpamMailbox()
 {
+        MessageMoveEvent messageMoveEvent = MessageMoveEvent.builder()
+            .session(MAILBOX_SESSION)
+            .messageMoves(MessageMoves.builder()
+                .previousMailboxIds(spamCapitalMailboxId)
+                .targetMailboxIds(mailboxId2)
+                .build())
+            .messageId(MESSAGE_ID)
+            .build();
+
+        
assertThat(listener.isMessageMovedOutOfSpamMailbox(messageMoveEvent).block()).isFalse();
+    }
+
+    @Test
+    void 
isMessageMovedOutOfSpamMailboxShouldReturnTrueWhenMessageMovedOutOfSpamMailbox()
 {
+        MessageMoveEvent messageMoveEvent = MessageMoveEvent.builder()
+            .session(MAILBOX_SESSION)
+            .messageMoves(MessageMoves.builder()
+                .previousMailboxIds(spamMailboxId)
+                .targetMailboxIds(mailboxId2)
+                .build())
+            .messageId(MESSAGE_ID)
+            .build();
+
+        
assertThat(listener.isMessageMovedOutOfSpamMailbox(messageMoveEvent).block()).isTrue();
+    }
+
+    @Test
+    void 
isMessageMovedOutOfSpamMailboxShouldReturnFalseWhenMessageMovedToTrash() {
+        MessageMoveEvent messageMoveEvent = MessageMoveEvent.builder()
+            .session(MAILBOX_SESSION)
+            .messageMoves(MessageMoves.builder()
+                .previousMailboxIds(spamMailboxId)
+                .targetMailboxIds(trashMailboxId)
+                .build())
+            .messageId(MESSAGE_ID)
+            .build();
+
+        
assertThat(listener.isMessageMovedOutOfSpamMailbox(messageMoveEvent).block()).isFalse();
+    }
+
+
+    @Test
+    void eventShouldCallReportSpamLearningWhenTheMovedEventMatches() throws 
Exception {
+        createMessage(inbox);
+        MessageMoveEvent messageMoveEvent = MessageMoveEvent.builder()
+            .session(MAILBOX_SESSION)
+            .messageMoves(MessageMoves.builder()
+                .previousMailboxIds(mailboxId1)
+                .targetMailboxIds(spamMailboxId)
+                .build())
+            .messageId(MESSAGE_ID)
+            .build();
+
+        listener.event(messageMoveEvent);
+
+        verify(rSpamDHttpClient).reportAsSpam(any());
+    }
+
+    @Test
+    void eventShouldCallHamLearningWhenTheMovedEventMatches() throws Exception 
{
+        createMessage(inbox);
+
+        MessageMoveEvent messageMoveEvent = MessageMoveEvent.builder()
+            .session(MAILBOX_SESSION)
+            .messageMoves(MessageMoves.builder()
+                .previousMailboxIds(spamMailboxId)
+                .targetMailboxIds(mailboxId1)
+                .build())
+            .messageId(MESSAGE_ID)
+            .build();
+
+        listener.event(messageMoveEvent);
+
+        verify(rSpamDHttpClient).reportAsHam(any());
+    }
+
+    @Test
+    void eventShouldCallReportHamLearningWhenTheMessageIsAddedInInbox() throws 
Exception {
+        SimpleMailboxMessage message = createMessage(inbox);
+
+        MailboxEvents.Added addedEvent = EventFactory.added()
+            .randomEventId()
+            .mailboxSession(MAILBOX_SESSION)
+            .mailbox(inbox)
+            .addMetaData(message.metaData())
+            .build();
+
+        listener.event(addedEvent);
+
+        verify(rSpamDHttpClient).reportAsHam(any());
+    }
+
+    @Test
+    void 
eventShouldNotCallReportHamLearningWhenTheMessageIsAddedInAMailboxOtherThanInbox()
 throws Exception {
+        SimpleMailboxMessage message = createMessage(mailbox1);
+
+        MailboxEvents.Added addedEvent = EventFactory.added()
+            .randomEventId()
+            .mailboxSession(MAILBOX_SESSION)
+            .mailbox(mailbox1)
+            .addMetaData(message.metaData())
+            .build();
+
+        listener.event(addedEvent);
+
+        verify(rSpamDHttpClient, never()).reportAsHam(any());
+    }
+
+    private SimpleMailboxMessage createMessage(Mailbox mailbox) throws 
MailboxException {
+        int size = 45;
+        int bodyStartOctet = 25;
+        byte[] content = "Subject: 
test\r\n\r\nBody\r\n".getBytes(StandardCharsets.UTF_8);
+        SimpleMailboxMessage message = new SimpleMailboxMessage(MESSAGE_ID, 
THREAD_ID, new Date(),
+            size, bodyStartOctet, new ByteContent(content), new Flags(), new 
PropertyBuilder().build(),
+            mailbox.getMailboxId());
+        MessageMetaData messageMetaData = 
mapperFactory.createMessageMapper(null).add(mailbox, message);
+        message.setUid(messageMetaData.getUid());
+        return message;
+    }
+}


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to