使用javamail发送邮件,准备工作
1.如果使用的是qq邮箱,则需要登录QQ邮箱,找到“设置--账户”找到如下图,将POP3/SMTP服务和IMAP/SMTP服务开启,然后生成授权码,这里的授权码,就是你要用来发邮件时,自己QQ邮箱的密码(注意:QQ邮箱用javamail发邮件,用的是授权码,而不是QQ邮箱的密码)
2.如果使用的是163邮箱,则需要登录163邮箱,找到“设置--POP3/SMTP/IMAP”,将其勾选上。对于163邮箱,有的邮箱能用163邮箱号和密码就能发邮件,但是有的163邮箱就必须得使用授权码,这个是因邮箱而异吧。。。我的163邮箱就得用授权码才能通过javamail发邮件,但是我一个朋友的邮箱用登录密码就可以通过javamail发邮件
我写的demo里,附件是由前端先上传到文件服务器(文件服务器以下简称“OSS”),然后前端将附件的信息(包含存储在OSS上的地址)再传给我,然后我再把附件添加到邮件体里。代码如下:
发件工具类:
import java.net.URL;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Properties;
import javax.activation.DataHandler;
import javax.activation.DataSource;
import javax.activation.URLDataSource;
import javax.mail.Flags;
import javax.mail.Message;
import javax.mail.Multipart;
import javax.mail.Session;
import javax.mail.Transport;
import javax.mail.internet.InternetAddress;
import javax.mail.internet.MimeBodyPart;
import javax.mail.internet.MimeMessage;
import javax.mail.internet.MimeMultipart;
import javax.mail.internet.MimeUtility;
import com.xhl.leads.leadsmail.sendmail.entity.MailAttachment;
public class SendMailUtil {
public static void sendMail() throws Exception {
int draft = 0;//默认不是草稿
int priority = 3;//默认是普通邮件 优先级(1:紧急 3:普通 5:低)
int receiptFlag = 0;//是否需要回执 默认是0,不需要回执
String host = "smtp.163.com";
Properties props = new Properties();
props.setProperty("mail.transport.protocol", "smtp");// "smtp"
props.setProperty("mail.smtp.host", host);// smtp.qq.com
props.setProperty("mail.smtp.port", "465");// 465
props.setProperty("mail.smtp.auth", "true");// "true"
// props.setProperty("mail.debug", "true");// "true" 注释掉后,控制台将不会再打印发送邮件主题内容的日志
props.setProperty("mail.smtp.socketFactory.class",
"javax.net.ssl.SSLSocketFactory");
props.setProperty("mail.smtp.socketFactory.fallback", "false");
System.setProperty("mail.mime.splitlongparameters", "false");//设置了附件名过长问题,从而导致附件名显示带bin的错误,造成附件异常
Session session = Session.getDefaultInstance(props);
String from = "****@163.com";//发件人邮箱
String passWord = "*****";
String content = "您好:邮件!!!";
Message message = new MimeMessage(session);
message.setSentDate(new Date());
// 设置发件人地址
message.setFrom(new InternetAddress(from));
// 设置主题
message.setSubject("这是一封邮件");
// 设置收件人
message.addRecipients(Message.RecipientType.TO,
InternetAddress.parse(MimeUtility.encodeText("*****@qq.com")));
// 设置抄送人
message.addRecipients(Message.RecipientType.CC,
InternetAddress.parse(MimeUtility.encodeText("")));//选填
// 设置密送人
message.addRecipients(Message.RecipientType.BCC,
InternetAddress.parse(MimeUtility.encodeText("")));//选填
if (draft == 1) { // 如果是草稿
message.setFlag(Flags.Flag.DRAFT, true);
}
// 设置优先级(1:紧急 3:普通 5:低)
if (priority == 1)
message.setHeader("X-Priority", "1");
// 如果receiptFlag=1 代表需要回执
if (receiptFlag == 1)
message.setHeader("Disposition-Notification-To", from);
// 设置邮件内容
Multipart multipart = new MimeMultipart();
MimeBodyPart txtPart = new MimeBodyPart();
txtPart.setContent(content, "text/html;charset=utf-8");
multipart.addBodyPart(txtPart);
List<MailAttachment> mailAttachmentList = new ArrayList<MailAttachment>(); //获取当前邮件附件集合
String attachmentUrl = "";
String fileName = "";
if (mailAttachmentList != null && mailAttachmentList.size() > 0) {
for (MailAttachment attachment : mailAttachmentList) {
attachmentUrl = attachment.getFilePath();
fileName = attachment.getFileName();
MimeBodyPart part = new MimeBodyPart();
URL url = new URL(attachmentUrl);
DataSource dataSource=new URLDataSource(url);
part.setDataHandler(new DataHandler(dataSource));
part.setFileName(MimeUtility.encodeText(fileName));
multipart.addBodyPart(part);
}
}
message.setContent(multipart);
message.setFlag(Flags.Flag.RECENT, true);
message.saveChanges();
if (draft == 0) {
Transport transport = session.getTransport("smtp");
transport.connect(host, from, passWord);
transport.sendMessage(message, message.getAllRecipients());
transport.close();
}
}
public static void main(String[] args) {
try {
sendMail();
} catch (Exception e) {
e.printStackTrace();
}
}
}
附件对象:
import lombok.Data;
@Data
public class MailAttachment {
private int id;
private String filePath;//附件在文件服务器上的路径
private String fileName;//附件的名字
private String fileSize;//附件的大小
private int fileOrder;//附件的顺序
private String fileType;//附件类型
}
网上的很多javamail发送邮件,在将附件添加到邮件体时,都是用的File文件的形式,但是经过实践,我发现用这种方式去将附件保存到邮件体中,对于我们这种先将附件存储在OOS上,然后再从OSS上取下附件,速度很慢;找了很多资料,终于找到了以url的形式将附件添加到邮件体中
1)网上最常用的保存附件到邮件体中的方法:以File的方式
FileDataSource fds = new FileDataSource(file); // 得到数据源
part.setDataHandler(new DataHandler(fds)); // 得到附件本身并至入BodyPart 将附件以文件的形式添加到javamail中
利用这种方法,我先将存储到文件服务器上的文件得到,然后在本地生成临时文件,将文件添加到邮件体中,待邮件发送成功后,将临时文件在删除,我发现速度很慢,尤其是附件好几兆的时候,发一封邮件都得用时六七分钟;
2)第二种保存附件到邮件体中的方法:以流的方式
DataSource dataSource= new ByteArrayDataSource(inputStream,"application/octet-stream");//将附件改为以流的形式添加到javamail中
part.setDataHandler(new DataHandler(dataSource));
针对1)的现象,我想是不是我可以不生成临时文件,而只是把附件从OSS上拿到这个文件的流,然后将流保存到邮件体中,发现这种方法会减少时间,但是也没有减少很多
3)第三种保存附件到邮件体中的方法:以url的方式-----最佳方案
URL url = new URL(attachmentUrl);
DataSource dataSource=new URLDataSource(url);
part.setDataHandler(new DataHandler(dataSource));
使用3)的方法,添加附件到邮件体中,既未生成临时文件,而且速度还极快。