java - 从独立应用程序轮询 GMail 收件箱中传入邮件的正确方法

标签 java email gmail jakarta-mail polling

我正在尝试轮询 GMail 收件箱以获取传入邮件。这是我所拥有的:

import java.util.Properties;

import javax.mail.Authenticator;
import javax.mail.Folder;
import javax.mail.Message;
import javax.mail.MessagingException;
import javax.mail.PasswordAuthentication;
import javax.mail.Session;
import javax.mail.event.MessageCountEvent;
import javax.mail.event.MessageCountListener;

import com.sun.mail.imap.IMAPFolder;
import com.sun.mail.imap.IMAPStore;

public class GmailIncomingTest {

    public static void main(String[] args) {
        try {
            String username = "my.user@gmail.com";
            String password = "mypassword";

            Properties properties = new Properties();
            properties.put("mail.smtp.auth", "true");
            properties.put("mail.smtp.host", "smtp.gmail.com");
            properties.put("mail.smtp.port", "587");

            Session session = Session.getDefaultInstance(properties, new Authenticator() {

                protected PasswordAuthentication getPasswordAuthentication() {
                    return new PasswordAuthentication(username, password);
                }
            });

            IMAPStore store = (IMAPStore) session.getStore("imaps");
            store.connect("smtp.gmail.com", username, password);

            IMAPFolder inbox = (IMAPFolder) store.getFolder("inbox");
            inbox.open(Folder.READ_ONLY);

            inbox.addMessageCountListener(new MessageCountListener() {

                @Override
                public void messagesRemoved(MessageCountEvent event) {

                }

                @Override
                public void messagesAdded(MessageCountEvent event) {
                    Message[] messages = event.getMessages();

                    for (Message message : messages) {
                        try {
                            System.out.println("Mail Subject:- " + message.getSubject());
                        } catch (MessagingException e) {
                            e.printStackTrace();
                        }
                    }
                }
            });

            new Thread(new Runnable() {
                private static final long KEEP_ALIVE_FREQ = 10000;

                @Override
                public void run() {
                    while (!Thread.interrupted()) {
                        try {
                            inbox.idle();
                            Thread.sleep(KEEP_ALIVE_FREQ);                                  
                        } catch (InterruptedException e) {
                        } catch (MessagingException e) {
                        }
                    }
                }
            }).start();                 
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

我想知道这是否是正确的方法,或者是否有其他更好的方法。

最佳答案

只要您的服务器支持 IDLE(gmail 将支持)并且您只想收到有关新邮件的通知(因为程序正在运行),那么下面的程序应该可以满足您的需求。如果服务器不支持 IDLE 和/或较旧的消息相关(或文件夹重命名等其他事件),那么您需要修改代码。看看这里的一些提示:https://github.com/salyh/elasticsearch-imap/blob/master/src/main/java/de/saly/elasticsearch/importer/imap/mailsource/ParallelPollingIMAPMailSource.java

import java.util.Properties;

import javax.mail.Folder;
import javax.mail.Message;
import javax.mail.MessagingException;
import javax.mail.Session;
import javax.mail.Store;
import javax.mail.event.MessageCountAdapter;
import javax.mail.event.MessageCountEvent;

import com.sun.mail.imap.IMAPFolder;
import com.sun.mail.imap.IMAPStore;

public class GmailIncomingTest {

    private static final String username = "xxx@gmail.com";
    private static final String password = "passwd";

    public static void main(String[] args) {

        Properties properties = new Properties();
        // properties.put("mail.debug", "true");
        properties.put("mail.store.protocol", "imaps");
        properties.put("mail.imaps.host", "imap.gmail.com");
        properties.put("mail.imaps.port", "993");
        properties.put("mail.imaps.timeout", "10000");

        Session session = Session.getInstance(properties); // not
                                                           // getDefaultInstance
        IMAPStore store = null;
        Folder inbox = null;

        try {
            store = (IMAPStore) session.getStore("imaps");
            store.connect(username, password);

            if (!store.hasCapability("IDLE")) {
                throw new RuntimeException("IDLE not supported");
            }

            inbox = (IMAPFolder) store.getFolder("INBOX");
            inbox.addMessageCountListener(new MessageCountAdapter() {

                @Override
                public void messagesAdded(MessageCountEvent event) {
                    Message[] messages = event.getMessages();

                    for (Message message : messages) {
                        try {
                            System.out.println("Mail Subject:- " + message.getSubject());
                        } catch (MessagingException e) {
                            e.printStackTrace();
                        }
                    }
                }
            });

            IdleThread idleThread = new IdleThread(inbox);
            idleThread.setDaemon(false);
            idleThread.start();

            idleThread.join();
            // idleThread.kill(); //to terminate from another thread

        } catch (Exception e) {
            e.printStackTrace();
        } finally {

            close(inbox);
            close(store);
        }
    }

    private static class IdleThread extends Thread {
        private final Folder folder;
        private volatile boolean running = true;

        public IdleThread(Folder folder) {
            super();
            this.folder = folder;
        }

        public synchronized void kill() {

            if (!running)
                return;
            this.running = false;
        }

        @Override
        public void run() {
            while (running) {

                try {
                    ensureOpen(folder);
                    System.out.println("enter idle");
                    ((IMAPFolder) folder).idle();
                } catch (Exception e) {
                    // something went wrong
                    // wait and try again
                    e.printStackTrace();
                    try {
                        Thread.sleep(100);
                    } catch (InterruptedException e1) {
                        // ignore
                    }
                }

            }
        }
    }

    public static void close(final Folder folder) {
        try {
            if (folder != null && folder.isOpen()) {
                folder.close(false);
            }
        } catch (final Exception e) {
            // ignore
        }

    }

    public static void close(final Store store) {
        try {
            if (store != null && store.isConnected()) {
                store.close();
            }
        } catch (final Exception e) {
            // ignore
        }

    }

    public static void ensureOpen(final Folder folder) throws MessagingException {

        if (folder != null) {
            Store store = folder.getStore();
            if (store != null && !store.isConnected()) {
                store.connect(username, password);
            }
        } else {
            throw new MessagingException("Unable to open a null folder");
        }

        if (folder.exists() && !folder.isOpen() && (folder.getType() & Folder.HOLDS_MESSAGES) != 0) {
            System.out.println("open folder " + folder.getFullName());
            folder.open(Folder.READ_ONLY);
            if (!folder.isOpen())
                throw new MessagingException("Unable to open folder " + folder.getFullName());
        }

    }
}

关于java - 从独立应用程序轮询 GMail 收件箱中传入邮件的正确方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23424003/

相关文章:

java - Helm Chart Spring Boot 应用程序启动后立即关闭

java - 让用户恢复从网页下载文件?

java - ISO C++ 禁止声明没有类型的 'init' [-fpermissive]

ios - 在 Parse 中更新用户电子邮件

java - gmail 回复不使用 javamail : cannot set reply

css - Gmail 忽略显示 :none

java - 将 Java 通配符类型参数转换为 kotlin

excel - 根据单元格值发送电子邮件

php - MailChimp 列表 ID 无效

php - 如何通过 PHP IMAP 从 Gmail 服务器读取电子邮件