Workaround server bugs

pull/162/head
M66B 6 years ago
parent 4f07e2e60a
commit 340a6e9e6c

@ -56,6 +56,7 @@ import javax.mail.MessageRemovedException;
import javax.mail.MessagingException; import javax.mail.MessagingException;
import javax.mail.UIDFolder; import javax.mail.UIDFolder;
import javax.mail.internet.InternetAddress; import javax.mail.internet.InternetAddress;
import javax.mail.internet.MimeMessage;
import javax.mail.search.AndTerm; import javax.mail.search.AndTerm;
import javax.mail.search.BodyTerm; import javax.mail.search.BodyTerm;
import javax.mail.search.ComparisonTerm; import javax.mail.search.ComparisonTerm;
@ -466,7 +467,7 @@ public class BoundaryCallbackMessages extends PagedList.BoundaryCallback<TupleMe
if (message == null) { if (message == null) {
message = Core.synchronizeMessage(context, message = Core.synchronizeMessage(context,
account, browsable, account, browsable,
state.ifolder, (IMAPMessage) isub[j], state.ifolder, (MimeMessage) isub[j],
true, true, true, true,
rules, null); rules, null);
found++; found++;

@ -61,6 +61,8 @@ import org.jsoup.Jsoup;
import org.jsoup.nodes.Element; import org.jsoup.nodes.Element;
import java.io.BufferedInputStream; import java.io.BufferedInputStream;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File; import java.io.File;
import java.io.FileInputStream; import java.io.FileInputStream;
import java.io.FileNotFoundException; import java.io.FileNotFoundException;
@ -742,7 +744,7 @@ class Core {
List<EntityRule> rules = db.rule().getEnabledRules(folder.id); List<EntityRule> rules = db.rule().getEnabledRules(folder.id);
try { try {
IMAPMessage imessage = (IMAPMessage) ifolder.getMessageByUID(uid); MimeMessage imessage = (MimeMessage) ifolder.getMessageByUID(uid);
if (imessage == null) if (imessage == null)
throw new MessageRemovedException(); throw new MessageRemovedException();
@ -762,7 +764,7 @@ class Core {
if (download && message != null) if (download && message != null)
downloadMessage(context, folder, ifolder, imessage, message.id, state); downloadMessage(context, folder, ifolder, imessage, message.id, state);
} finally { } finally {
imessage.invalidateHeaders(); ((IMAPMessage) imessage).invalidateHeaders();
} }
} catch (MessageRemovedException ex) { } catch (MessageRemovedException ex) {
Log.i(ex); Log.i(ex);
@ -1641,7 +1643,7 @@ class Core {
EntityMessage message = synchronizeMessage( EntityMessage message = synchronizeMessage(
context, context,
account, folder, account, folder,
ifolder, (IMAPMessage) isub[j], ifolder, (MimeMessage) isub[j],
false, download, false, download,
rules, state); rules, state);
ids[from + j] = message.id; ids[from + j] = message.id;
@ -1706,7 +1708,7 @@ class Core {
downloadMessage( downloadMessage(
context, context,
folder, ifolder, folder, ifolder,
(IMAPMessage) isub[j], ids[from + j], state); (MimeMessage) isub[j], ids[from + j], state);
} catch (FolderClosedException ex) { } catch (FolderClosedException ex) {
throw ex; throw ex;
} catch (Throwable ex) { } catch (Throwable ex) {
@ -1748,11 +1750,51 @@ class Core {
static EntityMessage synchronizeMessage( static EntityMessage synchronizeMessage(
Context context, Context context,
EntityAccount account, EntityFolder folder, EntityAccount account, EntityFolder folder,
IMAPFolder ifolder, IMAPMessage imessage, IMAPFolder ifolder, MimeMessage imessage,
boolean browsed, boolean download, boolean browsed, boolean download,
List<EntityRule> rules, State state) throws MessagingException, IOException { List<EntityRule> rules, State state) throws MessagingException, IOException {
long uid = ifolder.getUID(imessage); long uid = ifolder.getUID(imessage);
try {
return _synchronizeMessage(context, account, folder, uid, imessage, browsed, download, rules, state);
} catch (MessagingException ex) {
// https://javaee.github.io/javamail/FAQ#imapserverbug
if (MessageHelper.retryRaw(ex)) try {
Log.w(folder.name + " " + ex.getMessage());
Log.i(folder.name + " fetching raw message uid=" + uid);
ByteArrayOutputStream bos = new ByteArrayOutputStream();
imessage.writeTo(bos);
bos.close();
Properties properties = MessageHelper.getSessionProperties();
Session isession = Session.getInstance(properties, null);
Log.i(folder.name + " decoding again uid=" + uid);
ByteArrayInputStream bis = new ByteArrayInputStream(bos.toByteArray());
imessage = new MimeMessage(isession, bis);
bis.close();
Log.i(folder.name + " synchronizing again uid=" + uid);
return _synchronizeMessage(context, account, folder, uid, imessage, browsed, download, rules, state);
} catch (MessagingException ex1) {
if (MessageHelper.retryRaw(ex1))
Log.e(ex1);
throw ex1;
}
throw ex;
}
}
static EntityMessage _synchronizeMessage(
Context context,
EntityAccount account, EntityFolder folder,
long uid, MimeMessage imessage,
boolean browsed, boolean download,
List<EntityRule> rules, State state) throws MessagingException, IOException {
if (imessage.isExpunged()) { if (imessage.isExpunged()) {
Log.i(folder.name + " expunged uid=" + uid); Log.i(folder.name + " expunged uid=" + uid);
throw new MessageRemovedException("Expunged"); throw new MessageRemovedException("Expunged");
@ -2187,7 +2229,7 @@ class Core {
static void downloadMessage( static void downloadMessage(
Context context, Context context,
EntityFolder folder, IMAPFolder ifolder, EntityFolder folder, IMAPFolder ifolder,
IMAPMessage imessage, long id, State state) throws MessagingException, IOException { MimeMessage imessage, long id, State state) throws MessagingException, IOException {
if (state.getNetworkState().isRoaming()) if (state.getNetworkState().isRoaming())
return; return;

@ -1106,31 +1106,13 @@ public class MessageHelper {
EntityAttachment attachment; EntityAttachment attachment;
} }
MessageParts getMessageParts() throws IOException, FolderClosedException { MessageParts getMessageParts() throws IOException, MessagingException {
MessageParts parts = new MessageParts(); MessageParts parts = new MessageParts();
getMessageParts(imessage, parts, false);
MimeMessage cmessage = imessage;
try {
// Load body structure
cmessage.getContentID();
} catch (MessagingException ex) {
// https://javaee.github.io/javamail/FAQ#imapserverbug
if ("Unable to load BODYSTRUCTURE".equals(ex.getMessage())) {
Log.w(ex);
parts.warnings.add(Helper.formatThrowable(ex, false));
try {
cmessage = new MimeMessage(imessage);
} catch (MessagingException ignored) {
}
}
}
getMessageParts(cmessage, parts, false);
return parts; return parts;
} }
private void getMessageParts(Part part, MessageParts parts, boolean pgp) throws IOException, FolderClosedException { private void getMessageParts(Part part, MessageParts parts, boolean pgp) throws IOException, MessagingException {
try { try {
if (BuildConfig.DEBUG) if (BuildConfig.DEBUG)
Log.i("Part class=" + part.getClass() + " type=" + part.getContentType()); Log.i("Part class=" + part.getClass() + " type=" + part.getContentType());
@ -1272,11 +1254,18 @@ public class MessageHelper {
} catch (FolderClosedException ex) { } catch (FolderClosedException ex) {
throw ex; throw ex;
} catch (MessagingException ex) { } catch (MessagingException ex) {
if (retryRaw(ex))
throw ex;
Log.w(ex); Log.w(ex);
parts.warnings.add(Helper.formatThrowable(ex, false)); parts.warnings.add(Helper.formatThrowable(ex, false));
} }
} }
static boolean retryRaw(MessagingException ex) {
return ("Failed to load IMAP envelope".equals(ex.getMessage()) ||
"Unable to load BODYSTRUCTURE".equals(ex.getMessage()));
}
static boolean equal(Address[] a1, Address[] a2) { static boolean equal(Address[] a1, Address[] a2) {
if (a1 == null && a2 == null) if (a1 == null && a2 == null)
return true; return true;

Loading…
Cancel
Save