import java.io.File; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.UnsupportedEncodingException; import java.util.ArrayList; import java.util.List; import java.util.Properties; import javax.mail.BodyPart; import javax.mail.FetchProfile; import javax.mail.Folder; import javax.mail.Message; import javax.mail.MessagingException; import javax.mail.Multipart; import javax.mail.Part; import javax.mail.Session; import javax.mail.Store; import javax.mail.UIDFolder; import org.springframework.util.Assert; import org.springframework.util.FileCopyUtils; import org.springframework.util.StringUtils; import com.sun.mail.pop3.POP3Folder; /** * 邮件接收器,方法调用顺序:<code>open->receive->close</code>。 */ public class MailReceiver { public static final String POP3 = "pop3"; public static final String INBOX = "INBOX"; private String pop; private String serverName; private String serverPasswd; private MessageFilter msgFilter; /** * 附件下载后的存放目录 */ private String attachSavePath; private Store store; private POP3Folder inbox; private FetchProfile profile; /** * 构造器(不保存附件,不对接收邮件进行过滤处理) * * @param pop * POP Server URL * @param serverName * 用户名 * @param serverPasswd * 密码 * @param msgFilter * 邮件过滤器,<code>null</code>表示不过滤 */ public MailReceiver(String pop, String serverName, String serverPasswd) { this(pop, serverName, serverPasswd, null, null); } /** * 构造器(不保存附件) * * @param pop * POP Server URL * @param serverName * 用户名 * @param serverPasswd * 密码 * @param msgFilter * 邮件过滤器,<code>null</code>表示不过滤 */ public MailReceiver(String pop, String serverName, String serverPasswd, MessageFilter msgFilter) { this(pop, serverName, serverPasswd, msgFilter, null); } /** * 构造器(不对接收邮件进行过滤处理) * * @param pop * POP Server URL * @param serverName * 用户名 * @param serverPasswd * 密码 * @param attachSavePath * 附件存放路径,<code>null</code>表示不保存附件 */ public MailReceiver(String pop, String serverName, String serverPasswd, String attachSavePath) { this(pop, serverName, serverPasswd, null, attachSavePath); } /** * 构造器 * * @param pop * POP Server URL * @param serverName * 用户名 * @param serverPasswd * 密码 * @param msgFilter * 邮件过滤器,<code>null</code>表示不过滤 * @param attachSavePath * 附件存放路径,<code>null</code>表示不保存附件 */ public MailReceiver(String pop, String serverName, String serverPasswd, MessageFilter msgFilter, String attachSavePath) { super(); Assert.hasLength(pop, "Pop"); Assert.hasLength(serverName, "ServerName"); Assert.hasLength(serverPasswd, "ServerPasswd"); this.pop = pop; this.serverName = serverName; this.serverPasswd = serverPasswd; this.msgFilter = msgFilter; this.attachSavePath = attachSavePath; } /** * 连接邮件服务器,打开INBOX */ public void open() throws MessagingException { Properties props = new Properties(); Session session = Session.getDefaultInstance(props, null); this.store = session.getStore(POP3); store.connect(pop, serverName, serverPasswd); this.inbox = (POP3Folder) store.getFolder(INBOX); inbox.open(Folder.READ_ONLY); this.profile = new FetchProfile(); profile.add(UIDFolder.FetchProfileItem.UID); profile.add(FetchProfile.Item.ENVELOPE); } /** * 收取邮件,自动保存附件至指定目录,该方法不会关闭INOBX及连接。<br> * 调用 {@link #close()}方法关闭INBOX及连接。 * * @throws UnsupportedEncodingException * @throws IOException * @throws MessagingException */ public List<Message> receive() throws UnsupportedEncodingException, IOException, MessagingException { // 获取邮件及UID Message[] messages = inbox.getMessages(); inbox.fetch(messages, profile); // 过滤处理 List<Message> msgList = new ArrayList<Message>(); for (Message msg : messages) { if (msgFilter == null || msgFilter.filte(inbox, msg)) { // 保存附件 if (StringUtils.hasLength(attachSavePath) && MailUtils.containsAttach(msg)) { saveAttachment(msg); } msgList.add(msg); } } return msgList; } /** * 关闭INBOX及连接。 */ public void close() { try { inbox.close(false); store.close(); } catch (MessagingException e) { throw new MailException("关闭INBOX及连接出错", e); } } public POP3Folder getInbox() { return inbox; } /** * 保存附件 * * @throws Exception * @throws IOException * @throws MessagingException * @throws UnsupportedEncodingException */ private void saveAttachment(Part part) throws UnsupportedEncodingException, MessagingException, IOException { if (part.isMimeType("multipart/*")) { String filename = ""; Multipart mp = (Multipart) part.getContent(); for (int i = 0; i < mp.getCount(); i++) { BodyPart mpart = mp.getBodyPart(i); String disposition = mpart.getDisposition(); if ((disposition != null) && ((disposition.equals(Part.ATTACHMENT)) || (disposition .equals(Part.INLINE)))) { filename = MailUtils.decodeText(mpart.getFileName()); saveFile(filename, mpart.getInputStream()); } else if (mpart.isMimeType("multipart/*")) { saveAttachment(mpart); } else { filename = MailUtils.decodeText(mpart.getFileName()); if (filename != mpart.getFileName()) { saveFile(filename, mpart.getInputStream()); } } } } else if (part.isMimeType("message/rfc822")) { saveAttachment((Part) part.getContent()); } } /** * 保存附件到指定目录 * * @throws IOException * @throws FileNotFoundException */ private void saveFile(String filename, InputStream in) throws FileNotFoundException, IOException { File file = new File(attachSavePath + File.separator + filename); FileCopyUtils.copy(in, new FileOutputStream(file)); } }
import javax.mail.Message; import javax.mail.MessagingException; import com.sun.mail.pop3.POP3Folder; /** * 邮件过滤接口,用于实现只收取未读邮件这样的功能。 */ public interface MessageFilter { /** * 过滤邮件 * * @param box * 邮件文件夹 * @param message * 邮件消息 * @return 如何需要读取此邮件,返回<code>true</code>,否则返回<code>false</code> */ boolean filte(POP3Folder box, Message message) throws MessagingException; }
import java.io.IOException; import java.io.UnsupportedEncodingException; import javax.mail.BodyPart; import javax.mail.MessagingException; import javax.mail.Multipart; import javax.mail.Part; import javax.mail.internet.MimeUtility; import org.springframework.util.Assert; /** * 邮件处理实用类 */ public class MailUtils { private MailUtils() { } /** * <code>MimeUtility.decodeText(text)</code> */ public static String decodeText(String text) throws UnsupportedEncodingException { if (text == null) return null; String s = text.toLowerCase(); if (s.contains("gb2312") || s.contains("gbk")) { return MimeUtility.decodeText(text); } return text; } /** * 判断邮件是否包含附件 * * @throws IOException * @throws MessagingException */ public static boolean containsAttach(Part part) throws MessagingException, IOException { boolean attachflag = false; if (part.isMimeType("multipart/*")) { Multipart mp = (Multipart) part.getContent(); for (int i = 0; i < mp.getCount(); i++) { BodyPart mpart = mp.getBodyPart(i); String disposition = mpart.getDisposition(); if ((disposition != null) && ((disposition.equals(Part.ATTACHMENT)) || (disposition .equals(Part.INLINE)))) attachflag = true; else if (mpart.isMimeType("multipart/*")) { attachflag = containsAttach((Part) mpart); } else { String contype = mpart.getContentType(); if (contype.toLowerCase().indexOf("application") != -1) attachflag = true; if (contype.toLowerCase().indexOf("name") != -1) attachflag = true; } } } else if (part.isMimeType("message/rfc822")) { attachflag = containsAttach((Part) part.getContent()); } return attachflag; } /** * 解析邮件,把得到的邮件内容保存到<code>bodyText</code>对象中.<br> * 根据MimeType类型的不同执行不同的解析操作. * * @throws IOException * @throws MessagingException */ public static void getMailContent(Part part, StringBuffer bodyText) throws MessagingException, IOException { Assert.notNull(bodyText, "bodyText"); String contenttype = part.getContentType(); int nameindex = contenttype.indexOf("name"); boolean conname = false; if (nameindex != -1) conname = true; if (part.isMimeType("text/plain") && !conname) { bodyText.append((String) part.getContent()); } else if (part.isMimeType("text/html") && !conname) { bodyText.append((String) part.getContent()); } else if (part.isMimeType("multipart/*")) { Multipart multipart = (Multipart) part.getContent(); int counts = multipart.getCount(); for (int i = 0; i < counts; i++) { getMailContent(multipart.getBodyPart(i), bodyText); } } else if (part.isMimeType("message/rfc822")) { getMailContent((Part) part.getContent(), bodyText); } } }