Java邮件发送收取和监听

Author Avatar
ieayoio 9月 26, 2016
  • 在其它设备中阅读本文章

邮件协议

本文涉及到的协议主要包含:SMTP(Simple Mail Transfer Protocol,简单邮件传输协议),POP3(Post Office Protocol,邮局协议),IMAP(Internet Message Access Protocol,Internet邮件访问协议)。
通常情况下,smtp用来发送邮件。pop3和imap用来接收邮件,这样就有了pop3和imap有什么差别的疑问,大体上的差别在于,pop3虽然可以接收服务器上的邮件但是它对邮件的操作,比如,移动标记已读等等,都不会被反馈到客户端。imap提供客户端与服务端之间的双向通信,客户端对邮件的操作会反馈给服务端,客户端的操作,服务端也会同步做相应的操作,imap协议支持idle。
总体上来说,imap有很多优点,这些都是pop3所不能比的,但是国内的邮件服务商对imap的协议支持参差不齐,也限制了imap在国内的使用普及程度。

配置

配置项 说明
mail.xxx.host 邮件服务器主机
mail.xxx.port 邮件服务器端口
mail.xxx.auth 是否身份验证
mail.xxx.ssl.enable 是否启用SSL

默认端口

配置项 SMTP POP3 IMAP
普通方式 25 110 143
SSL方式 465 995 993

发送邮件

ieayoio_from@163.comieayoio_to@163.com,这里使用SSL协议,SSL协议的默认端口为465:

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
import javax.mail.*;
import javax.mail.internet.AddressException;
import javax.mail.internet.InternetAddress;
import javax.mail.internet.MimeMessage;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Properties;

/**
* Created by ieayoio on 16-9-19.
*/
public class SendMail {

public static void main(String[] args) {
boolean isSSL = true;
String host = "smtp.163.com";
// int port = 25;
int port = 465;
String from = "ieayoio_from@163.com";
String to = "ieayoio_to@163.com";
boolean isAuth = true;
final String username = "ieayoio_from@163.com";
final String password = "ieayoio.tk";

Properties props = new Properties();
props.put("mail.smtp.ssl.enable", isSSL);
props.put("mail.smtp.host", host);
props.put("mail.smtp.port", port);
props.put("mail.smtp.auth", isAuth);

Session session = Session.getDefaultInstance(props, new Authenticator() {
@Override
protected PasswordAuthentication getPasswordAuthentication() {
return new PasswordAuthentication(username, password);
}
});

try {
Message message = new MimeMessage(session);

message.setFrom(new InternetAddress(from));
message.addRecipient(Message.RecipientType.TO, new InternetAddress(to));

SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
String format = df.format(new Date());
message.setSubject("ieayoio的邮件测试" + format);
message.setText("博客ieayoio.tk");

Transport.send(message);
} catch (AddressException e) {
e.printStackTrace();
} catch (MessagingException e) {
e.printStackTrace();
}

System.out.println("发送完毕!");
}
}

接收邮件

使用SSL,接收username@163.com的邮件,假设他的密码是ieayoio.tk。

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
import javax.mail.*;
import java.util.Date;
import java.util.Properties;

/**
* Created by ieayoio on 16-9-19.
*/
public class FetchMail {

public static void main(String[] args) {
String protocol = "pop3";
boolean isSSL = true;
String host = "pop.163.com";
int port = 995;
String username = "username@163.com";
String password = "ieayoio.tk";

Properties props = new Properties();
props.put("mail.pop3.ssl.enable", isSSL);
props.put("mail.pop3.host", host);
props.put("mail.pop3.port", port);

Session session = Session.getDefaultInstance(props);

Store store = null;
Folder folder = null;
try {
store = session.getStore(protocol);
store.connect(username, password);

folder = store.getFolder("INBOX");
folder.open(Folder.READ_ONLY);

int size = folder.getMessageCount();
System.out.println("邮件个数:" + size);

System.out.println("最新一封邮件为:");
Message message = folder.getMessage(size);
String from = message.getFrom()[0].toString();
String subject = message.getSubject();
Date date = message.getSentDate();
System.out.println("From: " + from);
System.out.println("Subject: " + subject);
System.out.println("Date: " + date);
} catch (NoSuchProviderException e) {
e.printStackTrace();
} catch (MessagingException e) {
e.printStackTrace();
} finally {
try {
if (folder != null) {
folder.close(false);
}
if (store != null) {
store.close();
}
} catch (MessagingException e) {
e.printStackTrace();
}
}

System.out.println("接收完毕!");
}
}

邮件的监听收取

简单的收取邮件是一次性的,但是实际使用中,我们并不知道什么时候才会有新的邮件可收取,这时可以使用邮件监听,来实时获取邮件,这里我们使用imap协议,因为imap是支持idle的,如果所要收取的邮件服务器不支持idle,我们将将采用轮询的方式收取,这里要注意的是调用folder.getMessageCount()时可能会触发addMessageCountListener的调用。

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
import com.sun.mail.imap.IMAPFolder;

import javax.mail.*;
import javax.mail.event.MessageCountAdapter;
import javax.mail.event.MessageCountEvent;
import java.util.Properties;

/**
* Created by ieayoio on 16-9-19.
*/
public class Monitor {

public static void main(String args[]) {

System.out.println("\nTesting monitor\n");
String host = "imap.163.com";
int port = 993;
String user = "username@163.com";
String password = "ieayoio.tk";
String mbox = "INBOX";
String freqs = "5000";
boolean isOpenidle = true;

try {
Properties props = System.getProperties();

// 得到session对象
Session session = Session.getInstance(props, null);
// session.setDebug(true);

// 获取store对象
Store store = session.getStore("imap");

// Connect
store.connect(host, port, user, password);

// Open a Folder
Folder folder = store.getFolder(mbox);
if (folder == null || !folder.exists()) {
System.out.println("Invalid folder");
System.exit(1);
}

folder.open(Folder.READ_WRITE);

// Add messageCountListener to listen for new messages
folder.addMessageCountListener(new MessageCountAdapter() {
public void messagesAdded(MessageCountEvent ev) {
Message[] msgs = ev.getMessages();
System.out.println("Got " + msgs.length + " new messages");

// Just dump out the new messages
for (int i = 0; i < msgs.length; i++) {
try {
System.out.println("-----");
System.out.println("Message " +
msgs[i].getMessageNumber() + ":");
System.out.println(msgs[i].getSubject());
} catch (Exception ex) {
ex.printStackTrace();
}
}
}
});

// 检查是否支持imap idle,尝试使用idle
int freq = Integer.parseInt(freqs);
boolean supportsIdle = false;
try {
if (isOpenidle && folder instanceof IMAPFolder) {
IMAPFolder f = (IMAPFolder) folder;
f.idle();
supportsIdle = true;
}
} catch (FolderClosedException fex) {
throw fex;
} catch (MessagingException mex) {
supportsIdle = false;
}
for (; ; ) {
if (supportsIdle && folder instanceof IMAPFolder) {
IMAPFolder f = (IMAPFolder) folder;
f.idle();
} else {
System.out.println("idle不支持进入轮询");
Thread.sleep(freq); // sleep for freq milliseconds

// 注意。getMessageCount时会触发监听器
folder.getMessageCount();
}
}

} catch (Exception ex) {
ex.printStackTrace();
}
}
}

使用开源组件简单的邮件开发

大多数的文章讲解的是使用Apache Commons Email来进行一些邮件的简化开发,这里就不在对其进行介绍,有兴趣可以百度google,这里介绍另一种开源组件JoddMail,JoddMail可以方便的进行收发邮件,简化邮件的开发是一个不错的选择,以下是一段没有经过编译的代码简单展示一下使用SSL的方式发送邮件,有兴趣可以去官网查看使用说明

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
/**
* Created by ieayoio on 16-9-26.
*/
public class JoddSend {
public static void main(String[] args) {
SmtpServer smtpServer = SmtpSslServer
.create("smtp.gmail.com")
.authenticateWith("ieayoio_from@jodd.org", "password");
Email email = Email.create()
.from("ieayoio_from@jodd.org")
.to("ieayoio_to@jodd.org")
.subject("Hello!")
.addText("ieayoio.tk");
SendMailSession session = smtpServer.createSession();
session.open();
session.sendMail(email);
session.close();
}
}

参考链接:
https://my.oschina.net/huangyong/blog/178641
https://github.com/liutian/java-mail
http://jodd.org/doc/email.html


该博文来自于ieayoio的博客:ieayoio’s blog

本文链接:http://www.ieayoio.com/2016/09/26/Java邮件发送收取和监听/