(edit by king)最近要搞个提醒系统,也就是能够设置个时间,在那个时间发封邮件提醒的系统。为了能够更好的起到提醒的效果,暂定的方案是发送会议邀请。
以前知道outlook的会议邀请格式不能仅仅发送ics附件,这样和outlook发送的会议邀请不太一样,不能默认自动加入到本地日历中,需要直接将ics格式当作正文发送。
在网上找了下基于java的ical格式库,ical4j,用这个来创建ics格式文件。这个库的文档还算比较全,也有简单的例子,照着例子(http://wiki.modularity.net.au/ical4j/index.php?title=Examples#Creating_a_meeting_of_four_hour_duration )抄了一段代码,结果在outlook中显示不支持的ics格式。通过比对outlook发送的会议邀请邮件源代码,添加了icsCalendar.getProperties().add(Method.REQUEST);这个属性之后,终于能够在outlook中正常使用了。
但是这样的会议邀请在我的kmail中,却总是提示不需要应答。在设置参与者的时候,明明已经把我自己的邮箱作为必选者了,但是还是不能对会议邀请进行响应。还是继续对比原来的会议邀请,发现在添加Attendee对象的时候,还可以增加好几个属性,如PARTSTAT,RSVP,经过多次尝试(哈哈,给别人发了n多垃圾邮件)后,终于在设置了RSVP属性(值为TRUE)的时候,kmail终于能够提示“您的应答已被请求”,可以应答这个邀请了。
现在的代码:
public static void sendEventEmail(List> reqs,
List> opts, Date startTime, Date endTime,
String location, String name, String content)
throws IOException, ValidationException, IllegalArgumentException {
if (reqs == null || reqs.isEmpty()) {
throw new IllegalArgumentException(
"Required participant should not be empty!");
}
List tos = new ArrayList();
DateTime start = new DateTime(startTime);
DateTime end = new DateTime(endTime);
VEvent meeting = new VEvent(start, end, name);
TimeZoneRegistry registry = TimeZoneRegistryFactory.getInstance()
.createRegistry();
// 设置时区
TimeZone timezone = registry.getTimeZone("Asia/Shanghai");
VTimeZone tz = timezone.getVTimeZone();
meeting.getProperties().add(tz.getTimeZoneId());
meeting.getProperties().add(new Location(location));
meeting.getProperties().add(new Summary(name));
meeting.getProperties().add(new Description(content));
// 设置uid
UidGenerator ug;
Uid uid;
ug = new UidGenerator("uidGen");
uid = ug.generateUid();
meeting.getProperties().add(uid);
for (Pair participant : reqs) {
Attendee attendee = new Attendee(URI.create("mailto:"
+ participant.first()));
attendee.getParameters().add(Role.REQ_PARTICIPANT);
attendee.getParameters().add(PartStat.NEEDS_ACTION);
attendee.getParameters().add(Rsvp.TRUE);
attendee.getParameters().add(new Cn(participant.second()));
meeting.getProperties().add(attendee);
tos.add(participant.first());
}
if (opts != null && !opts.isEmpty()) {
for (Pair participant : opts) {
Attendee attendee = new Attendee(URI.create("mailto:"
+ participant.first()));
attendee.getParameters().add(Role.OPT_PARTICIPANT);
attendee.getParameters().add(new Cn(participant.second()));
meeting.getProperties().add(attendee);
tos.add(participant.first());
}
}
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.getComponents().add(meeting);
CalendarOutputter co = new CalendarOutputter(false);
Writer wtr = new StringWriter();
co.output(icsCalendar, wtr);
String mailContent = wtr.toString();
sendEmail(tos, name, mailContent);
}
其中sendEmail方法就是通过javamail发送邮件:
public static void sendEmail(List tos, String subject, String content) {
Properties properties = new Properties();
properties.put("mail.transport.protocol", "smtp");
properties.put("mail.smtp.user", "xxx");
properties.put("mail.smtp.host", "xxx");
properties.put("mail.smtp.port", "xxx");
properties.put("mail.smtp.auth", "true");
final String username = "xxx";
final String password = "xxx";
Authenticator authenticator = new Authenticator() {
protected PasswordAuthentication getPasswordAuthentication() {
return new PasswordAuthentication(username, password);
}
};
Transport transport = null;
try {
Session session = Session.getDefaultInstance(properties,
authenticator);
MimeMessage mimeMessage = new MimeMessage(session);
mimeMessage.setSubject(subject);
for(String to : tos) {
mimeMessage.addRecipient(Message.RecipientType.TO,
new InternetAddress(to));
}
mimeMessage.setFrom(new InternetAddress(
"[email protected]"));
mimeMessage.setContent(content,
"text/calendar;method=REQUEST;charset=UTF-8");
transport = session.getTransport();
transport.connect(username, password);
transport.sendMessage(mimeMessage, mimeMessage
.getRecipients(javax.mail.Message.RecipientType.TO));
} catch (MessagingException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} finally {
if (transport != null)
try {
transport.close();
} catch (MessagingException logOrIgnore) {
}
}
}
现在还发现的问题是: