【问题标题】:How to get email body text and attachments using mimemessage class in java如何使用 java 中的 mimemessage 类获取电子邮件正文和附件
【发布时间】:2020-10-06 02:10:57
【问题描述】:

在我的 SMTP 服务器代码中,我有一个 MimeMessage 实例,我想用它来提取传入的邮件正文(邮件文本)和邮件附件。为此,我在客户端和服务器端使用以下实现。但是,我只能检索邮件附件。该代码以某种方式检测到 CustomerEngineer.ahmet 两次,但它们都不包含邮件正文:“这是邮件正文”。我可以检索图像。

在我的 java 邮件客户端中,我创建了一个具有以下架构的邮件:

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);
    }

在我的服务器端,我使用以下逻辑:

 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();
        }
    }
}

【问题讨论】:

    标签: java jakarta-mail mime mime-message


    【解决方案1】:

    不太确定您的电子邮件结构。但请注意,多部分可以嵌套 - 因此您必须一直向下搜索主体。而使用 mutlipart/alternative,可能会有不止一个实体。

    在您的情况下,您可能正在查看

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

    一种结构。所以第一个多部分真的不包括身体。 考虑这段代码:

    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());
        }
    }
    

    在您的情况下,混淆来自两次添加 body-part:

        // 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);
    

    也许试试这个发送:

            // 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);            
    

    【讨论】:

    • 嗨,Jan,哦,哇,谢谢你,我不这么认为。我浏览了你构建的逻辑,但它仍然无法以某种方式为我点击:/当我尝试这个逻辑时,你建议我得到这个输出:消息是多部分/混合的;边界="----=_Part_0_1072408673.1592314025145" 我们有一个多部分/混合; boundary="----=_Part_0_1072408673.1592314025145" 内容 0 是应用程序/八位字节流; name=CustomerEngineer.ahmet 内容 1 是应用程序/八位字节流; name=CustomerEngineer.ahmet
    • 所以不知何故它只能检索附件,但在上面的客户端我添加了 messageBodyPart.setText("This is a message body") 虽然;。好烦人:D
    • 啊!您正在重复使用相同的 Body 部分!我会把它添加到答案中
    • 您好 Jan,首先我真的很感谢您抽出宝贵时间帮助我。我尝试了这个最终解决方案,但它仍然对我不起作用。我花了几乎一整天的时间来解决这个问题。在您更新的答案中,在最后一部分中您说 A simple -> 然后您共享两行代码,这是否意味着我应该从客户端删除所有内容并使用它?另外,我在您所说的区域创建了一个递归部分,现在我得到以下输出:“其他内容:com.sun.mail.util.BASE64DecoderStream”啊,我快要发疯了。非常感谢你..
    • 哇.. 真是太费脑筋了.. 非常感谢我能够理解它,它终于奏效了.. 我真的很感谢 Jan.
    【解决方案2】:

    就我而言,我需要从MimeMessage 中提取MimeBodyPart。这比我想象的要棘手,但我最终从BouncyCastle 抢走了这两种方法

     /**
     * extract an appropriate body part from the passed in MimeMessage
     */
    protected MimeBodyPart makeContentBodyPart(
        MimeMessage message)
        throws SMIMEException
    {
        MimeBodyPart content = new MimeBodyPart();
        //
        // add the headers to the body part.
        //
        try
        {
            message.removeHeader("Message-Id");
            message.removeHeader("Mime-Version");
    
            // JavaMail has a habit of reparsing some content types, if the bodypart is
            // a multipart it might be signed, we rebuild the body part using the raw input stream for the message.
            try
            {
                if (message.getContent() instanceof Multipart)
                {
                    content.setContent(message.getRawInputStream(), message.getContentType());
                    extractHeaders(content, message);
                    return content;
                }
            }
            catch (MessagingException e)
            {
                // fall back to usual method below
            }
            content.setContent(message.getContent(), message.getContentType());
            content.setDataHandler(message.getDataHandler());
            extractHeaders(content, message);
        }
        catch (MessagingException e)
        {
            throw new SMIMEException("exception saving message state.", e);
        }
        catch (IOException e)
        {
            throw new SMIMEException("exception getting message content.", e);
        }
    
        return content;
    }
    
    private void extractHeaders(MimeBodyPart content, MimeMessage message)
        throws MessagingException
    {
        Enumeration e = message.getAllHeaders();
    
        while (e.hasMoreElements())
        {
            Header hdr = (Header)e.nextElement();
            content.addHeader(hdr.getName(), hdr.getValue());
        }
    }
    

    【讨论】:

      猜你喜欢
      • 2015-03-29
      • 1970-01-01
      • 2013-06-08
      • 2013-04-30
      • 2011-07-09
      • 1970-01-01
      • 2013-07-25
      • 2017-12-12
      • 2020-07-04
      相关资源
      最近更新 更多