javajakarta-mailmimemime-message

How to get email body text and attachments using mimemessage class in java


In my SMTP server code, I have a MimeMessage instance that I want to use for extracting the incoming mailbody(mail text) and mail attachments. To do this, I use the below implementation on client and server sides. However, I am only able to retrieve mail attachments. The code somehow detects CustomerEngineer.ahmet thing two times and none of them contains the mail body which is : "This is a message body". I can retrieve the image though.

In my java mail client, I created a mail with the following schema:

try {
        // Create a default MimeMessage object
        Message message = new MimeMessage(session);

        message.setFrom(new InternetAddress(from));

        message.setRecipients(Message.RecipientType.TO, InternetAddress.parse(to));

        // Set Subject
        message.setSubject("Hi JAXenter");

        BodyPart messageBodyPart = new MimeBodyPart();

        messageBodyPart.setText("This is a message body");

        Multipart multipart = new MimeMultipart();

        multipart.addBodyPart(messageBodyPart);

        DataSource source = new FileDataSource(new File(System.getProperty("user.dir").concat("\\src\\main\\java\\emailrelayserver\\CustomerEngineer.png")));
        messageBodyPart.setDataHandler(new DataHandler(source));
        messageBodyPart.setFileName("CustomerEngineer.ahmet");
        multipart.addBodyPart(messageBodyPart);

        message.setContent(multipart);

        // Send message
        Transport.send(message);

        System.out.println("Sent message successfully....");

    } catch (MessagingException e) {
        throw new RuntimeException(e);
    }

On my server side I use the following logic:

 MimeMessage message = new MimeMessage(session, data);

public void seperateBodyAndAttachments(MimeMessage message) throws MessagingException, IOException {
    String mimeType = message.getContentType();
    Date dt = new Date();

    if (message.isMimeType("text/*")) {
        System.out.println("this containst a text file");
    }  else if (message.isMimeType("multipart/*")) {
        Multipart mp = (Multipart) message.getContent();
        int idx = 0;
        int count = mp.getCount();
        for (int i = 0; i < count; i++) {
            BodyPart part = mp.getBodyPart(i);
            String name = part.getDataHandler().getName();
            if (part.isMimeType("text/*")) {
                if (name == null) {
                    name = "text-" + (++idx) + ".txt";
                }
                System.out.println(name);
            } else {
                if (name == null) {
                    name = "attachment-" + (++idx);
                }
                FileOutputStream fos = new FileOutputStream(System.getProperty("user.dir").concat("\\src\\main\\resources\\DevEnvironmentConfigFile\\" + name));
                BufferedOutputStream bos = new BufferedOutputStream(fos);
                part.getDataHandler().writeTo(bos);
                bos.close();
            }
        }
    } else if (message.isMimeType("message/rfc822")) {
        // Not implemented
    } else {
        Object o = message.getContent();
        if (o instanceof String) {
            FileWriter fw = new FileWriter(System.getProperty("user.dir").concat("\\src\\main\\java\\emailrelayserver\\downloads\\"  + "text.txt"));
            BufferedWriter bw = new BufferedWriter(fw);
            bw.write((String)o);
            bw.close();
        } else if (o instanceof InputStream) {
            FileOutputStream fos = new FileOutputStream(System.getProperty("user.dir").concat("\\src\\main\\java\\emailrelayserver\\downloads\\"  +"message.dat"));
            BufferedOutputStream bos = new BufferedOutputStream(fos);
            message.getDataHandler().writeTo(bos);
            bos.close();
        } else {
            FileWriter fw = new FileWriter(System.getProperty("user.dir").concat("\\src\\main\\java\\emailrelayserver\\downloads\\"  +"unknown.txt"));
            BufferedWriter bw = new BufferedWriter(fw);
            bw.write((String)o);
            bw.close();
        }
    }
}

Solution

  • Not quite sure about your email structure. But be aware that multiparts can be nested - so you'll have to go all the way down in your search for the body. And with mutlipart/alternative, there might be more than one body.

    In your case, you could be looking at

    multipart/mixed
      multipart/alternative
        text/plain
        text/html
    attachment
    

    kind of structure. So the first multipart really does not include the body. Consider this code:

    public void seperateBodyAndAttachments(MimeMessage mm) throws MessagingException, IOException {
       String mimeType = message.getContentType();
       System.out.println("Message is a " + mimeType);  
       Object content = mm.getContent();
       if(content instanceof String) {
         System.out.println("Body: " + content);
       } else if(content instanceof MimeMultipart) {                
         MimeMultipart multi = (MimeMultipart)content;
         System.out.println("We have a "+ multi.getContentType());              
         for(int i = 0; i < multi.getCount(); ++i) {
            BodyPart bo = multi.getBodyPart(i);
            System.out.println("Content "+i+" is a " + bo.getContentType());
            //Now that body part could again be a MimeMultipart...
            Object bodyContent = bo.getContent();
            //possibly build a recurion here -> the logic is the same as for mm.getContent() above
          }
        } else {
            System.out.println("Some other content: " + content.getClass().getName());
        }
    }
    

    In your case, the confusion comes from adding body-part twice:

        // This is the object created
        BodyPart messageBodyPart = new MimeBodyPart();
        messageBodyPart.setText("This is a message body");
    
        Multipart multipart = new MimeMultipart();
    
        // you add a reference to this object into the multipart
        multipart.addBodyPart(messageBodyPart);
    
    
        DataSource source = new FileDataSource(new File(System.getProperty("user.dir").concat("\\src\\main\\java\\emailrelayserver\\CustomerEngineer.png")));
    
        //you CHANGE THE CONTENTS of the object to now contain your attachment
        messageBodyPart.setDataHandler(new DataHandler(source));
        messageBodyPart.setFileName("CustomerEngineer.ahmet");
    
        //and add it a second time.
        multipart.addBodyPart(messageBodyPart);
    

    Maybe try this for sending:

            // Set Subject
            message.setSubject("Hi JAXenter");
    
    
            Multipart multipart = new MimeMultipart("mixed");
            //Add Text Part         
            BodyPart textBodyPart = new MimeBodyPart();
            textBodyPart.setContent("This is a message body", "text/plain");
            multipart.addBodyPart(textBodyPart);
    
            //Add attachment
            DataSource source = new FileDataSource(new File(System.getProperty("user.dir").concat("\\src\\main\\java\\emailrelayserver\\CustomerEngineer.png")));
            BodyPart messageBodyPart = new MimeBodyPart();
            messageBodyPart.setDataHandler(new DataHandler(source));
            messageBodyPart.setFileName("CustomerEngineer.ahmet");
            multipart.addBodyPart(messageBodyPart);
    
            //Set this as message content
            message.setContent(multipart);
    
    
    
            //This will show you internal structure of your message! D
            message.saveChanges();
            message.writeTo(System.out);
    
            Transport.send(message);