代码之家  ›  专栏  ›  技术社区  ›  George

使用Java Mail下载附件

  •  93
  • George  · 技术社区  · 15 年前

    Message[] temp;
    

    我如何获取每个邮件的附件列表

    List<File> attachments;
    

    注: 请不要第三方LIB,只有JavaMail。

    5 回复  |  直到 15 年前
        1
  •  112
  •   rzwitserloot    5 年前

    List<File> attachments = new ArrayList<File>();
    for (Message message : temp) {
        Multipart multipart = (Multipart) message.getContent();
    
        for (int i = 0; i < multipart.getCount(); i++) {
            BodyPart bodyPart = multipart.getBodyPart(i);
            if(!Part.ATTACHMENT.equalsIgnoreCase(bodyPart.getDisposition()) &&
                   StringUtils.isBlank(bodyPart.getFileName())) {
                continue; // dealing with attachments only
            } 
            InputStream is = bodyPart.getInputStream();
            // -- EDIT -- SECURITY ISSUE --
            // do not do this in production code -- a malicious email can easily contain this filename: "../etc/passwd", or any other path: They can overwrite _ANY_ file on the system that this code has write access to!
    //      File f = new File("/tmp/" + bodyPart.getFileName());
            FileOutputStream fos = new FileOutputStream(f);
            byte[] buf = new byte[4096];
            int bytesRead;
            while((bytesRead = is.read(buf))!=-1) {
                fos.write(buf, 0, bytesRead);
            }
            fos.close();
            attachments.add(f);
        }
    }
    
        2
  •  34
  •   Kevin Eduard Piske mefi    6 年前

    这个问题很老了,但也许它会帮助别人。我想扩大戴维·拉比诺维茨的答案。

    if(!Part.ATTACHMENT.equalsIgnoreCase(bodyPart.getDisposition()))
    

    不应像预期的那样返回所有atachments,因为您可以在混合部分没有定义处置的情况下使用邮件。

       ----boundary_328630_1e15ac03-e817-4763-af99-d4b23cfdb600
    Content-Type: application/octet-stream;
        name="00000000009661222736_236225959_20130731-7.txt"
    Content-Transfer-Encoding: base64
    

    因此,在本例中,您还可以检查文件名。这样地:

    if (!Part.ATTACHMENT.equalsIgnoreCase(part.getDisposition()) && StringUtils.isBlank(part.getFileName())) {...}
    

    编辑

    有使用上述条件的完整工作代码。。因为每个零件都可以封装其他零件,并且附件应该嵌套在其中,所以使用递归遍历所有零件

    public List<InputStream> getAttachments(Message message) throws Exception {
        Object content = message.getContent();
        if (content instanceof String)
            return null;        
    
        if (content instanceof Multipart) {
            Multipart multipart = (Multipart) content;
            List<InputStream> result = new ArrayList<InputStream>();
    
            for (int i = 0; i < multipart.getCount(); i++) {
                result.addAll(getAttachments(multipart.getBodyPart(i)));
            }
            return result;
    
        }
        return null;
    }
    
    private List<InputStream> getAttachments(BodyPart part) throws Exception {
        List<InputStream> result = new ArrayList<InputStream>();
        Object content = part.getContent();
        if (content instanceof InputStream || content instanceof String) {
            if (Part.ATTACHMENT.equalsIgnoreCase(part.getDisposition()) || StringUtils.isNotBlank(part.getFileName())) {
                result.add(part.getInputStream());
                return result;
            } else {
                return new ArrayList<InputStream>();
            }
        }
    
        if (content instanceof Multipart) {
                Multipart multipart = (Multipart) content;
                for (int i = 0; i < multipart.getCount(); i++) {
                    BodyPart bodyPart = multipart.getBodyPart(i);
                    result.addAll(getAttachments(bodyPart));
                }
        }
        return result;
    }
    
        3
  •  9
  •   rzwitserloot    5 年前

    1.4 之后,你可以说

    // SECURITY LEAK - do not do this! Do not trust the 'getFileName' input. Imagine it is: "../etc/passwd", for example.
    // bodyPart.saveFile("/tmp/" + bodyPart.getFileName());
    

    而不是

        InputStream is = bodyPart.getInputStream();
        File f = new File("/tmp/" + bodyPart.getFileName());
        FileOutputStream fos = new FileOutputStream(f);
        byte[] buf = new byte[4096];
        int bytesRead;
        while((bytesRead = is.read(buf))!=-1) {
            fos.write(buf, 0, bytesRead);
        }
        fos.close();
    
        4
  •  6
  •   moe    8 年前

    您可以简单地使用apachecommons邮件API MimeMessageParser - getAttachmentList() 沿着Commons IO和Commons Lang。

    MimeMessageParser parser = ....
    parser.parse();
    for(DataSource dataSource : parser.getAttachmentList()) {
    
        if (StringUtils.isNotBlank(dataSource.getName())) {}
    
            //use apache commons IOUtils to save attachments
            IOUtils.copy(dataSource.getInputStream(), ..dataSource.getName()...)
        } else {
            //handle how you would want attachments without file names
            //ex. mails within emails have no file name
        }
    }
    
        5
  •  0
  •   andermirik    4 年前

    @Throws(Exception::class)
        fun getAttachments(message: Message): List<BodyPart>{
            val content = message.content
            if (content is String) return ArrayList<BodyPart>()
            if (content is Multipart) {
                val result: MutableList<BodyPart> = ArrayList<BodyPart>()
                for (i in 0 until content.count) {
                    result.addAll(getAttachments(content.getBodyPart(i)))
                }
                return result
            }
            return ArrayList<BodyPart>()
        }
    
        @Throws(Exception::class)
        private fun getAttachments(part: BodyPart): List<BodyPart> {
            val result: MutableList<BodyPart> = ArrayList<BodyPart>()
    
            if (Part.ATTACHMENT == part.disposition && !part.fileName.isNullOrBlank()){
                result.add(part)
            }
    
            val content = part.content
            if (content is Multipart) {
                for (i in 0 until (content ).count) {
                    val bodyPart = content.getBodyPart(i)
                    result.addAll(getAttachments(bodyPart)!!)
                }
            }
            return result
        }