在前面的教程里面我们都是用Session.getDefaultInstance(props)没有通过认证的方式取得session,这样明显的缺点是我们要连接邮件服务器的用户名和密码都要写死在代码里面,如:transport.connect("smtp.qq.com", "***@qq.com", "****");
store.connect("pop.qq.com", "*****@qq.com", "******");
这样子显得程序拓展性很差,如果要切换不同的用户就要修改源代码,这样是很麻烦的,还有用户名和密码明文地写在代码里很容易就泄露,这样是很不安全的。这一讲就是通过运用Authenticator类来进行邮件的认证。
Authenticator是一个抽象类,所以要extends Authenticator 抽象类在子类中覆盖父类中的 getPasswordAuthentication() 方法,就可以实现以不同的方式来进行登录邮箱时的用户身份认证。JavaMail 中的这种设计是使用了策略模式(Strategy),具体的请参看相关文章。
这一讲我们来建立一个通过对话框输入用户名和密码进行收发邮件。如果想了解不通过邮件认证连接服务器,请观看2~3讲的内容。
1、 首先我们建立一个继承Authenticator的子类。
1 import java.util.*;
2 import javax.mail.*;
3 import javax.swing.*;
4
5 public class GUIAuthenticator extends Authenticator {
6
7 protected PasswordAuthentication getPasswordAuthentication() {
8 String user;
9 String pwd;
10 // 弹出输入对话框
11 String result = JOptionPane.showInputDialog("请输入用户名和密码,以','隔开!");
12 StringTokenizer st = new StringTokenizer(result, ",");
13 user = st.nextToken();
14 pwd = st.nextToken();
15 return new PasswordAuthentication(user, pwd);
16 }
17 }
18
作用:这个类的作用是在连接邮件服务器的时候,就会调用这个类的
getPasswordAuthentication方法,然后提示输入用户名和密码。
Ps:这个只是一个很简单的类,只作为一个例子给大家参考,真正的邮件认证不是那么简单的。
2、 通过邮件认证发送邮件:
1 package com.mail;
2 import java.util.*;
3 import javax.mail.*;
4 import javax.mail.internet.*;
5 /**
6 * 通过邮件认证发送邮件
7 * @author sam
8 *
9 */
10 public class SendMailAuthenticator {
11
12 private String smtpServer = "smtp.qq.com";
13 private String from = "
[email protected]";
14 private String to = "
[email protected]";
15 private String subject = "测试使用邮件认证";
16 private String body = "测试使用邮件认证正文";
17
18 public void sendMail(Authenticator auth) throws Exception {
19 // 设置协议、是否身份验证、服务器等信息
20 Properties props = new Properties();
21 props.setProperty("mail.transport.protocol", "smtp");
22 props.setProperty("mail.smtp.auth", "true");
23 props.setProperty("mail.host", smtpServer);
24 // 通过传入的参数获得Authenticator子类对象
25 Session session = Session.getInstance(props, auth);
26 // 构造信息体
27 MimeMessage message = new MimeMessage(session);
28 // 发件地址
29 Address fromAddress = new InternetAddress(from);
30 message.setFrom(fromAddress);
31 // 收件地址
32 Address toAddress = new InternetAddress(to);
33 message.setRecipient(MimeMessage.RecipientType.TO, toAddress);
34
35 // 主题
36 message.setSubject(subject);
37 // 正文
38 message.setText(body);
39
40 message.saveChanges();
41
42 session.setDebug(true);
43
44 /*
45 * * 由于Session对象中注册了Authenticator子类对象,因此可以直接 *
46 * 从该Authenticator子类对象中获取登录的相关信息,故直接使用 * Transport 抽象类中静态 send()
47 * 方法来简化代码编写
48 */
49
50 Transport.send(message);
51
52 }
53
54 public static void main(String[] args) throws Exception {
55 SendMailAuthenticator send = new SendMailAuthenticator();
56 Authenticator auth = new GUIAuthenticator();
57 send.sendMail(auth);
58 }
59 }
60
3、 通过邮件认证接受邮件
1 package com.mail;
2 import java.util.*;
3 import javax.mail.*;
4 import javax.mail.internet.*;
5
6 /**
7 * 通过邮件认证接收邮件
8 * @author sam
9 *
10 */
11 public class RevMailAuthenticator {
12 //邮件服务器地址
13 private String smtpServer = "pop.qq.com";
14
15 public void sendMails(Authenticator auth) throws Exception {
16 // 设置协议、是否身份验证、服务器等信息
17 Properties props = new Properties();
18 props.setProperty("mail.transport.protocol", "pop3");
19 props.setProperty("mail.smtp.auth", "true");
20 props.setProperty("mail.host", smtpServer);
21 // 通过传入的参数获得Authenticator子类对象
22 Session session = Session.getInstance(props, auth);
23 /***********************************************************************
24 * 由于Session对象中注册了Authenticator子类对象,因此可以直接
25 *
26 * 从该Authenticator子类对象中获取登录的相关信息,故直接使用
27 *
28 * store.connect();而不用传递用户名和密码参数
29 */
30 Store store = session.getStore("pop3");
31 //连接pop.qq.com邮件服务器
32 store.connect();
33 //返回文件夹对象
34 Folder folder = store.getFolder("INBOX");
35 //设置仅读
36 folder.open(Folder.READ_ONLY);
37 //获取信息
38 Message message[] = folder.getMessages();
39 for(int i=message.length-1; i>0; i--) {
40 //打印主题
41 System.out.println(message[i].getSubject());
42 System.out.println("-----------------------------------------");
43 }
44 folder.close(true);
45 store.close();
46 }
47
48 // 测试
49 public static void main(String[] args) throws Exception {
50 RevMailAuthenticator sender = new RevMailAuthenticator();
51 // 这里体现了使用策略模式的好处,客户端可以选择使用
52 // 具体的哪一种身份验证方式来提交信息
53 //对话框方式输入用户名和密码
54 Authenticator auth = new GUIAuthenticator();
55 sender.sendMails(auth);
56 }
57 }
58
总结:通过邮件认证的方式连接邮件服务器,程序的通用性好了很多,我们每次运行程序的时候都可以切换不同的用户,程序灵活了很多,而且不用修改代码就可以重用。其实Authenticator是设计模式的一种,Authenticator 的具体子类来实现不同的身份验证方式,这样使得用户可以通过不同的登录方式来登录,现实中也是这样的。
如果教程哪里写得不对,或者有什么疑问可以留言给我,我会帮你解答!