发送Email的过程我们在上一节已经讲过了,客户端总是通过SMTP协议把邮件发送给MTA。
接收Email则相反,因为邮件最终到达收件人的MDA服务器,所以,接收邮件是收件人用自己的客户端把邮件从MDA服务器上抓取到本地的过程。
接收邮件使用最广泛的协议是POP3:Post Office Protocol version 3,它也是一个建立在TCP连接之上的协议。POP3服务器的标准端口是110,如果整个会话需要加密,那么使用加密端口995。
另一种接收邮件的协议是IMAP:Internet Mail Access Protocol,它使用标准端口143和加密端口993。IMAP和POP3的主要区别是,IMAP协议在本地的所有操作都会自动同步到服务器上,并且,IMAP可以允许用户在邮件服务器的收件箱中创建文件夹。
JavaMail也提供了IMAP协议的支持。因为POP3和IMAP的使用方式非常类似,因此我们只介绍POP3的用法。
使用POP3收取Email时,我们无需关心POP3协议底层,因为JavaMail提供了高层接口。首先需要连接到Store对象:
// 准备登录信息:String host = "pop3.example.com";int port = 995; String username = "bob@example.com"; String password = "password"; Properties props = new Properties(); props.setProperty("mail.store.protocol", "pop3"); // 协议名称props.setProperty("mail.pop3.host", host);// POP3主机名props.setProperty("mail.pop3.port", String.valueOf(port)); // 端口号// 启动SSL:props.put("mail.smtp.socketFactory.class", "javax.net.ssl.SSLSocketFactory"); props.put("mail.smtp.socketFactory.port", String.valueOf(port));// 连接到Store:URLName url = new URLName("pop3", host, post, "", username, password); Session session = Session.getInstance(props, null); session.setDebug(true); // 显示调试信息Store store = new POP3SSLStore(session, url); store.connect();
一个Store
对象表示整个邮箱的存储,要收取邮件,我们需要通过Store
访问指定的Folder
(文件夹),通常是INBOX
表示收件箱:
// 获取收件箱:Folder folder = store.getFolder("INBOX");// 以读写方式打开:folder.open(Folder.READ_WRITE);// 打印邮件总数/新邮件数量/未读数量/已删除数量:System.out.println("Total messages: " + folder.getMessageCount()); System.out.println("New messages: " + folder.getNewMessageCount()); System.out.println("Unread messages: " + folder.getUnreadMessageCount()); System.out.println("Deleted messages: " + folder.getDeletedMessageCount());// 获取每一封邮件:Message[] messages = folder.getMessages();for (Message message : messages) { // 打印每一封邮件: printMessage((MimeMessage) message); }
当我们获取到一个Message
对象时,可以强制转型为MimeMessage,然后打印出邮件主题、发件人、收件人等信息:
void printMessage(MimeMessage msg) throws IOException, MessagingException { // 邮件主题: System.out.println("Subject: " + MimeUtility.decodeText(msg.getSubject())); // 发件人: Address[] froms = msg.getFrom(); InternetAddress address = (InternetAddress) froms[0]; String personal = address.getPersonal(); String from = personal == null ? address.getAddress() : (MimeUtility.decodeText(personal) + " <" + address.getAddress() + ">"); System.out.println("From: " + from); // 继续打印收件人: ... }
比较麻烦的是获取邮件的正文。一个MimeMessage
对象也是一个Part
对象,它可能只包含一个文本,也可能是一个Multipart
对象,即由几个Part
构成,因此,需要递归地解析出完整的正文: