一、配置环境准备
1.1 mail.smtp.host查看
打开outlook:文件–》信息–》账户设置–》双击账户
1.2 修改本地hosts文件
最好在C:\Windows\System32\drivers\etc\hosts文件配置一下主机名,
ip可以在命令行中 ping mail.unipower.cn 查看到
hosts文件新增一行:
ip mail.unipower.cn
1.3 pom.xml
pom.xml新增依赖:
<!-- mail -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-mail</artifactId>
<version>2.1.3.RELEASE</version>
</dependency>
<dependency>
<groupId>javax.mail</groupId>
<artifactId>mail</artifactId>
<version>1.4.7</version>
</dependency>
二、代码demo
2.1 outlook会议邀请demo
import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Properties;
import java.util.UUID;
import javax.activation.DataHandler;
import javax.mail.Authenticator;
import javax.mail.BodyPart;
import javax.mail.Message;
import javax.mail.MessagingException;
import javax.mail.Multipart;
import javax.mail.PasswordAuthentication;
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.util.ByteArrayDataSource;
public class MailOutlook {
Session session; //创建session
static String name = "xxx@xxx.com"; //发送用户邮箱
static String pwd = "xxxxx"; //发送用户密码
static String username = "xxx@xxx.com"; //接收用户邮箱
static String title = "主题"; //发送邮件主题
static String text = "邮件正文"; //发送邮件内容
static String startTimew = "2019-05-14 08:00:00";//开始时间
static String endTimew = "2019-05-14 09:00:00"; //结束时间
//需要转换的时间
static String startTime = getUtc(startTimew);
static String endTime = getUtc(endTimew);
private static Properties emailProp = new Properties();
private static class EmailAuthenticator extends Authenticator {
@Override
protected PasswordAuthentication getPasswordAuthentication() {
String userId = emailProp.getProperty("userId", name);
String password = emailProp.getProperty("password", pwd);
return new PasswordAuthentication(userId, password);
}
}
public static void send() throws Exception {
try {
String fromEmail = emailProp.getProperty("fromEmail", name);
String toEmail=emailProp.getProperty("toEmail", username);
Properties props = new Properties();
try {
//端口一般为 25/465/487 可以使用telnet host port查看是否可用 比如 telnet mail.unipower.cn 25
props.put("mail.smtp.port", "25");
//配置outlook上查到的host
props.put("mail.smtp.host", "mail.unipower.cn");
props.put("mail.transport.protocol", "smtp");
props.put("mail.smtp.ssl", "true");
} catch (Exception e) {
e.printStackTrace();
}
Session session;
Authenticator authenticator = new EmailAuthenticator();
session = Session.getInstance(props, authenticator);
MimeMessage message = new MimeMessage(session);
//设置发件人
message.setFrom(new InternetAddress(fromEmail));
//设置单个收件人
message.addRecipient(Message.RecipientType.TO, new InternetAddress(toEmail));
/*
设置多收件人,Message.RecipientType.CC:密送
Message.RecipientType.BCC:抄送
Message.RecipientType.TO:收件人
*/
List<String> emails = new ArrayList<>();
emails.add("xxx@xxx.com")
message.addRecipients(Message.RecipientType.TO,setRecipientT0(emails));
message.setSubject(title);
StringBuffer buffer = new StringBuffer();
buffer.append("BEGIN:VCALENDAR\n"
+ "PRODID:-//Microsoft Corporation//Outlook 9.0 MIMEDIR//EN\n"
+ "VERSION:2.0\n"
+ "METHOD:REQUEST\n" //METHOD:CANCEL 取消会议 METHOD:REQUEST 创建和更新会议
+ "BEGIN:VEVENT\n"
+ "ATTENDEE;ROLE=REQ-PARTICIPANT;RSVP=TRUE:MAILTO:"+fromEmail+"\n"
+ "ORGANIZER:MAILTO:"+fromEmail+"\n"
+ "DTSTART:"+startTime+"\n"
+ "DTEND:"+endTime+"\n"
+ "LOCATION:会议室01\n"
//如果id相同的话,outlook会认为是同一个会议请求,所以使用uuid。
+ "UID:"+UUID.randomUUID().toString()+"\n"
+ "CATEGORIES:111111111r\n"
+ "DESCRIPTION:"+文本\\n内容+"\n\n" // 会议内容换行为\\n
+ "SUMMARY:2222222222t\n" + "PRIORITY:5\n"
+ "SEQUENCE:1\n" //设置优先级 其中cancel>update>create
+ "CLASS:PUBLIC\n" + "BEGIN:VALARM\n"
+ "TRIGGER:-PT15M\n" + "ACTION:DISPLAY\n"
+ "DESCRIPTION:Reminder\n" + "END:VALARM\n"
+ "END:VEVENT\n" + "END:VCALENDAR");
Multipart multipart = new MimeMultipart();
BodyPart messageBodyPart = new MimeBodyPart();
// 测试下来如果不这么转换的话,会以纯文本的形式发送过去,
//如果没有text/calendar;method=REQUEST;charset=\"UTF-8\",outlook会议附件的形式存在,而不是直接打开就是一个会议请求
messageBodyPart.setDataHandler(new DataHandler(new ByteArrayDataSource(buffer.toString(),
"text/calendar;method=REQUEST;charset=\"UTF-8\"")));
// 添加会议邀请内容
multipart.addBodyPart(messageBodyPart);
// 附件功能
// 创建消息部分
BodyPart fujianBodyPart = new MimeBodyPart();
// 添加网络附件
for (int i = 0; i < documents.size(); i++) {
URL url = new URL(documents.get(i).getUrl());
DataHandler dataHandler = new DataHandler(url);
MimeBodyPart messageBodyPart3 = new MimeBodyPart();
messageBodyPart3.setDataHandler(dataHandler);
messageBodyPart3.setFileName(MimeUtility.encodeText(documents.get(i).getName()));
multipart.addBodyPart(messageBodyPart3);
}
message.setContent(multipart,"text/html;charset=UTF-8");
//message.setText("测试");
Transport.send(message);
} catch (MessagingException me) {
me.printStackTrace();
} catch (Exception ex) {
ex.printStackTrace();
}
}
/*** 设置收件人/抄送人/密送人地址信息*/
private InternetAddress[] setRecipientT0(List<String> recipientT0List) throws MessagingException, UnsupportedEncodingException {
if (recipientT0List.size() > 0) {
InternetAddress[] sendTo = new InternetAddress[recipientT0List.size()];
for (int i = 0; i < recipientT0List.size(); i++) {
System.out.println("发送到:" + recipientT0List.get(i));
sendTo[i] = new InternetAddress(recipientT0List.get(i), "", "UTF-8");
}
return sendTo;
}
return null;
}
//转utc时间
public static String getUtc(String str){
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
long millionSeconds = 0;
try {
millionSeconds = sdf.parse(str).getTime();
} catch (ParseException e1) {
e1.printStackTrace();
}//毫秒
Date date = new Date(millionSeconds );
DateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); //格式化日期
String nowTime="";
nowTime= df.format(date);
String utcTime = nowTime.replace("-", "").replace(" ", "T").replace(":", "");//转换utc时间
return utcTime;
}
//main函数 测试
public static void main(String[] args) {
try {
send();
//cancel();
//update();
System.out.println("success");
} catch (Exception e) {
e.printStackTrace();
}
}
}
修改和创建其实只要UID保持一致然后修改以下内容,
- SEQUENCE:2 设置优先级 cance>update>create
取消会议主要是和修改uuid必须一致,主要是以下两点不一致:
- SEQUENCE:3 设置优先级 cance>update>create
- “METHOD:REQUEST\n” //METHOD:CANCEL 取消会议 METHOD:REQUEST 创建和更新会议
2.2 取消会议
public static void cancel() throws Exception {
try {
String fromEmail = emailProp.getProperty("fromEmail", name);
String toEmail=emailProp.getProperty("toEmail", username);
Properties props = new Properties();
try {
//端口一般为 25/465/487 可以使用telnet host port查看是否可用 比如 telnet mail.unipower.cn 25
props.put("mail.smtp.port", "25");
//配置outlook上查到的host
props.put("mail.smtp.host", "mail.unipower.cn");
props.put("mail.transport.protocol", "smtp");
props.put("mail.smtp.ssl", "true");
} catch (Exception e) {
e.printStackTrace();
}
Session session;
Authenticator authenticator = new EmailAuthenticator();
session = Session.getInstance(props, authenticator);
MimeMessage message = new MimeMessage(session);
message.setFrom(new InternetAddress(fromEmail));
//设置单个收件人
message.addRecipient(Message.RecipientType.TO, new InternetAddress(toEmail));
/*
设置多收件人,Message.RecipientType.CC:密送
Message.RecipientType.BCC:抄送
Message.RecipientType.TO:收件人
*/
List<String> emails = new ArrayList<>();
emails.add("xxx@xxx.com")
message.addRecipients(Message.RecipientType.TO,setRecipientT0(emails));
message.setSubject(title);
StringBuffer buffer = new StringBuffer();
buffer.append("BEGIN:VCALENDAR\n"
+ "PRODID:-//Microsoft Corporation//Outlook 9.0 MIMEDIR//EN\n"
+ "VERSION:2.0\n"
+ "METHOD:CANCEL \n" //METHOD:CANCEL 取消会议 METHOD:REQUEST 创建和更新会议
+ "BEGIN:VEVENT\n"
+ "ATTENDEE;ROLE=REQ-PARTICIPANT;RSVP=TRUE:MAILTO:"+fromEmail+"\n"
+ "ORGANIZER:MAILTO:"+fromEmail+"\n"
+ "DTSTART:"+startTime+"\n"
+ "DTEND:"+endTime+"\n"
+ "LOCATION:会议室01\n"
//这里的uuid要和会议邀请的uuid一致,实际生产中可以将uuid存到数据库中
+ "UID:"+XXX(和会议邀请uuid一致)+"\n"
+ "CATEGORIES:111111111r\n"
+ "DESCRIPTION:"+文本\\n内容+"\n\n" // 会议内容换行为\\n
+ "SUMMARY:2222222222t\n" + "PRIORITY:5\n"
+ "SEQUENCE:3\n" //设置优先级 其中cancel>update>create
+ "CLASS:PUBLIC\n" + "BEGIN:VALARM\n"
+ "TRIGGER:-PT15M\n" + "ACTION:DISPLAY\n"
+ "DESCRIPTION:Reminder\n" + "END:VALARM\n"
+ "END:VEVENT\n" + "END:VCALENDAR");
BodyPart messageBodyPart = new MimeBodyPart();
// 测试下来如果不这么转换的话,会以纯文本的形式发送过去,
//如果没有text/calendar;method=REQUEST;charset=\"UTF-8\",outlook会议附件的形式存在,而不是直接打开就是一个会议请求
messageBodyPart.setDataHandler(new DataHandler(new ByteArrayDataSource(buffer.toString(),
"text/calendar;method=REQUEST;charset=\"UTF-8\"")));
Multipart multipart = new MimeMultipart();
multipart.addBodyPart(messageBodyPart);
message.setContent(multipart);
//message.setText("测试");
Transport.send(message);
} catch (MessagingException me) {
me.printStackTrace();
} catch (Exception ex) {
ex.printStackTrace();
}
}
2.3 会议修改
public static void update() throws Exception {
try {
String fromEmail = emailProp.getProperty("fromEmail", name);
String toEmail=emailProp.getProperty("toEmail", username);
Properties props = new Properties();
try {
//端口一般为 25/465/487 可以使用telnet host port查看是否可用 比如 telnet mail.unipower.cn 25
props.put("mail.smtp.port", "25");
//配置outlook上查到的host
props.put("mail.smtp.host", "mail.unipower.cn");
props.put("mail.transport.protocol", "smtp");
props.put("mail.smtp.ssl", "true");
} catch (Exception e) {
e.printStackTrace();
}
Session session;
Authenticator authenticator = new EmailAuthenticator();
session = Session.getInstance(props, authenticator);
MimeMessage message = new MimeMessage(session);
message.setFrom(new InternetAddress(fromEmail));
//设置单个收件人
message.addRecipient(Message.RecipientType.TO, new InternetAddress(toEmail));
/*
设置多收件人,Message.RecipientType.CC:密送
Message.RecipientType.BCC:抄送
Message.RecipientType.TO:收件人
*/
List<String> emails = new ArrayList<>();
emails.add("xxx@xxx.com")
message.addRecipients(Message.RecipientType.TO,setRecipientT0(emails));
message.setSubject(title);
StringBuffer buffer = new StringBuffer();
buffer.append("BEGIN:VCALENDAR\n"
+ "PRODID:-//Microsoft Corporation//Outlook 9.0 MIMEDIR//EN\n"
+ "VERSION:2.0\n"
+ "METHOD:REQUEST\n" //METHOD:CANCEL 取消会议 METHOD:REQUEST 创建和更新会议
+ "BEGIN:VEVENT\n"
+ "ATTENDEE;ROLE=REQ-PARTICIPANT;RSVP=TRUE:MAILTO:"+fromEmail+"\n"
+ "ORGANIZER:MAILTO:"+fromEmail+"\n"
+ "DTSTART:"+startTime+"\n"
+ "DTEND:"+endTime+"\n"
+ "LOCATION:会议室01\n"
//这里的uuid要和会议邀请的uuid一致,实际生产中可以将uuid存到数据库中
+ "UID:"+XXX(和会议邀请uuid一致)+"\n"
+ "CATEGORIES:111111111r\n"
+ "DESCRIPTION:"+文本\\n内容+"\n\n" // 会议内容换行为\\n
+ "SUMMARY:2222222222t\n" + "PRIORITY:5\n"
+ "SEQUENCE:2\n" //设置优先级 其中cancel>update>create
+ "CLASS:PUBLIC\n" + "BEGIN:VALARM\n"
+ "TRIGGER:-PT15M\n" + "ACTION:DISPLAY\n"
+ "DESCRIPTION:Reminder\n" + "END:VALARM\n"
+ "END:VEVENT\n" + "END:VCALENDAR");
BodyPart messageBodyPart = new MimeBodyPart();
// 测试下来如果不这么转换的话,会以纯文本的形式发送过去,
//如果没有text/calendar;method=REQUEST;charset=\"UTF-8\",outlook会议附件的形式存在,而不是直接打开就是一个会议请求
messageBodyPart.setDataHandler(new DataHandler(new ByteArrayDataSource(buffer.toString(),
"text/calendar;method=REQUEST;charset=\"UTF-8\"")));
Multipart multipart = new MimeMultipart();
multipart.addBodyPart(messageBodyPart);
message.setContent(multipart);
//message.setText("测试");
Transport.send(message);
} catch (MessagingException me) {
me.printStackTrace();
} catch (Exception ex) {
ex.printStackTrace();
}
}
三、发送普通邮件
3.1 普通邮件工具类
/**
* @Author hld
* @Description 发送普通邮件
* @Date 16:18 2019/6/18
* @Param userList:收件人列表
* ccUserList:抄送人列表
* content:内容
* topic:标题
* @return
**/
public void normalEmail(List<String> userList,List<String> ccUserList,String content,String topic){
try {
String fromEmail = emailProp.getProperty("fromEmail", username);
Properties props = new Properties();
try {
props.put("mail.smtp.port", port);
props.put("mail.smtp.host", host);
props.put("mail.transport.protocol", "smtp");
props.put("mail.smtp.ssl", "true");
} catch (Exception e) {
e.printStackTrace();
}
Session session;
Authenticator authenticator = new EmailAuthenticator();
session = Session.getInstance(props, authenticator);
MimeMessage message = new MimeMessage(session);
message.setFrom(new InternetAddress(fromEmail)); //发件人
//设置多发件人 BCC:抄送 CC:密送 TO:收件人
if (userList != null && userList.size() > 0){
message.addRecipients(Message.RecipientType.TO,setRecipientT0(userList));
}
//设置单个发件人
//message.addRecipient(Message.RecipientType.TO, new InternetAddress(toEmail));
//设置抄送地址 BCC:抄送 CC:密送 TO:收件人
if (ccUserList != null && ccUserList.size() > 0){
message.addRecipients(Message.RecipientType.BCC,setRecipientT0(ccUserList));
}
message.setSubject(topic); //设置会议主题
// 添加网络附件
Multipart multipart = new MimeMultipart();
// 创建消息部分
BodyPart messageBodyPart = new MimeBodyPart();
// 消息
messageBodyPart.setText(content);
multipart.addBodyPart(messageBodyPart);
// 循环网络附件,获取url 附件名称等
for (int i = 0; i < documents.size(); i++) {
URL url = new URL(documents.get(i).getUrl());
DataHandler dataHandler = new DataHandler(url);
MimeBodyPart messageBodyPart3 = new MimeBodyPart();
messageBodyPart3.setDataHandler(dataHandler);
messageBodyPart3.setFileName(MimeUtility.encodeText(documents.get(i).getName()));
multipart.addBodyPart(messageBodyPart3);
}
// 发送完整消息
message.setContent(multipart);
// message.setText(content);
Transport.send(message);
} catch (MessagingException me) {
me.printStackTrace();
} catch (Exception ex) {
ex.printStackTrace();
}
}