diff --git a/tests/Sync/Sync/EmailITipTest.php b/tests/Sync/Sync/EmailITipTest.php new file mode 100644 index 0000000..ec78332 --- /dev/null +++ b/tests/Sync/Sync/EmailITipTest.php @@ -0,0 +1,81 @@ +emptyTestFolder('INBOX', 'mail'); + $this->registerDevice(); + + // Test INBOX + $folderId = '38b950ebd62cd9a66929c89615d0fc04'; + $syncKey = 0; + $request = << + + + + + {$syncKey} + {$folderId} + + + + EOF; + + $response = $this->request($request, 'Sync'); + $this->assertEquals(200, $response->getStatusCode()); + $syncKey++; + + // Append messages + $this->appendMail('INBOX', 'mail.itip1'); + $this->appendMail('INBOX', 'mail.itip.invalid'); + $this->appendMail('INBOX', 'mail.sync2'); + + // Test that the synchornization works with the invalid itip in the middle + $request = << + + + + + {$syncKey} + {$folderId} + 1 + 1 + + 0 + 1 + + 2 + 51200 + 0 + + + + + + EOF; + + $response = $this->request($request, 'Sync'); + + $this->assertEquals(200, $response->getStatusCode()); + + $dom = $this->fromWbxml($response->getBody()); + $xpath = $this->xpath($dom); + + // print($dom->saveXML()); + + $root = "//ns:Sync/ns:Collections/ns:Collection"; + $this->assertSame('1', $xpath->query("{$root}/ns:Status")->item(0)->nodeValue); + $this->assertSame(strval(++$syncKey), $xpath->query("{$root}/ns:SyncKey")->item(0)->nodeValue); + $this->assertSame($folderId, $xpath->query("{$root}/ns:CollectionId")->item(0)->nodeValue); + // We expect all three messages to synchronize, even if we fail to parse the invitation in the middle + $this->assertSame(3, $xpath->query("{$root}/ns:Commands/ns:Add")->count()); + } +} diff --git a/tests/src/mail.itip.invalid b/tests/src/mail.itip.invalid new file mode 100644 index 0000000..cace895 --- /dev/null +++ b/tests/src/mail.itip.invalid @@ -0,0 +1,51 @@ +MIME-Version: 1.0 +Date: Thu, 07 Dec 2023 13:29:14 +0100 +Message-ID: <14ab307198d32cee00b38ffb54c9e577@nestle.kolab.ch> +From: "Organizer" <$from> +To: <$to> +Subject: Invalid itip invitation +Content-Type: multipart/alternative; + boundary="=_f39ac9438326f676a8d562e163aa31e0" + +--=_f39ac9438326f676a8d562e163aa31e0 +Content-Transfer-Encoding: quoted-printable +Content-Type: text/plain; charset=UTF-8; + format=flowed + +*Test* +--=_f39ac9438326f676a8d562e163aa31e0 +Content-Transfer-Encoding: 8bit +Content-Type: text/calendar; charset=UTF-8; method=REQUEST; name=event.ics + +BEGIN:VCALENDAR +VERSION:2.0 +PRODID:-//Roundcube 1.5-git//Sabre VObject 4.5.3//EN +CALSCALE:GREGORIAN +METHOD:REQUEST +BEGIN:VTIMEZONE +TZID:Europe/Warsaw +BEGIN:DAYLIGHT +DTSTART:20230326T010000 +TZOFFSETFROM:+0100 +TZOFFSETTO:+0200 +TZNAME:CEST +END:DAYLIGHT +BEGIN:DAYLIGHT +DTSTART:20240331T010000 +TZOFFSETFROM:+0100 +TZOFFSETTO:+0200 +TZNAME:CEST +END:DAYLIGHT +BEGIN:STANDARD +DTSTART:20231029T010000 +TZOFFSETFROM:+0200 +TZOFFSETTO:+0100 +TZNAME:CET +END:STANDARD +END:VTIMEZONE +BEGIN:VEVENT +DTSTART;TZID=Europe/Warsaw:20231207T140000 +END:VEVENT +END:VCALENDAR + +--=_f39ac9438326f676a8d562e163aa31e0--