Проблема с почтой Джакарты: MessageCountAdapter, похоже, не работаетJAVA

Программисты JAVA общаются здесь
Ответить
Anonymous
 Проблема с почтой Джакарты: MessageCountAdapter, похоже, не работает

Сообщение Anonymous »

Я столкнулся с проблемой при использовании Jakarta Mail для получения электронных писем и сбора определенных ключевых слов. Подробности:
Исходный код выглядит следующим образом:

Код: Выделить всё

package org.example.receiver.kit.component;

import jakarta.mail.Folder;
import jakarta.mail.Message;
import jakarta.mail.MessagingException;
import jakarta.mail.Session;
import jakarta.mail.Store;
import jakarta.mail.event.MessageCountAdapter;
import jakarta.mail.event.MessageCountEvent;
import lombok.NonNull;
import org.eclipse.angus.mail.imap.IdleManager;
import org.springframework.stereotype.Component;

import java.io.Closeable;
import java.io.IOException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.function.Consumer;
import java.util.logging.Logger;

@Component
public class MailReceiver implements Receiver {
public static final Logger logger = Logger.getLogger(MailReceiver.class.getName());
public static final String INBOX = "INBOX";

public static class CustomMessageCountAdapter extends MessageCountAdapter {
private final IdleManager idleManager;
private final Folder inbox;
private final Consumer messageConsumer;

public CustomMessageCountAdapter(IdleManager idleManager, Folder inbox, Consumer messageConsumer) {
this.idleManager = idleManager;
this.inbox = inbox;
this.messageConsumer = messageConsumer;
}

@Override
public void messagesAdded(MessageCountEvent e) {
logger.info("Receive" + e.getMessages().length + "mail(s)");
messageConsumer.accept(e.getMessages());

try {
idleManager.watch(inbox);
} catch (MessagingException ex) {
throw new RuntimeException(ex);
}
}

@Override
public void messagesRemoved(MessageCountEvent e) {
logger.info("Delete" + e.getMessages().length + "mail(s)");
messageConsumer.accept(e.getMessages());

try {
idleManager.watch(inbox);
} catch (MessagingException ex) {
throw new RuntimeException(ex);
}
}
}

public record MailProcessCleaner(Store mailStore, Folder inbox, ExecutorService es) implements Closeable {
public static final Logger logger = Logger.getLogger(MailReceiver.class.getName());
@Override
public void close() throws IOException {
try {
if (inbox.isOpen()) {
inbox.close();
logger.info("Mail server was closed");
}
if (mailStore.isConnected()) {
mailStore.close();
logger.info("Disconnection");
}
es.shutdown();
logger.info("Close thread pool");
} catch (MessagingException e) {
throw new RuntimeException(e);
}
}
}

@Override
public MailProcessCleaner receive(Consumer messageConsumer, @NonNull MailSessionProvider sessionProvider) throws MessagingException {
Session session = sessionProvider.provide();
ExecutorService es = Executors.newCachedThreadPool();
try {
IdleManager idleManager = new IdleManager(session, es);

Store mailStore = session.getStore();
mailStore.connect();

Folder inbox = mailStore.getFolder(INBOX);
inbox.open(Folder.READ_ONLY);

inbox.addMessageCountListener(getMessageCountAdapter(idleManager, inbox, messageConsumer));

idleManager.watch(inbox);

// messageConsumer.accept(inbox.getMessages());

return new MailProcessCleaner(mailStore, inbox, es);

} catch (IOException e) {
throw new RuntimeException(e);
}
}

protected MessageCountAdapter getMessageCountAdapter(IdleManager idleManager, Folder inbox, Consumer  messageConsumer) {
return new CustomMessageCountAdapter(idleManager, inbox, messageConsumer);
}

}
Моя конфигурация:

Код: Выделить всё

package org.example.receiver.kit.component;

import jakarta.mail.Authenticator;
import jakarta.mail.PasswordAuthentication;
import jakarta.mail.Session;
import lombok.Getter;

import java.util.Properties;
import java.util.logging.Logger;

@Getter
public abstract class MailSessionProvider implements Provider {
public static final Logger logger = Logger.getLogger(MailSessionProvider.class.getName());
private final String username;
private final String protocol;
private final String host;
private final Integer port;
private final boolean sslEnabled;
public static final String PASSWORD_ENV_KEY = "__MAIL_PASSWORD";

protected Properties defaultProperties = new Properties();

public MailSessionProvider(String username, String protocol, String host, Integer port, boolean sslEnabled) {
this.username = username;
this.protocol = protocol;
this.host = host;
this.port = port;
this.sslEnabled = sslEnabled;
createDefaultProperties();
}

private void createDefaultProperties() {
// https://jakarta.ee/specifications/mail/2.1/jakarta-mail-spec-2.1#a823
defaultProperties.setProperty("mail.store.protocol", this.protocol);
defaultProperties.setProperty("mail.imap.host", this.host);
defaultProperties.setProperty("mail.imap.port", String.valueOf(this.port));
defaultProperties.setProperty("mail.imap.ssl.enable", String.valueOf(this.sslEnabled));
defaultProperties.setProperty("mail.imap.starttls.enable", "false");
//     defaultProperties.setProperty("mail.imap.nio.enable", "true");
defaultProperties.setProperty("mail.imap.usesocketchannels", "true");
}

@Override
public Session provide() {
Properties properties = getConnectionProperties();

if (properties == null) {
properties = defaultProperties;
}

return Session.getInstance(
properties,
new Authenticator() {
@Override
protected PasswordAuthentication getPasswordAuthentication() {
return new PasswordAuthentication(username, getPassword());
}
});
}

public final String getPassword() {
return System.getenv(PASSWORD_ENV_KEY);
}

@Override
public Properties getConnectionProperties() {
return defaultProperties;
}

protected void setDefaultProperty(String key, String value) {
defaultProperties.setProperty(key, value);
}
}
Ввод:

Код: Выделить всё

@Autowired
FeishuMailSessionProvider feishuMailSessionProvider;

@Autowired
FeishuMailReceiver feishuMailReceiver;
@Test
public void test() throws MessagingException {
MailReceiver.MailProcessCleaner cleaner = feishuMailReceiver.receive((messages) -> {
try {
for (Message message : messages) {
System.out.println("Got" + Arrays.toString(message.getFrom()));
System.out.println(message.getSubject());
System.out.println(message.getContent());

}
} catch (IOException | MessagingException e) {
throw new RuntimeException(e);
}
System.out.println(messages.length);
}, feishuMailSessionProvider);

for(;;);
}
**Среда:**
  • JDK 17
  • spring-boot-starter-mail
  • Тестовое письмо: Feishu Mail (китайский поставщик услуг электронной почты)
Описание проблемы:
Программа работает нормально некоторое время после запуска. Когда я отправляю тестовые электронные письма на зарегистрированный адрес электронной почты, он успешно их получает и запускает уведомления — я получаю сообщение «Получить 1 письмо».
Однако есть два странных поведения:
  • Он больше не отправляет уведомления, когда я удаляю электронные письма. Хотя это не влияет на мою текущую функциональность, мне интересно узнать причину.
  • После того, как программа проработает около 30 минут, MessageCountAdapter, кажется, перестает получать новые электронные письма и не вызывает мой переопределенный метод messagesAdded. Однако, если я отправлю электронное письмо в течение 1–5 минут после запуска программы, она будет работать нормально — 6 минут, 10 минут или даже дольше (я еще не проверял верхний предел).
Может кто-нибудь объяснить такое поведение?

Подробнее здесь: https://stackoverflow.com/questions/798 ... em-to-work
Ответить

Быстрый ответ

Изменение регистра текста: 
Смайлики
:) :( :oops: :roll: :wink: :muza: :clever: :sorry: :angel: :read: *x)
Ещё смайлики…
   
К этому ответу прикреплено по крайней мере одно вложение.

Если вы не хотите добавлять вложения, оставьте поля пустыми.

Максимально разрешённый размер вложения: 15 МБ.

Вернуться в «JAVA»