Fix cancellation messages for deleted attendee
* We weren't sending a proper ics file for the deleted attendee, and
this caused Exchange to send a message to the wrong people (the
referenced bug)
* Split out code that adds attendees to outgoing mail
* Changed the optional last argument to createMessageForX to be a specified
attendee, i.e. the only addressee to be used for the message
Bug: 2548465
Change-Id: I629fcfaffe621408ea460d42c9c7c283929f7e79
diff --git a/src/com/android/exchange/adapter/CalendarSyncAdapter.java b/src/com/android/exchange/adapter/CalendarSyncAdapter.java
index f87ca4e..f418309 100644
--- a/src/com/android/exchange/adapter/CalendarSyncAdapter.java
+++ b/src/com/android/exchange/adapter/CalendarSyncAdapter.java
@@ -1699,10 +1699,9 @@
// Send a cancellation message to each of them
msg = CalendarUtilities.createMessageForEventId(mContext, eventId,
Message.FLAG_OUTGOING_MEETING_CANCEL, clientId, mAccount,
- false);
+ removedAttendee);
if (msg != null) {
// Just send it to the removed attendee
- msg.mTo = removedAttendee;
userLog("Queueing cancellation to removed attendee " + msg.mTo);
mOutgoingMailList.add(msg);
}
diff --git a/src/com/android/exchange/utility/CalendarUtilities.java b/src/com/android/exchange/utility/CalendarUtilities.java
index 266ab69..049ca30 100644
--- a/src/com/android/exchange/utility/CalendarUtilities.java
+++ b/src/com/android/exchange/utility/CalendarUtilities.java
@@ -1213,6 +1213,51 @@
}
/**
+ * Add an attendee to the ics attachment and the to list of the Message being composed
+ * @param ics the ics attachment writer
+ * @param toList the list of addressees for this email
+ * @param attendeeName the name of the attendee
+ * @param attendeeEmail the email address of the attendee
+ * @param messageFlag the flag indicating the action to be indicated by the message
+ * @param account the sending account of the email
+ */
+ static private void addAttendeeToMessage(SimpleIcsWriter ics, ArrayList<Address> toList,
+ String attendeeName, String attendeeEmail, int messageFlag, Account account) {
+ if ((messageFlag & Message.FLAG_OUTGOING_MEETING_REQUEST_MASK) != 0) {
+ String icalTag = ICALENDAR_ATTENDEE_INVITE;
+ if ((messageFlag & Message.FLAG_OUTGOING_MEETING_CANCEL) != 0) {
+ icalTag = ICALENDAR_ATTENDEE_CANCEL;
+ }
+ if (attendeeName != null) {
+ icalTag += ";CN=" + SimpleIcsWriter.quoteParamValue(attendeeName);
+ }
+ ics.writeTag(icalTag, "MAILTO:" + attendeeEmail);
+ toList.add(attendeeName == null ? new Address(attendeeEmail) :
+ new Address(attendeeEmail, attendeeName));
+ } else if (attendeeEmail.equalsIgnoreCase(account.mEmailAddress)) {
+ String icalTag = null;
+ switch (messageFlag) {
+ case Message.FLAG_OUTGOING_MEETING_ACCEPT:
+ icalTag = ICALENDAR_ATTENDEE_ACCEPT;
+ break;
+ case Message.FLAG_OUTGOING_MEETING_DECLINE:
+ icalTag = ICALENDAR_ATTENDEE_DECLINE;
+ break;
+ case Message.FLAG_OUTGOING_MEETING_TENTATIVE:
+ icalTag = ICALENDAR_ATTENDEE_TENTATIVE;
+ break;
+ }
+ if (icalTag != null) {
+ if (attendeeName != null) {
+ icalTag += ";CN="
+ + SimpleIcsWriter.quoteParamValue(attendeeName);
+ }
+ ics.writeTag(icalTag, "MAILTO:" + attendeeEmail);
+ }
+ }
+ }
+
+ /**
* Create a Message for an (Event) Entity
* @param entity the Entity for the Event (as might be retrieved by CalendarProvider)
* @param messageFlag the Message.FLAG_XXX constant indicating the type of email to be sent
@@ -1223,11 +1268,11 @@
static public EmailContent.Message createMessageForEntity(Context context, Entity entity,
int messageFlag, String uid, Account account) {
return createMessageForEntity(context, entity, messageFlag, uid, account,
- true /*requireAddressees*/);
+ null /*specifiedAttendee*/);
}
static public EmailContent.Message createMessageForEntity(Context context, Entity entity,
- int messageFlag, String uid, Account account, boolean requireAddressees) {
+ int messageFlag, String uid, Account account, String specifiedAttendee) {
ContentValues entityValues = entity.getEntityValues();
ArrayList<NamedContentValues> subValues = entity.getSubValues();
boolean isException = entityValues.containsKey(Events.ORIGINAL_EVENT);
@@ -1437,45 +1482,26 @@
}
String attendeeEmail = ncvValues.getAsString(Attendees.ATTENDEE_EMAIL);
String attendeeName = ncvValues.getAsString(Attendees.ATTENDEE_NAME);
+
// This shouldn't be possible, but allow for it
if (attendeeEmail == null) continue;
-
- if ((messageFlag & Message.FLAG_OUTGOING_MEETING_REQUEST_MASK) != 0) {
- String icalTag = ICALENDAR_ATTENDEE_INVITE;
- if ((messageFlag & Message.FLAG_OUTGOING_MEETING_CANCEL) != 0) {
- icalTag = ICALENDAR_ATTENDEE_CANCEL;
- }
- if (attendeeName != null) {
- icalTag += ";CN=" + SimpleIcsWriter.quoteParamValue(attendeeName);
- }
- ics.writeTag(icalTag, "MAILTO:" + attendeeEmail);
- toList.add(attendeeName == null ? new Address(attendeeEmail) :
- new Address(attendeeEmail, attendeeName));
- } else if (attendeeEmail.equalsIgnoreCase(account.mEmailAddress)) {
- String icalTag = null;
- switch (messageFlag) {
- case Message.FLAG_OUTGOING_MEETING_ACCEPT:
- icalTag = ICALENDAR_ATTENDEE_ACCEPT;
- break;
- case Message.FLAG_OUTGOING_MEETING_DECLINE:
- icalTag = ICALENDAR_ATTENDEE_DECLINE;
- break;
- case Message.FLAG_OUTGOING_MEETING_TENTATIVE:
- icalTag = ICALENDAR_ATTENDEE_TENTATIVE;
- break;
- }
- if (icalTag != null) {
- if (attendeeName != null) {
- icalTag += ";CN="
- + SimpleIcsWriter.quoteParamValue(attendeeName);
- }
- ics.writeTag(icalTag, "MAILTO:" + attendeeEmail);
- }
+ // If we only want to send to the specifiedAttendee, eliminate others here
+ if ((specifiedAttendee != null) &&
+ !attendeeEmail.equalsIgnoreCase(specifiedAttendee)) {
+ continue;
}
+
+ addAttendeeToMessage(ics, toList, attendeeName, attendeeEmail, messageFlag,
+ account);
}
}
}
+ // Manually add the specifiedAttendee if he wasn't added in the Attendees loop
+ if (toList.isEmpty() && (specifiedAttendee != null)) {
+ addAttendeeToMessage(ics, toList, null, specifiedAttendee, messageFlag, account);
+ }
+
// Create the organizer tag for ical
if (organizerEmail != null) {
String icalTag = "ORGANIZER";
@@ -1491,8 +1517,8 @@
}
}
- // If we have no "to" list and addressees are required (the default), we're done
- if (toList.isEmpty() && requireAddressees) return null;
+ // If we have no "to" list, we're done
+ if (toList.isEmpty()) return null;
// Write out the "to" list
Address[] toArray = new Address[toList.size()];
@@ -1547,11 +1573,11 @@
static public EmailContent.Message createMessageForEventId(Context context, long eventId,
int messageFlag, String uid, Account account) throws RemoteException {
return createMessageForEventId(context, eventId, messageFlag, uid, account,
- true /*requireAddressees*/);
+ null /*specifiedAttendee*/);
}
static public EmailContent.Message createMessageForEventId(Context context, long eventId,
- int messageFlag, String uid, Account account, boolean requireAddressees)
+ int messageFlag, String uid, Account account, String specifiedAttendee)
throws RemoteException {
ContentResolver cr = context.getContentResolver();
EntityIterator eventIterator =
@@ -1563,7 +1589,7 @@
while (eventIterator.hasNext()) {
Entity entity = eventIterator.next();
return createMessageForEntity(context, entity, messageFlag, uid, account,
- requireAddressees);
+ specifiedAttendee);
}
} finally {
eventIterator.close();