diff --git a/app/src/main/java/eu/faircode/email/MessageHelper.java b/app/src/main/java/eu/faircode/email/MessageHelper.java index 530f61afa0..85f340ce73 100644 --- a/app/src/main/java/eu/faircode/email/MessageHelper.java +++ b/app/src/main/java/eu/faircode/email/MessageHelper.java @@ -24,12 +24,16 @@ import android.content.SharedPreferences; import android.net.MailTo; import android.net.Uri; import android.text.TextUtils; +import android.util.Base64; import androidx.documentfile.provider.DocumentFile; import androidx.preference.PreferenceManager; +import com.sun.mail.util.ASCIIUtility; +import com.sun.mail.util.BASE64DecoderStream; import com.sun.mail.util.FolderClosedIOException; import com.sun.mail.util.MessageRemovedIOException; +import com.sun.mail.util.QDecoderStream; import org.jsoup.nodes.Document; import org.jsoup.nodes.Element; @@ -37,6 +41,7 @@ import org.jsoup.nodes.Element; import java.io.BufferedInputStream; import java.io.BufferedOutputStream; import java.io.BufferedReader; +import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.File; import java.io.FileInputStream; @@ -1186,11 +1191,11 @@ public class MessageHelper { if (text == null) return null; + // https://tools.ietf.org/html/rfc2045 // https://tools.ietf.org/html/rfc2047 // encoded-word = "=?" charset "?" encoding "?" encoded-text "?=" int i = 0; - boolean first = true; List parts = new ArrayList<>(); while (i < text.length()) { @@ -1211,8 +1216,6 @@ public class MessageHelper { break; String plain = text.substring(i, s); - if (!first) - plain = plain.replaceAll("[ \t\n\r]$", ""); if (!TextUtils.isEmpty(plain)) parts.add(new MimeTextPart(plain)); @@ -1222,7 +1225,6 @@ public class MessageHelper { text.substring(q2 + 1, e))); i = e + 2; - first = false; } if (i < text.length()) @@ -1235,6 +1237,20 @@ public class MessageHelper { MimeTextPart p2 = parts.get(p + 1); if (p1.charset != null && p1.charset.equalsIgnoreCase(p2.charset) && p1.encoding != null && p1.encoding.equalsIgnoreCase(p2.encoding)) { + try { + byte[] b1 = decodeWord(p1.text, p1.encoding); + byte[] b2 = decodeWord(p2.text, p2.encoding); + byte[] b = new byte[b1.length + b2.length]; + System.arraycopy(b1, 0, b, 0, b1.length); + System.arraycopy(b2, 0, b, b1.length, b2.length); + p1.text = new String(b, p1.charset); + p1.charset = null; + p2.encoding = null; + parts.remove(p + 1); + continue; + } catch (Throwable ex) { + Log.w(ex); + } p1.text += p2.text; parts.remove(p + 1); } else @@ -1247,6 +1263,24 @@ public class MessageHelper { return sb.toString(); } + static byte[] decodeWord(String word, String encoding) throws IOException { + ByteArrayInputStream bis = new ByteArrayInputStream(ASCIIUtility.getBytes(word)); + + InputStream is; + if (encoding.equalsIgnoreCase("B")) + is = new BASE64DecoderStream(bis); + else if (encoding.equalsIgnoreCase("Q")) + is = new QDecoderStream(bis); + else + throw new UnsupportedEncodingException("Encoding=" + encoding); + + int count = bis.available(); + byte[] bytes = new byte[count]; + count = is.read(bytes, 0, count); + + return Arrays.copyOf(bytes, count); + } + private static class MimeTextPart { String charset; String encoding; @@ -1267,10 +1301,10 @@ public class MessageHelper { if (charset == null) return text; - String word = "=?" + charset + "?" + encoding + "?" + text + "?="; try { - return decodeMime(MimeUtility.decodeWord(word)); + return decodeMime(new String(decodeWord(text, encoding), charset)); } catch (Throwable ex) { + String word = "=?" + charset + "?" + encoding + "?" + text + "?="; Log.w(new IllegalArgumentException(word, ex)); return word; }