mirror of
https://github.com/moparisthebest/davmail
synced 2025-01-13 22:48:07 -05:00
Caldav: id 2900599, implement optional attendees in notifications
git-svn-id: http://svn.code.sf.net/p/davmail/code/trunk@897 3d1905a2-6b24-0410-a738-b14d5a86fcbd
This commit is contained in:
parent
fa7ed285b1
commit
3b92c1978b
@ -55,7 +55,6 @@ import javax.mail.MessagingException;
|
||||
import javax.mail.internet.MimeMessage;
|
||||
import javax.mail.internet.MimeMultipart;
|
||||
import javax.mail.internet.MimePart;
|
||||
import javax.mail.internet.MimeUtility;
|
||||
import java.io.*;
|
||||
import java.net.HttpURLConnection;
|
||||
import java.net.NoRouteToHostException;
|
||||
@ -2183,6 +2182,7 @@ public class ExchangeSession {
|
||||
|
||||
class Participants {
|
||||
String attendees;
|
||||
String optionalAttendees;
|
||||
String organizer;
|
||||
}
|
||||
|
||||
@ -2196,6 +2196,7 @@ public class ExchangeSession {
|
||||
*/
|
||||
protected Participants getParticipants(boolean isNotification) throws IOException {
|
||||
HashSet<String> attendees = new HashSet<String>();
|
||||
HashSet<String> optionalAttendees = new HashSet<String>();
|
||||
String organizer = null;
|
||||
BufferedReader reader = null;
|
||||
try {
|
||||
@ -2224,7 +2225,11 @@ public class ExchangeSession {
|
||||
&& (!isNotification
|
||||
|| line.indexOf("RSVP=TRUE") >= 0
|
||||
|| line.indexOf("PARTSTAT=NEEDS-ACTION") >= 0)) {
|
||||
attendees.add(value);
|
||||
if (line.indexOf("ROLE=OPT-PARTICIPANT") >= 0) {
|
||||
optionalAttendees.add(value);
|
||||
} else {
|
||||
attendees.add(value);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -2235,16 +2240,8 @@ public class ExchangeSession {
|
||||
}
|
||||
}
|
||||
Participants participants = new Participants();
|
||||
if (!attendees.isEmpty()) {
|
||||
StringBuilder result = new StringBuilder();
|
||||
for (String recipient : attendees) {
|
||||
if (result.length() > 0) {
|
||||
result.append(", ");
|
||||
}
|
||||
result.append(recipient);
|
||||
}
|
||||
participants.attendees = result.toString();
|
||||
}
|
||||
participants.attendees = StringUtil.join(attendees, ", ");
|
||||
participants.optionalAttendees = StringUtil.join(optionalAttendees, ", ");
|
||||
participants.organizer = organizer;
|
||||
return participants;
|
||||
}
|
||||
@ -2261,7 +2258,7 @@ public class ExchangeSession {
|
||||
protected EventResult createOrUpdate() throws IOException {
|
||||
String boundary = UUID.randomUUID().toString();
|
||||
ByteArrayOutputStream baos = new ByteArrayOutputStream();
|
||||
OutputStreamWriter writer = new OutputStreamWriter(baos, "ASCII");
|
||||
MimeOutputStreamWriter writer = new MimeOutputStreamWriter(baos);
|
||||
int status = 0;
|
||||
PutMethod putmethod = new PutMethod(URIUtil.encodePath(href));
|
||||
putmethod.setRequestHeader("Translate", "f");
|
||||
@ -2275,60 +2272,51 @@ public class ExchangeSession {
|
||||
putmethod.setRequestHeader("Content-Type", "message/rfc822");
|
||||
String method = getICSMethod(icsBody);
|
||||
|
||||
writer.write("Content-Transfer-Encoding: 7bit\r\n" +
|
||||
"Content-class: ");
|
||||
writer.write(contentClass);
|
||||
writer.write("\r\n");
|
||||
writer.writeHeader("Content-Transfer-Encoding", "7bit");
|
||||
writer.writeHeader("Content-class", contentClass);
|
||||
// append date
|
||||
SimpleDateFormat formatter = new SimpleDateFormat("EEE, dd MMM yyyy hh:mm:ss Z", Locale.ENGLISH);
|
||||
writer.write("Date: ");
|
||||
writer.write(formatter.format(new Date()));
|
||||
writer.write("\r\n");
|
||||
writer.writeHeader("Date", new Date());
|
||||
|
||||
// Make sure invites have a proper subject line
|
||||
writer.writeHeader("Subject", getICSSummary(icsBody));
|
||||
|
||||
if ("urn:content-classes:calendarmessage".equals(contentClass)) {
|
||||
// need to parse attendees and organizer to build recipients
|
||||
Participants participants = getParticipants(true);
|
||||
String recipients;
|
||||
if (email.equalsIgnoreCase(participants.organizer)) {
|
||||
// current user is organizer => notify all
|
||||
recipients = participants.attendees;
|
||||
writer.writeHeader("To", participants.attendees);
|
||||
writer.writeHeader("Cc", participants.optionalAttendees);
|
||||
// do not send notification if no recipients found
|
||||
if (participants.attendees == null && participants.optionalAttendees == null) {
|
||||
status = HttpStatus.SC_NO_CONTENT;
|
||||
}
|
||||
} else {
|
||||
// notify only organizer
|
||||
recipients = participants.organizer;
|
||||
writer.writeHeader("To", participants.organizer);
|
||||
// do not send notification if no recipients found
|
||||
if (participants.organizer == null) {
|
||||
status = HttpStatus.SC_NO_CONTENT;
|
||||
}
|
||||
}
|
||||
|
||||
// Make sure invites have a proper subject line
|
||||
writer.write("Subject: " + MimeUtility.encodeText(getICSSummary(icsBody), "UTF-8", null) + "\r\n");
|
||||
|
||||
// do not send notification if no recipients found
|
||||
if (recipients != null && recipients.length() > 0) {
|
||||
writer.write("To: ");
|
||||
writer.write(recipients);
|
||||
writer.write("\r\n");
|
||||
} else {
|
||||
status = HttpStatus.SC_NO_CONTENT;
|
||||
}
|
||||
} else {
|
||||
// Make sure invites have a proper subject line
|
||||
writer.write("Subject: " + MimeUtility.encodeText(getICSSummary(icsBody), "UTF-8", null) + "\r\n");
|
||||
|
||||
// need to parse attendees and organizer to build recipients
|
||||
Participants participants = getParticipants(false);
|
||||
// storing appointment, full recipients header
|
||||
writer.write("To: ");
|
||||
if (participants.attendees != null) {
|
||||
writer.write(participants.attendees);
|
||||
writer.writeHeader("To", participants.attendees);
|
||||
} else {
|
||||
writer.write(email);
|
||||
// use current user as attendee
|
||||
writer.writeHeader("To", email);
|
||||
}
|
||||
writer.writeHeader("Cc", participants.optionalAttendees);
|
||||
|
||||
writer.write("\r\n");
|
||||
writer.write("From: ");
|
||||
if (participants.organizer != null) {
|
||||
writer.write(participants.organizer);
|
||||
writer.writeHeader("From", participants.organizer);
|
||||
} else {
|
||||
writer.write(email);
|
||||
writer.writeHeader("From", email);
|
||||
}
|
||||
writer.write("\r\n");
|
||||
// if not organizer, set REPLYTIME to force Outlook in attendee mode
|
||||
if (participants.organizer != null && !email.equalsIgnoreCase(participants.organizer)) {
|
||||
if (icsBody.indexOf("METHOD:") < 0) {
|
||||
@ -2340,50 +2328,39 @@ public class ExchangeSession {
|
||||
}
|
||||
}
|
||||
}
|
||||
writer.write("MIME-Version: 1.0\r\n" +
|
||||
"Content-Type: multipart/alternative;\r\n" +
|
||||
"\tboundary=\"----=_NextPart_");
|
||||
writer.write(boundary);
|
||||
writer.write("\"\r\n" +
|
||||
"\r\n" +
|
||||
"This is a multi-part message in MIME format.\r\n" +
|
||||
"\r\n" +
|
||||
"------=_NextPart_");
|
||||
writer.write(boundary);
|
||||
writer.writeHeader("MIME-Version", "1.0");
|
||||
writer.writeHeader("Content-Type", "multipart/alternative;\r\n"+
|
||||
"\tboundary=\"----=_NextPart_"+boundary+"\"");
|
||||
writer.writeLn();
|
||||
writer.writeLn("This is a multi-part message in MIME format.");
|
||||
writer.writeLn();
|
||||
writer.writeLn("------=_NextPart_"+boundary);
|
||||
|
||||
// Write a part of the message that contains the
|
||||
// ICS description so that invites contain the description text
|
||||
String description = getICSDescription(icsBody).replaceAll("\\\\[Nn]", "\r\n");
|
||||
|
||||
if (description.length() > 0) {
|
||||
writer.write("\r\n" +
|
||||
"Content-Type: text/plain;\r\n" +
|
||||
"\tcharset=\"utf-8\"\r\n" +
|
||||
"content-transfer-encoding: 8bit\r\n" +
|
||||
"\r\n");
|
||||
writer.writeHeader("Content-Type", "text/plain;\r\n" +
|
||||
"\tcharset=\"utf-8\"");
|
||||
writer.writeHeader("content-transfer-encoding", "8bit");
|
||||
writer.writeLn();
|
||||
writer.flush();
|
||||
baos.write(description.getBytes("UTF-8"));
|
||||
writer.write("\r\n" +
|
||||
"------=_NextPart_" +
|
||||
boundary);
|
||||
|
||||
writer.writeLn();
|
||||
writer.writeLn("------=_NextPart_"+boundary);
|
||||
}
|
||||
|
||||
writer.write("\r\n" +
|
||||
"Content-class: ");
|
||||
writer.write(contentClass);
|
||||
writer.write("\r\n" +
|
||||
"Content-Type: text/calendar;\r\n" +
|
||||
"\tmethod=");
|
||||
writer.write(method);
|
||||
writer.write(";\r\n" +
|
||||
"\tcharset=\"utf-8\"\r\n" +
|
||||
"Content-Transfer-Encoding: 8bit\r\n\r\n");
|
||||
writer.writeHeader("Content-class", contentClass);
|
||||
writer.writeHeader("Content-Type", "text/calendar;\r\n"+
|
||||
"\tmethod="+method+";\r\n"+
|
||||
"\tcharset=\"utf-8\""
|
||||
);
|
||||
writer.writeHeader("Content-Transfer-Encoding", "8bit");
|
||||
writer.writeLn();
|
||||
writer.flush();
|
||||
baos.write(fixICS(icsBody, false).getBytes("UTF-8"));
|
||||
writer.write("\r\n------=_NextPart_");
|
||||
writer.write(boundary);
|
||||
writer.write("--\r\n");
|
||||
writer.writeLn();
|
||||
writer.writeLn("------=_NextPart_"+boundary+"--");
|
||||
writer.close();
|
||||
putmethod.setRequestEntity(new ByteArrayRequestEntity(baos.toByteArray(), "message/rfc822"));
|
||||
try {
|
||||
|
82
src/java/davmail/exchange/MimeOutputStreamWriter.java
Normal file
82
src/java/davmail/exchange/MimeOutputStreamWriter.java
Normal file
@ -0,0 +1,82 @@
|
||||
/*
|
||||
* DavMail POP/IMAP/SMTP/CalDav/LDAP Exchange Gateway
|
||||
* Copyright (C) 2009 Mickael Guessant
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
package davmail.exchange;
|
||||
|
||||
import javax.mail.internet.MimeUtility;
|
||||
import java.io.*;
|
||||
import java.util.Date;
|
||||
import java.util.Locale;
|
||||
import java.text.SimpleDateFormat;
|
||||
|
||||
/**
|
||||
* Mime OutputStreamWriter to build in memory Mime message.
|
||||
*/
|
||||
public class MimeOutputStreamWriter extends OutputStreamWriter {
|
||||
public MimeOutputStreamWriter(OutputStream out) throws UnsupportedEncodingException {
|
||||
super(out,"ASCII");
|
||||
}
|
||||
|
||||
/**
|
||||
* Write MIME header
|
||||
* @param header header name
|
||||
* @param value header value
|
||||
* @throws IOException on error
|
||||
*/
|
||||
public void writeHeader(String header, String value) throws IOException {
|
||||
// do not write empty headers
|
||||
if (value != null && value.length() > 0) {
|
||||
write(header);
|
||||
write(": ");
|
||||
write(MimeUtility.encodeText(value, "UTF-8", null));
|
||||
writeLn();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Write MIME header
|
||||
* @param header header name
|
||||
* @param value header value
|
||||
* @throws IOException on error
|
||||
*/
|
||||
public void writeHeader(String header, Date value) throws IOException {
|
||||
SimpleDateFormat formatter = new SimpleDateFormat("EEE, dd MMM yyyy hh:mm:ss Z", Locale.ENGLISH);
|
||||
writeHeader(header, formatter.format(value));
|
||||
}
|
||||
|
||||
/**
|
||||
* Write line.
|
||||
*
|
||||
* @param line line content
|
||||
* @throws IOException on error
|
||||
*/
|
||||
public void writeLn(String line) throws IOException {
|
||||
write(line);
|
||||
write("\r\n");
|
||||
}
|
||||
|
||||
/**
|
||||
* Write CRLF.
|
||||
*
|
||||
* @throws IOException on error
|
||||
*/
|
||||
public void writeLn() throws IOException {
|
||||
write("\r\n");
|
||||
}
|
||||
|
||||
}
|
@ -18,6 +18,8 @@
|
||||
*/
|
||||
package davmail.util;
|
||||
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* Various string handling methods
|
||||
*/
|
||||
@ -95,4 +97,26 @@ public final class StringUtil {
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Join values with given separator.
|
||||
*
|
||||
* @param values value set
|
||||
* @param separator separator
|
||||
* @return joined values
|
||||
*/
|
||||
public static String join(Set<String> values, String separator) {
|
||||
if (values != null && !values.isEmpty()) {
|
||||
StringBuilder result = new StringBuilder();
|
||||
for (String value : values) {
|
||||
if (result.length() > 0) {
|
||||
result.append(separator);
|
||||
}
|
||||
result.append(value);
|
||||
}
|
||||
return result.toString();
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user