邮件协议
本文涉及到的协议主要包含: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:
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;
public class SendMail {
public static void main(String[] args) { boolean isSSL = true; String host = "smtp.163.com";
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;
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;
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.getInstance(props, null);
Store store = session.getStore("imap");
store.connect(host, port, user, password);
Folder folder = store.getFolder(mbox); if (folder == null || !folder.exists()) { System.out.println("Invalid folder"); System.exit(1); }
folder.open(Folder.READ_WRITE);
folder.addMessageCountListener(new MessageCountAdapter() { public void messagesAdded(MessageCountEvent ev) { Message[] msgs = ev.getMessages(); System.out.println("Got " + msgs.length + " 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(); } } } });
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);
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
|
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邮件发送收取和监听/