You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
228 lines
7.3 KiB
228 lines
7.3 KiB
package de.srsoftware.widerhall.mail; |
|
|
|
import com.sun.mail.imap.IMAPFolder; |
|
import de.srsoftware.widerhall.Constants; |
|
import org.slf4j.Logger; |
|
import org.slf4j.LoggerFactory; |
|
|
|
import javax.mail.*; |
|
import java.time.Duration; |
|
import java.util.Date; |
|
import java.util.HashSet; |
|
import java.util.Properties; |
|
|
|
public class ImapClient { |
|
|
|
private static final Logger LOG = LoggerFactory.getLogger(ImapClient.class); |
|
private final int port; |
|
private final String host, username, password, folderName; |
|
private final ProblemListener problemListener; |
|
private IMAPFolder inbox; |
|
private ListeningThread listeningThread; |
|
private Heartbeat heartbeat; |
|
|
|
private class ListeningThread extends Thread { |
|
|
|
private static final Logger LOG = LoggerFactory.getLogger(ListeningThread.class); |
|
private HashSet<MessageHandler> listeners = new HashSet<>(); |
|
private boolean stopped = false; |
|
private Session session; |
|
|
|
public ListeningThread addListener(MessageHandler messageHandler) { |
|
listeners.add(messageHandler); |
|
return this; |
|
} |
|
|
|
public ListeningThread dropListeners() { |
|
listeners.clear(); |
|
return this; |
|
} |
|
|
|
@Override |
|
public void run() { |
|
while (!stopped) { |
|
try { |
|
sleep(5000); |
|
} catch (InterruptedException interruptedException) { |
|
interruptedException.printStackTrace(); |
|
} |
|
try { |
|
openInbox(); |
|
} catch (MessagingException e){ |
|
LOG.warn("Verbindung-Problem:",e); |
|
problemListener.onImapException(e); |
|
} |
|
} |
|
} |
|
|
|
private void openInbox() throws MessagingException { |
|
LOG.debug("Verbinden und Einloggen…"); |
|
Properties props = imapProps(); |
|
session = Session.getInstance(props); |
|
Store store = session.getStore(Constants.IMAPS); |
|
store.connect(host,username,password); |
|
LOG.debug("Verbunden. Öffne {}:",folderName); |
|
inbox = (IMAPFolder)store.getFolder(folderName); |
|
inbox.open(IMAPFolder.READ_WRITE); |
|
|
|
while (!stopped){ |
|
handleMessages(); |
|
problemListener.clearProblems(); |
|
LOG.debug("Warte."); |
|
inbox.idle(true); |
|
} |
|
} |
|
|
|
private void handleMessages() throws MessagingException { |
|
LOG.debug("Reading email of {}:",username); |
|
if (!inbox.isOpen()) inbox.open(IMAPFolder.READ_WRITE); |
|
for (Message message : inbox.getMessages()){ |
|
if (message.isSet(Flags.Flag.SEEN)) continue; |
|
handle(message); |
|
Folder folder = message.getFolder(); |
|
if (!folder.isOpen()) folder.open(Folder.READ_WRITE); |
|
message.setFlag(Flags.Flag.SEEN,true); |
|
} |
|
} |
|
|
|
private void handle(Message message) throws MessagingException { |
|
LOG.debug("Verarbeite {}",message.getSubject()); |
|
for (MessageHandler listener : listeners) listener.onMessageReceived(message); |
|
} |
|
|
|
private Properties imapProps() { |
|
Properties props = new Properties(); |
|
props.put(Constants.PROTOCOL,Constants.IMAPS); |
|
return props; |
|
} |
|
|
|
public ListeningThread doStop() { |
|
stopped = true; |
|
return this; |
|
} |
|
} |
|
|
|
private class Heartbeat extends Thread{ |
|
|
|
private static final Logger LOG = LoggerFactory.getLogger(Heartbeat.class); |
|
private boolean stopped = false; |
|
|
|
@Override |
|
public void run() { |
|
while (!stopped){ |
|
try { |
|
sleep(300034); |
|
if (inbox != null) continue; |
|
LOG.debug("Sende NOOP"); |
|
inbox.doCommand(protocol -> { |
|
protocol.simpleCommand("NOOP",null); |
|
return null; |
|
}); |
|
} catch (InterruptedException | MessagingException e) { |
|
e.printStackTrace(); |
|
} |
|
} |
|
} |
|
|
|
public Heartbeat doStop() { |
|
stopped = true; |
|
return this; |
|
} |
|
} |
|
|
|
public ImapClient(String host, int port, String username, String password, String folderName,ProblemListener listener) { |
|
this.host = host; |
|
this.port = port; |
|
this.username = username; |
|
this.password = password; |
|
this.folderName = folderName; |
|
this.problemListener = listener; |
|
} |
|
|
|
public ImapClient addListener(MessageHandler messageHandler) { |
|
if (listeningThread == null) listeningThread = new ListeningThread(); |
|
listeningThread.addListener(messageHandler); |
|
return this; |
|
} |
|
|
|
public void dropMailsOlderThan(Integer holdTime) throws MessagingException { |
|
var now = new Date(); |
|
if (holdTime == null) return; |
|
LOG.info("Removing mails older than {} days:",holdTime); |
|
if (!inbox.isOpen()) inbox.open(IMAPFolder.READ_WRITE); |
|
for (Message message : inbox.getMessages()){ |
|
Date receivedDate = message.getReceivedDate(); |
|
Duration duration = Duration.between(receivedDate.toInstant(),now.toInstant()); |
|
var days = duration.toDays(); |
|
LOG.info("Message {} is {} days old!",days); |
|
if (days > holdTime){ |
|
LOG.info("…removing"); |
|
Folder folder = message.getFolder(); |
|
if (!folder.isOpen()) folder.open(Folder.READ_WRITE); |
|
message.setFlag(Flags.Flag.DELETED, true); |
|
} |
|
} |
|
inbox.expunge(); |
|
} |
|
|
|
|
|
public String host(){ |
|
return host; |
|
} |
|
|
|
public String username(){ |
|
return username; |
|
} |
|
|
|
public String password(){ |
|
return password; |
|
} |
|
|
|
public int port(){ |
|
return port; |
|
} |
|
|
|
public String folderName(){ |
|
return folderName; |
|
} |
|
|
|
public ImapClient move(Message message, String destinationFolder) throws MessagingException { |
|
if (listeningThread == null || listeningThread.stopped) throw new IllegalStateException("IMAP client not connected!"); |
|
var source = message.getFolder(); |
|
if (!source.isOpen()) source.open(Folder.READ_WRITE); |
|
var messages = new Message[]{message}; |
|
var store = source.getStore(); |
|
var dest = store.getFolder(new URLName(destinationFolder)); |
|
if (!dest.exists()) dest.create(Folder.HOLDS_MESSAGES); |
|
source.copyMessages(messages,dest); |
|
source.setFlags(messages, new Flags(Flags.Flag.DELETED), true); |
|
source.close(true); |
|
return this; |
|
} |
|
|
|
|
|
public ImapClient start() { |
|
stop(); |
|
|
|
LOG.info("Erzeuge ListeningThread für {}…",username); |
|
(listeningThread = new ListeningThread()).start(); |
|
|
|
LOG.info("Erzeuge Heartbeat für {}…",username); |
|
(heartbeat = new Heartbeat()).start(); |
|
|
|
return this; |
|
} |
|
|
|
public ImapClient stop(){ |
|
if (listeningThread != null) { |
|
LOG.info("Stoppe alten ListeningThread für {}…",username); |
|
listeningThread.dropListeners().doStop(); |
|
listeningThread = null; |
|
} |
|
if (heartbeat != null){ |
|
heartbeat.doStop(); |
|
heartbeat = null; |
|
} |
|
return this; |
|
} |
|
}
|
|
|