邮件协议
本文涉及到的协议主要包含: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.com给ieayoio_to@163.com,这里使用SSL协议,SSL协议的默认端口为465:
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的邮件,假设他的密码是bob123456。
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 = "bob123456";
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
的调用。
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 = "bob132456";
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的方式发送邮件,有兴趣可以去官网查看使用说明
/**
* 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