【java】读取邮件,以阿里云邮箱pop3协议、163邮箱imaps/imap协议为例


 

1、看效果

1.1、阿里云邮箱

 

 

  

 

 1.2、163邮箱

 

 

 

 

 

 

 

2、代码

 

  1 import com.sun.mail.imap.IMAPFolder;
  2 import com.sun.mail.imap.protocol.IMAPProtocol;
  3 import org.apache.tomcat.util.http.fileupload.IOUtils;
  4 import org.springframework.util.ObjectUtils;
  5 
  6 import javax.mail.*;
  7 import javax.mail.internet.InternetAddress;
  8 import javax.mail.internet.MimeMessage;
  9 import javax.mail.internet.MimeUtility;
 10 import java.io.*;
 11 import java.text.ParseException;
 12 import java.text.SimpleDateFormat;
 13 import java.util.*;
 14 
 15 public class ShowMail {
 16 
 17     public static String NORM_DATETIME_PATTERN = "yyyy-MM-dd hh:mm:ss";
 18     private MimeMessage mimeMessage;
 19     /**
 20      * 附件下载后的存放目录
 21      */
 22     private String saveAttachPath = "";
 23     /**
 24      * 存放邮件内容的StringBuffer对象
 25      */
 26     private StringBuffer bodyText = new StringBuffer();
 27 
 28     /**
 29      * 构造函数,初始化一个MimeMessage对象
 30      *
 31      * @param mimeMessage
 32      */
 33     public ShowMail(MimeMessage mimeMessage) {
 34         this.mimeMessage = mimeMessage;
 35     }
 36 
 37     /**
 38      * 获得发件人的地址和姓名
 39      *
 40      * @return
 41      * @throws MessagingException
 42      */
 43     public String getFrom() throws MessagingException {
 44         InternetAddress address[] = (InternetAddress[]) mimeMessage.getFrom();
 45         String from = address[0].getAddress();
 46         if (from == null) {
 47             from = "";
 48         }
 49         String personal = address[0].getPersonal();
 50 
 51         if (personal == null) {
 52             personal = "";
 53         }
 54 
 55         String fromAddr = null;
 56         if (personal != null || from != null) {
 57             fromAddr = personal + "<" + from + ">";
 58         }
 59         return fromAddr;
 60     }
 61 
 62     /**
 63      * 获得邮件的收件人,抄送,和密送的地址和姓名,根据所传递的参数的不同
 64      *
 65      * @param type "to"----收件人 "cc"---抄送人地址 "bcc"---密送人地址
 66      * @return
 67      * @throws MessagingException
 68      * @throws UnsupportedEncodingException
 69      */
 70     public String getMailAddress(String type) throws MessagingException, UnsupportedEncodingException {
 71         if (ObjectUtils.isEmpty(type)) {
 72             return "";
 73         }
 74 
 75         String addType = type.toUpperCase();
 76 
 77         if (!addType.equals("TO") && !addType.equals("CC") && !addType.equals("BCC")) {
 78             return "";
 79         }
 80         InternetAddress[] address;
 81 
 82         if (addType.equals("TO")) {
 83             address = (InternetAddress[]) mimeMessage.getRecipients(Message.RecipientType.TO);
 84         } else if (addType.equals("CC")) {
 85             address = (InternetAddress[]) mimeMessage.getRecipients(Message.RecipientType.CC);
 86         } else {
 87             address = (InternetAddress[]) mimeMessage.getRecipients(Message.RecipientType.BCC);
 88         }
 89 
 90         if (ObjectUtils.isEmpty(address)) {
 91             return "";
 92         }
 93         StringBuilder mailAddr = new StringBuilder();
 94         String emailAddr;
 95         String personal;
 96         for (int i = 0; i < address.length; i++) {
 97             emailAddr = address[i].getAddress();
 98             if (emailAddr == null) {
 99                 emailAddr = "";
100             } else {
101                 emailAddr = MimeUtility.decodeText(emailAddr);
102             }
103             personal = address[i].getPersonal();
104             if (personal == null) {
105                 personal = "";
106             } else {
107                 personal = MimeUtility.decodeText(personal);
108             }
109             mailAddr.append(",").append(personal).append("<").append(emailAddr).append(">");
110         }
111         return mailAddr.toString().substring(1);
112     }
113 
114     /**
115      * 获得邮件主题
116      *
117      * @return
118      * @throws MessagingException
119      * @throws UnsupportedEncodingException
120      */
121     public String getSubject() throws MessagingException, UnsupportedEncodingException {
122         String subject = MimeUtility.decodeText(mimeMessage.getSubject());
123         if (subject == null) {
124             subject = "";
125         }
126         return subject;
127     }
128 
129     /**
130      * 获得邮件发送日期
131      *
132      * @return
133      * @throws MessagingException
134      */
135     public String getSentDate() throws MessagingException {
136         Date sentDate = mimeMessage.getSentDate();
137         SimpleDateFormat format = new SimpleDateFormat(NORM_DATETIME_PATTERN);
138         return format.format(sentDate);
139     }
140 
141     /**
142      * 获得邮件正文内容
143      *
144      * @return
145      */
146     public String getBodyText() {
147         return bodyText.toString();
148     }
149 
150     /**
151      * 解析邮件,把得到的邮件内容保存到一个StringBuffer对象中,解析邮件
152      * 主要是根据MimeType类型的不同执行不同的操作,一步一步的解析
153      * @param part
154      * @throws MessagingException
155      * @throws IOException
156      */
157     public void getMailContent(Part part) throws MessagingException, IOException {
158 
159         String contentType = part.getContentType();
160 
161         int nameIndex = contentType.indexOf("name");
162 
163         boolean conName = false;
164 
165         if (nameIndex != -1) {
166             conName = true;
167         }
168 
169         if (part.isMimeType("text/plain") && conName == false) {
170             bodyText.append((String) part.getContent());
171         } else if (part.isMimeType("text/html") && conName == false) {
172             bodyText.append((String) part.getContent());
173         } else if (part.isMimeType("multipart/*")) {
174             Multipart multipart = (Multipart) part.getContent();
175             int counts = multipart.getCount();
176             for (int i = 0; i < counts; i++) {
177                 this.getMailContent(multipart.getBodyPart(i));
178             }
179         } else if (part.isMimeType("message/rfc822")) {
180             this.getMailContent((Part) part.getContent());
181         }
182     }
183 
184     /**
185      * 判断此邮件是否需要回执,如果需要回执返回"true",否则返回"false"
186      *
187      * @return
188      * @throws MessagingException
189      */
190     public boolean getReplySign() throws MessagingException {
191 
192         boolean replySign = false;
193 
194         String needReply[] = mimeMessage.getHeader("Disposition-Notification-To");
195 
196         if (needReply != null) {
197             replySign = true;
198         }
199         return replySign;
200     }
201 
202     /**
203      * 判断此邮件是否已读,如果未读返回false,反之返回true
204      *
205      * @return
206      * @throws MessagingException
207      */
208     public boolean isNew() throws MessagingException {
209         boolean isNew = false;
210         Flags flags = mimeMessage.getFlags();
211         Flags.Flag[] flag = flags.getSystemFlags();
212         for (int i = 0; i < flag.length; i++) {
213             if (flag[i] == Flags.Flag.SEEN) {
214                 isNew = true;
215             }
216         }
217         return isNew;
218     }
219 
220     /**
221      * 判断此邮件是否包含附件
222      *
223      * @param part
224      * @return
225      * @throws MessagingException
226      * @throws IOException
227      */
228     public boolean isContainAttach(Part part) throws MessagingException, IOException {
229         boolean attachFlag = false;
230         if (part.isMimeType("multipart/*")) {
231             Multipart mp = (Multipart) part.getContent();
232             BodyPart mPart;
233             String conType;
234             for (int i = 0; i < mp.getCount(); i++) {
235                 mPart = mp.getBodyPart(i);
236                 String disposition = mPart.getDisposition();
237                 if (Part.ATTACHMENT.equals(disposition) || Part.INLINE.equals(disposition)) {
238                     attachFlag = true;
239                 } else if (mPart.isMimeType("multipart/*")) {
240                     attachFlag = this.isContainAttach(mPart);
241                 } else {
242                     conType = mPart.getContentType();
243                     if (conType.toLowerCase().indexOf("application") != -1 || conType.toLowerCase().indexOf("name") != -1){
244                         attachFlag = true;
245                     }
246                 }
247             }
248         } else if (part.isMimeType("message/rfc822")) {
249             attachFlag = isContainAttach((Part) part.getContent());
250         }
251         return attachFlag;
252     }
253 
254     /**
255      * 保存附件
256      *
257      * @param part
258      * @throws MessagingException
259      * @throws IOException
260      */
261     public void saveAttachMent(Part part) throws MessagingException, IOException {
262         String fileName;
263         if (part.isMimeType("multipart/*")) {
264             Multipart mp = (Multipart) part.getContent();
265             BodyPart mPart;
266             for (int i = 0; i < mp.getCount(); i++) {
267                 mPart = mp.getBodyPart(i);
268                 String disposition = mPart.getDisposition();
269                 if (Part.ATTACHMENT.equals(disposition) || Part.INLINE.equals(disposition)) {
270                     fileName = mPart.getFileName();
271                     if (null != fileName && fileName.toLowerCase().indexOf("gb2312") != -1) {
272                         fileName = MimeUtility.decodeText(fileName);
273                     }
274                     this.saveFile(fileName, mPart.getInputStream());
275                 } else if (mPart.isMimeType("multipart/*")) {
276                     this.saveAttachMent(mPart);
277                 } else {
278                     fileName = mPart.getFileName();
279                     if ((fileName != null) && (fileName.toLowerCase().indexOf("GB2312") != -1)) {
280                         fileName = MimeUtility.decodeText(fileName);
281                         this.saveFile(fileName, mPart.getInputStream());
282                     }
283                 }
284             }
285         } else if (part.isMimeType("message/rfc822")) {
286             this.saveAttachMent((Part) part.getContent());
287         }
288     }
289 
290     /**
291      * 设置附件存放路径
292      *
293      * @param attachPath
294      */
295     public void setAttachPath(String attachPath) {
296         this.saveAttachPath = attachPath;
297     }
298 
299     /**
300      * 获得附件存放路径
301      *
302      * @return
303      */
304     public String getAttachPath() {
305         return saveAttachPath;
306     }
307 
308     /**
309      * 真正的保存附件到指定目录里
310      *
311      * @param fileName
312      * @param in
313      * @throws IOException
314      */
315     private void saveFile(String fileName, InputStream in) throws IOException {
316         String osName = System.getProperty("os.name");
317         String storeDir = this.getAttachPath();
318         if (null == osName) {
319             osName = "";
320         }
321         if (osName.toLowerCase().indexOf("win") != -1) {
322             if (ObjectUtils.isEmpty(storeDir))
323                 storeDir = "C:\\tmp";
324         } else {
325             storeDir = "/tmp";
326         }
327         FileOutputStream fos = new FileOutputStream(new File(storeDir + File.separator + fileName));
328         IOUtils.copy(in, fos);
329         IOUtils.closeQuietly(fos);
330         IOUtils.closeQuietly(in);
331     }
332 
333     /**
334      *  获取阿里云邮箱信息
335      *
336      * @param host 邮件服务器
337      * @param username 邮箱名
338      * @param password 密码
339      * @param protocol 协议
340      * @return
341      * @throws MessagingException
342      */
343     public static Message[] getALiYunMessage(String host, String username, String password, String protocol) throws MessagingException {
344         Properties props = new Properties();
345         Session session = Session.getDefaultInstance(props, null);
346 
347         Store store = session.getStore(protocol);
348         store.connect(host, username, password);
349 
350         Folder folder = store.getFolder("INBOX");
351         folder.open(Folder.READ_ONLY);
352         return folder.getMessages();
353     }
354 
355 
356     /**
357      * 获取163邮箱信息
358      *
359      * @param host
360      * @param username
361      * @param password
362      * @param protocol
363      * @return
364      * @throws MessagingException
365      */
366     public static Message[] getWEMessage(String host, String username, String password, String protocol) throws MessagingException {
367         Properties props = System.getProperties();
368         props.setProperty("mail.store.protocol", protocol);
369         Session session = Session.getDefaultInstance(props, null);
370         Store store = session.getStore(protocol);
371         store.connect(host, username, password);
372         Folder folder = store.getFolder("INBOX");
373 
374         if (folder instanceof IMAPFolder) {
375             IMAPFolder imapFolder = (IMAPFolder)folder;
376             //javamail中使用id命令有校验checkOpened, 所以要去掉id方法中的checkOpened();
377             imapFolder.doCommand(new IMAPFolder.ProtocolCommand() {
378                 public Object doCommand(IMAPProtocol p) throws com.sun.mail.iap.ProtocolException {
379                     p.id("FUTONG");
380                     return null;
381                 }
382             });
383         }
384 
385         if(folder != null) {
386             folder.open(Folder.READ_WRITE);
387         }
388 
389         return folder.getMessages();
390     }
391 
392     /**
393      * 过滤邮箱信息
394      *
395      * @param messages
396      * @param fromMail 只读取该邮箱发来的邮件,如果为空则不过滤
397      * @param startDate 只读取该日期以后的邮件,如果为空则不过滤
398      * @return
399      * @throws MessagingException
400      */
401     public static List<Message> filterMessage(Message[] messages, String fromMail, String startDate) throws MessagingException, ParseException {
402         List<Message> messageList = new ArrayList<>();
403         if (ObjectUtils.isEmpty(messages)) {
404             return messageList;
405         }
406         boolean isEnptyFromMail = ObjectUtils.isEmpty(fromMail);
407         boolean isEnptyStartDate = ObjectUtils.isEmpty(startDate);
408         if (isEnptyFromMail && isEnptyStartDate) {
409             return Arrays.asList(messages);
410         }
411 
412         String from;
413         for (Message message: messages) {
414             from = (message.getFrom()[0]).toString();
415             if (isEnptyFromMail) {
416                 if (new SimpleDateFormat(NORM_DATETIME_PATTERN).parse(startDate).getTime() > message.getSentDate().getTime()) {
417                     continue;
418                 }
419             } else if (null != from && from.contains(fromMail)) {
420                 if (!isEnptyStartDate && new SimpleDateFormat(NORM_DATETIME_PATTERN).parse(startDate).getTime() > message.getSentDate().getTime()) {
421                     continue;
422                 }
423             } else {
424                 continue;
425             }
426             messageList.add(message);
427         }
428         return messageList;
429     }
430 
431     /**
432      * 打印邮件
433      *
434      * @param messageList
435      * @throws IOException
436      * @throws MessagingException
437      */
438     public static void printMailMessage(List<Message> messageList) throws IOException, MessagingException {
439         System.out.println("邮件数量:" + messageList.size());
440         ShowMail re;
441         Message message;
442         for (int i = 0, leng = messageList.size(); i < leng; i++) {
443             message = messageList.get(i);
444             re = new ShowMail((MimeMessage) message);
445             System.out.println("邮件【" + i + "】主题:" + re.getSubject());
446             System.out.println("邮件【" + i + "】发送时间:" + re.getSentDate());
447             System.out.println("邮件【" + i + "】是否需要回复:" + re.getReplySign());
448             System.out.println("邮件【" + i + "】是否已读:" + re.isNew());
449             System.out.println("邮件【" + i + "】是否包含附件:" + re.isContainAttach( message));
450             System.out.println("邮件【" + i + "】发送人地址:" + re.getFrom());
451             System.out.println("邮件【" + i + "】收信人地址:" + re.getMailAddress("to"));
452             System.out.println("邮件【" + i + "】抄送:" + re.getMailAddress("cc"));
453             System.out.println("邮件【" + i + "】暗抄:" + re.getMailAddress("bcc"));
454             System.out.println("邮件【" + i + "】发送时间:" + re.getSentDate());
455             System.out.println("邮件【" + i + "】邮件ID:" + ((MimeMessage) message).getMessageID());
456             re.getMailContent(message);
457             System.out.println("邮件【" + i + "】正文内容:\r\n" + re.getBodyText());
458             re.setAttachPath("D:\\Download\\mailFile\\");
459             re.saveAttachMent(message);
460         }
461     }
462 
463     public static void main(String[] args) throws MessagingException, IOException, ParseException {
464         // 阿里云登录信息
465 //        String host = "pop3.mxhichina.com";
466 //        String username = "liwei@xiaostudy.com";
467 //        String password = "密码";
468 //        String protocol = "pop3";
469 //        String fromMail = "XXX@163.com";
470 //        String startDate = "2020-2-24 23:35:40";
471 //        List<Message> messageList = filterMessage(getALiYunMessage(host, username, password, protocol), fromMail, startDate);
472 
473         // 163登录信息
474         String host = "imap.163.com";
475         String username = "XXX@163.com";
476         String password = "授权码,不是密码";
477         String protocol = "imaps";
478         String fromMail = "liwei@xiaostudy.com";
479         String startDate = "2020-2-24 23:35:40";
480         List<Message> messageList = filterMessage(getWEMessage(host, username, password, protocol), fromMail, startDate);
481 
482         printMailMessage(messageList);
483     }
484 }

 

参考文章:https://blog.csdn.net/qq_34173549/article/details/79661997

                  https://www.xuebuyuan.com/731341.html

 

3、163邮箱的imap协议的参考

这篇文章:https://www.cnblogs.com/shihaiming/p/10416383.html

 

 

 注:我当时测试props.setProperty("mail.store.protocol", "imaps");也行


免责声明!

本站转载的文章为个人学习借鉴使用,本站对版权不负任何法律责任。如果侵犯了您的隐私权益,请联系本站邮箱yoyou2525@163.com删除。



 
粤ICP备18138465号  © 2018-2025 CODEPRJ.COM