Repository: james-project Updated Branches: refs/heads/master 5d5e3732d -> 7c7fb76db
MAILET-146 Add a mailet to attach a parsed Calendar to mail HEADERs Project: http://git-wip-us.apache.org/repos/asf/james-project/repo Commit: http://git-wip-us.apache.org/repos/asf/james-project/commit/3bdeb527 Tree: http://git-wip-us.apache.org/repos/asf/james-project/tree/3bdeb527 Diff: http://git-wip-us.apache.org/repos/asf/james-project/diff/3bdeb527 Branch: refs/heads/master Commit: 3bdeb527e1f639755dbb0dfd13535bd42d07134c Parents: 8256ad1 Author: Benoit Tellier <btell...@linagora.com> Authored: Fri Jan 13 15:24:03 2017 +0700 Committer: Benoit Tellier <btell...@linagora.com> Committed: Wed Jan 18 17:12:31 2017 +0700 ---------------------------------------------------------------------- .gitattributes | 1 + mailet/icalendar/pom.xml | 5 + .../james/transport/mailets/ICALToHeader.java | 129 ++++++++++++ .../transport/mailets/ICALToHeadersTest.java | 210 +++++++++++++++++++ .../src/test/resources/ics/meeting.ics | 44 ++++ .../src/test/resources/ics/meeting_2.ics | 31 +++ .../resources/ics/meeting_without_dtstamp.ics | 43 ++++ 7 files changed, 463 insertions(+) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/james-project/blob/3bdeb527/.gitattributes ---------------------------------------------------------------------- diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 0000000..68ee809 --- /dev/null +++ b/.gitattributes @@ -0,0 +1 @@ +*.ics eol=crlf \ No newline at end of file http://git-wip-us.apache.org/repos/asf/james-project/blob/3bdeb527/mailet/icalendar/pom.xml ---------------------------------------------------------------------- diff --git a/mailet/icalendar/pom.xml b/mailet/icalendar/pom.xml index 457db1f..e64a33b 100644 --- a/mailet/icalendar/pom.xml +++ b/mailet/icalendar/pom.xml @@ -163,6 +163,11 @@ <scope>test</scope> </dependency> <dependency> + <groupId>com.github.fge</groupId> + <artifactId>throwing-lambdas</artifactId> + <version>0.5.0</version> + </dependency> + <dependency> <groupId>com.google.guava</groupId> <artifactId>guava</artifactId> </dependency> http://git-wip-us.apache.org/repos/asf/james-project/blob/3bdeb527/mailet/icalendar/src/main/java/org/apache/james/transport/mailets/ICALToHeader.java ---------------------------------------------------------------------- diff --git a/mailet/icalendar/src/main/java/org/apache/james/transport/mailets/ICALToHeader.java b/mailet/icalendar/src/main/java/org/apache/james/transport/mailets/ICALToHeader.java new file mode 100644 index 0000000..82b2597 --- /dev/null +++ b/mailet/icalendar/src/main/java/org/apache/james/transport/mailets/ICALToHeader.java @@ -0,0 +1,129 @@ +/**************************************************************** + * Licensed to the Apache Software Foundation (ASF) under one * + * or more contributor license agreements. See the NOTICE file * + * distributed with this work for additional information * + * regarding copyright ownership. The ASF licenses this file * + * to you under the Apache License, Version 2.0 (the * + * "License"); you may not use this file except in compliance * + * with the License. You may obtain a copy of the License at * + * * + * http://www.apache.org/licenses/LICENSE-2.0 * + * * + * Unless required by applicable law or agreed to in writing, * + * software distributed under the License is distributed on an * + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * + * KIND, either express or implied. See the License for the * + * specific language governing permissions and limitations * + * under the License. * + ****************************************************************/ + +package org.apache.james.transport.mailets; + +import java.util.Map; + +import javax.mail.MessagingException; +import javax.mail.internet.MimeMessage; + +import org.apache.mailet.Mail; +import org.apache.mailet.base.GenericMailet; + +import com.github.fge.lambdas.Throwing; +import com.google.common.annotations.VisibleForTesting; +import com.google.common.base.Strings; + +import net.fortuna.ical4j.model.Calendar; +import net.fortuna.ical4j.model.Property; +import net.fortuna.ical4j.model.component.VEvent; + +/** + * ICALToHeader takes a Map of filenames to ICAL4J calendars, will pick the first Calendar, + * and add it to the headers of the e-mail. + * + * The following headers will be added : X_MEETING_UID, X_MEETING_METHOD, X_MEETING_RECURRENCE_ID, X_MEETING_SEQUENCE, + * X_MEETING_DTSTAMP + * + * The only configuration parameter for this mailet is the attribute the ICAL4J Calendar map should be attached to, + * named <b>attribute</b>. + * + * Configuration example : + * + * <pre> + * <code> + * <mailet matcher=??? class=ICALToHeader> + * <attribute>icalendars</attribute> + * </mailet> + * </code> + * </pre> + */ +public class ICALToHeader extends GenericMailet { + public static final String ATTRIBUTE_PROPERTY = "attribute"; + public static final String ATTRIBUTE_DEFAULT_NAME = "icalendar"; + + public static final String X_MEETING_UID_HEADER = "X-MEETING-UID"; + public static final String X_MEETING_METHOD_HEADER = "X-MEETING-METHOD"; + public static final String X_MEETING_RECURRENCE_ID_HEADER = "X-MEETING-RECURRENCE-ID"; + public static final String X_MEETING_SEQUENCE_HEADER = "X-MEETING-SEQUENCE"; + public static final String X_MEETING_DTSTAMP_HEADER = "X-MEETING-DTSTAMP"; + + private String attribute; + + @Override + public String getMailetInfo() { + return "ICALToHeader Mailet"; + } + + @Override + public void init() throws MessagingException { + attribute = getInitParameter(ATTRIBUTE_PROPERTY, ATTRIBUTE_DEFAULT_NAME); + if (Strings.isNullOrEmpty(attribute)) { + throw new MessagingException("Attribute " + attribute + " can not be empty or null"); + } + } + + @Override + public void service(Mail mail) throws MessagingException { + if (mail.getAttribute(attribute) == null) { + return; + } + try { + getCalendarMap(mail) + .values() + .stream() + .findAny() + .ifPresent(Throwing.<Calendar>consumer(calendar -> writeToHeaders(calendar, mail)) + .sneakyThrow()); + } catch (ClassCastException e) { + log("Received a mail with " + attribute + " not being an ICAL object for mail " + mail.getName()); + } + } + + @VisibleForTesting + String getAttribute() { + return attribute; + } + + @SuppressWarnings("unchecked") + private Map<String, Calendar> getCalendarMap(Mail mail) { + return (Map<String, Calendar>) mail.getAttribute(attribute); + } + + private void writeToHeaders(Calendar calendar, Mail mail) throws MessagingException { + MimeMessage mimeMessage = mail.getMessage(); + VEvent vevent = (VEvent) calendar.getComponent("VEVENT"); + addIfPresent(mimeMessage, X_MEETING_METHOD_HEADER, calendar.getMethod()); + addIfPresent(mimeMessage, X_MEETING_UID_HEADER, vevent.getUid()); + addIfPresent(mimeMessage, X_MEETING_RECURRENCE_ID_HEADER, vevent.getRecurrenceId()); + addIfPresent(mimeMessage, X_MEETING_SEQUENCE_HEADER, vevent.getSequence()); + addIfPresent(mimeMessage, X_MEETING_DTSTAMP_HEADER, vevent.getDateStamp()); + } + + private void addIfPresent(MimeMessage mimeMessage, String headerName, Property property) { + if (property != null) { + try { + mimeMessage.addHeader(headerName, property.getValue()); + } catch (MessagingException e) { + log("Could not add header " + headerName + " with value " + property.getValue(), e); + } + } + } +} http://git-wip-us.apache.org/repos/asf/james-project/blob/3bdeb527/mailet/icalendar/src/test/java/org/apache/james/transport/mailets/ICALToHeadersTest.java ---------------------------------------------------------------------- diff --git a/mailet/icalendar/src/test/java/org/apache/james/transport/mailets/ICALToHeadersTest.java b/mailet/icalendar/src/test/java/org/apache/james/transport/mailets/ICALToHeadersTest.java new file mode 100644 index 0000000..924817a --- /dev/null +++ b/mailet/icalendar/src/test/java/org/apache/james/transport/mailets/ICALToHeadersTest.java @@ -0,0 +1,210 @@ +/**************************************************************** + * Licensed to the Apache Software Foundation (ASF) under one * + * or more contributor license agreements. See the NOTICE file * + * distributed with this work for additional information * + * regarding copyright ownership. The ASF licenses this file * + * to you under the Apache License, Version 2.0 (the * + * "License"); you may not use this file except in compliance * + * with the License. You may obtain a copy of the License at * + * * + * http://www.apache.org/licenses/LICENSE-2.0 * + * * + * Unless required by applicable law or agreed to in writing, * + * software distributed under the License is distributed on an * + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * + * KIND, either express or implied. See the License for the * + * specific language governing permissions and limitations * + * under the License. * + ****************************************************************/ + +package org.apache.james.transport.mailets; + +import static org.assertj.core.api.Assertions.assertThat; + +import javax.mail.MessagingException; + +import org.apache.mailet.Mail; +import org.apache.mailet.base.test.FakeMail; +import org.apache.mailet.base.test.FakeMailetConfig; +import org.apache.mailet.base.test.MimeMessageBuilder; +import org.junit.Before; +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.ExpectedException; + +import com.google.common.collect.ImmutableMap; + +import net.fortuna.ical4j.data.CalendarBuilder; +import net.fortuna.ical4j.model.Calendar; + +public class ICALToHeadersTest { + + @Rule + public ExpectedException expectedException = ExpectedException.none(); + + private ICALToHeader testee; + + @Before + public void setUp() { + testee = new ICALToHeader(); + } + + @Test + public void getMailetInfoShouldReturnExpectedValue() { + assertThat(testee.getMailetInfo()).isEqualTo("ICALToHeader Mailet"); + } + + @Test + public void initShouldSetAttributeWhenAbsent() throws Exception { + testee.init(FakeMailetConfig.builder() + .mailetName("ICALToHeader") + .build()); + + assertThat(testee.getAttribute()).isEqualTo(ICALToHeader.ATTRIBUTE_DEFAULT_NAME); + } + + @Test + public void initShouldSetAttributeWhenPresent() throws Exception { + String attribute = "attribute"; + testee.init(FakeMailetConfig.builder() + .mailetName("ICALToHeader") + .setProperty(ICALToHeader.ATTRIBUTE_PROPERTY, attribute) + .build()); + + assertThat(testee.getAttribute()).isEqualTo(attribute); + } + + @Test + public void initShouldThrowOnEmptyAttribute() throws Exception { + expectedException.expect(MessagingException.class); + + testee.init(FakeMailetConfig.builder() + .mailetName("ICALToHeader") + .setProperty(ICALToHeader.ATTRIBUTE_PROPERTY, "") + .build()); + } + + @Test + public void serviceShouldNotModifyMailsWithoutIcalAttribute() throws Exception { + testee.init(FakeMailetConfig.builder().build()); + Mail mail = FakeMail.builder() + .mimeMessage(MimeMessageBuilder.defaultMimeMessage()) + .build(); + + testee.service(mail); + + assertThat(mail.getMessage().getHeader(ICALToHeader.X_MEETING_UID_HEADER)).isNull(); + } + + @Test + public void serviceShouldNotFailOnMailsWithWrongAttributeType() throws Exception { + testee.init(FakeMailetConfig.builder().build()); + Mail mail = FakeMail.builder() + .mimeMessage(MimeMessageBuilder.defaultMimeMessage()) + .attribute(ICALToHeader.ATTRIBUTE_DEFAULT_NAME, "This is the wrong type") + .build(); + + testee.service(mail); + + assertThat(mail.getMessage().getHeader(ICALToHeader.X_MEETING_UID_HEADER)).isNull(); + } + + @Test + public void serviceShouldNotFailOnMailsWithWrongParametrizedAttribute() throws Exception { + ImmutableMap<String, String> wrongParametrizedMap = ImmutableMap.<String, String>builder() + .put("key", "value") + .build(); + + testee.init(FakeMailetConfig.builder().build()); + Mail mail = FakeMail.builder() + .mimeMessage(MimeMessageBuilder.defaultMimeMessage()) + .attribute(ICALToHeader.ATTRIBUTE_DEFAULT_NAME, wrongParametrizedMap) + .build(); + + testee.service(mail); + + assertThat(mail.getMessage().getHeader(ICALToHeader.X_MEETING_UID_HEADER)).isNull(); + } + + @Test + public void serviceShouldWriteSingleICalendarToHeaders() throws Exception { + Calendar calendar = new CalendarBuilder().build(ClassLoader.getSystemResourceAsStream("ics/meeting.ics")); + ImmutableMap<String, Calendar> icals = ImmutableMap.<String, Calendar>builder() + .put("key", calendar) + .build(); + + testee.init(FakeMailetConfig.builder().build()); + Mail mail = FakeMail.builder() + .mimeMessage(MimeMessageBuilder.defaultMimeMessage()) + .attribute(ICALToHeader.ATTRIBUTE_DEFAULT_NAME, icals) + .build(); + + testee.service(mail); + + assertThat(mail.getMessage().getHeader(ICALToHeader.X_MEETING_METHOD_HEADER)).containsOnly("REQUEST"); + assertThat(mail.getMessage().getHeader(ICALToHeader.X_MEETING_UID_HEADER)) + .containsOnly("f1514f44bf39311568d640727cff54e819573448d09d2e5677987ff29caa01a9e047feb2aab16e43439a608f28671ab7c10e754ce92be513f8e04ae9ff15e65a9819cf285a6962bc"); + assertThat(mail.getMessage().getHeader(ICALToHeader.X_MEETING_DTSTAMP_HEADER)).containsOnly("20170106T115036Z"); + assertThat(mail.getMessage().getHeader(ICALToHeader.X_MEETING_RECURRENCE_ID_HEADER)).isNull(); + assertThat(mail.getMessage().getHeader(ICALToHeader.X_MEETING_SEQUENCE_HEADER)).containsOnly("0"); + } + + @Test + public void serviceShouldNotWriteHeaderWhenPropertyIsAbsent() throws Exception { + Calendar calendar = new CalendarBuilder().build(ClassLoader.getSystemResourceAsStream("ics/meeting_without_dtstamp.ics")); + ImmutableMap<String, Calendar> icals = ImmutableMap.<String, Calendar>builder() + .put("key", calendar) + .build(); + + testee.init(FakeMailetConfig.builder().build()); + Mail mail = FakeMail.builder() + .mimeMessage(MimeMessageBuilder.defaultMimeMessage()) + .attribute(ICALToHeader.ATTRIBUTE_DEFAULT_NAME, icals) + .build(); + + testee.service(mail); + + assertThat(mail.getMessage().getHeader(ICALToHeader.X_MEETING_METHOD_HEADER)).containsOnly("REQUEST"); + assertThat(mail.getMessage().getHeader(ICALToHeader.X_MEETING_UID_HEADER)) + .containsOnly("f1514f44bf39311568d640727cff54e819573448d09d2e5677987ff29caa01a9e047feb2aab16e43439a608f28671ab7c10e754ce92be513f8e04ae9ff15e65a9819cf285a6962bc"); + assertThat(mail.getMessage().getHeader(ICALToHeader.X_MEETING_DTSTAMP_HEADER)).isNull(); + assertThat(mail.getMessage().getHeader(ICALToHeader.X_MEETING_RECURRENCE_ID_HEADER)).isNull(); + assertThat(mail.getMessage().getHeader(ICALToHeader.X_MEETING_SEQUENCE_HEADER)).containsOnly("0"); + } + + @Test + public void serviceShouldWriteOnlyOneICalendarToHeaders() throws Exception { + Calendar calendar = new CalendarBuilder().build(ClassLoader.getSystemResourceAsStream("ics/meeting.ics")); + Calendar calendar2 = new CalendarBuilder().build(ClassLoader.getSystemResourceAsStream("ics/meeting_2.ics")); + ImmutableMap<String, Calendar> icals = ImmutableMap.<String, Calendar>builder() + .put("key", calendar) + .put("key2", calendar2) + .build(); + + testee.init(FakeMailetConfig.builder().build()); + Mail mail = FakeMail.builder() + .mimeMessage(MimeMessageBuilder.defaultMimeMessage()) + .attribute(ICALToHeader.ATTRIBUTE_DEFAULT_NAME, icals) + .build(); + + testee.service(mail); + + assertThat(mail.getMessage().getHeader(ICALToHeader.X_MEETING_UID_HEADER)).hasSize(1); + } + + @Test + public void serviceShouldNotFailOnEmptyMaps() throws Exception { + ImmutableMap<String, Calendar> icals = ImmutableMap.<String, Calendar>builder() + .build(); + + testee.init(FakeMailetConfig.builder().build()); + Mail mail = FakeMail.builder() + .mimeMessage(MimeMessageBuilder.defaultMimeMessage()) + .attribute(ICALToHeader.ATTRIBUTE_DEFAULT_NAME, icals) + .build(); + + testee.service(mail); + + assertThat(mail.getMessage().getHeader(ICALToHeader.X_MEETING_UID_HEADER)).isNull(); + } +} http://git-wip-us.apache.org/repos/asf/james-project/blob/3bdeb527/mailet/icalendar/src/test/resources/ics/meeting.ics ---------------------------------------------------------------------- diff --git a/mailet/icalendar/src/test/resources/ics/meeting.ics b/mailet/icalendar/src/test/resources/ics/meeting.ics new file mode 100644 index 0000000..ad46f3b --- /dev/null +++ b/mailet/icalendar/src/test/resources/ics/meeting.ics @@ -0,0 +1,44 @@ +BEGIN:VCALENDAR +PRODID:-//Aliasource Groupe LINAGORA//OBM Calendar 3.2.1-rc2//FR +CALSCALE:GREGORIAN +X-OBM-TIME:1483703436 +VERSION:2.0 +METHOD:REQUEST +BEGIN:VEVENT +CREATED:20170106T115035Z +LAST-MODIFIED:20170106T115036Z +DTSTAMP:20170106T115036Z +DTSTART:20170111T090000Z +DURATION:PT1H30M +TRANSP:OPAQUE +SEQUENCE:0 +SUMMARY:Sprint planning #23 +DESCRIPTION: +CLASS:PUBLIC +PRIORITY:5 +ORGANIZER;X-OBM-ID=128;CN=Raphael OUAZANA:MAILTO:ouaz...@linagora.com +X-OBM-DOMAIN:linagora.com +X-OBM-DOMAIN-UUID:02874f7c-d10e-102f-acda-0015176f7922 +LOCATION:Hangout +CATEGORIES: +X-OBM-COLOR: +UID:f1514f44bf39311568d640727cff54e819573448d09d2e5677987ff29caa01a9e047fe + b2aab16e43439a608f28671ab7c10e754ce92be513f8e04ae9ff15e65a9819cf285a6962bc +ATTENDEE;CUTYPE=INDIVIDUAL;RSVP=TRUE;CN=Matthieu EXT_BAECHLER;PARTSTAT=NEE + DS-ACTION;X-OBM-ID=302:MAILTO:baech...@linagora.com +ATTENDEE;CUTYPE=INDIVIDUAL;RSVP=TRUE;CN=Laura ROYET;PARTSTAT=NEEDS-ACTION; + X-OBM-ID=723:MAILTO:ro...@linagora.com +ATTENDEE;CUTYPE=INDIVIDUAL;RSVP=TRUE;CN=Raphael OUAZANA;PARTSTAT=ACCEPTED; + X-OBM-ID=128:MAILTO:ouaz...@linagora.com +ATTENDEE;CUTYPE=INDIVIDUAL;RSVP=TRUE;CN=Luc DUZAN;PARTSTAT=NEEDS-ACTION;X- + OBM-ID=715:MAILTO:du...@linagora.com +ATTENDEE;CUTYPE=RESOURCE;CN=Salle de reunion Lyon;PARTSTAT=ACCEPTED;X-OBM- + ID=66:MAILTO:nore...@linagora.com +ATTENDEE;CUTYPE=INDIVIDUAL;RSVP=TRUE;CN=Antoine DUPRAT;PARTSTAT=NEEDS-ACTI + ON;X-OBM-ID=453:MAILTO:dup...@linagora.com +ATTENDEE;CUTYPE=INDIVIDUAL;RSVP=TRUE;CN=Benoît TELLIER;PARTSTAT=NEEDS-ACTI + ON;X-OBM-ID=623:MAILTO:tell...@linagora.com +ATTENDEE;CUTYPE=INDIVIDUAL;RSVP=TRUE;CN=Quynh Quynh N NGUYEN;PARTSTAT=NEED + S-ACTION;X-OBM-ID=769:MAILTO:ngu...@linagora.com +END:VEVENT +END:VCALENDAR http://git-wip-us.apache.org/repos/asf/james-project/blob/3bdeb527/mailet/icalendar/src/test/resources/ics/meeting_2.ics ---------------------------------------------------------------------- diff --git a/mailet/icalendar/src/test/resources/ics/meeting_2.ics b/mailet/icalendar/src/test/resources/ics/meeting_2.ics new file mode 100644 index 0000000..1a51add --- /dev/null +++ b/mailet/icalendar/src/test/resources/ics/meeting_2.ics @@ -0,0 +1,31 @@ +BEGIN:VCALENDAR +PRODID:-//Aliasource Groupe LINAGORA//OBM Calendar 3.2.1-rc2//FR +CALSCALE:GREGORIAN +X-OBM-TIME:1483439571 +VERSION:2.0 +METHOD:REQUEST +BEGIN:VEVENT +CREATED:20170103T103250Z +LAST-MODIFIED:20170103T103250Z +DTSTAMP:20170103T103250Z +DTSTART:20170120T100000Z +DURATION:PT30M +TRANSP:OPAQUE +SEQUENCE:0 +SUMMARY:Sprint Social #3 Demo +DESCRIPTION: +CLASS:PUBLIC +PRIORITY:5 +ORGANIZER;X-OBM-ID=468;CN=Attendee 1:MAILTO:attendee1@linagora. + com +X-OBM-DOMAIN:linagora.com +X-OBM-DOMAIN-UUID:02874f7c-d10e-102f-acda-0015176f7922 +LOCATION:hangout +CATEGORIES: +X-OBM-COLOR: +UID:f1514f44bf39311568d64072ac247c17656ceafde3b4b3eba961c8c5184cdc6ee047fe + b2aab16e43439a608f28671ab7c10e754c301b1e32001ad51dd20eac2fc7af20abf4093bbe +ATTENDEE;CUTYPE=INDIVIDUAL;RSVP=TRUE;CN=Attendee 2;PARTSTAT=NEEDS-ACTI + ON;X-OBM-ID=348:MAILTO:attend...@linagora.com +END:VEVENT +END:VCALENDAR http://git-wip-us.apache.org/repos/asf/james-project/blob/3bdeb527/mailet/icalendar/src/test/resources/ics/meeting_without_dtstamp.ics ---------------------------------------------------------------------- diff --git a/mailet/icalendar/src/test/resources/ics/meeting_without_dtstamp.ics b/mailet/icalendar/src/test/resources/ics/meeting_without_dtstamp.ics new file mode 100644 index 0000000..7f52920 --- /dev/null +++ b/mailet/icalendar/src/test/resources/ics/meeting_without_dtstamp.ics @@ -0,0 +1,43 @@ +BEGIN:VCALENDAR +PRODID:-//Aliasource Groupe LINAGORA//OBM Calendar 3.2.1-rc2//FR +CALSCALE:GREGORIAN +X-OBM-TIME:1483703436 +VERSION:2.0 +METHOD:REQUEST +BEGIN:VEVENT +CREATED:20170106T115035Z +LAST-MODIFIED:20170106T115036Z +DTSTART:20170111T090000Z +DURATION:PT1H30M +TRANSP:OPAQUE +SEQUENCE:0 +SUMMARY:Sprint planning #23 +DESCRIPTION: +CLASS:PUBLIC +PRIORITY:5 +ORGANIZER;X-OBM-ID=128;CN=Raphael OUAZANA:MAILTO:ouaz...@linagora.com +X-OBM-DOMAIN:linagora.com +X-OBM-DOMAIN-UUID:02874f7c-d10e-102f-acda-0015176f7922 +LOCATION:Hangout +CATEGORIES: +X-OBM-COLOR: +UID:f1514f44bf39311568d640727cff54e819573448d09d2e5677987ff29caa01a9e047fe + b2aab16e43439a608f28671ab7c10e754ce92be513f8e04ae9ff15e65a9819cf285a6962bc +ATTENDEE;CUTYPE=INDIVIDUAL;RSVP=TRUE;CN=Matthieu EXT_BAECHLER;PARTSTAT=NEE + DS-ACTION;X-OBM-ID=302:MAILTO:baech...@linagora.com +ATTENDEE;CUTYPE=INDIVIDUAL;RSVP=TRUE;CN=Laura ROYET;PARTSTAT=NEEDS-ACTION; + X-OBM-ID=723:MAILTO:ro...@linagora.com +ATTENDEE;CUTYPE=INDIVIDUAL;RSVP=TRUE;CN=Raphael OUAZANA;PARTSTAT=ACCEPTED; + X-OBM-ID=128:MAILTO:ouaz...@linagora.com +ATTENDEE;CUTYPE=INDIVIDUAL;RSVP=TRUE;CN=Luc DUZAN;PARTSTAT=NEEDS-ACTION;X- + OBM-ID=715:MAILTO:du...@linagora.com +ATTENDEE;CUTYPE=RESOURCE;CN=Salle de reunion Lyon;PARTSTAT=ACCEPTED;X-OBM- + ID=66:MAILTO:nore...@linagora.com +ATTENDEE;CUTYPE=INDIVIDUAL;RSVP=TRUE;CN=Antoine DUPRAT;PARTSTAT=NEEDS-ACTI + ON;X-OBM-ID=453:MAILTO:dup...@linagora.com +ATTENDEE;CUTYPE=INDIVIDUAL;RSVP=TRUE;CN=Benoît TELLIER;PARTSTAT=NEEDS-ACTI + ON;X-OBM-ID=623:MAILTO:tell...@linagora.com +ATTENDEE;CUTYPE=INDIVIDUAL;RSVP=TRUE;CN=Quynh Quynh N NGUYEN;PARTSTAT=NEED + S-ACTION;X-OBM-ID=769:MAILTO:ngu...@linagora.com +END:VEVENT +END:VCALENDAR --------------------------------------------------------------------- To unsubscribe, e-mail: server-dev-unsubscr...@james.apache.org For additional commands, e-mail: server-dev-h...@james.apache.org