JMail接收及解析邮件

前期准备工作

  1. 首先需要将邮箱开启POP3服务
    以126邮箱为例,如图所示,开启POP3,加一个授权码并记住,记下最下面的POP3服务器地址
    在这里插入图片描述

  2. 发送一封测试邮件
    在这里插入图片描述
    笔者这里用126邮箱发送了一封邮件(带附件)给qq邮箱,随后qq邮箱回复邮件(也带附件)给126邮箱,下文将读取126邮箱中收到的这封邮件。

  3. 引入Maven依赖

    1
    2
    3
    4
    5
    <dependency>
    <groupId>javax.mail</groupId>
    <artifactId>mail</artifactId>
    <version>1.4.7</version>
    </dependency>

上代码

ReceiveEmailProcess 方法中有两个方法,processEmail方法传入三个参数,pop3主机(例如:pop.126.com),用户名,授权码,上文已提到。execute方法处理收件夹,具体义务逻辑在子类中重写。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
package com.cong;

import java.util.Properties;
import javax.mail.Folder;
import javax.mail.MessagingException;
import javax.mail.Session;
import javax.mail.Store;


public abstract class ReceiveEmailProcess {

public EmailParseResult processEmail(String pop3Host, String user, String password) {
Properties properties = new Properties();
properties.put("mail.store.protocol", "pop3");
properties.put("mail.pop3.host", pop3Host);
properties.put("mail.pop3.port", "995");
properties.put("mail.pop3.starttls.enable", "true");
Session emailSession = Session.getDefaultInstance(properties);
Folder emailFolder = null;
Store store = null;
EmailParseResult result = null;
try {
store = emailSession.getStore("pop3s");
store.connect(pop3Host, user, password);
emailFolder = store.getFolder("INBOX");
emailFolder.open(Folder.READ_ONLY);
result = execute(emailFolder);
} catch (MessagingException e) {
e.printStackTrace();
} finally {
try {
emailFolder.close(false);
store.close();
} catch (MessagingException e) {
e.printStackTrace();
}
return result;
}
}

EmailParseResult execute(Folder emailFolder) {
throw new UnsupportedOperationException("execute method haven't implement.");
}

}




具体的业务逻辑类,其中可以获取到每一封邮件的title,发送时间,具体文本内容,附件等。
execute主要做过滤邮件,处理头信息。
parseEmail方法主要作解析邮件正文。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
package com.cong;

import javax.mail.*;
import javax.mail.internet.MimeMultipart;
import javax.mail.internet.MimeUtility;
import javax.mail.search.*;
import java.io.*;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.LinkedList;

public class DownloadAttachmentProcess extends ReceiveEmailProcess{
@Override
EmailParseResult execute(Folder emailFolder) {
EmailParseResult result = null;
Calendar calendar = Calendar.getInstance();
calendar.setTime(new Date());
calendar.add(Calendar.DAY_OF_WEEK, -2);
Date twoDaysAgo = calendar.getTime();
// 过滤两天前之前且来自ONE_EMAIL_ADDRESS的邮件
SearchTerm filterTerm = new AndTerm(new FromStringTerm(${ONE_EMAIL_ADDRESS}),
new SentDateTerm(ComparisonTerm.LT, twoDaysAgo));

try {
result = new EmailParseResult();
Message[] messages = emailFolder.search(filterTerm);
System.out.println("messages.length---" + messages.length);
for (int i = 0; i < messages.length; i++) {
Message msg = messages[i];
String from = msg.getFrom()[0].toString();
if (from.startsWith("=?")) {
from = MimeUtility.decodeText(from);
}
String subject = msg.getSubject();

String sendDate = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(msg.getSentDate());
System.out.println("---------------------------------");
System.out.println("subject: " + subject);
System.out.println("from: " + from);
System.out.println("sendDate: " + sendDate);
System.out.println("msg ContentType: " + msg.getContentType());
System.out.println("msg MessageNumber: " + msg.getMessageNumber());
System.out.println("msg Message-ID: " + msg.getHeader("Message-ID")[0]);

parseEmail(msg);
result.setCode(EmailParseResult.SUCCESS).setSuccess(true).setMessage("parsed success!");
}
} catch (MessagingException e) {
e.printStackTrace();
result.setCode(EmailParseResult.FAILED).setSuccess(false).setMessage("parsed failed!");
} catch (IOException e) {
e.printStackTrace();
result.setCode(EmailParseResult.FAILED).setSuccess(false).setMessage("parsed failed!");
} finally {
return result;
}
}

void parseEmail(Message msg) throws MessagingException, IOException {
if (msg.isMimeType("multipart/**")) {
Multipart mp = (Multipart) msg.getContent();
System.out.println("mp.getCount()" + mp.getCount());
LinkedList<Multipart> mpList = new LinkedList<Multipart>();
mpList.add(mp);
for (int j = 0; j < mp.getCount(); ++j) {
BodyPart bp = mp.getBodyPart(j);
if (bp.getDisposition() != null) {
String fileName = bp.getFileName();
if (fileName.startsWith("=?")) {
fileName = MimeUtility.decodeText(fileName);
}

System.out.println("fileName: " + fileName);
File file = new File("G:\\out\\" + fileName);

file.createNewFile();
BufferedOutputStream outputStream = new BufferedOutputStream(new FileOutputStream(file));
InputStream inputStream = bp.getInputStream();
int len = 0;
byte[] buffer = new byte[1024];
while ((len = inputStream.read(buffer)) != -1) {
outputStream.write(buffer, 0, len);
}
outputStream.close();
} else if (bp.isMimeType("text/plain")) {
System.out.println((String) bp.getContent());
} else if (bp.isMimeType("multipart/**")) {
// 既有附件,又有图片等嵌入资源时
MimeMultipart content = (MimeMultipart) bp.getContent();
for (int k = 0; k < mp.getCount(); ++k) {
BodyPart contentBodyPart = content.getBodyPart(k);
if (contentBodyPart.isMimeType("text/plain")) {
// 此处仅处理邮件的文本内容
System.out.println("multipart/** text/plain" + (String) contentBodyPart.getContent());
} else {
System.out.println("multipart/** !text/plain" + contentBodyPart.getContentType());
}
}
}
}
} else if (msg.isMimeType("text/plain")) {
System.out.println((String) msg.getContent());
} else {
System.out.println(msg.getContentType() + " 暂不支持 ");
}
}
}

简单做一个结果返回类

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
package com.cong;

public class EmailParseResult {

public static final int SUCCESS = 200;
public static final int FAILED = 500;

private boolean success;
private int code;
private String message;

public boolean isSuccess() {
return success;
}

public EmailParseResult setSuccess(boolean success) {
this.success = success;
return this;
}

public int getCode() {
return code;
}

public EmailParseResult setCode(int code) {
this.code = code;
return this;
}

public String getMessage() {
return message;
}

public EmailParseResult setMessage(String message) {
this.message = message;
return this;
}

@Override
public String toString() {
return "EmailParseResult{" +
"success=" + success +
", code=" + code +
", message='" + message + '\'' +
'}';
}
}

main类测试

1
2
3
4
5
6
7
8
9
10
11
12
13
14
package com.cong;

public class Starter {

public static void main(String[] args) {

String host = "pop.126.com";
String username = "${YOUR_EMAIL_ADDRESS}";
String password = "${AUTHORIZATION_CODE}"; // 授权码
EmailParseResult result = new DownloadAttachmentProcess().processEmail(host, username, password);
System.out.println(result);
}
}

测试结果

邮件正文和附件顺利拿到。
在这里插入图片描述
在这里插入图片描述