web-dev-qa-db-fra.com

Télécharger des pièces jointes à l'aide de Java Mail

Maintenant que j'ai téléchargé tous les messages et que je les stocke dans

Message[] temp;

Comment puis-je obtenir la liste des pièces jointes pour chacun de ces messages à

List<File> attachments;

Remarque: pas de bibliothèque tierce, s'il vous plaît, uniquement JavaMail.

93
folone

Sans exception, mais va ici:

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);
    }
}
97
David Rabinowitz

La question est très ancienne, mais peut-être que cela aidera quelqu'un. Je voudrais développer la réponse de David Rabinowitz. 

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

ne doit pas renvoyer tous les pièces jointes comme prévu, car vous pouvez avoir du courrier contenant une partie mélangée sans disposition définie. 

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

dans ce cas, vous pouvez également vérifier le nom du fichier. Comme ça: 

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

MODIFIER

il existe un code de travail complet utilisant la condition décrite ci-dessus .. Étant donné que chaque partie peut encapsuler une autre pièce et que la pièce jointe doit être imbriquée, la récursivité est utilisée pour parcourir toutes les pièces

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;
}
28
mefi

Un peu de temps pour le code où vous enregistrez le fichier joint:

avec javax mail version 1.4 et après, vous pouvez dire

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

au lieu de

    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();
9
kommradHomer

Vous pouvez simplement utiliser l'API Apache Commons Mail MimeMessageParser - getAttachmentList () le long de Commons IO et de 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
    }
}
3
Stackee007

Voici mon interprétation de la solution de mefi .

private static void attachments(
    final BodyPart body, final BiConsumer<String, InputStream> consumer)
    throws MessagingException, IOException {
    final Multipart content;
    try {
        content = (Multipart) body.getContent();
        for (int i = 0; i < content.getCount(); i++) {
            attachments(content.getBodyPart(i), consumer);
        }
        return;
    } catch (final ClassCastException cce) {
    }
    if (!Part.ATTACHMENT.equalsIgnoreCase(body.getDisposition())) {
        return;
    }
    final String name = body.getFileName();
    if (name == null || name.trim().isEmpty()) {
        return;
    }
    try (final InputStream stream = body.getInputStream()) {
        consumer.accept(name, stream);
    }
}

public static void attachments(
    final Message message, final BiConsumer<String, InputStream> consumer)
    throws IOException, MessagingException {
    final Multipart content;
    try {
        content = (Multipart) message.getContent();
    } catch (final ClassCastException cce) {
        return;
    }
    for (int i = 0; i < content.getCount(); i++) {
        attachments(content.getBodyPart(i), consumer);
    }
}
0
Jin Kwon