Android JavaMail IMAP在10秒后超时
我目前正在开发一个带有后台服务的电子邮件应用程序,该服务与JavaMail空闲功能结合使用。后台服务通过每10分钟发出一次检查来保持空闲功能正常工作,因为正在使用的服务器Exchange server有时会在连接10到30分钟之间的任何位置断开连接 虽然这目前运行良好,且空闲/推送功能运行良好,但偶尔会引发以下异常:Android JavaMail IMAP在10秒后超时,java,android,jakarta-mail,exchange-server,imap,Java,Android,Jakarta Mail,Exchange Server,Imap,我目前正在开发一个带有后台服务的电子邮件应用程序,该服务与JavaMail空闲功能结合使用。后台服务通过每10分钟发出一次检查来保持空闲功能正常工作,因为正在使用的服务器Exchange server有时会在连接10到30分钟之间的任何位置断开连接 虽然这目前运行良好,且空闲/推送功能运行良好,但偶尔会引发以下异常: java.util.concurrent.TimeoutException: com.sun.mail.imap.IMAPSSLStore.finalize() timed out
java.util.concurrent.TimeoutException: com.sun.mail.imap.IMAPSSLStore.finalize() timed out after 10 seconds
使用此版本的JavaMail时,不会遇到其他问题:
//JavaMail
compile 'com.sun.mail:android-mail:1.5.5'
检查我们的bug报告系统,这导致应用程序在30种不同的情况下崩溃。空闲和保持活动功能的代码如下所示:
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) 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");
}
imapFolder = (IMAPFolder) imapStore.getFolder("Inbox");
imapFolder.open(IMAPFolder.READ_WRITE);
databaseRecords = dbManager.getReceivedEmailRecordsCount();
if (databaseRecords < imapFolder.getMessageCount()) {
Log.d(TAG, "Receiving Mail...");
receiveMail(imapFolder.getMessages());
} else {
Log.d(TAG, "Records match.");
}
Folder[] fdr = imapStore.getDefaultFolder().list();
for (Folder fd : fdr)
System.out.println(">> " + fd.getName());
imapFolder.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
Boolean proceed = true;
try {
Message[] messages = e.getMessages();
Log.d(TAG, "Last Subject 1: " + lastSubject + " " + "Last Date: " + lastDate);
Log.d(TAG, "Current Subject 1: " + messages[0].getSubject() + " " + "Last Date: " + messages[0].getSentDate().toString());
if (lastSubject != null && lastDate != null) {
Log.d(TAG, "Existing last subject or date");
if (lastSubject.equals(messages[0].getSubject()) && lastDate.equals(messages[0].getSentDate().toString())) {
Log.d(TAG, "Stopping proceed");
proceed = false;
} else {
Log.d(TAG, "Allowing proceed");
proceed = true;
lastSubject = messages[0].getSubject();
lastDate = messages[0].getSentDate().toString();
}
} else {
Log.d(TAG, "No existing last subject or date");
lastSubject = messages[0].getSubject();
lastDate = messages[0].getSentDate().toString();
}
Log.d(TAG, "Last Subject 2: " + lastSubject + " " + "Last Date: " + lastDate);
Log.d(TAG, "Current Subject 2: " + messages[0].getSubject() + " " + "Last Date: " + messages[0].getSentDate().toString());
if (proceed) {
Log.d(TAG, "Proceeding...");
System.out.println("messages.length---" + messages.length);
getMessages(messages);
} else {
Log.d(TAG, "Not Proceeding...");
}
} catch (Exception ex) {
Log.d(TAG, "CATCH 2");
ex.printStackTrace();
}
}
public void messagesRemoved(MessageCountEvent e) {
System.out.println("Message Removed Event fired");
}
});
imapFolder.addMessageChangedListener(new MessageChangedListener() {
public void messageChanged(MessageChangedEvent e) {
System.out.println("Message Changed Event fired");
}
});
startListening(imapFolder);
//close the store and folder objects
// emailFolder.close(false);
// store.close();
} catch (MessagingException e) {
Log.d(TAG, "CATCH 3");
AndroidUtils.closeEmailFolder(imapFolder);
AndroidUtils.closeEmailStore(imapStore);
Handler handler = new Handler(Looper.getMainLooper());
Runnable runnable = new Runnable() {
@Override
public void run() {
checkConnectivity();
}
};
handler.postDelayed(runnable, 30 * 1000); // 30 seconds
} catch (Exception e) {
Log.d(TAG, "CATCH 4");
e.printStackTrace();
}
}
}).start();
}
private void getMessages(Message[] messages) {
Log.d(TAG, "getMessages()");
try {
for (Message message : messages) {
if (!message.getFlags().contains(Flags.Flag.SEEN)) {
message.setFlag(Flags.Flag.SEEN, true);
if (message.getSubject().startsWith("<confirm>")) {
Log.d(TAG, "Sender is looking for a confirm receipt");
sendConfirmReceipt(message);
}
//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) {
Log.d(TAG, "CATCH 5");
ex.printStackTrace();
}
}
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");
//getMessages(imapFolder.getMessages());
imapFolder.idle();
} catch (FolderClosedException fex) {
Log.d(TAG, "CATCH 6");
//Server closes connection.
Log.d(TAG, "FolderClosedException. Server potentially dropped connection. Retrying connection...");
fex.printStackTrace();
AndroidUtils.closeEmailFolder(imapFolder);
AndroidUtils.closeEmailStore(imapStore);
checkConnectivity();
} catch (MessagingException e) {
Log.d(TAG, "CATCH 7");
//Idle isn't supported by server.
Log.d(TAG, "Messaging exception during IDLE: ");
e.printStackTrace();
AndroidUtils.closeEmailFolder(imapFolder);
}
}
// 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 * 10; // 10 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) {
Log.d(TAG, "CATCH 7");
// Ignore, just aborting the thread...
Log.d(TAG, "Interrupted...");
e.printStackTrace();
} catch (MessagingException e) {
Log.d(TAG, "CATCH 8");
// Shouldn't really happen...
Log.d(TAG, "Unexpected exception while keeping alive the IDLE connection");
e.printStackTrace();
}
}
}
}
因此,我如何保持idle函数工作,并使用检查/中断线程不断地继续接收电子邮件,而不抛出“TimeoutException”?确保处理完所有连接后确实关闭了它们。试一下/最后是你的朋友 万一你漏掉了一个,这个案子有一个新的答案