User Tools

Site Tools


technology:blackberry:email

Reading the Body of an Email

On RIM's website, there is a web page explaining how to read the text or HTML body of an email. The method they provide is recursive, which is great because each mail server–Domino, Exchange, etc–encodes MIME messages in a different way. Hence I can't rely on finding the TextBodyPart in the same location all the time.

So I pasted RIM's code into my project and adjusted it for my own needs. Unfortunately, it produced NullPointerExceptions when reading certain types of mail. After a bit of research, I found that RIM had published fragile code. For example:

 else if (obj instanceof MimeBodyPart)
   {
      MimeBodyPart mbp = (MimeBodyPart)obj;
      if (mbp.getContentType().indexOf(ContentType.TYPE_TEXT_HTML_STRING) != -1)
      {
        readEmailBody(mbp);
      }
   }

The code above looks fine at first glance…it properly casts the 'obj' object into a MimeBodyPart object, then uses it. But notice the if condition:

if (''mbp.getContentType().indexOf(....)''

The problem with nested calls like this is that the first method might return null. And any method involked on null will produce a NullPointerException.

So I added some null checking to RIM's code to make it safer. At the same time, I encapsulated the method in a class. The class takes an descendant of Message class as a parameter. And I added a getText() method to make it easy to retrieve the text. The class can be used like this:

      EmailProcessor emp = new EmailProcessor(SomeMessageObject.getContent());
      String text = emp.getText();

The revise code from RIM now looks like this:

    private class EmailProcessor
    {
        private boolean _hasSupportedAttachment = false;
 
        private boolean _hasUnsupportedAttachment = false;
 
        private String _plainTextMessage = null;
 
        private String _htmlMessage = null;
 
        private String status = null;
 
        private EmailProcessor()
        {
        }// hide the default constructor...force use of 1-arg constructor
 
        public EmailProcessor(Object obj)
        {
            findEmailBody(obj);
 
        }
 
        /**
         * This method returns the body content to the calling program If both plain text and HTML
         * are available, the plain text will be returned.
         *
         * @return
         */
        public String getText()
        {
            if (_plainTextMessage != null)
                return _plainTextMessage;
            if (_htmlMessage != null)
                return _htmlMessage;
            return "";
        }
 
        /**
         * This method is recursive. It reads the incoming object's data type and acts accordingly.
         * It populates two class variables that hold the plain text and HTML versions of the
         * message. The getText() method can be used to retrieve the text.
         *
         * @param obj
         */
        private void findEmailBody(Object obj)
        {
            // Reset the attachment flags.
 
            if (obj instanceof Multipart)
            {
                Multipart mp = (Multipart) obj;
 
                // Extract all of the parts within the Multipart message.
                for (int count = 0; count < mp.getCount(); ++count)
                {
                    findEmailBody(mp.getBodyPart(count));
                }
            }
            else if (obj instanceof TextBodyPart)
            {
                // This message only has a text body.
                TextBodyPart tbp = (TextBodyPart) obj;
                readEmailBody(tbp);
            }
            else if (obj instanceof MimeBodyPart)
            {
                MimeBodyPart mbp = (MimeBodyPart) obj;
                String cType = mbp.getContentType();
                if (cType != null)
                {
                    if (cType.indexOf(ContentType.TYPE_TEXT_HTML_STRING) != -1)
                    {
                        // The message has no attachments.
                        // Read the email body, which may contain a
                        // TexBodyPart, MimeBodyPart or both.
                        readEmailBody(mbp);
                    }
                    else if (cType.equals(ContentType.TYPE_MULTIPART_MIXED_STRING) || cType.equals(ContentType.TYPE_MULTIPART_ALTERNATIVE_STRING))
                    {
                        // The message has attachments or we are at the
                        // top level of the message. Dig deeper to find the body.
                        // Extract all of the parts within the MimeBodyPart message.
                        findEmailBody(mbp.getContent());
                    }
                }
            }
            else if (obj instanceof SupportedAttachmentPart)
            {
                // This is a supported attachment.
                _hasSupportedAttachment = true;
            }
            else if (obj instanceof UnsupportedAttachmentPart)
            {
                // This is an unsupported attachment.
                _hasUnsupportedAttachment = true;
            }
        }
 
        private void readEmailBody(TextBodyPart tbp)
        {
            // reality check
            if (tbp == null)
                return;
 
            // This is the plain text body.
            _plainTextMessage = (String) tbp.getContent();
 
            // Determine if all of the text body part is present.
            if (tbp.hasMore() && !tbp.moreRequestSent())
            {
                // It does, request more of the message.
                try
                {
                    Transport.more(tbp, true);
                    status = "Requesting more of the plain text message body. Reopen the screen to view it once more has been received.";
                }
                catch (Exception ex)
                {
                    //nothing we can do...
                    //Dialog.alert("Exception: " + ex.toString());
                }
            }
        }
 
        // Displays the HTML or plain text body of the email message.
        private void readEmailBody(MimeBodyPart mbp)
        {
            // reality check
            if (mbp == null)
                return;
 
            // Extract the content of the message.
            Object obj = mbp.getContent();
            String mimeType = mbp.getContentType();
            String body = null;
 
            // Determine if the data returned is a String or a byte array.
            // If the BlackBerry is able to convert the HTML content
            // into a String, then a String should be returned. If
            // the encoding is not supported a byte array is returned
            // to allow your application to work with the raw data.
 
            if (obj instanceof String)
            {
                body = (String) obj;
            }
            else if (obj instanceof byte[])
            {
                body = new String((byte[]) obj);
            }
 
            if (mimeType != null)
            {
                if (mimeType.indexOf(ContentType.TYPE_TEXT_PLAIN_STRING) != -1)
                {
                    // This is the plain text body.
                    _plainTextMessage = body;
 
                    // Determine if all of the text body part is present.
                    if (mbp!=null && mbp.hasMore() && !mbp.moreRequestSent())
                    {
                        // It does, request more of the message.
                        try
                        {
                            Transport.more(mbp, true);
                            status = "Requesting more of the plain text message body. Reopen the screen to view it once more has been received.";
                        }
                        catch (Exception ex)
                        {
                            // nothing we can do...
                            // Dialog.alert("Exception: " + ex.toString());
                        }
                    }
                }
                else if (mimeType.indexOf(ContentType.TYPE_TEXT_HTML_STRING) != -1)
                {
                    // This is the HTML body part of the message.
                    _htmlMessage = body;
 
                    // Determine if all of the HTML body part is present.
                    if (mbp!=null && mbp.hasMore() && !mbp.moreRequestSent())
                    {
                        // It does, request more of the message.
                        try
                        {
                            Transport.more(mbp, true);
                            status = "Requesting more of the HTML message body. Reopen the screen to view it once more has been received.";
                        }
                        catch (Exception ex)
                        {
                            // nothing we can do....
                            // Dialog.alert("Exception: " + ex.toString());
                        }
                    }
                }
            }
        }
    }
/home/cfreyer/public_html/data/pages/technology/blackberry/email.txt · Last modified: 2011/02/17 11:50 by Chris Freyer