package de.srsoftware.widerhall.mail; import com.sun.mail.imap.IMAPFolder; import de.srsoftware.widerhall.Constants; import org.json.simple.JSONObject; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import javax.mail.*; 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 boolean stopped = true; private IMAPFolder inbox; private HashSet listeners = new HashSet<>(); private class ListeningThread extends Thread { private static final Logger LOG = LoggerFactory.getLogger(ListeningThread.class); @Override public void run() { while (!stopped) { try { openInbox(); } catch (MessagingException e){ LOG.warn("Connection problem:",e); try { sleep(1000); } catch (InterruptedException interruptedException) { interruptedException.printStackTrace(); } } } } private void openInbox() throws MessagingException { LOG.debug("Connecting and logging in…"); Properties props = imapProps(); Session session = Session.getInstance(props); Store store = session.getStore(Constants.IMAPS); store.connect(host,username,password); LOG.debug("Connected, opening {}:",folderName); inbox = (IMAPFolder)store.getFolder(folderName); inbox.open(IMAPFolder.READ_WRITE); while (!stopped){ handleMessages(); LOG.debug("Idling."); inbox.idle(true); } } private void handleMessages() throws MessagingException { LOG.debug("reading email:"); if (!inbox.isOpen()){ inbox.open(IMAPFolder.READ_WRITE); } for (Message message : inbox.getMessages()){ if (message.isSet(Flags.Flag.SEEN)) continue; handle(message); message.setFlag(Flags.Flag.SEEN,true); } } private void handle(Message message) throws MessagingException { LOG.debug("Handling {}",message.getSubject()); for (MessageHandler listener : listeners) listener.onMessageReceived(message); } private Properties imapProps() { Properties props = new Properties(); props.put(Constants.PROTOCOL,Constants.IMAPS); return props; } } private class Heartbeat extends Thread{ private static final Logger LOG = LoggerFactory.getLogger(Heartbeat.class); @Override public void run() { while (!stopped){ try { sleep(300034); if (inbox != null) continue; LOG.debug("sending NOOP"); inbox.doCommand(protocol -> { protocol.simpleCommand("NOOP",null); return null; }); } catch (InterruptedException | MessagingException e) { e.printStackTrace(); } } } } public ImapClient(String host, int port, String username, String password, String folderName) { this.host = host; this.port = port; this.username = username; this.password = password; this.folderName = folderName; } public ImapClient addListener(MessageHandler messageHandler) { listeners.add(messageHandler); return this; } 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 void start() { stopped = false; LOG.debug("Creating ListeningThread…"); new ListeningThread().start(); LOG.debug("Creating Heartbeat…"); new Heartbeat().start(); } public void stop(){ stopped = true; } }