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>
+ *         &lt;mailet matcher=??? class=ICALToHeader&gt;
+ *             &lt;attribute&gt;icalendars&lt;/attribute&gt;
+ *         &lt;/mailet&gt;
+ *     </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

Reply via email to