Search code examples
javaoutlookjakarta-mail

Javax Mail Untitled attachment in Outlook


I try to make a java mail sending app, but when i add a .docx attachment Outlook show: "Untitled attachment xxxx.docx" My code:

MimeMessage message = new MimeMessage(session); // Message
message.setHeader("Content-Type", "text/html; charset=UTF-8");
message.setFrom(new InternetAddress(from));
message.addRecipient(Message.RecipientType.TO, address);
message.setSubject(subject, "UTF-8");
Multipart multipart = new MimeMultipart(); // body
BodyPart messageBodyPart = new MimeBodyPart();
messageBodyPart.setContent(body, "text/html; charset=utf-8"); //html body text
multipart.addBodyPart(messageBodyPart); // body add html text
if(file != null) {
    for (File f : file) {
        MimeBodyPart attachPart = new MimeBodyPart();
        attachPart.attachFile(f.getAbsolutePath(), MimeTypeUtils.getContentTypeByFileName(f.getName()), "base64");
//                attachPart.setFileName(f.getName());
        multipart.addBodyPart(attachPart); // body add attachment
    }
}
message.setContent(multipart); // message add body content
Transport.send(message);

There are problem only with a small amount of .docx file, but it's annoying. Someone can help me? And the "getContentTypeByFileName":

public class MimeTypeUtils {
    private static final Map<String, String> fileExtensionMap;
    static {
        fileExtensionMap = new HashMap<>();
        fileExtensionMap.put("docx", "application/vnd.openxmlformats-officedocument.wordprocessingml.document");
    }
    public static String getContentTypeByFileName(String fileName) {
        FileNameMap mimeTypes = URLConnection.getFileNameMap();
        String contentType = "";
        contentType = mimeTypes.getContentTypeFor(fileName);
        if (contentType == null || contentType.isEmpty()) {
            String extension = FilenameUtils.getExtension(fileName);
            contentType = fileExtensionMap.get(extension);
        }
        return contentType;
    }
}

Solution

  • I have a problem in encapsulation the MimeMesage. My old sollution:

    MimeMessage { // the whole message
        Multipart{
            BodyPart // here is the body
            MimeBodyPart //this is the attachment
        }
    }
    

    But the correct way is:

    MimeMessage {
        Multipart {
            MimeBodyPart {
                MimeBodyPart // plain text of body
                MimeBodyPart // html text of body
            }
            MimeBodyPart // attachment
            MimeBodyPart // attachment2 ...
        }
    }
    

    Code example:

    MimeMessage message = new MimeMessage(session);
    message.addHeader("Content-Type", "multipart/mixed; charset=UTF-8");
    
    Multipart multipart = new MimeMultipart("alternative");
    
    MimeBodyPart messageBodyPartPlain = new MimeBodyPart();
    messageBodyPartPlain.setContent("Plain body text", "text/plain; charset=utf-8");
    multipart.addBodyPart(messageBodyPartPlain);
    
    MimeBodyPart messageBodyPart = new MimeBodyPart();
    messageBodyPart.setContent("Html body text", "text/html; charset=utf-8");
    multipart.addBodyPart(messageBodyPart);
    
    MimeBodyPart mbp = new MimeBodyPart();
    mbp.setContent(multipart);
    
    Multipart mp2 = new MimeMultipart("mixed");
    mp2.addBodyPart(mbp);
    
    for (Attachment a : attachments) {
        if (a != null && a.getFile() != null) {
            MimeBodyPart mbp2 = new MimeBodyPart();
            FileDataSource fds = new FileDataSource(a.getFile()) {
                public String getContentType() {
                    return MimeTypeUtils.getContentTypeByFileName(a.getName());
                }
            };
            mbp2.setDataHandler(new DataHandler(fds));
            mbp2.setFileName(a.getName());
            mp2.addBodyPart(mbp2);
        }
    }
    
    message.setContent(mp2);
    

    And after this change, everything working correctly.