通过 apache common java api 转发带有附件的电子邮件(使用 JavaMailApi 读取)

Posted

技术标签:

【中文标题】通过 apache common java api 转发带有附件的电子邮件(使用 JavaMailApi 读取)【英文标题】:Forward an email(read using JavaMailApi) with Attachments by apache common java api 【发布时间】:2020-08-02 19:37:41 【问题描述】:

我正在阅读来自 Outlook 网络邮件的邮件并获取邮件列表('javax.mail.Message')。现在我想使用 java 程序将这些消息转发到另一个电子邮件地址。

    private void sendTestMail(String from, String subject, String sentDate, Object object, Message message)
            throws EmailException, Exception 

        MultiPartEmail email = new MultiPartEmail();
        email.setHostName(forwardHost);

        email.addTo(mailRecipients(to));
        email.setFrom(emailFrom);
        email.setSubject(subject);
        email.setMsg("Testing email by sahil.");

        EmailAttachment attachment = new EmailAttachment();
        attachment.setPath("c:\\sahil\\test.jpg");
        attachment.setDisposition(EmailAttachment.ATTACHMENT);
        attachment.setDescription("Picture_of_John");
        attachment.setName("John.jpg");
        email.attach(attachment);  


        MimeMultipart multiPart = getMimeMultipart(message);
        email.addPart(multiPart);

        email.send();
       

如果我在上面的代码中的两行下面注释,那么它工作正常。

MimeMultipart multiPart = getMimeMultipart(message);
email.addPart(multiPart);

但是这两行我得到了例外。

2020-04-20 15:41:44,271 ERROR com.st.ict.ols.service.impl.ReplyToMessageServiceImpl [main]  Inner Exception occurred while processing individual message. Error stacktrace is[org.apache.commons.mail.EmailException: Sending the email to the following server failed : smtpapp1.sgp.st.com:25
    at org.apache.commons.mail.Email.sendMimeMessage(Email.java:1421)
    at org.apache.commons.mail.Email.send(Email.java:1448)
    at com.st.ict.ols.service.impl.ReplyToMessageServiceImpl.sendTestMail(ReplyToMessageServiceImpl.java:342)
    at com.st.ict.ols.service.impl.ReplyToMessageServiceImpl.processMessage(ReplyToMessageServiceImpl.java:167)
    at com.st.ict.ols.service.impl.MessageServiceImpl.processMessage(MessageServiceImpl.java:22)
    at com.st.ict.ols.OlsMailSenderApplication.run(OlsMailSenderApplication.java:36)
    at org.springframework.boot.SpringApplication.callRunner(SpringApplication.java:732)
    at org.springframework.boot.SpringApplication.callRunners(SpringApplication.java:716)
    at org.springframework.boot.SpringApplication.afterRefresh(SpringApplication.java:703)
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:304)
    at com.st.ict.ols.OlsMailSenderApplication.main(OlsMailSenderApplication.java:27)
Caused by: javax.mail.MessagingException: IOException while sending message;
  nested exception is:
    java.io.IOException: Exception writing Multipart
    at com.sun.mail.smtp.SMTPTransport.sendMessage(SMTPTransport.java:1308)
    at javax.mail.Transport.send0(Transport.java:255)
    at javax.mail.Transport.send(Transport.java:124)
    at org.apache.commons.mail.Email.sendMimeMessage(Email.java:1411)
    ... 10 more
Caused by: java.io.IOException: Exception writing Multipart
    at com.sun.mail.handlers.multipart_mixed.writeTo(multipart_mixed.java:83)
    at javax.activation.ObjectDataContentHandler.writeTo(DataHandler.java:884)
    at javax.activation.DataHandler.writeTo(DataHandler.java:317)
    at javax.mail.internet.MimeBodyPart.writeTo(MimeBodyPart.java:1652)
    at javax.mail.internet.MimeBodyPart.writeTo(MimeBodyPart.java:961)
    at javax.mail.internet.MimeMultipart.writeTo(MimeMultipart.java:553)
    at com.sun.mail.handlers.multipart_mixed.writeTo(multipart_mixed.java:81)
    at javax.activation.ObjectDataContentHandler.writeTo(DataHandler.java:884)
    at javax.activation.DataHandler.writeTo(DataHandler.java:317)
    at javax.mail.internet.MimeBodyPart.writeTo(MimeBodyPart.java:1652)
    at javax.mail.internet.MimeMessage.writeTo(MimeMessage.java:1850)
    at com.sun.mail.smtp.SMTPTransport.sendMessage(SMTPTransport.java:1259)
    ... 13 more
Caused by: javax.mail.MessagingException: Empty multipart: multipart/mixed; 
    boundary="----=_Part_1_1176580790.1587377502798"
    at javax.mail.internet.MimeMultipart.writeTo(MimeMultipart.java:548)
    at com.sun.mail.handlers.multipart_mixed.writeTo(multipart_mixed.java:81)
    ... 24 more

我编写的代码是为了从 JavaMailApi 的 Message 对象中检索 MimeMultipart 以使用附加函数在 apache common 的 org.apache.commons.mail.MultiPartEmail 对象中设置。

    public MimeMultipart getMimeMultipart(Message message) throws Exception 
        Object content = message.getContent();
        if (content instanceof String)
            return null;        

        if (content instanceof MimeMultipart) 
            MimeMultipart multiPartResult = new MimeMultipart();
            MimeMultipart multiPart = (MimeMultipart) content;

            List<BodyPart> result = new ArrayList<>();
            for (int i = 0; i < multiPart.getCount(); i++) 
                BodyPart bodyPart = (BodyPart) multiPart.getBodyPart(i);
                result.addAll(getMimeMultipart(bodyPart));
            
            for(BodyPart part:result) 
                multiPart.addBodyPart(part);
            
            return multiPartResult;

        
        return null;
    

    private List<BodyPart> getMimeMultipart(BodyPart part) throws Exception
        List<BodyPart> result = new ArrayList<>();
        Object content = part.getContent();

        if (content instanceof InputStream || content instanceof String) 
            if (Part.ATTACHMENT.equalsIgnoreCase(part.getDisposition()) || StringUtils.isNotBlank(part.getFileName())) 
                result.add(part);
            
            return result;
        

        if (content instanceof MimeMultipart) 
                MimeMultipart multipart = (MimeMultipart) content;
                for (int i = 0; i < multipart.getCount(); i++) 
                    BodyPart bodyPart =  (BodyPart) multipart.getBodyPart(i);
                    result.addAll(getMimeMultipart(bodyPart));
                
        
        return result;
    

我能够转发不包括附件的电子邮件,但在转发附件/内嵌图像时遇到了问题。 请帮我解决这个问题。

我可以将完整的邮件作为附件转发,如何按原样转发邮件。

MultiPartEmail email = new MultiPartEmail();
MimeMultipart mp = new MimeMultipart();
MimeBodyPart fmbp = new MimeBodyPart();
fmbp.setContent(message, "message/rfc822");
fmbp.setDisposition(Part.INLINE);
mp.addBodyPart(fmbp);
email.setContent(mp);

或者如果我使用代码

MimeMultipart mp = (MimeMultipart) message.getContent();
email.setContent(mp, message.getContentType());

我收到这样的转发电子邮件 screenshot of forwarded encoded mail

【问题讨论】:

所有 Apache 库都掩盖了真正发生的事情,但您可能想阅读此JavaMail FAQ entry on forwarding messages。 @BillShannon 感谢您的链接,现在我可以将邮件(带有附件和内嵌图像的完整邮件)作为附件转发。但我需要按原样转发消息。我应该怎么做才能转发邮件,而不是作为附件? “前进”是什么意思?你真的是指“重新发送”吗?您想假装这是一条全新的消息并将其发送给新的收件人吗?只需使用消息调用 Transport.send 并为其指定一个新地址即可。您可能需要先使用newMsg = new MimeMessage(oldMsg); 复制它 @BillShannon 我需要阅读来自一个 Outlook 客户端的消息并将这些消息发送到另一个电子邮件 ID。通过使用'email.setContent(readMessage, "message/rfc822");'我能够以某种方式实现它。当我将已读邮件发送到 Gmail 时,它看起来很完美,但是当我将已读邮件发送到 Outlook 时。我将其作为附件接收。 @BillShannon check image 我发送给其他 Outlook 的电子邮件 ID 看起来像这样。但对于 Gmail,它运行良好。 【参考方案1】:

这里的情况是从一个邮件服务器读取邮件并将相同的消息发送到同一应用程序中的另一个电子邮件 ID。

为了实现这一点,我使用 Java Mail API 来读取和发送。 如果您在两个步骤中使用不同的主机,请确保更新属性。

    private void sendMailJavax(Message oldMessage) 
        try  
            // creating a new message using the older message
            MimeMessage message = new MimeMessage((MimeMessage)oldMessage);
            // updating properties as per sender Mailing API
            message.getSession().getProperties().clear();
            message.getSession().getProperties().setProperty("mail.smtp.host", forwardHost);

            // setting appropriate headers. // make sure you don't append using .add methods.
            message.setFrom(new InternetAddress(emailFrom));
            message.setRecipient(Message.RecipientType.TO, new InternetAddress(to));
            message.setReplyTo(new Address[]  new InternetAddress(replyToEmail));

            Transport.send(message); 
            System.out.println("Email Sent  successfully...."); 
             catch (MessagingException mex)  
                mex.printStackTrace(); 
             
    

【讨论】:

以上是关于通过 apache common java api 转发带有附件的电子邮件(使用 JavaMailApi 读取)的主要内容,如果未能解决你的问题,请参考以下文章

FLINK 读取MYSQL数据-通过JDBC方式

Apache commons(Java常用工具包)简介

日常Exception第三十三回:Flink运行jar包报错NoSuchMethodError: org.apache.flink.api.common.functions.Runtime....

日常Exception第三十三回:Flink运行jar包报错NoSuchMethodError: org.apache.flink.api.common.functions.Runtime....

ftp中ftpClient类的API

Apache commons 文件上传替代方案