最近项目在做会议日程时需要发送邮件提醒,并要能把日程以会议邀请的方式显示在日历中(邮件通过邮件客户端接收如outlook、Foxmail等),利用ical4j可以读写iCalendar 数据流,把日程信息作为邮件正文发送会议邀请。(了解更多iCal4j信息(http://www.ibm.com/developerworks/cn/java/j-lo-ical4j/))
好了,贴上代码:
首先是把会议邀请信息生成标准格式的字符串
/**
*将会议邀请信息生成标准格式的字符串
* @param startTime 开始时间
* @param endTime 结束时间
* @param title 会议名称
* @param organizerName 组织者名称
* @param organizerEmail 组织者Email
* @param location 地点
* @param description 描述
* @param participatorNames 参与者名称列表,与participatorEmails一一对应
* @param participatorEmails 参与者Email列表
* @return
*/
public static String getICalText(Date startTime, Date endTime, String title, String organizerName, String organizerEmail, String location, String description, List<String> participatorNames, List<String> participatorEmails){
if(startTime != null && endTime != null && StringUtils.isNotBlank(organizerEmail) && participatorEmails != null && !participatorEmails.isEmpty() && participatorNames != null && participatorNames.size() == participatorEmails.size()) {
try {
SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd-HH-mm-ss");
String begin = format.format(startTime);
String over = format.format(endTime);
// 创建一个时区(TimeZone)
TimeZoneRegistry registry = TimeZoneRegistryFactory.getInstance().createRegistry();
TimeZone timezone = registry.getTimeZone("PRC");
VTimeZone tz = timezone.getVTimeZone();
//起始时间
java.util.Calendar startDate = java.util.Calendar.getInstance(timezone);
//月份从0开始
startDate.set(java.util.Calendar.MONTH, Integer.parseInt(begin.toString().split("-")[1].trim()) - 1);
startDate.set(java.util.Calendar.DAY_OF_MONTH, Integer.parseInt(begin.toString().split("-")[2].trim()));
startDate.set(java.util.Calendar.YEAR, Integer.parseInt(begin.toString().split("-")[0].trim()));
startDate.set(java.util.Calendar.HOUR_OF_DAY, Integer.parseInt(begin.toString().split("-")[3].trim()));
startDate.set(java.util.Calendar.MINUTE, Integer.parseInt(begin.toString().split("-")[4].trim()));
startDate.set(java.util.Calendar.SECOND, Integer.parseInt(begin.toString().split("-")[5].trim()));
//结束时间
java.util.Calendar endDate = java.util.Calendar.getInstance(timezone);
endDate.set(java.util.Calendar.MONTH, Integer.parseInt(over.toString().split("-")[1].trim()) - 1);
endDate.set(java.util.Calendar.DAY_OF_MONTH, Integer.parseInt(over.toString().split("-")[2].trim()));
endDate.set(java.util.Calendar.YEAR, Integer.parseInt(over.toString().split("-")[0].trim()));
endDate.set(java.util.Calendar.HOUR_OF_DAY, Integer.parseInt(over.toString().split("-")[3].trim()));
endDate.set(java.util.Calendar.MINUTE, Integer.parseInt(over.toString().split("-")[4].trim()));
endDate.set(java.util.Calendar.SECOND, Integer.parseInt(over.toString().split("-")[5].trim()));
// 创建事件
DateTime start = new DateTime(startDate.getTime());
DateTime end = new DateTime(endDate.getTime());
String eventTitle = "";
if(StringUtils.isNotBlank(title)){
eventTitle = title;
}
VEvent meeting = new VEvent(start, end, eventTitle);
// 添加时区信息
meeting.getProperties().add(tz.getTimeZoneId());
// 生成唯一标志符
UidGenerator ug = new UidGenerator("uidGen");
Uid uid = ug.generateUid();
meeting.getProperties().add(uid);
// 组织者
Organizer organizer = new Organizer(URI.create("mailto:" + organizerEmail));
organizer.getParameters().add(new Cn(organizerName));
meeting.getProperties().add(organizer);
if(StringUtils.isNotBlank(location)) {
meeting.getProperties().add(new Location(location));
}
if(StringUtils.isNotBlank(description)) {
meeting.getProperties().add(new Description(description));
}
// 添加参加者 .
for (int i = 0; i < participatorEmails.size(); i++) {
Attendee dev = new Attendee(URI.create("mailto:" + participatorEmails.get(i)));
dev.getParameters().add(Role.REQ_PARTICIPANT);
dev.getParameters().add(new Cn(participatorNames.get(i)));
meeting.getProperties().add(dev);
}
// 创建日历
Calendar icsCalendar = new Calendar();
icsCalendar.getProperties().add(new ProdId("-//Events Calendar//iCal4j 1.0//EN"));
icsCalendar.getProperties().add(Version.VERSION_2_0);
icsCalendar.getProperties().add(Method.REQUEST);
icsCalendar.getProperties().add(CalScale.GREGORIAN);
// 添加事件
icsCalendar.getComponents().add(meeting);
CalendarOutputter outputter = new CalendarOutputter();
Writer writer = new StringWriter();
outputter.output(icsCalendar, writer);
return writer.toString();
} catch (Exception e) {
LOG.error(e.getMessage());
}
}
return "";
}
然后就是通过javamail发送邮件,这里需要采用MimeMultipart分块发送:
/**
* 邮件通知工具
*
*/
abstract class EmailUtils {
private static Session session;
private static Transport transport;
/**
*
* @param title
* @param content
* @param encoding
* @param html 是否作为HTML发送
* @param icalText 会议邀请信息
* @param to
* @param attachs
*/
public static void send(String title, String content, String encoding, boolean html, String icalText, String to, File... attachs)
throws MessagingException, IOException{
String mimeType = html ? "text/html; charset=" + encoding : "text/plain; charset=" + encoding;
MimeMessage message = new MimeMessage(session);
message.setFrom(new InternetAddress(Configuration.getString("email.address", "")));
message.addRecipients(MimeMessage.RecipientType.TO, to);
message.setSubject(title, encoding);
MimeMultipart multipart = new MimeMultipart();
BodyPart bodypart = new MimeBodyPart();
bodypart.setContent(content, mimeType);
multipart.addBodyPart(bodypart);
if (icalText != null && icalText.trim().length() > 0) {
bodypart = new MimeBodyPart();
bodypart.setContent(icalText, "text/calendar; method=REQUEST; charset=" + encoding);
bodypart.setDataHandler(new DataHandler(new ByteArrayDataSource(icalText,
"text/calendar;method=REQUEST;charset=" + encoding)));
multipart.addBodyPart(bodypart);
}
message.setContent(multipart);
transport.sendMessage(message, message.getAllRecipients());
}
public static void connect() throws MessagingException {
Properties props = new Properties();
// https://javamail.java.net/nonav/docs/api/com/sun/mail/smtp/package-summary.html
if (Configuration.getBoolean("email.smtp.auth", true)) {
props.setProperty("mail.smtp.auth", "true");
}
props.setProperty("mail.smtp.host", Configuration.getString("email.host", ""));
if (Configuration.getInt("email.port", -1) > 0) {
props.setProperty("mail.smtp.port", Configuration.getString("email.port", "-1"));
}
if (Configuration.getInt("email.connectiontimeout", -1) > 0) {
props.setProperty("mail.smtp.connectiontimeout", Configuration.getString("email.connectiontimeout", "-1"));
}
if (Configuration.getInt("email.timeout", -1) > 0) {
props.setProperty("mail.smtp.timeout", Configuration.getString("email.timeout", "-1"));
}
if (Configuration.getInt("email.writetimeout", -1) > 0) {
props.setProperty("mail.smtp.writetimeout", Configuration.getString("email.writetimeout", "-1"));
}
if (Configuration.getBoolean("email.smtp.auth.plain.disable", false)) {
props.setProperty("mail.smtp.auth.plain.disable", "true");
}
// 使用SSL连接,见com.sun.mail.smtp.SMTPTransport
// 某些邮件服务器,如Google,需要SSL安全连接
if (Configuration.getBoolean("email.smtp.ssl", false)) {
props.setProperty("mail.smtp.ssl.enable", "true");
}
session = Session.getInstance(props);
transport = session.getTransport("smtp");
if (Configuration.getBoolean("email.smtp.auth", true)) {
transport.connect("user", "password");
} else {
transport.connect();
}
}
public static void close() {
try {
if (transport != null) {
transport.close();
transport = null;
}
} catch (Exception e) {
}
session = null;
}
}