MAILET-148 Create mailet to transform map of ICAL to list of JSONs
Project: http://git-wip-us.apache.org/repos/asf/james-project/repo Commit: http://git-wip-us.apache.org/repos/asf/james-project/commit/cb844422 Tree: http://git-wip-us.apache.org/repos/asf/james-project/tree/cb844422 Diff: http://git-wip-us.apache.org/repos/asf/james-project/diff/cb844422 Branch: refs/heads/master Commit: cb844422302e735d43bff0d9ab51aedf39ce7d97 Parents: 3bdeb52 Author: Benoit Tellier <btell...@linagora.com> Authored: Mon Jan 16 10:00:40 2017 +0700 Committer: Benoit Tellier <btell...@linagora.com> Committed: Wed Jan 18 17:39:45 2017 +0700 ---------------------------------------------------------------------- mailet/icalendar/pom.xml | 33 ++ .../transport/mailets/ICALToJsonAttribute.java | 174 ++++++++ .../james/transport/mailets/model/ICAL.java | 163 ++++++++ .../mailets/ICALToJsonAttributeTest.java | 414 +++++++++++++++++++ .../james/transport/mailets/model/ICALTest.java | 196 +++++++++ .../resources/ics/meeting_without_method.ics | 30 ++ .../resources/ics/meeting_without_sequence.ics | 30 ++ .../test/resources/ics/meeting_without_uid.ics | 29 ++ mailet/pom.xml | 17 + 9 files changed, 1086 insertions(+) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/james-project/blob/cb844422/mailet/icalendar/pom.xml ---------------------------------------------------------------------- diff --git a/mailet/icalendar/pom.xml b/mailet/icalendar/pom.xml index e64a33b..c66123e 100644 --- a/mailet/icalendar/pom.xml +++ b/mailet/icalendar/pom.xml @@ -168,6 +168,21 @@ <version>0.5.0</version> </dependency> <dependency> + <groupId>com.fasterxml.jackson.core</groupId> + <artifactId>jackson-databind</artifactId> + <version>${jackson-data.version}</version> + </dependency> + <dependency> + <groupId>com.fasterxml.jackson.datatype</groupId> + <artifactId>jackson-datatype-jdk8</artifactId> + <version>${jackson-data.version}</version> + </dependency> + <dependency> + <groupId>com.github.steveash.guavate</groupId> + <artifactId>guavate</artifactId> + <version>${guavate.version}</version> + </dependency> + <dependency> <groupId>com.google.guava</groupId> <artifactId>guava</artifactId> </dependency> @@ -177,6 +192,24 @@ <scope>test</scope> </dependency> <dependency> + <groupId>net.javacrumbs.json-unit</groupId> + <artifactId>json-unit</artifactId> + <version>1.5.5</version> + <scope>test</scope> + </dependency> + <dependency> + <groupId>net.javacrumbs.json-unit</groupId> + <artifactId>json-unit-fluent</artifactId> + <version>1.5.5</version> + <scope>test</scope> + </dependency> + <dependency> + <groupId>nl.jqno.equalsverifier</groupId> + <artifactId>equalsverifier</artifactId> + <version>1.7.5</version> + <scope>test</scope> + </dependency> + <dependency> <groupId>org.assertj</groupId> <artifactId>assertj-core</artifactId> <version>${assertj-3.version}</version> http://git-wip-us.apache.org/repos/asf/james-project/blob/cb844422/mailet/icalendar/src/main/java/org/apache/james/transport/mailets/ICALToJsonAttribute.java ---------------------------------------------------------------------- diff --git a/mailet/icalendar/src/main/java/org/apache/james/transport/mailets/ICALToJsonAttribute.java b/mailet/icalendar/src/main/java/org/apache/james/transport/mailets/ICALToJsonAttribute.java new file mode 100644 index 0000000..1e314af --- /dev/null +++ b/mailet/icalendar/src/main/java/org/apache/james/transport/mailets/ICALToJsonAttribute.java @@ -0,0 +1,174 @@ +/**************************************************************** + * 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.io.Serializable; +import java.util.Map; +import java.util.UUID; +import java.util.stream.Stream; + +import javax.mail.MessagingException; + +import org.apache.commons.lang3.tuple.Pair; +import org.apache.james.transport.mailets.model.ICAL; +import org.apache.mailet.Mail; +import org.apache.mailet.MailAddress; +import org.apache.mailet.base.GenericMailet; + +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.datatype.jdk8.Jdk8Module; +import com.github.steveash.guavate.Guavate; +import com.google.common.base.Charsets; +import com.google.common.base.Strings; + +import net.fortuna.ical4j.model.Calendar; + +/** + * ICALToJsonAttribute takes a map of ICAL4J objects attached as attribute, and output the map of corresponding json bytes as + * an other attribute, with unique String keys. + * + * The JSON contains the following fields : + * + * <ul> + * <li><b>ical</b> : the raw ical string, in UTF-8</li> + * <li><b>sender</b> : the sender of the mail (compulsory, mail without sender will be discarded)</li> + * <li><b>recipient</b> : the recipient of the mail. If the mail have several recipients, each recipient will have + * its own JSON.</li> + * <li><b>uid</b> : the UID of the ical (optional)</li> + * <li><b>sequence</b> : the sequence of the ical (optional)</li> + * <li><b>dtstamp</b> : the date stamp of the ical (optional)</li> + * <li><b>method</b> : the method of the ical (optional)</li> + * <li><b>recurrence-id</b> : the recurrence-id of the ical (optional)</li> + * </ul> + * + * Example are included in test call ICalToJsonAttributeTest. + * + * Configuration example : + * + * <pre> + * <code> + * <mailet matcher=??? class=ICALToJsonAttribute> + * <sourceAttribute>icalendars</sourceAttribute> + * <destinationAttribute>icalendarJson</destinationAttribute> + * </mailet> + * </code> + * </pre> + */ +public class ICALToJsonAttribute extends GenericMailet { + + public static final String SOURCE_ATTRIBUTE_NAME = "source"; + public static final String DESTINATION_ATTRIBUTE_NAME = "destination"; + public static final String DEFAULT_SOURCE_ATTRIBUTE_NAME = "icalendar"; + public static final String DEFAULT_DESTINATION_ATTRIBUTE_NAME = "icalendarJson"; + + private final ObjectMapper objectMapper; + private String sourceAttributeName; + private String destinationAttributeName; + + public ICALToJsonAttribute() { + this.objectMapper = new ObjectMapper() + .registerModule(new Jdk8Module()); + } + + public String getSourceAttributeName() { + return sourceAttributeName; + } + + public String getDestinationAttributeName() { + return destinationAttributeName; + } + + @Override + public String getMailetInfo() { + return "ICALToJson Mailet"; + } + + @Override + public void init() throws MessagingException { + sourceAttributeName = getInitParameter(SOURCE_ATTRIBUTE_NAME, DEFAULT_SOURCE_ATTRIBUTE_NAME); + destinationAttributeName = getInitParameter(DESTINATION_ATTRIBUTE_NAME, DEFAULT_DESTINATION_ATTRIBUTE_NAME); + if (Strings.isNullOrEmpty(sourceAttributeName)) { + throw new MessagingException(SOURCE_ATTRIBUTE_NAME + " configuration parameter can not be null or empty"); + } + if (Strings.isNullOrEmpty(destinationAttributeName)) { + throw new MessagingException(DESTINATION_ATTRIBUTE_NAME + " configuration parameter can not be null or empty"); + } + } + + @Override + public void service(Mail mail) throws MessagingException { + if (mail.getAttribute(sourceAttributeName) == null) { + return; + } + if (mail.getSender() == null) { + log("Skipping " + mail.getName() + " because no sender"); + return; + } + try { + Map<String, Calendar> calendars = getCalendarMap(mail); + Map<String, byte[]> jsonsInByteForm = calendars.entrySet() + .stream() + .flatMap(calendar -> toJson(calendar, mail)) + .collect(Guavate.toImmutableMap(Pair::getKey, Pair::getValue)); + mail.setAttribute(destinationAttributeName, (Serializable) jsonsInByteForm); + } catch (ClassCastException e) { + log("Received a mail with " + sourceAttributeName + " not being an ICAL object for mail " + mail.getName(), e); + } + } + + @SuppressWarnings("unchecked") + private Map<String, Calendar> getCalendarMap(Mail mail) { + return (Map<String, Calendar>) mail.getAttribute(sourceAttributeName); + } + + private Stream<Pair<String, byte[]>> toJson(Map.Entry<String, Calendar> entry, Mail mail) { + return mail.getRecipients() + .stream() + .flatMap(recipient -> toICAL(entry.getValue(), recipient, mail.getSender())) + .flatMap(ical -> toJson(ical, mail.getName())) + .map(json -> Pair.of(UUID.randomUUID().toString(), json.getBytes(Charsets.UTF_8))); + } + + private Stream<String> toJson(ICAL ical, String mailName) { + try { + return Stream.of(objectMapper.writeValueAsString(ical)); + } catch (JsonProcessingException e) { + log("Error while serializing Calendar for mail " + mailName, e); + return Stream.of(); + } catch (Exception e) { + log("Exception caught while attaching ICAL to the email as JSON for mail " + mailName, e); + return Stream.of(); + } + } + + private Stream<ICAL> toICAL(Calendar calendar, MailAddress recipient, MailAddress sender) { + try { + return Stream.of(ICAL.builder() + .from(calendar) + .recipient(recipient) + .sender(sender) + .build()); + } catch (Exception e) { + log("Exception while converting calendar to ICAL", e); + return Stream.of(); + } + } +} http://git-wip-us.apache.org/repos/asf/james-project/blob/cb844422/mailet/icalendar/src/main/java/org/apache/james/transport/mailets/model/ICAL.java ---------------------------------------------------------------------- diff --git a/mailet/icalendar/src/main/java/org/apache/james/transport/mailets/model/ICAL.java b/mailet/icalendar/src/main/java/org/apache/james/transport/mailets/model/ICAL.java new file mode 100644 index 0000000..b873a93 --- /dev/null +++ b/mailet/icalendar/src/main/java/org/apache/james/transport/mailets/model/ICAL.java @@ -0,0 +1,163 @@ +/**************************************************************** + * 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.model; + +import java.util.Objects; +import java.util.Optional; + +import org.apache.mailet.MailAddress; + +import com.fasterxml.jackson.annotation.JsonProperty; +import com.google.common.base.Preconditions; + +import net.fortuna.ical4j.model.Calendar; +import net.fortuna.ical4j.model.Property; +import net.fortuna.ical4j.model.component.VEvent; + +public class ICAL { + + public static final String DEFAULT_SEQUENCE_VALUE = "0"; + + public static class Builder { + private String ical; + private String sender; + private String recipient; + private Optional<String> uid = Optional.empty(); + private Optional<String> sequence = Optional.empty(); + private Optional<String> dtstamp = Optional.empty(); + private Optional<String> method = Optional.empty(); + private Optional<String> recurrenceId = Optional.empty(); + + public Builder from(Calendar calendar) { + this.ical = calendar.toString(); + VEvent vevent = (VEvent) calendar.getComponent("VEVENT"); + this.uid = optionalOf(vevent.getUid()); + this.method = optionalOf(calendar.getMethod()); + this.recurrenceId = optionalOf(vevent.getRecurrenceId()); + this.sequence = optionalOf(vevent.getSequence()); + this.dtstamp = optionalOf(vevent.getDateStamp()); + return this; + } + + private Optional<String> optionalOf(Property property) { + return Optional.ofNullable(property).map(Property::getValue); + } + + public Builder sender(MailAddress sender) { + this.sender = sender.asString(); + return this; + } + + + public Builder recipient(MailAddress recipient) { + this.recipient = recipient.asString(); + return this; + } + + public ICAL build() { + Preconditions.checkNotNull(recipient); + Preconditions.checkNotNull(sender); + Preconditions.checkNotNull(ical); + Preconditions.checkState(uid.isPresent(), "uid is a compulsary property of an ICAL object"); + Preconditions.checkState(method.isPresent(), "method is a compulsary property of an ICAL object"); + Preconditions.checkState(dtstamp.isPresent(), "dtstamp is a compulsary property of an ICAL object"); + return new ICAL(ical, sender, recipient, uid, sequence, dtstamp, method, recurrenceId); + } + } + + public static Builder builder() { + return new Builder(); + } + + private final String ical; + private final String sender; + private final String recipient; + private final Optional<String> uid; + private final Optional<String> sequence; + private final Optional<String> dtstamp; + private final Optional<String> method; + private final Optional<String> recurrenceId; + + private ICAL(String ical, String sender, String recipient, Optional<String> uid, Optional<String> sequence, Optional<String> dtstamp, + Optional<String> method, Optional<String> recurrenceId) { + this.ical = ical; + this.sender = sender; + this.recipient = recipient; + this.uid = uid; + this.sequence = sequence; + this.dtstamp = dtstamp; + this.method = method; + this.recurrenceId = recurrenceId; + } + + public String getIcal() { + return ical; + } + + public String getSender() { + return sender; + } + + public String getRecipient() { + return recipient; + } + + public Optional<String> getUid() { + return uid; + } + + public String getSequence() { + return sequence.orElse(DEFAULT_SEQUENCE_VALUE); + } + + public Optional<String> getDtstamp() { + return dtstamp; + } + + public Optional<String> getMethod() { + return method; + } + + @JsonProperty("recurrence-id") + public Optional<String> getRecurrenceId() { + return recurrenceId; + } + + @Override + public final boolean equals(Object o) { + if (o instanceof ICAL) { + ICAL that = (ICAL) o; + return Objects.equals(that.ical, this.ical) + && Objects.equals(that.sender, this.sender) + && Objects.equals(that.recipient, this.recipient) + && Objects.equals(that.uid, this.uid) + && Objects.equals(that.sequence, this.sequence) + && Objects.equals(that.dtstamp, this.dtstamp) + && Objects.equals(that.method, this.method) + && Objects.equals(that.recurrenceId, this.recurrenceId); + } + return false; + } + + @Override + public final int hashCode() { + return Objects.hash(ical, sender, recipient, uid, sequence, dtstamp, method, recurrenceId); + } +} http://git-wip-us.apache.org/repos/asf/james-project/blob/cb844422/mailet/icalendar/src/test/java/org/apache/james/transport/mailets/ICALToJsonAttributeTest.java ---------------------------------------------------------------------- diff --git a/mailet/icalendar/src/test/java/org/apache/james/transport/mailets/ICALToJsonAttributeTest.java b/mailet/icalendar/src/test/java/org/apache/james/transport/mailets/ICALToJsonAttributeTest.java new file mode 100644 index 0000000..f100584 --- /dev/null +++ b/mailet/icalendar/src/test/java/org/apache/james/transport/mailets/ICALToJsonAttributeTest.java @@ -0,0 +1,414 @@ +/**************************************************************** + * 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 net.javacrumbs.jsonunit.fluent.JsonFluentAssert.assertThatJson; +import static org.assertj.core.api.Assertions.assertThat; + +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; + +import javax.mail.MessagingException; + +import org.apache.mailet.Mail; +import org.apache.mailet.MailAddress; +import org.apache.mailet.base.MailAddressFixture; +import org.apache.mailet.base.test.FakeMail; +import org.apache.mailet.base.test.FakeMailetConfig; +import org.junit.Before; +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.ExpectedException; + +import com.google.common.base.Charsets; +import com.google.common.collect.ImmutableMap; + +import net.fortuna.ical4j.data.CalendarBuilder; +import net.fortuna.ical4j.model.Calendar; + +public class ICALToJsonAttributeTest { + public static final MailAddress SENDER = MailAddressFixture.ANY_AT_JAMES; + public static final String MEETING_ICS = "\"BEGIN:VCALENDAR\\r\\n" + + "PRODID:-//Aliasource Groupe LINAGORA//OBM Calendar 3.2.1-rc2//FR\\r\\n" + + "CALSCALE:GREGORIAN\\r\\n" + + "X-OBM-TIME:1483703436\\r\\n" + + "VERSION:2.0\\r\\n" + + "METHOD:REQUEST\\r\\n" + + "BEGIN:VEVENT\\r\\n" + + "CREATED:20170106T115035Z\\r\\n" + + "LAST-MODIFIED:20170106T115036Z\\r\\n" + + "DTSTAMP:20170106T115036Z\\r\\n" + + "DTSTART:20170111T090000Z\\r\\n" + + "DURATION:PT1H30M\\r\\n" + + "TRANSP:OPAQUE\\r\\n" + + "SEQUENCE:0\\r\\n" + + "SUMMARY:Sprint planning #23\\r\\n" + + "DESCRIPTION:\\r\\n" + + "CLASS:PUBLIC\\r\\n" + + "PRIORITY:5\\r\\n" + + "ORGANIZER;X-OBM-ID=128;CN=Raphael OUAZANA:MAILTO:ouaz...@linagora.com\\r\\n" + + "X-OBM-DOMAIN:linagora.com\\r\\n" + + "X-OBM-DOMAIN-UUID:02874f7c-d10e-102f-acda-0015176f7922\\r\\n" + + "LOCATION:Hangout\\r\\n" + + "CATEGORIES:\\r\\n" + + "X-OBM-COLOR:\\r\\n" + + "UID:f1514f44bf39311568d640727cff54e819573448d09d2e5677987ff29caa01a9e047feb2aab16e43439a608f28671ab7c10e754ce92be513f8e04ae9ff15e65a9819cf285a6962bc\\r\\n" + + "ATTENDEE;CUTYPE=INDIVIDUAL;RSVP=TRUE;CN=Matthieu EXT_BAECHLER;PARTSTAT=NEEDS-ACTION;X-OBM-ID=302:MAILTO:baech...@linagora.com\\r\\n" + + "ATTENDEE;CUTYPE=INDIVIDUAL;RSVP=TRUE;CN=Laura ROYET;PARTSTAT=NEEDS-ACTION;X-OBM-ID=723:MAILTO:ro...@linagora.com\\r\\n" + + "ATTENDEE;CUTYPE=INDIVIDUAL;RSVP=TRUE;CN=Raphael OUAZANA;PARTSTAT=ACCEPTED;X-OBM-ID=128:MAILTO:ouaz...@linagora.com\\r\\n" + + "ATTENDEE;CUTYPE=INDIVIDUAL;RSVP=TRUE;CN=Luc DUZAN;PARTSTAT=NEEDS-ACTION;X-OBM-ID=715:MAILTO:du...@linagora.com\\r\\n" + + "ATTENDEE;CUTYPE=RESOURCE;CN=Salle de reunion Lyon;PARTSTAT=ACCEPTED;X-OBM-ID=66:MAILTO:nore...@linagora.com\\r\\n" + + "ATTENDEE;CUTYPE=INDIVIDUAL;RSVP=TRUE;CN=Antoine DUPRAT;PARTSTAT=NEEDS-ACTION;X-OBM-ID=453:MAILTO:dup...@linagora.com\\r\\n" + + "ATTENDEE;CUTYPE=INDIVIDUAL;RSVP=TRUE;CN=\\\"Benoît TELLIER\\\";PARTSTAT=NEEDS-ACTION;X-OBM-ID=623:MAILTO:tell...@linagora.com\\r\\n" + + "ATTENDEE;CUTYPE=INDIVIDUAL;RSVP=TRUE;CN=Quynh Quynh N NGUYEN;PARTSTAT=NEEDS-ACTION;X-OBM-ID=769:MAILTO:ngu...@linagora.com\\r\\n" + + "END:VEVENT\\r\\n" + + "END:VCALENDAR\\r\\n" + + "\""; + public static final String SMALL_ICS = "\"BEGIN:VCALENDAR\\r\\n" + + "PRODID:-//Aliasource Groupe LINAGORA//OBM Calendar 3.2.1-rc2//FR\\r\\n" + + "CALSCALE:GREGORIAN\\r\\n" + + "X-OBM-TIME:1483439571\\r\\n" + + "VERSION:2.0\\r\\n" + + "METHOD:REQUEST\\r\\n" + + "BEGIN:VEVENT\\r\\n" + + "CREATED:20170103T103250Z\\r\\n" + + "LAST-MODIFIED:20170103T103250Z\\r\\n" + + "DTSTAMP:20170103T103250Z\\r\\n" + + "DTSTART:20170120T100000Z\\r\\n" + + "DURATION:PT30M\\r\\n" + + "TRANSP:OPAQUE\\r\\n" + + "SEQUENCE:0\\r\\n" + + "SUMMARY:Sprint Social #3 Demo\\r\\n" + + "DESCRIPTION:\\r\\n" + + "CLASS:PUBLIC\\r\\n" + + "PRIORITY:5\\r\\n" + + "ORGANIZER;X-OBM-ID=468;CN=Attendee 1:MAILTO:attend...@linagora.com\\r\\n" + + "X-OBM-DOMAIN:linagora.com\\r\\n" + + "X-OBM-DOMAIN-UUID:02874f7c-d10e-102f-acda-0015176f7922\\r\\n" + + "LOCATION:hangout\\r\\n" + + "CATEGORIES:\\r\\n" + + "X-OBM-COLOR:\\r\\n" + + "UID:f1514f44bf39311568d64072ac247c17656ceafde3b4b3eba961c8c5184cdc6ee047feb2aab16e43439a608f28671ab7c10e754c301b1e32001ad51dd20eac2fc7af20abf4093bbe\\r\\n" + + "ATTENDEE;CUTYPE=INDIVIDUAL;RSVP=TRUE;CN=Attendee 2;PARTSTAT=NEEDS-ACTION;X-OBM-ID=348:MAILTO:attend...@linagora.com\\r\\n" + + "END:VEVENT\\r\\n" + + "END:VCALENDAR\\r\\n" + + "\""; + + @Rule + public ExpectedException expectedException = ExpectedException.none(); + + private ICALToJsonAttribute testee; + + @Before + public void setUp() { + testee = new ICALToJsonAttribute(); + } + + @Test + public void getMailetInfoShouldReturnExpectedValue() throws Exception { + assertThat(testee.getMailetInfo()).isEqualTo("ICALToJson Mailet"); + } + + @Test + public void initShouldSetAttributesWhenAbsent() throws Exception { + testee.init(FakeMailetConfig.builder().build()); + + assertThat(testee.getSourceAttributeName()).isEqualTo(ICALToJsonAttribute.DEFAULT_SOURCE_ATTRIBUTE_NAME); + assertThat(testee.getDestinationAttributeName()).isEqualTo(ICALToJsonAttribute.DEFAULT_DESTINATION_ATTRIBUTE_NAME); + } + + @Test + public void initShouldThrowOnEmptySourceAttribute() throws Exception { + expectedException.expect(MessagingException.class); + + testee.init(FakeMailetConfig.builder() + .setProperty(ICALToJsonAttribute.SOURCE_ATTRIBUTE_NAME, "") + .build()); + } + + @Test + public void initShouldThrowOnEmptyDestinationAttribute() throws Exception { + expectedException.expect(MessagingException.class); + + testee.init(FakeMailetConfig.builder() + .setProperty(ICALToJsonAttribute.DESTINATION_ATTRIBUTE_NAME, "") + .build()); + } + + @Test + public void initShouldSetAttributesWhenPresent() throws Exception { + String destination = "myDestination"; + String source = "mySource"; + testee.init(FakeMailetConfig.builder() + .setProperty(ICALToJsonAttribute.SOURCE_ATTRIBUTE_NAME, source) + .setProperty(ICALToJsonAttribute.DESTINATION_ATTRIBUTE_NAME, destination) + .build()); + + assertThat(testee.getSourceAttributeName()).isEqualTo(source); + assertThat(testee.getDestinationAttributeName()).isEqualTo(destination); + } + + @Test + public void serviceShouldFilterMailsWithoutICALs() throws Exception { + testee.init(FakeMailetConfig.builder().build()); + + Mail mail = FakeMail.builder() + .sender(SENDER) + .recipient(MailAddressFixture.OTHER_AT_JAMES) + .build(); + testee.service(mail); + + assertThat(mail.getAttribute(ICALToJsonAttribute.DEFAULT_DESTINATION_ATTRIBUTE_NAME)) + .isNull(); + } + + @Test + public void serviceShouldNotFailOnWrongAttributeType() throws Exception { + testee.init(FakeMailetConfig.builder().build()); + + Mail mail = FakeMail.builder() + .sender(SENDER) + .recipient(MailAddressFixture.OTHER_AT_JAMES) + .attribute(ICALToJsonAttribute.DEFAULT_SOURCE_ATTRIBUTE_NAME, "wrong type") + .build(); + testee.service(mail); + + assertThat(mail.getAttribute(ICALToJsonAttribute.DEFAULT_DESTINATION_ATTRIBUTE_NAME)) + .isNull(); + } + + @Test + public void serviceShouldNotFailOnWrongAttributeParameter() throws Exception { + testee.init(FakeMailetConfig.builder().build()); + + ImmutableMap<String, String> wrongParametrizedMap = ImmutableMap.<String, String>builder() + .put("key", "value") + .build(); + Mail mail = FakeMail.builder() + .sender(SENDER) + .recipient(MailAddressFixture.OTHER_AT_JAMES) + .attribute(ICALToJsonAttribute.DEFAULT_SOURCE_ATTRIBUTE_NAME, wrongParametrizedMap) + .build(); + testee.service(mail); + + assertThat(mail.getAttribute(ICALToJsonAttribute.DEFAULT_DESTINATION_ATTRIBUTE_NAME)) + .isNull(); + } + + @Test + public void serviceShouldFilterMailsWithoutSender() throws Exception { + testee.init(FakeMailetConfig.builder().build()); + + Calendar calendar = new CalendarBuilder().build(ClassLoader.getSystemResourceAsStream("ics/meeting.ics")); + ImmutableMap<String, Calendar> icals = ImmutableMap.<String, Calendar>builder() + .put("key", calendar) + .build(); + Mail mail = FakeMail.builder() + .recipient(MailAddressFixture.OTHER_AT_JAMES) + .attribute(ICALToJsonAttribute.DEFAULT_SOURCE_ATTRIBUTE_NAME, icals) + .build(); + testee.service(mail); + + assertThat(mail.getAttribute(ICALToJsonAttribute.DEFAULT_DESTINATION_ATTRIBUTE_NAME)) + .isNull(); + } + + @SuppressWarnings("unchecked") + @Test + public void serviceShouldAttachEmptyListWhenNoRecipient() throws Exception { + testee.init(FakeMailetConfig.builder().build()); + + Calendar calendar = new CalendarBuilder().build(ClassLoader.getSystemResourceAsStream("ics/meeting.ics")); + ImmutableMap<String, Calendar> icals = ImmutableMap.<String, Calendar>builder() + .put("key", calendar) + .build(); + Mail mail = FakeMail.builder() + .sender(SENDER) + .attribute(ICALToJsonAttribute.DEFAULT_SOURCE_ATTRIBUTE_NAME, icals) + .build(); + testee.service(mail); + + assertThat((Map) mail.getAttribute(ICALToJsonAttribute.DEFAULT_DESTINATION_ATTRIBUTE_NAME)) + .isEmpty(); + } + + @SuppressWarnings("unchecked") + @Test + public void serviceShouldAttachJson() throws Exception { + testee.init(FakeMailetConfig.builder().build()); + + Calendar calendar = new CalendarBuilder().build(ClassLoader.getSystemResourceAsStream("ics/meeting.ics")); + ImmutableMap<String, Calendar> icals = ImmutableMap.<String, Calendar>builder() + .put("key", calendar) + .build(); + MailAddress recipient = MailAddressFixture.ANY_AT_JAMES2; + Mail mail = FakeMail.builder() + .sender(SENDER) + .recipient(recipient) + .attribute(ICALToJsonAttribute.DEFAULT_SOURCE_ATTRIBUTE_NAME, icals) + .build(); + testee.service(mail); + + Map<String, byte[]> jsons = (Map<String, byte[]>) mail.getAttribute(ICALToJsonAttribute.DEFAULT_DESTINATION_ATTRIBUTE_NAME); + assertThat(jsons).hasSize(1); + assertThatJson(new String(jsons.values().iterator().next(), Charsets.UTF_8)) + .isEqualTo("{" + + "\"ical\": " + MEETING_ICS +"," + + "\"sender\": \"" + SENDER.asString() + "\"," + + "\"recipient\": \"" + recipient.asString() + "\"," + + "\"uid\": \"f1514f44bf39311568d640727cff54e819573448d09d2e5677987ff29caa01a9e047feb2aab16e43439a608f28671ab7c10e754ce92be513f8e04ae9ff15e65a9819cf285a6962bc\"," + + "\"sequence\": \"0\"," + + "\"dtstamp\": \"20170106T115036Z\"," + + "\"method\": \"REQUEST\"," + + "\"recurrence-id\": null" + + "}"); + } + + @SuppressWarnings("unchecked") + @Test + public void serviceShouldAttachJsonForSeveralRecipient() throws Exception { + testee.init(FakeMailetConfig.builder().build()); + + Calendar calendar = new CalendarBuilder().build(ClassLoader.getSystemResourceAsStream("ics/meeting.ics")); + ImmutableMap<String, Calendar> icals = ImmutableMap.<String, Calendar>builder() + .put("key", calendar) + .build(); + Mail mail = FakeMail.builder() + .sender(SENDER) + .recipients(MailAddressFixture.OTHER_AT_JAMES, MailAddressFixture.ANY_AT_JAMES2) + .attribute(ICALToJsonAttribute.DEFAULT_SOURCE_ATTRIBUTE_NAME, icals) + .build(); + testee.service(mail); + + Map<String, byte[]> jsons = (Map<String, byte[]>) mail.getAttribute(ICALToJsonAttribute.DEFAULT_DESTINATION_ATTRIBUTE_NAME); + assertThat(jsons).hasSize(2); + List<String> actual = toSortedValueList(jsons); + + assertThatJson(actual.get(0)).isEqualTo("{" + + "\"ical\": " + MEETING_ICS +"," + + "\"sender\": \"" + SENDER.asString() + "\"," + + "\"recipient\": \"" + MailAddressFixture.ANY_AT_JAMES2.asString() + "\"," + + "\"uid\": \"f1514f44bf39311568d640727cff54e819573448d09d2e5677987ff29caa01a9e047feb2aab16e43439a608f28671ab7c10e754ce92be513f8e04ae9ff15e65a9819cf285a6962bc\"," + + "\"sequence\": \"0\"," + + "\"dtstamp\": \"20170106T115036Z\"," + + "\"method\": \"REQUEST\"," + + "\"recurrence-id\": null" + + "}"); + assertThatJson(actual.get(1)).isEqualTo("{" + + "\"ical\": " + MEETING_ICS +"," + + "\"sender\": \"" + SENDER.asString() + "\"," + + "\"recipient\": \"" + MailAddressFixture.OTHER_AT_JAMES.asString() + "\"," + + "\"uid\": \"f1514f44bf39311568d640727cff54e819573448d09d2e5677987ff29caa01a9e047feb2aab16e43439a608f28671ab7c10e754ce92be513f8e04ae9ff15e65a9819cf285a6962bc\"," + + "\"sequence\": \"0\"," + + "\"dtstamp\": \"20170106T115036Z\"," + + "\"method\": \"REQUEST\"," + + "\"recurrence-id\": null" + + "}"); + } + + @SuppressWarnings("unchecked") + @Test + public void serviceShouldAttachJsonForSeveralICALs() throws Exception { + testee.init(FakeMailetConfig.builder().build()); + + 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(); + MailAddress recipient = MailAddressFixture.OTHER_AT_JAMES; + Mail mail = FakeMail.builder() + .sender(SENDER) + .recipient(recipient) + .attribute(ICALToJsonAttribute.DEFAULT_SOURCE_ATTRIBUTE_NAME, icals) + .build(); + testee.service(mail); + + Map<String, byte[]> jsons = (Map<String, byte[]>) mail.getAttribute(ICALToJsonAttribute.DEFAULT_DESTINATION_ATTRIBUTE_NAME); + assertThat(jsons).hasSize(2); + List<String> actual = toSortedValueList(jsons); + + assertThatJson(actual.get(0)).isEqualTo("{" + + "\"ical\": " + SMALL_ICS +"," + + "\"sender\": \"" + SENDER.asString() + "\"," + + "\"recipient\": \"" + recipient.asString() + "\"," + + "\"uid\": \"f1514f44bf39311568d64072ac247c17656ceafde3b4b3eba961c8c5184cdc6ee047feb2aab16e43439a608f28671ab7c10e754c301b1e32001ad51dd20eac2fc7af20abf4093bbe\"," + + "\"sequence\": \"0\"," + + "\"dtstamp\": \"20170103T103250Z\"," + + "\"method\": \"REQUEST\"," + + "\"recurrence-id\": null" + + "}"); + assertThatJson(actual.get(1)).isEqualTo("{" + + "\"ical\": " + MEETING_ICS +"," + + "\"sender\": \"" + SENDER.asString() + "\"," + + "\"recipient\": \"" + recipient.asString() + "\"," + + "\"uid\": \"f1514f44bf39311568d640727cff54e819573448d09d2e5677987ff29caa01a9e047feb2aab16e43439a608f28671ab7c10e754ce92be513f8e04ae9ff15e65a9819cf285a6962bc\"," + + "\"sequence\": \"0\"," + + "\"dtstamp\": \"20170106T115036Z\"," + + "\"method\": \"REQUEST\"," + + "\"recurrence-id\": null" + + "}"); + } + + @SuppressWarnings("unchecked") + @Test + public void serviceShouldFilterInvalidICS() throws Exception { + testee.init(FakeMailetConfig.builder().build()); + + Calendar calendar = new CalendarBuilder().build(ClassLoader.getSystemResourceAsStream("ics/meeting.ics")); + Calendar calendar2 = new CalendarBuilder().build(ClassLoader.getSystemResourceAsStream("ics/meeting_without_uid.ics")); + ImmutableMap<String, Calendar> icals = ImmutableMap.<String, Calendar>builder() + .put("key", calendar) + .put("key2", calendar2) + .build(); + MailAddress recipient = MailAddressFixture.OTHER_AT_JAMES; + Mail mail = FakeMail.builder() + .sender(SENDER) + .recipient(recipient) + .attribute(ICALToJsonAttribute.DEFAULT_SOURCE_ATTRIBUTE_NAME, icals) + .build(); + testee.service(mail); + + Map<String, byte[]> jsons = (Map<String, byte[]>) mail.getAttribute(ICALToJsonAttribute.DEFAULT_DESTINATION_ATTRIBUTE_NAME); + assertThat(jsons).hasSize(1); + List<String> actual = toSortedValueList(jsons); + + assertThatJson(actual.get(0)).isEqualTo("{" + + "\"ical\": " + MEETING_ICS + "," + + "\"sender\": \"" + SENDER.asString() + "\"," + + "\"recipient\": \"" + recipient.asString() + "\"," + + "\"uid\": \"f1514f44bf39311568d640727cff54e819573448d09d2e5677987ff29caa01a9e047feb2aab16e43439a608f28671ab7c10e754ce92be513f8e04ae9ff15e65a9819cf285a6962bc\"," + + "\"sequence\": \"0\"," + + "\"dtstamp\": \"20170106T115036Z\"," + + "\"method\": \"REQUEST\"," + + "\"recurrence-id\": null" + + "}"); + } + + private List<String> toSortedValueList(Map<String, byte[]> jsons) { + return jsons.values() + .stream() + .map(bytes -> new String(bytes, Charsets.UTF_8)) + .sorted() + .collect(Collectors.toList()); + } +} http://git-wip-us.apache.org/repos/asf/james-project/blob/cb844422/mailet/icalendar/src/test/java/org/apache/james/transport/mailets/model/ICALTest.java ---------------------------------------------------------------------- diff --git a/mailet/icalendar/src/test/java/org/apache/james/transport/mailets/model/ICALTest.java b/mailet/icalendar/src/test/java/org/apache/james/transport/mailets/model/ICALTest.java new file mode 100644 index 0000000..f8ab4ab --- /dev/null +++ b/mailet/icalendar/src/test/java/org/apache/james/transport/mailets/model/ICALTest.java @@ -0,0 +1,196 @@ +/**************************************************************** + * 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.model; + +import static org.assertj.core.api.Assertions.assertThat; + +import org.apache.mailet.MailAddress; +import org.apache.mailet.base.MailAddressFixture; +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.ExpectedException; + +import net.fortuna.ical4j.data.CalendarBuilder; +import net.fortuna.ical4j.model.Calendar; +import nl.jqno.equalsverifier.EqualsVerifier; + +public class ICALTest { + + @Rule + public ExpectedException expectedException = ExpectedException.none(); + + @Test + public void buildShouldFailWhenNoCalendar() throws Exception { + expectedException.expect(NullPointerException.class); + + ICAL.builder() + .recipient(MailAddressFixture.ANY_AT_JAMES) + .sender(MailAddressFixture.OTHER_AT_JAMES) + .build(); + } + + @Test + public void buildShouldFailWhenNoSender() throws Exception { + expectedException.expect(NullPointerException.class); + + Calendar calendar = new CalendarBuilder().build(ClassLoader.getSystemResourceAsStream("ics/meeting.ics")); + + ICAL.builder() + .recipient(MailAddressFixture.ANY_AT_JAMES) + .from(calendar) + .build(); + } + + @Test + public void buildShouldFailWhenNoRecipient() throws Exception { + expectedException.expect(NullPointerException.class); + + Calendar calendar = new CalendarBuilder().build(ClassLoader.getSystemResourceAsStream("ics/meeting.ics")); + + ICAL.builder() + .sender(MailAddressFixture.OTHER_AT_JAMES) + .from(calendar) + .build(); + } + + + @Test + public void buildShouldWork() throws Exception { + Calendar calendar = new CalendarBuilder().build(ClassLoader.getSystemResourceAsStream("ics/meeting.ics")); + + MailAddress recipient = MailAddressFixture.ANY_AT_JAMES; + MailAddress sender = MailAddressFixture.OTHER_AT_JAMES; + ICAL ical = ICAL.builder() + .recipient(recipient) + .sender(sender) + .from(calendar) + .build(); + + assertThat(ical.getRecipient()).isEqualTo(recipient.asString()); + assertThat(ical.getSender()).isEqualTo(sender.asString()); + assertThat(ical.getUid()) + .contains("f1514f44bf39311568d640727cff54e819573448d09d2e5677987ff29caa01a9e047feb2aab16e43439a608f28671ab7" + + "c10e754ce92be513f8e04ae9ff15e65a9819cf285a6962bc"); + assertThat(ical.getMethod()).contains("REQUEST"); + assertThat(ical.getRecurrenceId()).isEmpty(); + assertThat(ical.getDtstamp()).contains("20170106T115036Z"); + assertThat(ical.getSequence()).isEqualTo("0"); + assertThat(ical.getIcal()).isEqualTo("BEGIN:VCALENDAR\r\n" + + "PRODID:-//Aliasource Groupe LINAGORA//OBM Calendar 3.2.1-rc2//FR\r\n" + + "CALSCALE:GREGORIAN\r\n" + + "X-OBM-TIME:1483703436\r\n" + + "VERSION:2.0\r\n" + + "METHOD:REQUEST\r\n" + + "BEGIN:VEVENT\r\n" + + "CREATED:20170106T115035Z\r\n" + + "LAST-MODIFIED:20170106T115036Z\r\n" + + "DTSTAMP:20170106T115036Z\r\n" + + "DTSTART:20170111T090000Z\r\n" + + "DURATION:PT1H30M\r\n" + + "TRANSP:OPAQUE\r\n" + + "SEQUENCE:0\r\n" + + "SUMMARY:Sprint planning #23\r\n" + + "DESCRIPTION:\r\n" + + "CLASS:PUBLIC\r\n" + + "PRIORITY:5\r\n" + + "ORGANIZER;X-OBM-ID=128;CN=Raphael OUAZANA:MAILTO:ouaz...@linagora.com\r\n" + + "X-OBM-DOMAIN:linagora.com\r\n" + + "X-OBM-DOMAIN-UUID:02874f7c-d10e-102f-acda-0015176f7922\r\n" + + "LOCATION:Hangout\r\n" + + "CATEGORIES:\r\n" + + "X-OBM-COLOR:\r\n" + + "UID:f1514f44bf39311568d640727cff54e819573448d09d2e5677987ff29caa01a9e047feb2aab16e43439a608f28671ab7c10e754ce92be513f8e04ae9ff15e65a9819cf285a6962bc\r\n" + + "ATTENDEE;CUTYPE=INDIVIDUAL;RSVP=TRUE;CN=Matthieu EXT_BAECHLER;PARTSTAT=NEEDS-ACTION;X-OBM-ID=302:MAILTO:baech...@linagora.com\r\n" + + "ATTENDEE;CUTYPE=INDIVIDUAL;RSVP=TRUE;CN=Laura ROYET;PARTSTAT=NEEDS-ACTION;X-OBM-ID=723:MAILTO:ro...@linagora.com\r\n" + + "ATTENDEE;CUTYPE=INDIVIDUAL;RSVP=TRUE;CN=Raphael OUAZANA;PARTSTAT=ACCEPTED;X-OBM-ID=128:MAILTO:ouaz...@linagora.com\r\n" + + "ATTENDEE;CUTYPE=INDIVIDUAL;RSVP=TRUE;CN=Luc DUZAN;PARTSTAT=NEEDS-ACTION;X-OBM-ID=715:MAILTO:du...@linagora.com\r\n" + + "ATTENDEE;CUTYPE=RESOURCE;CN=Salle de reunion Lyon;PARTSTAT=ACCEPTED;X-OBM-ID=66:MAILTO:nore...@linagora.com\r\n" + + "ATTENDEE;CUTYPE=INDIVIDUAL;RSVP=TRUE;CN=Antoine DUPRAT;PARTSTAT=NEEDS-ACTION;X-OBM-ID=453:MAILTO:dup...@linagora.com\r\n" + + "ATTENDEE;CUTYPE=INDIVIDUAL;RSVP=TRUE;CN=\"Benoît TELLIER\";PARTSTAT=NEEDS-ACTION;X-OBM-ID=623:MAILTO:tell...@linagora.com\r\n" + + "ATTENDEE;CUTYPE=INDIVIDUAL;RSVP=TRUE;CN=Quynh Quynh N NGUYEN;PARTSTAT=NEEDS-ACTION;X-OBM-ID=769:MAILTO:ngu...@linagora.com\r\n" + + "END:VEVENT\r\n" + + "END:VCALENDAR\r\n"); + } + + @Test + public void equalsAndHashCodeShouldBeWellImplemented() { + EqualsVerifier.forClass(ICAL.class).verify(); + } + + @Test + public void buildShouldThrowOnCalendarWithoutDtstamp() throws Exception { + Calendar calendar = new CalendarBuilder().build(ClassLoader.getSystemResourceAsStream("ics/meeting_without_dtstamp.ics")); + + expectedException.expect(IllegalStateException.class); + + MailAddress recipient = MailAddressFixture.ANY_AT_JAMES; + MailAddress sender = MailAddressFixture.OTHER_AT_JAMES; + ICAL.builder() + .recipient(recipient) + .sender(sender) + .from(calendar) + .build(); + } + + @Test + public void buildShouldThrowOnCalendarWithoutUid() throws Exception { + Calendar calendar = new CalendarBuilder().build(ClassLoader.getSystemResourceAsStream("ics/meeting_without_uid.ics")); + + expectedException.expect(IllegalStateException.class); + + MailAddress recipient = MailAddressFixture.ANY_AT_JAMES; + MailAddress sender = MailAddressFixture.OTHER_AT_JAMES; + ICAL.builder() + .recipient(recipient) + .sender(sender) + .from(calendar) + .build(); + } + + @Test + public void buildShouldThrowOnCalendarWithoutMethod() throws Exception { + Calendar calendar = new CalendarBuilder().build(ClassLoader.getSystemResourceAsStream("ics/meeting_without_method.ics")); + + expectedException.expect(IllegalStateException.class); + + MailAddress recipient = MailAddressFixture.ANY_AT_JAMES; + MailAddress sender = MailAddressFixture.OTHER_AT_JAMES; + ICAL.builder() + .recipient(recipient) + .sender(sender) + .from(calendar) + .build(); + } + + @Test + public void buildShouldSetDefaultValueWhenCalendarWithoutSequence() throws Exception { + Calendar calendar = new CalendarBuilder().build(ClassLoader.getSystemResourceAsStream("ics/meeting_without_sequence.ics")); + + MailAddress recipient = MailAddressFixture.ANY_AT_JAMES; + MailAddress sender = MailAddressFixture.OTHER_AT_JAMES; + ICAL ical = ICAL.builder() + .recipient(recipient) + .sender(sender) + .from(calendar) + .build(); + + assertThat(ical.getSequence()).isEqualTo(ICAL.DEFAULT_SEQUENCE_VALUE); + } +} http://git-wip-us.apache.org/repos/asf/james-project/blob/cb844422/mailet/icalendar/src/test/resources/ics/meeting_without_method.ics ---------------------------------------------------------------------- diff --git a/mailet/icalendar/src/test/resources/ics/meeting_without_method.ics b/mailet/icalendar/src/test/resources/ics/meeting_without_method.ics new file mode 100644 index 0000000..2d628f6 --- /dev/null +++ b/mailet/icalendar/src/test/resources/ics/meeting_without_method.ics @@ -0,0 +1,30 @@ +BEGIN:VCALENDAR +PRODID:-//Aliasource Groupe LINAGORA//OBM Calendar 3.2.1-rc2//FR +CALSCALE:GREGORIAN +X-OBM-TIME:1483439571 +VERSION:2.0 +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/cb844422/mailet/icalendar/src/test/resources/ics/meeting_without_sequence.ics ---------------------------------------------------------------------- diff --git a/mailet/icalendar/src/test/resources/ics/meeting_without_sequence.ics b/mailet/icalendar/src/test/resources/ics/meeting_without_sequence.ics new file mode 100644 index 0000000..ad57338 --- /dev/null +++ b/mailet/icalendar/src/test/resources/ics/meeting_without_sequence.ics @@ -0,0 +1,30 @@ +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 +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/cb844422/mailet/icalendar/src/test/resources/ics/meeting_without_uid.ics ---------------------------------------------------------------------- diff --git a/mailet/icalendar/src/test/resources/ics/meeting_without_uid.ics b/mailet/icalendar/src/test/resources/ics/meeting_without_uid.ics new file mode 100644 index 0000000..f7e0c2d --- /dev/null +++ b/mailet/icalendar/src/test/resources/ics/meeting_without_uid.ics @@ -0,0 +1,29 @@ +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: +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/cb844422/mailet/pom.xml ---------------------------------------------------------------------- diff --git a/mailet/pom.xml b/mailet/pom.xml index 1c68cad..fa203b2 100644 --- a/mailet/pom.xml +++ b/mailet/pom.xml @@ -59,6 +59,8 @@ <assertj-3.version>3.3.0</assertj-3.version> <assertj-1-guava.version>1.3.1</assertj-1-guava.version> <slf4j.version>1.7.7</slf4j.version> + <jackson-data.version>2.6.3</jackson-data.version> + <guavate.version>1.0.0</guavate.version> </properties> @@ -197,6 +199,21 @@ <artifactId>slf4j-api</artifactId> <version>${slf4j.version}</version> </dependency> + <dependency> + <groupId>com.fasterxml.jackson.core</groupId> + <artifactId>jackson-databind</artifactId> + <version>${jackson-data.version}</version> + </dependency> + <dependency> + <groupId>com.fasterxml.jackson.datatype</groupId> + <artifactId>jackson-datatype-jdk8</artifactId> + <version>${jackson-data.version}</version> + </dependency> + <dependency> + <groupId>com.github.steveash.guavate</groupId> + <artifactId>guavate</artifactId> + <version>${guavate.version}</version> + </dependency> </dependencies> </dependencyManagement> --------------------------------------------------------------------- To unsubscribe, e-mail: server-dev-unsubscr...@james.apache.org For additional commands, e-mail: server-dev-h...@james.apache.org