使用 JavaMail 创建多部分

Posted

技术标签:

【中文标题】使用 JavaMail 创建多部分【英文标题】:Create multipart using JavaMail 【发布时间】:2016-06-26 19:06:31 【问题描述】:

我想创建一个MimeMessage,它必须有两个部分,如下图所示(Part_0 和 Part_2)

我正在尝试使用下面的代码来生成 s/mime

public static void main(String[] a) throws Exception 

    // create some properties and get the default Session
    Properties props = new Properties();
    // props.put("mail.smtp.host", host);

    Session session = Session.getInstance(props, null);
    // session.setDebug(debug);
    MimeMessage msg = new MimeMessage(session);
    try 

        msg.addHeader("Content-Type", "multipart/signed; protocol=\"application/pkcs7-signature;");

        msg.setFrom(new InternetAddress(FROM_EMAIL));
        InternetAddress[] address = new InternetAddress(
            TO_EMAIL);
        msg.setRecipients(Message.RecipientType.TO, address);
        msg.setSubject("Test Subject");
        msg.setSentDate(new Date());

        // create and fill the first message part
        MimeBodyPart bodyPart1 = new MimeBodyPart();

        bodyPart1.setHeader("Content-Type", "text/html; charset=utf-8");
        bodyPart1.setContent("<b>Hello World</b>", "text/html");

        Multipart multiPart = new MimeMultipart();
        multiPart.addBodyPart(bodyPart1, 0);

        try (OutputStream str = Files.newOutputStream(Paths
                .get(UNSIGNED_MIME))) 
            bodyPart1.writeTo(str);
        

        signMime();

        MimeBodyPart attachPart = new MimeBodyPart();

        String filename = SIGNED_VALUE;

        DataSource source = new FileDataSource(filename);

        attachPart.setDataHandler(new DataHandler(source));
        attachPart.setFileName("smime.p7s");
        attachPart.addHeader("Content-Type", "application/pkcs7-signature; name=smime.p7s;");
        attachPart.addHeader("Content-Transfer-Encoding", "base64");
        attachPart.addHeader("Content-Description", "S/MIME Cryptographic Signature");

        multiPart.addBodyPart(attachPart);

        msg.setContent(multiPart, "multipart/signed; protocol=\"application/pkcs7-signature\"; ");

        msg.saveChanges();
        try (OutputStream str = Files.newOutputStream(Paths
                .get(SIGNED_MIME))) 
            msg.writeTo(str);
        

     catch (MessagingException mex) 
        mex.printStackTrace();
        Exception ex = null;
        if ((ex = mex.getNextException()) != null) 
            ex.printStackTrace();
        
    

我使用了两个MimeBodyPart,但是我总是得到一个 Part_0 并生成了如下所示的 eml 文件。

【问题讨论】:

【参考方案1】:

我没有尝试编译它,但你想要的是这样的。内部多部分是外部多部分的主体部分。

    msg.setFrom(new InternetAddress(FROM_EMAIL));
    InternetAddress[] address = new InternetAddress(
        TO_EMAIL);
    msg.setRecipients(Message.RecipientType.TO, address);
    msg.setSubject("Test Subject");
    msg.setSentDate(new Date());

    MultipartSigned multiSigned = new MultipartSigned();

    // create and fill the first message part
    MimeBodyPart bodyPart1 = new MimeBodyPart();

    bodyPart1.setText("<b>Hello World</b>", "utf-8", "html");

    Multipart multiPart = new MimeMultipart();
    multiPart.addBodyPart(bodyPart1);

    // add other content to the inner multipart here

    MimeBodyPart body = new MimeBodyPart();
    body.setContent(multiPart);
    multiSigned.addBodyPart(body);

    try (OutputStream str = Files.newOutputStream(Paths
            .get(UNSIGNED_MIME))) 
        body.writeTo(str);
    

    signMime();

    MimeBodyPart attachPart = new MimeBodyPart();

    String filename = SIGNED_VALUE;

    attachPart.attachFile(filename,
            "application/pkcs7-signature; name=smime.p7s", "base64");
    attachPart.setFileName("smime.p7s");
    attachPart.addHeader("Content-Description",
            "S/MIME Cryptographic Signature");

    multiSigned.addBodyPart(attachPart);
    msg.setContent(multiSigned);

    msg.saveChanges();

你需要这个:

public class MultipartSigned extends MimeMultipart 
    public MultipartSigned() 
        super("signed");
        ContentType ct = new ContentType(contentType);
        ct.setParameter("protocol", "application/pkcs7-signature");
        contentType = ct.toString();
    

您可以通过将更多功能移到 MultipartSigned 类中来使这更简洁。

【讨论】:

亲爱的@Bill 感谢您的关注。这解决了我的问题。 你好@Bill 我应该在 msg.saveChanges() 之前添加 msg.setContent(multiSigned);因为当我尝试 saveChanges() 时,它会给出错误“不平衡的引用字符串” 是的,对不起,我忘记了。【参考方案2】:

您正在寻找的是Spring Mime Helper。

【讨论】:

有帮助,但如果我是发帖者,我只会使用第三方库作为最后的手段。 你是对的@DavidS :) 我会先检查@Bill Shannon 的答案

以上是关于使用 JavaMail 创建多部分的主要内容,如果未能解决你的问题,请参考以下文章

Jmeter Groovy JavaMail API 多部分向示例结果添加内容

JavaMail 问题或错误?

javamail 阅读邮件时,有啥理由使用 Message 而不是 MimeMessage 等?

如何使用 javamail 在 android 应用程序中处理 multipart/alternative?

JavaWeb学习总结(五十二)——使用JavaMail创建邮件和发送邮件

JavaMail邮件发送