it-swarm.com.de

Laden Sie Anhänge mit Java Mail herunter

Nun, da ich alle Nachrichten heruntergeladen und gespeichert habe

Message[] temp;

Wie bekomme ich die Liste der Anhänge für jede dieser Nachrichten an?

List<File> attachments;

Hinweis: Keine Drittanbieter-Libs, bitte nur JavaMail.

93
folone

Ohne Ausnahmebehandlung geht es aber hier:

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

Die Frage ist sehr alt, aber vielleicht hilft sie jemandem. Ich möchte die Antwort von David Rabinowitz erweitern. 

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

sie sollten nicht alle Zusätze wie erwartet zurückgeben, da Sie E-Mails haben können, bei denen der gemischte Teil ohne definierte Disposition ist. 

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

in diesem Fall können Sie auch nach Dateinamen suchen. So was: 

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

EDIT

es gibt den gesamten Arbeitscode mit der oben beschriebenen Bedingung. Da jedes Teil andere Teile einkapseln kann und der Anhang verschachtelt sein sollte, wird Rekursion zum Durchlaufen aller Teile verwendet

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

Einige Zeitersparnis für den Code, in dem Sie die Anhangsdatei speichern:

mit javax mail version 1.4 und danach kann man sagen

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

anstatt

    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

Sie können Apache Commons Mail API MimeMessageParser - getAttachmentList () zusammen mit Commons IO und Commons Lang verwenden.

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

Hier ist meine Wiedergabe von mefis Lösung .

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