分析新需求时,发现收件邮箱有问题导致发送邮件失败时并没有抛出预估的sendfailedexception异常,在网上找了许多博客也没有说清楚院校,在我进行一些测试后断定,这个和发邮件的服务器有关
导入依赖
<dependency>
<groupId>com.sun.mail</groupId>
<artifactId>javax.mail</artifactId>
<version>1.6.2</version>
</dependency>
代码示例
需要邮件发送服务器的邮箱和密钥,一般来说密钥不等于密码;以QQ邮箱和163邮箱为例,在 安全设置或账号与安全中可找到开启 SMTP服务,然后生成授权码,这个授权码就是我们用到的密钥;可在其帮助或者说明文档中找到对应的服务器地址和端口。smtp为发送邮件服务,imap为接收邮件服务。
一些参数并不一定是非得设置,视情况而定,下面是测试代码。
import javax.activation.DataHandler;
import javax.activation.DataSource;
import javax.mail.*;
import javax.mail.internet.*;
import javax.mail.util.ByteArrayDataSource;
import java.io.FileInputStream;
import java.io.InputStream;
import java.util.Properties;
/**
* @Description
* @Author
*/
public class MailTest {
public static void main(String[] args) {
String username1 = ""; // 邮箱
String password1 = ""; // 密钥
String host1 = "smtp.163.com";
String username2 = "";
String password2 = "";
String host2 = "smtp.qq.com";
sendingEmails(username2, password2, host2);
}
private static void sendingEmails(String username, String password, String host) {
try {
// 创建连接对象,用来连接邮箱地址
Properties props = new Properties();
// 设置发送邮箱的服务器协议
props.setProperty("mail.transport.protocol", "SMTP");
// 设置服务器地址
props.setProperty("mail.smtp.host", host);
// 设置服务器端口
props.setProperty("mail.smtp.port", "465"); // qq为 465或587
// 发件人是否合法,需为true
props.setProperty("mail.smtp.auth", "true");
// 若为ssl连接则需要设置
props.setProperty("mail.smtp.socketFactory.class", "javax.net.ssl.SSLSocketFactory");
props.setProperty("mail.smtp.socketFactory.port", "465");
// 设计发送邮件的账号和密码,此处的密码大都为密钥,要看服务器决定
Session session = Session.getInstance(props, new Authenticator() {
@Override
protected PasswordAuthentication getPasswordAuthentication() {
return new PasswordAuthentication(username, password);
}
});
Message msg = new MimeMessage(session);
// 创建收件人 可以用数组存多个收件人
// Address[] address = new InternetAddress[2];
// address[0]=new InternetAddress("");
// address[1]=new InternetAddress("");
Address address = new InternetAddress("email@qq.com");
// 设置发件人属性,需和登录邮箱一致
msg.setFrom(new InternetAddress(username));
// 设置收件人或者抄送人等,收件人地址(可用数组存放多个收件人)
msg.setRecipient(Message.RecipientType.TO, address);
// msg.setRecipients(Message.RecipientType.TO, address); // 多个收件人
msg.setText("test"); // 设置邮件内容(不携带附件有效)
// ------------携带附件,若没有附件可不配置------------
// 设置邮件正文,msg.setText()设置的内容会失效
Multipart multipart = new MimeMultipart();
MimeBodyPart messageBody = new MimeBodyPart();
// 第一个参数为邮件正文,第二个参数未解析类型
messageBody.setContent("test","text/html");
multipart.addBodyPart(messageBody);
// 添加附件,可添加多个附件,要注意文件名
MimeBodyPart mimeBodyPart = new MimeBodyPart();
// 需上传的附件的Inputstream
InputStream inputStream = new FileInputStream("E:\\information\\新建文本文档.txt");
DataSource source = new ByteArrayDataSource(inputStream, "application/octet-stream");
mimeBodyPart.setDataHandler(new DataHandler(source));
mimeBodyPart.setFileName("test.txt"); // 附件文件名字
multipart.addBodyPart(mimeBodyPart);
msg.setContent(multipart);
// ------------------------------------------
// 发送邮件
Transport.send(msg);
} catch (Exception e) {
// 捕获抛出的异常,打印在控制台
System.err.println("" + e);
}
}
}
抛出异常分析
源码的注释说明了,Transport.send()这个方法会抛出MessagingException和SendFailedException这两个异常;
抛出MessagingException一般是除发送外的其他异常情况;抛出SendFailedException则是邮件发送的问题,但经过测试发现这个异常是否抛出还和邮件服务器有关。
以QQ邮箱和163邮箱为例
我用这两个服务器向同一个不存在的邮箱(email@qq.com)发送邮件,QQ是程序抛出异常,163是退回邮件(没有异常被捕获)
QQ
163
如果是@后面的域名问题都会退回邮件
QQ
163
像收件邮箱满了之类的也是退回邮件,sendFailedException这个异常和服务器的反馈有关。