1. 程式人生 > >java mail 實現郵件的推送

java mail 實現郵件的推送

今天在做郵件的推送功能,即當郵件伺服器接收到新郵件時,客戶端這邊可以立即接收到。

思路:利用 Java Mail IMAP IDLE 去實現此功能

剛開始利用 folder.idle()去實現,程式碼如下,但出現一個問題,接收到新郵件之後,會自動斷開監聽。

 IMAPFolder folder = (IMAPFolder)store.getFolder("INBOX");
        folder.open(Folder.READ_WRITE);
        folder.addMessageCountListener(new MessageCountAdapter() {
            @Override
            public void messagesAdded(MessageCountEvent e) {
                super.messagesAdded(e);
                Message[] msgs = e.getMessages();
                for(int i=0;i<msgs.length;i++){
                    try {
                        Log.e("add 郵件","add 郵件主題"+msgs[i].getSubject());
                    } catch (MessagingException e1) {
                        e1.printStackTrace();
                    }
                }
               
            }

            @Override
            public void messagesRemoved(MessageCountEvent e) {
                super.messagesRemoved(e);
                Message[] msgs = e.getMessages();
                for(int i=0;i<msgs.length;i++){
                    try {
                        Log.e("remove 郵件","remove 郵件主題"+msgs[i].getSubject());
                    } catch (MessagingException e1) {
                        e1.printStackTrace();
                    }
                }
            }
        });
        folder.idle(true);

 檢視官方文件:

Google翻譯:與idle()類似,但如果一次為真,則在第一次通知後中止IDLE命令,以允許呼叫者同步處理任何通知。

然後我就用folder.idle()去替代folder.idle(true),但貌似還是沒起作用,下面是idle()方法的介紹

Google翻譯:如果伺服器支援,則使用IMAP IDLE命令(請參閱RFC 2177)進入空閒模式,以便伺服器可以傳送未經請求的新訊息到達等通知,而無需客戶端不斷輪詢伺服器。 使用適當的偵聽器來通知新訊息或其他事件。 當另一個執行緒(例如,偵聽器執行緒)需要為該資料夾發出IMAP命令時,將終止空閒模式並返回此方法。 通常,呼叫者將在迴圈中呼叫此方法。
mail.imap.minidletime屬性在從此方法返回之前強制執行最小延遲,以確保其他執行緒有機會在呼叫者再次呼叫此方法之前發出命令。 預設延遲為10毫秒。

最後如何解決的:

利用IdleManager迅速解決了此問題(查閱了官網文件)

 ExecutorService es = Executors.newCachedThreadPool();
        final IdleManager idleManager = new IdleManager(session, es);
        IMAPFolder folder = (IMAPFolder)store.getFolder("INBOX");
        folder.open(Folder.READ_WRITE);
        folder.addMessageCountListener(new MessageCountAdapter() {
            @Override
            public void messagesAdded(MessageCountEvent e) {
                super.messagesAdded(e);
                Folder folder = (Folder)e.getSource();
                Message[] msgs = e.getMessages();
                for(int i=0;i<msgs.length;i++){
                    try {
                        Log.e("add 郵件","add 郵件主題"+msgs[i].getSubject());
                    } catch (MessagingException e1) {
                        e1.printStackTrace();
                    }
                }
                try {
                    idleManager.watch(folder);
                } catch (MessagingException e1) {
                    e1.printStackTrace();
                }
            }

            @Override
            public void messagesRemoved(MessageCountEvent e) {
                super.messagesRemoved(e);
                Message[] msgs = e.getMessages();
                for(int i=0;i<msgs.length;i++){
                    try {
                        Log.e("remove 郵件","remove 郵件主題"+msgs[i].getSubject());
                    } catch (MessagingException e1) {
                        e1.printStackTrace();
                    }
                }
            }
        });
        idleManager.watch(folder);

 目前此方法測試良好,但可能會出現斷線重連的狀況,IMAP指出30分鐘內無任何響應,會自動斷開連線,所以這個問題我們也得重視。