Sample code for 30+ languages & platforms
Android™

Processing a multipart/report Delivery Status Notification (Bounce Notification)

See more Email Object Examples

This example discusses the format of Delivery Status Notification emails and how to process them.

Chilkat Android™ Downloads

Android™
// Important: Don't forget to include the call to System.loadLibrary
// as shown at the bottom of this code sample.
package com.test;

import android.app.Activity;
import com.chilkatsoft.*;

import android.widget.TextView;
import android.os.Bundle;

public class SimpleActivity extends Activity {

  private static final String TAG = "Chilkat";

  // Called when the activity is first created.
  @Override
  public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

    boolean success = false;

    //  Here are the MIME structures, showing the content-type and nesting of the MIME parts of three sample
    //  multipart/report DSN (Delivery Status Notification) emails.

    //  This 1st sample includes a "text/rfc822-headers" MIME subpart. 

    //  multipart/report
    //      text/plain
    //      message/delivery-status
    //      text/rfc822-headers
    //      message/rfc822

    //  This 2nd sample lacks the text/rfc-headers part, but the "report type" information
    //  is offered in both plain-text and HTML formats.

    //  multipart/report
    //      multipart/alternative
    //          text/plain
    //          text/html
    //      message/delivery-status
    //      message/rfc822

    //  ----------------------------------------------------------------------------------------------------

    //  A multipart/report MIME delivery status notification follows a specific format defined by the Internet Engineering Task Force (IETF) in RFC 3464, 
    //  which outlines the "An Extensible Message Format for Delivery Status Notifications" standard. The format consists of multiple parts within a 
    //  multipart/report structure. Here's an overview of the main parts involved:
    //  
    //  The 1st sub-part under multipart/report is the body of the DSN to be displayed by the email client (such as Outlook).
    //  It can be a simple text/plain body, or it can be multipart/alternative and offer a few alternative format, typically plain-text and HTML.
    //  HTML is best for viewing a program such as Outlook. 
    //  This part of the multipart/report is not structured for programmatic processing.  It's meant to be viewed by a human.

    //  --------------------
    //  The "message/delivery-status" part within a multipart/report MIME structure follows a specific format to provide details about the delivery status
    //  of an email message.  Here's an overview of the format and the key components within the "message/delivery-status" part:
    //  
    //  (1) Content-Type and Reporting-UA:
    //  The "message/delivery-status" part begins with the Content-Type header specifying "message/delivery-status". 
    //  It may also include a Reporting-UA (Reporting User Agent) field that identifies the software or system generating the delivery status notification.
    //  
    //  For example:
    //  
    //  Content-Type: message/delivery-status
    //  Reporting-UA: Example Mail System 1.0
    //  
    //  (2) Fields:
    //  The "message/delivery-status" part contains a series of fields, each providing specific information about the delivery status. 
    //  These fields are structured as key-value pairs.
    //  
    //  Common fields include:
    //  
    //      Final-Recipient: Specifies the recipient for whom the delivery status is being reported.
    //      Action: Describes the action performed by the reporting system (e.g., failed, delivered, delayed, etc.).
    //      Status: Indicates the status code or reason for the delivery attempt result.
    //      Remote-MTA: Specifies the host or system that attempted the delivery.
    //      Diagnostic-Code: Provides additional diagnostic information, such as error codes or explanations.
    //  
    //  For example:
    //  
    //  Final-Recipient: rfc822; john.doe@example.com
    //  Action: failed
    //  Status: 5.1.1
    //  Remote-MTA: smtp.example.com
    //  Diagnostic-Code: smtp; 550 Requested action not taken: mailbox unavailable
    //  
    //  (3) Additional Fields:
    //  Additional fields may be included in the "message/delivery-status" part to provide further information about the delivery attempt. 
    //  These fields can vary depending on the implementation or specific needs of the system generating the delivery status notification.
    //  For example:
    //  
    //  X-Spam-Flag: YES
    //  X-Spam-Score: 7.2
    //  
    //  Note: The specific fields and their values within the "message/delivery-status" part can vary depending on the implementation
    //  or the email server/application generating the delivery status notification. The structure described above represents the standard format
    //  as defined in RFC 3464, but variations may exist in practice.

    //  --------------------

    //  The "text/rfc822-headers" MIME part, if included, contains the headers of the original email message
    //  for which the delivery status notification is being generated. It provides a subset of the headers from the original message,
    //  typically excluding the message body and attachments.
    //  
    //  The purpose of including the "text/rfc822-headers" part is to provide contextual information about the original message.
    //  It allows the recipient to review the original headers, such as the subject, sender, recipients, date, and other relevant information,
    //  in order to understand the context and details of the email message for which the delivery status notification is being generated.
    //  
    //  Note that the specific headers included in the "text/rfc822-headers" part can vary based on the implementation or requirements
    //  of the system generating the delivery status notification.

    //  --------------------

    //  If the message/rfc822 part is present, it contains the full MIME of the email that was not delivered.
    //  In Chilkat terminology, this is an attached message.

    //  OK, let's write code to process a multipart/report email.

    CkEmail email = new CkEmail();
    success = email.LoadEml("qa_data/eml/deliveryStatus.eml");
    //  success = email.LoadEml("qa_data/eml/sample_multipart_report.eml");
    if (success == false) {
        Log.i(TAG, email.lastErrorText());
        return;
        }

    //  Verify this is a multipart/report email..
    if (email.IsMultipartReport() == false) {
        Log.i(TAG, "Not a multipart/report email.");
        return;
        }

    //  Get the body that is to be displayed to a human in an email program (such as Outlook).
    if (email.HasPlainTextBody() == true) {
        Log.i(TAG, "Plain text body:");
        //  println email.GetPlainTextBody();
        }
    else {
        if (email.HasHtmlBody() == true) {
            //  Convert HTML to plain-text..
            CkHtmlToText h2t = new CkHtmlToText();
            Log.i(TAG, "HTML body converted to plain-text:");
            Log.i(TAG, h2t.toText(email.getHtmlBody()));
            }
        else {
            Log.i(TAG, "Has no plain-text or HTML body...");
            }

        }

    Log.i(TAG, "---------------------------------");

    //  Now get information from the message/delivery-status part (or the message/disposition-notification part)
    Log.i(TAG, "--- Delivery Status Information:");
    Log.i(TAG, "Status: " + email.getDeliveryStatusInfo("Status"));
    Log.i(TAG, "Action: " + email.getDeliveryStatusInfo("Action"));
    Log.i(TAG, "Reporting-MTA: " + email.getDeliveryStatusInfo("Reporting-MTA"));

    CkJsonObject jsonDsnInfo = new CkJsonObject();
    email.GetDsnInfo(jsonDsnInfo);
    jsonDsnInfo.put_EmitCompact(false);
    Log.i(TAG, jsonDsnInfo.emit());

    Log.i(TAG, "---------------------------------");

    //  If the multipart/report contains a text/rfc822-headers, it can be retrieved like this:
    String headersText = email.getNthTextPartOfType(0,"text/rfc822-headers",false,false);
    if (email.get_LastMethodSuccess() == true) {
        Log.i(TAG, "The text/rfc822-headers part exists..");
        Log.i(TAG, "");
        Log.i(TAG, headersText);

        //  If you wish to process the headers, you can load them into a MIME object and use the Chilkat MIME functionality to examine the headers.
        CkMime mime = new CkMime();
        mime.LoadMime(headersText);

        //  Do whatever you want.. 
        //  For example, look at the "To" header.
        Log.i(TAG, "MIME To header:");
        Log.i(TAG, mime.getHeaderField("To"));
        }

    Log.i(TAG, "---------------------------------");

    //  Finally, if the original email was attached, you can load it into another Chilkat Email object instance and
    //  do what you want with it..

    if (email.get_NumAttachedMessages() > 0) {
        //  Get the 1st attachment message (assume we don't have more than one attached message)
        CkEmail origEmail = new CkEmail();
        success = email.GetAttachedEmail(0,origEmail);
        if (success == true) {
            Log.i(TAG, "Attached message subject: " + origEmail.subject());
            //  Do whatever else you want..
            }

        }


  }

  static {
      System.loadLibrary("chilkat");

      // Note: If the incorrect library name is passed to System.loadLibrary,
      // then you will see the following error message at application startup:
      //"The application <your-application-name> has stopped unexpectedly. Please try again."
  }
}