Proposal for cfpop/cfimap deliverystatus

I have a cron job which automatically processes bounces from transactional emails such as order confirmations. My script finds the original recipient address via one of these headers:

X-Failed-Recipients
Final-Recipient

Recently I’ve found that some bounces have Final-Recipient not in the headers, but in a section of the email which is neither in the message body nor in attachments.

The mime type is:

message/delivery-status

The query returned by cfpop/cfimap does not include a deliverystatus column because the Java source for those tags does not check for the message/delivery-status mime type.

I know Adobe doesn’t parse it either but it would be awesome for Lucee devs to have yet another advantage, made possible by Lucee being open source!

And it’s a super easy feature to add, with changes in only one file:

/core/src/main/java/lucee/runtime/net/mail/MailClient.java

In fact, I’ve already done the coding!

I haven’t submitted a pull request because I don’t know what the workflow is for that, but here are the changes required:

Branch: 6.1

--- a/core/src/main/java/lucee/runtime/net/mail/MailClient.java
+++ b/core/src/main/java/lucee/runtime/net/mail/MailClient.java
@@ -121,18 +121,19 @@ public abstract class MailClient implements PoolItem {
        private static final Collection.Key FLAGGED = KeyConstants._flagged;
        private static final Collection.Key RECENT = KeyConstants._recent;
        private static final Collection.Key SEEN = KeyConstants._seen;
+       private static final Collection.Key DELIVERY_STATUS = KeyConstants._deliverystatus;
 
        public static final int TYPE_POP3 = 0;
        public static final int TYPE_IMAP = 1;
 
        private String _popHeaders[] = { "date", "from", "messagenumber", "messageid", "replyto", "subject", "cc", "to", "size", "header", "uid" };
        private String _popAll[] = { "date", "from", "messagenumber", "messageid", "replyto", "subject", "cc", "to", "size", "header", "uid", "answered", "deleted", "draft", "flagged",
-                       "recent", "seen", "body", "textBody", "HTMLBody", "attachments", "attachmentfiles", "cids" };
+                       "recent", "seen", "body", "textBody", "HTMLBody", "attachments", "attachmentfiles", "cids", "deliverystatus" };
 
        private String _imapHeaders[] = { "date", "from", "messagenumber", "messageid", "replyto", "subject", "cc", "to", "size", "header", "uid", "answered", "deleted", "draft",
                        "flagged", "recent", "seen" };
        private String _imapAll[] = { "date", "from", "messagenumber", "messageid", "replyto", "subject", "cc", "to", "size", "header", "uid", "answered", "deleted", "draft",
-                       "flagged", "recent", "seen", "body", "textBody", "HTMLBody", "attachments", "attachmentfiles", "cids" };
+                       "flagged", "recent", "seen", "body", "textBody", "HTMLBody", "attachments", "attachmentfiles", "cids", "deliverystatus" };
 
        private String server = null;
        private String username = null;
@@ -541,6 +542,11 @@ public abstract class MailClient implements PoolItem {
                        query.setAtEL(HTML_BODY, row, content);
                        body.append(content);
                }
+               else if (message.isMimeType("message/delivery-status")) {
+                       String content = getConent(message);
+                       query.setAtEL(DELIVERY_STATUS, row, content);
+                       body.append(content);
+               }
                else {
                        Object content = message.getContent();
                        if (content instanceof MimeMultipart) {
@@ -618,6 +624,11 @@ public abstract class MailClient implements PoolItem {
                                query.setAtEL(HTML_BODY, row, content);
                                if (body.length() == 0) body.append(content);
                        }
+                       else if (bodypart.isMimeType("message/delivery-status")) {
+                               content = getConent(bodypart);
+                               query.setAtEL(DELIVERY_STATUS, row, content);
+                               if (body.length() == 0) body.append(content);
+                       }
                        else if ((content = bodypart.getContent()) instanceof Multipart) {
                                getMultiPart(query, row, attachments, attachmentFiles, cids, (Multipart) content, body);
                        }

Branch: 5.4

--- a/core/src/main/java/lucee/runtime/net/mail/MailClient.java
+++ b/core/src/main/java/lucee/runtime/net/mail/MailClient.java
@@ -112,13 +112,14 @@ public abstract class MailClient implements PoolItem {
        private static final Collection.Key HTML_BODY = KeyImpl.getInstance("HTMLBody");
        private static final Collection.Key ATTACHMENTS = KeyImpl.getInstance("attachments");
        private static final Collection.Key ATTACHMENT_FILES = KeyImpl.getInstance("attachmentfiles");
+       private static final Collection.Key DELIVERY_STATUS = KeyImpl.getInstance("deliverystatus");
 
        public static final int TYPE_POP3 = 0;
        public static final int TYPE_IMAP = 1;
 
        private String _flddo[] = { "date", "from", "messagenumber", "messageid", "replyto", "subject", "cc", "to", "size", "header", "uid" };
        private String _fldnew[] = { "date", "from", "messagenumber", "messageid", "replyto", "subject", "cc", "to", "size", "header", "uid", "body", "textBody", "HTMLBody",
-                       "attachments", "attachmentfiles", "cids" };
+                       "attachments", "attachmentfiles", "cids", "deliverystatus" };
        private String server = null;
        private String username = null;
        private String password = null;
@@ -449,6 +450,11 @@ public abstract class MailClient implements PoolItem {
                        query.setAtEL(HTML_BODY, row, content);
                        body.append(content);
                }
+               else if (message.isMimeType("message/delivery-status")) {
+                       String content = getConent(message);
+                       query.setAtEL(DELIVERY_STATUS, row, content);
+                       body.append(content);
+               }
                else {
                        Object content = message.getContent();
                        if (content instanceof MimeMultipart) {
@@ -526,6 +532,11 @@ public abstract class MailClient implements PoolItem {
                                query.setAtEL(HTML_BODY, row, content);
                                if (body.length() == 0) body.append(content);
                        }
+                       else if (bodypart.isMimeType("message/delivery-status")) {
+                               content = getConent(bodypart);
+                               query.setAtEL(DELIVERY_STATUS, row, content);
+                               if (body.length() == 0) body.append(content);
+                       }
                        else if ((content = bodypart.getContent()) instanceof Multipart) {
                                getMultiPart(query, row, attachments, attachmentFiles, cids, (Multipart) content, body);
                        }
4 Likes

@kenricashe Great work. Nice feature can add to Lucee. Thanks for your code snippets.

I’ve created the enhancement ticket for this in Lucee Jira : [LDEV-4844] - Lucee
I will do some tests and create a PR for this enhancement

3 Likes

I found the instructions on how to build Lucee from source and testing revealed another file that needs a slight edit:

/core/src/main/java/lucee/runtime/type/util/KeyConstants.java

added at line 2829:

public static final Key _deliverystatus = KeyImpl._const("deliverystatus");

I also found CONTRIBUTING.md in the repo and would be super stoked if I’d be allowed to submit the pull request so I can get my little icon in the Contributors section on GitHub. :grinning:

2 Likes

Okay @kenricashe , Create a PR for this ticket. Once you’ve done, please update here

2 Likes

Done!

1 Like