【问题标题】:Android JavaMail Detect If Server Goes OfflineAndroid JavaMail 检测服务器是否离线
【发布时间】:2017-05-30 16:38:28
【问题描述】:

我目前正在开发一个带有后台服务的电子邮件应用程序,该服务与 JavaMail Idle 功能结合使用。后台服务通过每 29 分钟发出一次检查来保持空闲功能正常工作(因为正在使用的服务器(Exchange 服务器))有时会在连接 30 分钟后断开连接。

虽然这可以完美运行,但如果 Exchange 服务器处于脱机状态,则应用程序将继续尝试无限期地重新连接到 IMAP 文件夹。我注意到凌晨 3 点到 6 点(典型的 Exchange 更新时间)之间的数据使用量激增。

为避免增加数据使用量,我希望实现应用程序尝试重新连接到 IMAP 文件夹三次然后向用户显示服务器离线的警告并且将重试新的连接尝试的功能在 30 分钟内。

为了实现这一点,如果应用程序无法连接到 IMAP 文件夹,我将如何检测 Exchange 服务器是否实际上处于脱机/更新状态以及是否会引发任何异常?好像会抛出异常,然后我可以保存一个本地 int 变量,并在每次抛出异常时将其加一,然后在第三次向用户显示警报。

我目前的代码实现如下:

public void checkInboxEmail(final String host, final String user, final String password) {

    Log.d(TAG, "checkEmail");

    this.host = host;
    this.user = user;
    this.password = password;

    new Thread(new Runnable() {
        @Override
        public void run() {
            try {
                Log.d(TAG, "checkEmail - run()");

                long databaseRecords;

                //create properties field
                Properties properties = new Properties();
                properties.put("mail.store.protocol", "imaps");
                properties.put("mail.imaps.ssl.trust", "*");
                properties.put("mail.debug", "true");

                emailSession = Session.getInstance(properties, new Authenticator() {
                    protected PasswordAuthentication getPasswordAuthentication() {
                        return new PasswordAuthentication(user, password);
                    }
                });


                IMAPStore imapStore = (IMAPStore) emailSession.getStore("imaps");
                // imapStore.connect();

                imapStore.connect(host, user, password);

                if (imapStore.isConnected()) {
                    Log.d("MailPush", "Successfully connected to IMAP");
                } else {
                    Log.d("MailPush", "Not connected to IMAP");
                }

                final IMAPFolder folder = (IMAPFolder) imapStore.getFolder("Inbox");
                folder.open(IMAPFolder.READ_WRITE);

                databaseRecords = dbManager.getReceivedEmailRecordsCount();

                if (databaseRecords < folder.getMessageCount()) {
                    Log.d(TAG, "Receiving Mail...");
                    receiveMail(folder.getMessages());
                } else {
                    Log.d(TAG, "Records match.");
                }

                Folder[] fdr = imapStore.getDefaultFolder().list();
                for (Folder fd : fdr)
                    System.out.println(">> " + fd.getName());

                folder.addMessageCountListener(new MessageCountListener() {

                    public void messagesAdded(MessageCountEvent e) {

                        System.out.println("Message Added Event Fired");
                        Log.d(TAG, "MESSAGE TYPE: " + e.getType());
                        //ADDED = 1 & REMOVED = 2

                        try {
                            Message[] messages = e.getMessages();

                            System.out.println("messages.length---" + messages.length);

                            for (Message message : messages) {
                                if (!message.getFlags().contains(Flags.Flag.SEEN)) {

                                    //Message is new (hasn't been seen) > Message Details
                                    System.out.println("---------------------------------");
                                    System.out.println("Email Number " + (message.getMessageNumber()));
                                    System.out.println("Subject: " + message.getSubject());
                                    System.out.println("From: " + message.getFrom()[0]);
                                    System.out.println("Text: " + message.getContent().toString());

                                    String from = message.getFrom()[0].toString();

                                    String cc = InternetAddress.toString(message.getRecipients(Message.RecipientType.CC));
                                    Log.d(TAG, "CC 1: " + cc);

                                    Address[] recipients = message.getRecipients(Message.RecipientType.CC);
                                    cc = InternetAddress.toString(recipients);
                                    Log.d(TAG, "CC 2: " + cc);

                                    //Check Encryption Details > Add SEEN Flag > Add to database
                                    checkEncryption((MimeMessage) message, from, cc);
                                }
                            }
                        } catch (Exception ex) {
                            ex.printStackTrace();
                        }
                    }

                    public void messagesRemoved(MessageCountEvent e) {
                        System.out.println("Message Removed Event fired");
                    }
                });

                folder.addMessageChangedListener(new MessageChangedListener() {

                    public void messageChanged(MessageChangedEvent e) {
                        System.out.println("Message Changed Event fired");
                    }
                });

                startListening(folder);

                //close the store and folder objects
                //   emailFolder.close(false);
                //   store.close();

            } catch (NoSuchProviderException e) {
                e.printStackTrace();
            } catch (MessagingException e) {
                e.printStackTrace();
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }).start();
}

private void startListening(IMAPFolder imapFolder) {
    Log.d(TAG, "startListening");

    // We need to create a new thread to keep alive the connection
    Thread t = new Thread(
            new KeepAliveRunnable(imapFolder), "IdleConnectionKeepAlive"
    );

    t.start();

    while (!Thread.interrupted()) {
        Log.d(TAG, "Starting IDLE");
        try {
            Log.d(TAG, "Setting IDLE");
            imapFolder.idle();
        } catch (FolderClosedException fex) {
            //Server closes connection.
            Log.d(TAG, "FolderClosedException. Server potentially dropped connection. Retrying connection...");
            fex.printStackTrace();

            if (!isServiceRunning(MyService.class)) {
                Log.d(TAG, "Service isn't running. Starting service...");

                //Start service
                Intent intent = new Intent(context, MyService.class);
                intent.putExtra("host", host);
                intent.putExtra("email", user);
                intent.putExtra("password", password);

                context.startService(intent);
            } else {
                Log.d(TAG, "Service is already running. Checking email...");
                checkInboxEmail(host, user, password);
            }
        } catch (MessagingException e) {
            //Idle isn't supported by server.
            Log.d(TAG, "Messaging exception during IDLE: ");
            e.printStackTrace();
        }
    }

    // Shutdown keep alive thread
    if (t.isAlive()) {
        Log.d(TAG, "Interrupting thread");
        t.interrupt();
    }
}

private static class KeepAliveRunnable implements Runnable {

    private final String TAG = getClass().getName();

    private static final long KEEP_ALIVE_FREQ = 60000 * 29; // 29 minutes (Exchange connection drops after 20-30 minutes)

    private IMAPFolder folder;

    KeepAliveRunnable(IMAPFolder folder) {
        this.folder = folder;
    }

    @Override
    public void run() {
        while (!Thread.interrupted()) {
            try {
                Thread.sleep(KEEP_ALIVE_FREQ);

                // Perform a messageCount check just to keep alive the connection
                Log.d(TAG, "Performing a messageCount check to keep the connection alive");
                folder.getMessageCount();
            } catch (InterruptedException e) {
                // Ignore, just aborting the thread...
                Log.d(TAG, "Interrupted...");
                e.printStackTrace();
            } catch (MessagingException e) {
                // Shouldn't really happen...
                Log.d(TAG, "Unexpected exception while keeping alive the IDLE connection");
                e.printStackTrace();
            }
        }
    }
}

private void receiveMail(Message[] messages) {
    try {

        System.out.println("messages.length---" + messages.length);

        for (Message message : messages) {
            if (!message.getFlags().contains(Flags.Flag.SEEN)) {

                //Message is new (hasn't been seen) > Message Details
                System.out.println("---------------------------------");
                System.out.println("Email Number " + (message.getMessageNumber()));
                System.out.println("Subject: " + message.getSubject());
                System.out.println("From: " + message.getFrom()[0]);
                System.out.println("Text: " + message.getContent().toString());

                String from = message.getFrom()[0].toString();
                String cc = InternetAddress.toString(message.getRecipients(Message.RecipientType.CC));

                //Check Encryption Details > Add SEEN Flag > Add to database
                checkEncryption((MimeMessage) message, from, cc);
            }
        }
    } catch (Exception ex) {
        ex.printStackTrace();
    }
}

【问题讨论】:

    标签: java android jakarta-mail exchange-server imap


    【解决方案1】:

    如果服务器已启动但不接受连接,则连接将立即失败(有例外)。如果服务器关闭,并且您设置了连接超时,则连接将在超时后失败(有一个例外)。

    【讨论】:

    • 会有哪些例外?
    • MessagingException,可能是一些子类,例如 com.sun.mail.util.MailConnectException。
    【解决方案2】:

    为了澄清@BillShannon 的回答,如果服务器 host 已启动但 Exchange 不接受连接,则连接将立即失败并返回 ConnectException: connection refused。如果服务器主机已关闭,则连接将在超时后失败,并出现 ConnectException: connect timeout(或可能是 SocketTimeoutException),无论您是否设置了连接超时,因为平台始终有一个。

    【讨论】:

    • @BillShannon,我添加了一个 MessagingException 作为我的“checkInboxEmail”函数的捕获,因此会向用户显示一个警报(在异常被捕获 3 次之后)但是我怎样才能停止 JavaMail试图重新连接?这是否只是通过使用不同的超时,然后使用处理程序来延迟运行函数,直到距当前时间 30 分钟?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2020-07-13
    • 2011-05-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-03-20
    • 2017-05-03
    相关资源
    最近更新 更多