diff --git a/app/src/main/java/eu/faircode/email/Core.java b/app/src/main/java/eu/faircode/email/Core.java index a10a8159ae..12e9f397c9 100644 --- a/app/src/main/java/eu/faircode/email/Core.java +++ b/app/src/main/java/eu/faircode/email/Core.java @@ -4236,6 +4236,8 @@ class Core { label = (r.isDelivered() ? MessageHelper.FLAG_DELIVERED : MessageHelper.FLAG_NOT_DELIVERED); else if (r.isDispositionNotification()) label = (r.isMdnDisplayed() ? MessageHelper.FLAG_DISPLAYED : MessageHelper.FLAG_NOT_DISPLAYED); + else if (r.isFeedbackReport()) + label = MessageHelper.FLAG_COMPLAINT; if (label != null) { Map map = new HashMap<>(); diff --git a/app/src/main/java/eu/faircode/email/MessageHelper.java b/app/src/main/java/eu/faircode/email/MessageHelper.java index 907656c0b3..38b438a8fd 100644 --- a/app/src/main/java/eu/faircode/email/MessageHelper.java +++ b/app/src/main/java/eu/faircode/email/MessageHelper.java @@ -198,6 +198,7 @@ public class MessageHelper { static final String FLAG_NOT_DELIVERED = "$NotDelivered"; static final String FLAG_DISPLAYED = "$Displayed"; static final String FLAG_NOT_DISPLAYED = "$NotDisplayed"; + static final String FLAG_COMPLAINT = "Complaint"; static final String FLAG_LOW_IMPORTANCE = "$LowImportance"; static final String FLAG_HIGH_IMPORTANCE = "$HighImportance"; @@ -1349,7 +1350,8 @@ public class MessageHelper { ContentType ct = new ContentType(imessage.getContentType()); String reportType = ct.getParameter("report-type"); if ("delivery-status".equalsIgnoreCase(reportType) || - "disposition-notification".equalsIgnoreCase(reportType)) { + "disposition-notification".equalsIgnoreCase(reportType) || + "feedback-report".equalsIgnoreCase(reportType)) { MessageParts parts = new MessageParts(); getMessageParts(null, imessage, parts, null); for (AttachmentPart apart : parts.attachments) @@ -2979,7 +2981,9 @@ public class MessageHelper { boolean isReport() { String ct = contentType.getBaseType(); - return Report.isDeliveryStatus(ct) || Report.isDispositionNotification(ct); + return (Report.isDeliveryStatus(ct) || + Report.isDispositionNotification(ct) || + Report.isFeedbackReport(ct)); } } @@ -3362,6 +3366,11 @@ public class MessageHelper { w.append(report.disposition); } + if (report.isFeedbackReport()) { + if (!TextUtils.isEmpty(report.feedback)) + w.append(report.feedback); + } + if (w.length() > 0) warnings.add(w.toString()); } else @@ -4294,7 +4303,9 @@ public class MessageHelper { !Part.ATTACHMENT.equalsIgnoreCase(disposition) && TextUtils.isEmpty(filename)) { parts.text.add(new PartHolder(part, contentType)); } else { - if (Report.isDeliveryStatus(ct) || Report.isDispositionNotification(ct)) + if (Report.isDeliveryStatus(ct) || + Report.isDispositionNotification(ct) || + Report.isFeedbackReport(ct)) parts.extra.add(new PartHolder(part, contentType)); AttachmentPart apart = new AttachmentPart(); @@ -4703,6 +4714,7 @@ public class MessageHelper { String diagnostic; String disposition; String refid; + String feedback; String html; Report(String type, String content) { @@ -4762,6 +4774,15 @@ public class MessageHelper { this.refid = value; break; } + } else if (isFeedbackReport(type)) { + // https://datatracker.ietf.org/doc/html/rfc5965 + feedback = "complaint"; + switch (name) { + case "Feedback-Type": + // abuse, fraud, other, virus + feedback = value; + break; + } } } } catch (Throwable ex) { @@ -4780,6 +4801,10 @@ public class MessageHelper { return isDispositionNotification(type); } + boolean isFeedbackReport() { + return isFeedbackReport(type); + } + boolean isDelivered() { return ("delivered".equals(action) || "relayed".equals(action) || "expanded".equals(action)); } @@ -4839,5 +4864,9 @@ public class MessageHelper { static boolean isDispositionNotification(String type) { return "message/disposition-notification".equalsIgnoreCase(type); } + + static boolean isFeedbackReport(String type) { + return "message/feedback-report".equalsIgnoreCase(type); + } } }