2013-06-18 5 views
1

Я пытаюсь использовать mime4j для разбора электронной почты, все работает нормально, однако я не могу получить имя файла вложения. К сожалению, BodyDescriptor не содержит эту информацию в полях содержимого или по типу содержимого.Получение имени файла вложения электронной почты с помощью mime4j

Я прочитал, что MaximalBodyDescriptor будет содержать имя файла, однако я не знаю, как сказать парсеру вернуть объект MaximalBodyDescriptor.

Мой обработчик реализует интерфейс ContentHandler. Я не вижу альтернативного интерфейса, который бы работал.

Любые советы, оцененные.

+0

У меня такая же проблема. Интересно, может ли @Joe Cheng пролить свет на него? –

ответ

0

Это вспомогательный класс, который мы успешно используем для синтаксического анализа электронных писем со своими вложениями. В этом подходе attach.getFileName() имеет имя файла.

package com.bitplan.smartCRM; 

import java.awt.Toolkit; 
import java.awt.datatransfer.Clipboard; 
import java.awt.datatransfer.ClipboardOwner; 
import java.awt.datatransfer.DataFlavor; 
import java.awt.datatransfer.StringSelection; 
import java.awt.datatransfer.Transferable; 
import java.io.ByteArrayInputStream; 
import java.io.File; 
import java.io.FileInputStream; 
import java.io.FileOutputStream; 
import java.io.IOException; 
import java.io.InputStream; 
import java.util.ArrayList; 
import java.util.Date; 
import java.util.Enumeration; 
import java.util.List; 
import java.util.Properties; 
import java.util.logging.Level; 
import java.util.logging.Logger; 

import javax.mail.Flags; 
import javax.mail.Folder; 
import javax.mail.MessagingException; 
import javax.mail.Session; 
import javax.mail.Store; 
import javax.mail.Transport; 
import javax.mail.internet.InternetAddress; 
import javax.mail.internet.MimeMessage; 

import org.apache.commons.io.IOUtils; 
import org.apache.james.mime4j.MimeException; 
import org.apache.james.mime4j.dom.Body; 
import org.apache.james.mime4j.dom.Entity; 
import org.apache.james.mime4j.dom.Message; 
import org.apache.james.mime4j.dom.MessageBuilder; 
import org.apache.james.mime4j.dom.MessageServiceFactory; 
import org.apache.james.mime4j.dom.Multipart; 
import org.apache.james.mime4j.dom.SingleBody; 
import org.apache.james.mime4j.dom.TextBody; 
import org.apache.james.mime4j.dom.address.MailboxList; 
import org.apache.james.mime4j.message.MessageImpl; 
import org.apache.james.mime4j.stream.Field; 

import com.bitplan.restinterface.Configuration; 

/** 
* EMail Helper class 
* 
* @author wf 
* @author Denis Lunev <[email protected]> 
* @see http 
*  ://www.mozgoweb.com/posts/how-to-parse-mime-message-using-mime4j-library 
* /
*/ 
public class EMailHelper implements ClipboardOwner { 

    public static boolean debug = true; 
    public static Logger LOGGER = Logger 
      .getLogger("com.bitplan.common.EMailHelper"); 
    private StringBuffer txtBody; 
    private StringBuffer htmlBody; 
    private ArrayList<Entity> attachments; 

    /** 
    * get a String from an input Stream 
    * 
    * @param inputStream 
    * @return 
    * @throws IOException 
    */ 
    public String fromInputStream(InputStream inputStream) throws IOException { 
     String result = IOUtils.toString(inputStream); 
     // System.out.println(result); 
     return result; 
    } 

    /** 
    * get the full Mail from a message 
    * 
    * @param message 
    * @return 
    * @throws MessagingException 
    * @throws IOException 
    */ 
    public String fullMail(javax.mail.Message message) throws MessagingException, 
      IOException { 
     StringBuffer sBuf = new StringBuffer(); 
     @SuppressWarnings("unchecked") 
     Enumeration<javax.mail.Header> headers = message.getAllHeaders(); 
     while (headers.hasMoreElements()) { 
      javax.mail.Header header = headers.nextElement(); 
      sBuf.append(header.getName() + ": " + header.getValue() + "\n"); 
     } 
     sBuf.append(fromInputStream(message.getInputStream())); 
     return sBuf.toString(); 
    } 

    /** 
    * Authentication 
    */ 
    public static class Authentication { 
     enum AuthenticationType { 
      pop3, smtp 
     }; 

     String host; 
     String user; 
     String password; 
     AuthenticationType authenticationType; 
     Transport mTransport; 

     /** 
     * create an Authentication from the configuration 
     * 
     * @param configuration 
     * @param pAuthType 
     */ 
     public Authentication(Configuration configuration, 
       AuthenticationType pAuthType) { 
      authenticationType = pAuthType; 
      String prefix = pAuthType.name() + "."; 
      // use prefix e.g. pop3.host/smtp.host 
      host = (String) configuration.toMap().get(prefix + "host"); 
      user = (String) configuration.toMap().get(prefix + "user"); 
      password = (String) configuration.toMap().get(prefix + "password"); 
     } 

     /** 
     * authenticate for sending/receiving e-mail 
     * 
     * @throws MessagingException 
     */ 
     public Transport authenticate() throws MessagingException { 
      Properties lProps = new Properties(); 
      Session session = Session.getDefaultInstance(lProps); 
      switch (authenticationType) { 
      case pop3: 
       Store store = session.getStore("pop3"); 
       store.connect(host, user, password); 
       store.close(); 
       return null; 
      case smtp: 
       // http://javamail.kenai.com/nonav/javadocs/com/sun/mail/smtp/package-summary.html 
       mTransport = session.getTransport("smtp"); 
       mTransport.connect(host, user, password); 
       return mTransport; 
      } 
      return null; 
     } 
    } 

    /** 
    * send the given e-mail 
    * 
    * @param email 
    * @throws MessagingException 
    */ 
    public void send(EMail email, Configuration configuration) 
      throws MessagingException { 
     Authentication lAuth = new Authentication(configuration, 
       Authentication.AuthenticationType.pop3); 
     Properties lProps = System.getProperties(); 
     lProps.put("mail.smtp.host", lAuth.host); 
     // WF 2004-09-18: make sure full qualified domain name is used for localhost 
     // the default InetAddress.getLocalHost().getHostName() might not work ... 
     // lProps.put("mail.smtp.localhost",java.net.InetAddress.getLocalHost().getCanonicalHostName()); 
     Session lSession = Session.getInstance(lProps); 
     MimeMessage lMsg = new MimeMessage(lSession); 
     lMsg.setFrom(new InternetAddress(email.getFromAdr())); 
     lMsg.setRecipients(javax.mail.Message.RecipientType.TO, 
       InternetAddress.parse(email.getToAdr())); 
     if (email.getCC() != null) 
      lMsg.setRecipients(javax.mail.Message.RecipientType.CC, 
        InternetAddress.parse(email.getCC())); 
     /* 
     * if (bcc()!=null) lMsg.setRecipients(Message.RecipientType.BCC, 
     * InternetAddress.parse(bcc())); lMsg.setHeader("X-Mailer", "JavaMail"); 
     * lMsg.setSentDate(new Date()); lMsg.setSubject(subject()); 
     * lMsg.setText(content()); lMsg.saveChanges(); Transport 
     * lTransport=lAuth.authenticate(); if (lTransport!=null) 
     * lTransport.sendMessage(lMsg,lMsg.getAllRecipients()); } else { 
     * Transport.send(lMsg); } 
     */ 
    } 

    /** 
    * retrieve pop3 mail from the given host 
    * 
    * @param pop3host 
    * @param user 
    * @param password 
    * @throws Exception 
    */ 
    public List<EMail> retrievePop3Mail(EMailManager eMailmanager, 
      Configuration configuration) throws Exception { 
     List<EMail> result = new ArrayList<EMail>(); 
     Properties lProps = new Properties(); 
     Session session = Session.getDefaultInstance(lProps); 
     Store store = session.getStore("pop3"); 
     File attachmentDirectory = (File) configuration.toMap().get(
       "attachmentDirectory"); 
     // get a pop3 authentication 
     Authentication auth = new Authentication(configuration, 
       Authentication.AuthenticationType.pop3); 
     store.connect(auth.host, auth.user, auth.password); 

     Folder remoteInbox = store.getFolder("INBOX"); 
     remoteInbox.open(Folder.READ_WRITE); 
     javax.mail.Message message[] = remoteInbox.getMessages(); 
     if (message.length > 0) { 
      // get all messages 
      LOGGER.log(Level.INFO, "Getting " + message.length 
        + " messages from POP3 Server '" + store.getURLName() + "'"); 
      for (int i = 0; i < message.length; i++) { 
       if (!message[i].isSet(Flags.Flag.DELETED)) { 
        EMail email = eMailmanager.create(); 
        String mailInput = this.fullMail(message[i]); 
        // System.out.print(mailInput); 
        ByteArrayInputStream mailStream = new ByteArrayInputStream(
          mailInput.getBytes()); 
        this.parseMessage(email, mailStream, attachmentDirectory); 
        result.add(email); 
        message[i].setFlag(Flags.Flag.DELETED, true); 
       } 
      } // for 
     } // if 
     remoteInbox.close(true); 
     store.close(); 
     return result; 
    } 

    /** 
    * parse the Message into the given EMail 
    * 
    * @param email 
    * @param fileName 
    * @param attachmentDirectory 
    * 
    * @throws Exception 
    */ 
    public void parseMessage(EMail email, String fileName, 
      String attachmentDirectory) throws Exception { 
     parseMessage(email, new File(fileName), new File(attachmentDirectory)); 
    } 

    /** 
    * strip the brackets 
    * 
    * @param addressList 
    * @return 
    */ 
    public String stripBrackets(MailboxList addressList) { 
     String result = null; 
     if (addressList != null) { 
      result = addressList.toString(); 
      if (result.startsWith("[") && result.endsWith("]")) { 
       result = result.substring(1, result.length() - 1); 
      } 
     } 
     return result; 
    } 

    /** 
    * parse the Message from the given file into the given e-mail using the given 
    * attachmentDirectory 
    * 
    * @param email 
    * @param file 
    * @param attachmentDirectory 
    * @throws Exception 
    */ 
    public void parseMessage(EMail email, File file, File attachmentDirectory) 
      throws Exception { 
     if (!file.canRead() || (!file.isFile())) 
      throw new IllegalArgumentException(file.getCanonicalPath() 
        + " is not a readable file"); 
     // Get stream from file 
     FileInputStream fis = new FileInputStream(file); 
     parseMessage(email, fis, attachmentDirectory); 
    } 

    /** 
    * parse the Message from the given file into the given e-mail using the given 
    * attachmentDirectory 
    * 
    * @param email 
    * @param emailInputStream 
    * @param attachmentDirectory 
    * @throws Exception 
    */ 
    public void parseMessage(EMail email, InputStream eMailInputStream, 
      File attachmentDirectory) throws Exception { 

     Message mimeMsg = null; 
     if (!attachmentDirectory.isDirectory()) 
      throw new IllegalArgumentException(attachmentDirectory.getCanonicalPath() 
        + " is not a directory"); 

     txtBody = new StringBuffer(); 
     htmlBody = new StringBuffer(); 
     attachments = new ArrayList<Entity>(); 
     Exception ex = null; 
     try { 
      // Create message with stream from file 
      // If you want to parse String, you can use: 
      // Message mimeMsg = new Message(new 
      // ByteArrayInputStream(mimeSource.getBytes())); 
      MessageServiceFactory factory = MessageServiceFactory.newInstance(); 
      MessageBuilder msgBuilder = factory.newMessageBuilder(); 
      try { 
       mimeMsg = msgBuilder.parseMessage(eMailInputStream); 
      } catch (Throwable th) { 
       LOGGER.log(Level.SEVERE,th.getClass().getName()); 
       LOGGER.log(Level.SEVERE,th.getMessage()); 
      } 
      if (mimeMsg == null) { 
       LOGGER.log(Level.SEVERE, "could not read mime msg:\n", 
         this.fromInputStream(eMailInputStream)); 
       return; 
      } 
      // Get some standard headers 
      if (mimeMsg.getTo() != null) 
       email.setToAdr(stripBrackets(mimeMsg.getTo().flatten())); 
      email.setFromAdr(stripBrackets(mimeMsg.getFrom())); 
      email.setSubject(mimeMsg.getSubject()); 
      email.setSendDate(mimeMsg.getDate()); 
      email.setEMailId(mimeMsg.getMessageId()); 
      LOGGER.log(Level.INFO, "To: " + email.getToAdr()); 
      LOGGER.log(Level.INFO, "From: " + email.getFromAdr()); 
      LOGGER.log(Level.INFO, "Subject: " + mimeMsg.getSubject()); 

      // Get custom header by name 
      Field priorityFld = mimeMsg.getHeader().getField("X-Priority"); 
      // If header doesn't found it returns null 
      if (priorityFld != null) { 
       // Print header value 
       LOGGER.log(Level.FINEST, "Priority: " + priorityFld.getBody()); 
      } 

      // If message contains many parts - parse all parts 
      if (mimeMsg.isMultipart()) { 
       Multipart multipart = (Multipart) mimeMsg.getBody(); 
       parseBodyParts(multipart); 
       // fix mime4j 0.7.2 behaviour to have no separate text/plain part 
       if (txtBody.length() == 0) { 
        txtBody.append(multipart.getPreamble()); 
       } 
      } else { 
       // If it's single part message, just get text body 
       String text = getTxtPart(mimeMsg); 
       txtBody.append(text); 
      } 
      email.setContent(txtBody.toString()); 

      // Print text and HTML bodies 
      if (debug) { 
       LOGGER.log(Level.FINEST, "Text body: " + txtBody.toString()); 
       LOGGER.log(Level.FINEST, "Html body: " + htmlBody.toString()); 
      } 
      // loop over attachments 
      for (Entity attach : attachments) { 
       writeAttachment(attach, attachmentDirectory); 
      } 
     } catch (Exception cex) { 
      ex = cex; 
     } finally { 
      if (eMailInputStream != null) { 
       try { 
        eMailInputStream.close(); 
       } catch (IOException ioex2) { 
        ioex2.printStackTrace(); 
       } 
      } 
     } 
     if (ex != null) { 
      throw ex; 
     } 
    } 

    /** 
    * write the given Attachment 
    * 
    * @param attach 
    * @param attachmentDirectory 
    * @throws IOException 
    */ 
    public void writeAttachment(Entity attach, File attachmentDirectory) 
      throws IOException { 
     String attName = attach.getFilename(); 
     // Create file with specified name 
     if (attName == null) { 
      LOGGER.log(Level.WARNING, "attachment has no file name using 'attachment" 
        + attach.hashCode() + "' instead"); 
      attName = "attachment" + attach.hashCode(); 
     } 

     FileOutputStream fos = new FileOutputStream(new File(attachmentDirectory, 
       attName)); 
     try { 
      writeBody(fos, attach.getBody()); 
     } finally { 
      fos.close(); 
     } 
    } 

    /** 
    * write the given body to the given fileoutput stream 
    * 
    * @param fos 
    * @param body 
    * @throws IOException 
    */ 
    public void writeBody(FileOutputStream fos, Body body) throws IOException { 
     if (body instanceof SingleBody) { 
      ((SingleBody) body).writeTo(fos); 
     } else if (body instanceof MessageImpl) { 
      writeBody(fos, ((MessageImpl) body).getBody()); 
     } else { 
      LOGGER.log(Level.WARNING, "can't handle body of type " 
        + body.getClass().getSimpleName()); 
     } 
    } 

    /** 
    * This method classifies bodyPart as text, html or attached file 
    * 
    * @param multipart 
    * @throws IOException 
    */ 
    private void parseBodyParts(Multipart multipart) throws IOException { 
     // loop over the parts 
     for (Entity part : multipart.getBodyParts()) { 
      String mimeType = part.getMimeType(); 
      if (mimeType.equals("text/plain")) { 
       String txt = getTxtPart(part); 
       txtBody.append(txt); 
      } else if (mimeType.equals("text/html")) { 
       String html = getTxtPart(part); 
       htmlBody.append(html); 
      } else if (part.getDispositionType() != null 
        && !part.getDispositionType().equals("")) { 
       // If DispositionType is null or empty, it means that it's multipart, 
       // not attached file 
       attachments.add(part); 
      } 

      // If current part contains other, parse it again by recursion 
      if (part.isMultipart()) { 
       parseBodyParts((Multipart) part.getBody()); 
      } 
     } 
    } 

    /** 
    * 
    * @param part 
    * @return 
    * @throws IOException 
    */ 
    private String getTxtPart(Entity part) throws IOException { 
     // Get content from body 
     TextBody tb = (TextBody) part.getBody(); 
     return this.fromInputStream(tb.getInputStream()); 
    } 

    /** 
    * Place a String on the clipboard, and make this class the owner of the 
    * Clipboard's contents. 
    * 
    * @param aString 
    */ 
    public void setClipboardContents(String aString) { 
     StringSelection stringSelection = new StringSelection(aString); 
     Clipboard clipboard = Toolkit.getDefaultToolkit().getSystemClipboard(); 
     clipboard.setContents(stringSelection, this); 
    } 

    /** 
    * get text from the clipboard 
    * 
    * @return 
    * @throws Exception 
    */ 
    public String getClipboardText() throws Exception { 
     Clipboard clipboard = Toolkit.getDefaultToolkit().getSystemClipboard(); 
     String text = (String) clipboard.getData(DataFlavor.stringFlavor); 
     return text; 
    } 

    /** 
    * get Mail from clipboard 
    * 
    * @param email 
    * @param attachmentDirectory 
    * @return 
    * @throws Exception 
    */ 
    public boolean getMailFromClipboard(EMail email, File attachmentDirectory) 
      throws Exception { 
     String mailText = getClipboardText(); 
     if (mailText == null) 
      return false; 
     this.parseMessage(email, 
       new ByteArrayInputStream(mailText.getBytes("UTF-8")), 
       attachmentDirectory); 
     return true; 
    } 

    /* 
    * (non-Javadoc) 
    * 
    * @see 
    * java.awt.datatransfer.ClipboardOwner#lostOwnership(java.awt.datatransfer 
    * .Clipboard, java.awt.datatransfer.Transferable) 
    */ 
    @Override 
    public void lostOwnership(Clipboard clipboard, Transferable contents) { 
    } 

} 
0

Я рекомендую использовать Token streams.

Это довольно прямолинейно.

Вы можете найти вложение с помощью заголовков вашего многочастного раздела:

Content-Disposition:attachment; filename="toto.txt" 

Вы должны быть осторожны при обработке заголовка с ним ... Он может быть почты заголовки или заголовок многослойную раздел ....

 Смежные вопросы

  • Нет связанных вопросов^_^