diff --git a/src/java/davmail/exchange/ews/EWSMethod.java b/src/java/davmail/exchange/ews/EWSMethod.java index 7d8c2b4b..287e276c 100644 --- a/src/java/davmail/exchange/ews/EWSMethod.java +++ b/src/java/davmail/exchange/ews/EWSMethod.java @@ -491,6 +491,7 @@ public abstract class EWSMethod extends PostMethod { protected List attendees; protected final List fieldNames = new ArrayList(); protected List occurrences; + protected ItemId referenceItemId; @Override public String toString() { @@ -524,6 +525,9 @@ public abstract class EWSMethod extends PostMethod { writer.write(new String(mimeContent)); writer.write(""); } + if (referenceItemId != null) { + referenceItemId.write(writer); + } // write ordered fields for (String key : fieldNames) { if ("MeetingTimeZone".equals(key)) { @@ -726,7 +730,7 @@ public abstract class EWSMethod extends PostMethod { */ public Item getResponseItem() throws EWSException { checkSuccess(); - if (responseItems != null && responseItems.size() == 1) { + if (responseItems != null && responseItems.size() > 0) { return responseItems.get(0); } else { return null; @@ -871,6 +875,18 @@ public abstract class EWSMethod extends PostMethod { } } } + + public static String responseTypeToPartstat(String responseType) { + if ("Accept".equals(responseType)) { + return "ACCEPTED"; + } else if ("Tentative".equals(responseType)) { + return "TENTATIVE"; + } else if ("Decline".equals(responseType)) { + return "DECLINED"; + } else { + return "NEEDS-ACTION"; + } + } protected void handleAttendee(XMLStreamReader reader, Item item, String attendeeType) throws XMLStreamException { Attendee attendee = new Attendee(); @@ -889,15 +905,7 @@ public abstract class EWSMethod extends PostMethod { attendee.name = XMLStreamUtil.getElementText(reader); } else if ("ResponseType".equals(tagLocalName)) { String responseType = XMLStreamUtil.getElementText(reader); - if ("Accept".equals(responseType)) { - attendee.partstat = "ACCEPTED"; - } else if ("Tentative".equals(responseType)) { - attendee.partstat = "TENTATIVE"; - } else if ("Decline".equals(responseType)) { - attendee.partstat = "DECLINED"; - } else { - attendee.partstat = "NEEDS-ACTION"; - } + attendee.partstat = responseTypeToPartstat(responseType); } } } diff --git a/src/java/davmail/exchange/ews/EwsExchangeSession.java b/src/java/davmail/exchange/ews/EwsExchangeSession.java index 9fd238e4..c6ed22ed 100644 --- a/src/java/davmail/exchange/ews/EwsExchangeSession.java +++ b/src/java/davmail/exchange/ews/EwsExchangeSession.java @@ -38,6 +38,7 @@ import org.apache.commons.httpclient.params.HttpClientParams; import javax.mail.MessagingException; import javax.mail.Session; +import javax.mail.internet.InternetAddress; import javax.mail.internet.MimeMessage; import javax.mail.util.SharedByteArrayInputStream; import java.io.BufferedReader; @@ -1292,6 +1293,8 @@ public class EwsExchangeSession extends ExchangeSession { // first try to load existing event String currentEtag = null; ItemId currentItemId = null; + String ownerResponseReply = null; + EWSMethod.Item currentItem = getEwsItem(folderPath, itemName); if (currentItem != null) { currentItemId = new ItemId(currentItem); @@ -1381,8 +1384,12 @@ public class EwsExchangeSession extends ExchangeSession { //updates.add(Field.createFieldUpdate("outlookmessageclass", "IPM.Appointment")); // force urlcompname updates.add(Field.createFieldUpdate("urlcompname", convertItemNameToEML(itemName))); - if (vCalendar.isMeeting() && vCalendar.isMeetingOrganizer()) { - updates.add(Field.createFieldUpdate("apptstateflags", "1")); + if (vCalendar.isMeeting()) { + if (vCalendar.isMeetingOrganizer()) { + updates.add(Field.createFieldUpdate("apptstateflags", "1")); + } else { + updates.add(Field.createFieldUpdate("apptstateflags", "3")); + } } else { updates.add(Field.createFieldUpdate("apptstateflags", "0")); } @@ -1409,16 +1416,24 @@ public class EwsExchangeSession extends ExchangeSession { for (VProperty property : attendeeProperties) { String attendeeEmail = vCalendar.getEmailValue(property); if (attendeeEmail != null && attendeeEmail.indexOf('@') >= 0) { - EWSMethod.Attendee attendee = new EWSMethod.Attendee(); - attendee.email = attendeeEmail; - attendee.name = property.getParamValue("CN"); + if (email.equals(attendeeEmail)) { + String ownerPartStat = property.getParamValue("PARTSTAT"); + if ("ACCEPTED".equals(ownerPartStat)) { + ownerResponseReply = "AcceptItem"; + // do not send DeclineItem to avoid deleting target event + //} else if ("DECLINED".equals(ownerPartStat)) { + // ownerResponseReply = "DeclineItem"; + } else if ("TENTATIVE".equals(ownerPartStat)) { + ownerResponseReply = "TentativelyAcceptItem"; + } + } + InternetAddress internetAddress = new InternetAddress(attendeeEmail, property.getParamValue("CN")); String attendeeRole = property.getParamValue("ROLE"); if ("REQ-PARTICIPANT".equals(attendeeRole)) { - requiredAttendees.add(attendeeEmail); + requiredAttendees.add(internetAddress.toString()); } else { - optionalAttendees.add(attendeeEmail); + optionalAttendees.add(internetAddress.toString()); } - newItem.addAttendee(attendee); } } } @@ -1474,6 +1489,25 @@ public class EwsExchangeSession extends ExchangeSession { } } + // force responsetype on Exchange 2007 + if (ownerResponseReply != null) { + EWSMethod.Item responseTypeItem = new EWSMethod.Item(); + responseTypeItem.referenceItemId = new ItemId("ReferenceItemId", createOrUpdateItemMethod.getResponseItem()); + responseTypeItem.type = ownerResponseReply; + createOrUpdateItemMethod = new CreateItemMethod(MessageDisposition.SaveOnly, SendMeetingInvitations.SendToNone, null, responseTypeItem); + executeMethod(createOrUpdateItemMethod); + + // force urlcompname again + ArrayList updates = new ArrayList(); + updates.add(Field.createFieldUpdate("urlcompname", convertItemNameToEML(itemName))); + createOrUpdateItemMethod = new UpdateItemMethod(MessageDisposition.SaveOnly, + ConflictResolution.AlwaysOverwrite, + SendMeetingInvitationsOrCancellations.SendToNone, + new ItemId(createOrUpdateItemMethod.getResponseItem()), + updates); + executeMethod(createOrUpdateItemMethod); + } + ItemId newItemId = new ItemId(createOrUpdateItemMethod.getResponseItem()); GetItemMethod getItemMethod = new GetItemMethod(BaseShape.ID_ONLY, newItemId, false); getItemMethod.addAdditionalProperty(Field.get("etag")); @@ -1510,6 +1544,7 @@ public class EwsExchangeSession extends ExchangeSession { getItemMethod = new GetItemMethod(BaseShape.ID_ONLY, itemId, true); getItemMethod.addAdditionalProperty(Field.get("reminderset")); getItemMethod.addAdditionalProperty(Field.get("calendaruid")); + getItemMethod.addAdditionalProperty(Field.get("myresponsetype")); getItemMethod.addAdditionalProperty(Field.get("requiredattendees")); getItemMethod.addAdditionalProperty(Field.get("optionalattendees")); getItemMethod.addAdditionalProperty(Field.get("modifiedoccurrences")); @@ -1570,7 +1605,12 @@ public class EwsExchangeSession extends ExchangeSession { for (EWSMethod.Attendee attendee : attendees) { VProperty attendeeProperty = new VProperty("ATTENDEE", "mailto:" + attendee.email); attendeeProperty.addParam("CN", attendee.name); - attendeeProperty.addParam("PARTSTAT", attendee.partstat); + String myResponseType = getItemMethod.getResponseItem().get(Field.get("myresponsetype").getResponseName()); + if ("Exchange2007_SP1".equals(serverVersion) && email.equalsIgnoreCase(attendee.email) && myResponseType != null) { + attendeeProperty.addParam("PARTSTAT", EWSMethod.responseTypeToPartstat(myResponseType)); + } else { + attendeeProperty.addParam("PARTSTAT", attendee.partstat); + } //attendeeProperty.addParam("RSVP", "TRUE"); attendeeProperty.addParam("ROLE", attendee.role); localVCalendar.addFirstVeventProperty(attendeeProperty); diff --git a/src/java/davmail/exchange/ews/Field.java b/src/java/davmail/exchange/ews/Field.java index f0014867..1893e86b 100644 --- a/src/java/davmail/exchange/ews/Field.java +++ b/src/java/davmail/exchange/ews/Field.java @@ -196,6 +196,7 @@ public final class Field { FIELD_MAP.put("ismeeting", new UnindexedFieldURI("item:IsMeeting")); FIELD_MAP.put("apptstateflags", new ExtendedFieldURI(ExtendedFieldURI.DistinguishedPropertySetType.Appointment, 0x8217, ExtendedFieldURI.PropertyType.Integer)); // PidLidAppointmentStateFlags 1: Meeting, 2: Received, 4: Cancelled FIELD_MAP.put("appointmentstate", new UnindexedFieldURI("calendar:AppointmentState")); + FIELD_MAP.put("myresponsetype", new UnindexedFieldURI("calendar:MyResponseType")); FIELD_MAP.put("calendaruid", new ExtendedFieldURI(ExtendedFieldURI.DistinguishedPropertySetType.PublicStrings, "urn:schemas:calendar:uid", ExtendedFieldURI.PropertyType.String)); FIELD_MAP.put("meetingtimezone", new UnindexedFieldURI("calendar:MeetingTimeZone")); diff --git a/src/java/davmail/exchange/ews/ItemId.java b/src/java/davmail/exchange/ews/ItemId.java index fe41e804..86c3d9aa 100644 --- a/src/java/davmail/exchange/ews/ItemId.java +++ b/src/java/davmail/exchange/ews/ItemId.java @@ -25,6 +25,7 @@ import java.io.Writer; * Item id. */ public class ItemId { + protected final String name; protected final String id; protected final String changeKey; @@ -34,6 +35,25 @@ public class ItemId { * @param item response item */ public ItemId(EWSMethod.Item item) { + this("ItemId", item); + } + + /** + * Build Item id object from item id. + * + * @param itemId item id + */ + public ItemId(String itemId) { + this("ItemId", itemId); + } + + /** + * Build Item id from response item. + * + * @param item response item + */ + public ItemId(String name, EWSMethod.Item item) { + this.name = name; this.id = item.get("ItemId"); this.changeKey = item.get("ChangeKey"); } @@ -43,7 +63,8 @@ public class ItemId { * * @param itemId item id */ - public ItemId(String itemId) { + public ItemId(String name, String itemId) { + this.name = name; this.id = itemId; this.changeKey = null; } @@ -55,7 +76,9 @@ public class ItemId { * @throws IOException on error */ public void write(Writer writer) throws IOException { - writer.write("