From: Gunnar Wrobel Date: Sun, 22 Aug 2010 16:28:10 +0000 (+0200) Subject: Start using Horde_Itip in Kolab_Resource. X-Git-Url: https://git.internetallee.de/?a=commitdiff_plain;h=8b696adbdbe5666e61e096a5d195fc86915f61ab;p=horde.git Start using Horde_Itip in Kolab_Resource. --- diff --git a/framework/Itip/TODO b/framework/Itip/TODO index 6e934b060..4580e7378 100644 --- a/framework/Itip/TODO +++ b/framework/Itip/TODO @@ -1,3 +1,3 @@ - + - Merge with Horde Imp (Changes [Horde]: Extended message body; improved From, Changes [Kolab]: Do not automatically set the sequence attribute to 0 if it does not exist -> http://bugs.horde.org/ticket/4863; use lower case mailto -> http://bugs.horde.org/ticket/4872; Missing UID in the vEvent causes failure; - - Complete unit testing + - Use parse_url diff --git a/framework/Kolab_Resource/TODO b/framework/Kolab_Resource/TODO new file mode 100644 index 000000000..356532e8a --- /dev/null +++ b/framework/Kolab_Resource/TODO @@ -0,0 +1,12 @@ + - Start cleaning up classes + + - Ensure the unit tests are working in git again. + + - Integrate into Kolab_Filter git and ensure it is working with the + resource handling. + + - Use Horde_Lock + + - At some point merge with Kronolith_Resource (wait for that until + you work on Kronolith again). + diff --git a/framework/Kolab_Resource/lib/Horde/Kolab/Resource.php b/framework/Kolab_Resource/lib/Horde/Kolab/Resource.php index 623f3bba8..0079bbb60 100644 --- a/framework/Kolab_Resource/lib/Horde/Kolab/Resource.php +++ b/framework/Kolab_Resource/lib/Horde/Kolab/Resource.php @@ -619,125 +619,48 @@ class Kolab_Resource * @param string $uid The UID of the event. * @param boolean $is_update Is this an event update? */ - function sendITipReply($cn, $resource, $itip, $type = RM_ITIP_ACCEPT, - $organiser, $uid, $is_update) - { + function sendITipReply( + $cn, $resource, $itip, $type, $organiser, $uid, $is_update, $comment = null + ) { Horde::logMessage(sprintf('sendITipReply(%s, %s, %s, %s)', - $cn, $resource, get_class($itip), $type), 'DEBUG'); - - // Build the reply. - $vCal = new Horde_Icalendar(); - $vCal->setAttribute('PRODID', '-//kolab.org//NONSGML Kolab Server 2//EN'); - $vCal->setAttribute('METHOD', 'REPLY'); - - $summary = _('No summary available'); + $cn, $resource, get_class($itip), $type), + 'DEBUG'); - $itip_reply = Horde_Icalendar::newComponent('VEVENT', $vCal); - $itip_reply->setAttribute('UID', $uid); - if (!is_a($itip->getAttribute('SUMMARY'), 'PEAR_error')) { - $itip_reply->setAttribute('SUMMARY', $itip->getAttribute('SUMMARY')); - $summary = $itip->getAttribute('SUMMARY'); - } - if (!is_a($itip->getAttribute('DESCRIPTION'), 'PEAR_error')) { - $itip_reply->setAttribute('DESCRIPTION', $itip->getAttribute('DESCRIPTION')); - } - if (!is_a($itip->getAttribute('LOCATION'), 'PEAR_error')) { - $itip_reply->setAttribute('LOCATION', $itip->getAttribute('LOCATION')); - } - $itip_reply->setAttribute('DTSTART', $itip->getAttribute('DTSTART'), array_pop($itip->getAttribute('DTSTART', true))); - if (!is_a($itip->getAttribute('DTEND'), 'PEAR_error')) { - $itip_reply->setAttribute('DTEND', $itip->getAttribute('DTEND'), array_pop($itip->getAttribute('DTEND', true))); - } else { - $itip_reply->setAttribute('DURATION', $itip->getAttribute('DURATION'), array_pop($itip->getAttribute('DURATION', true))); - } - if (!is_a($itip->getAttribute('SEQUENCE'), 'PEAR_error')) { - $itip_reply->setAttribute('SEQUENCE', $itip->getAttribute('SEQUENCE')); - } else { - $itip_reply->setAttribute('SEQUENCE', 0); - } - $itip_reply->setAttribute('ORGANIZER', $itip->getAttribute('ORGANIZER'), array_pop($itip->getAttribute('ORGANIZER', true))); - - // Let's try and remove this code and just create - // the ATTENDEE stuff in the reply from scratch - // $attendees = $itip->getAttribute( 'ATTENDEE' ); - // if( !is_array( $attendees ) ) { - // $attendees = array( $attendees ); - // } - // $params = $itip->getAttribute( 'ATTENDEE', true ); - // for( $i = 0; $i < count($attendees); $i++ ) { - // $attendee = preg_replace('/^mailto:\s*/i', '', $attendees[$i]); - // if ($attendee != $resource) { - // continue; - // } - // $params = $params[$i]; - // break; - // } - - $params = array(); - $params['CN'] = $cn; - switch ($type) { + $itip_reply = new Horde_Kolab_Resource_Itip_Response( + $itip, + new Horde_Kolab_Resource_Itip_Resource_Base( + $resource, $cn + ) + ); + switch($type) { case RM_ITIP_DECLINE: - Horde::logMessage(sprintf('Sending DECLINE iTip reply to %s', - $organiser), 'DEBUG'); - $message = $is_update - ? sprintf(_("%s has declined the update to the following event:"), $resource) . "\n\n" . $summary - : sprintf(_("%s has declined the invitation to the following event:"), $resource) . "\n\n" . $summary; - $subject = _("Declined: ") . $summary; - $params['PARTSTAT'] = 'DECLINED'; + $type = new Horde_Kolab_Resource_Itip_Response_Type_Decline( + $resource, $itip + ); break; - case RM_ITIP_ACCEPT: - Horde::logMessage(sprintf('Sending ACCEPT iTip reply to %s', $organiser), 'DEBUG'); - $message = $is_update - ? sprintf(_("%s has accepted the update to the following event:"), $resource) . "\n\n" . $summary - : sprintf(_("%s has accepted the invitation to the following event:"), $resource) . "\n\n" . $summary; - $subject = _("Accepted: ") . $summary; - $params['PARTSTAT'] = 'ACCEPTED'; + $type = new Horde_Kolab_Resource_Itip_Response_Type_Accept( + $resource, $itip + ); break; - case RM_ITIP_TENTATIVE: - Horde::logMessage(sprintf('Sending TENTATIVE iTip reply to %s', $organiser), 'DEBUG'); - $message = $is_update - ? sprintf(_("%s has tentatively accepted the update to the following event:"), $resource) . "\n\n" . $summary - : sprintf(_("%s has tentatively accepted the invitation to the following event:"), $resource) . "\n\n" . $summary; - $subject = _("Tentative: ") . $summary; - $params['PARTSTAT'] = 'TENTATIVE'; + $type = new Horde_Kolab_Resource_Itip_Response_Type_Tentative( + $resource, $itip + ); break; - - default: - Horde::logMessage(sprintf('Unknown iTip method (%s passed to sendITipReply())', $type), 'ERR'); } + list($headers, $message) = $itip_reply->getMessage( + $type, + '-//kolab.org//NONSGML Kolab Server 2//EN', + $comment + ); - $itip_reply->setAttribute('ATTENDEE', 'MAILTO:' . $resource, $params); - $vCal->addComponent($itip_reply); - - $ics = new MIME_Part('text/calendar', $vCal->exportvCalendar(), 'UTF-8' ); - //$ics->setName('event-reply.ics'); - $ics->setContentTypeParameter('method', 'REPLY'); - - //$mime->addPart($body); - //$mime->addPart($ics); - // The following was ::convertMimePart($mime). This was removed so that we - // send out single-part MIME replies that have the iTip file as the body, - // with the correct mime-type header set, etc. The reason we want to do this - // is so that Outlook interprets the messages as it does Outlook-generated - // responses, i.e. double-clicking a reply will automatically update your - // meetings, showing different status icons in the UI, etc. - $mime = &MIME_Message::convertMimePart($ics); - $mime->setCharset('UTF-8'); - $mime->setTransferEncoding('quoted-printable'); - $mime->transferEncodeContents(); - - // Build the reply headers. - $msg_headers = new MIME_Headers(); - $msg_headers->addHeader('Date', date('r')); - $msg_headers->addHeader('From', "$cn <$resource>"); - $msg_headers->addHeader('To', $organiser); - $msg_headers->addHeader('Subject', $subject); - $msg_headers->addMIMEHeaders($mime); + Horde::logMessage(sprintf('Sending %s iTip reply to %s', + $type->getStatus(), + $organiser), 'DEBUG'); $reply = new Horde_Kolab_Resource_Reply( - $resource, $organiser, $msg_headers, $mime + $resource, $organiser, $headers, $message ); Horde::logMessage('Successfully prepared iTip reply', 'DEBUG'); return $reply; diff --git a/framework/Kolab_Resource/lib/Horde/Kolab/Resource/Itip.php b/framework/Kolab_Resource/lib/Horde/Kolab/Resource/Itip.php deleted file mode 100644 index 9d0926a1a..000000000 --- a/framework/Kolab_Resource/lib/Horde/Kolab/Resource/Itip.php +++ /dev/null @@ -1,257 +0,0 @@ - - * @author Gunnar Wrobel - * @license http://www.fsf.org/copyleft/lgpl.html LGPL - * @link http://pear.horde.org/index.php?package=Kolab_Server - */ - -/** - * Handles Itip data. - * - * Copyright 2004-2010 Klarälvdalens Datakonsult AB - * - * See the enclosed file COPYING for license information (LGPL). If you did not - * receive this file, see - * http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. - * - * @category Kolab - * @package Kolab_Filter - * @author Steffen Hansen - * @author Gunnar Wrobel - * @license http://www.fsf.org/copyleft/lgpl.html LGPL - * @link http://pear.horde.org/index.php?package=Kolab_Server - */ -class Horde_Kolab_Resource_Itip -{ - - /** - * Reference to the Icalendar iTip object. - * - * @var Horde_Icalendar_Vevent - */ - private $_itip; - - /** - * Constructor. - * - * @param Horde_Icalendar_Vevent $itip An iCalendar iTip object. - */ - public function __construct($itip) - { - $this->_itip = $itip; - } - - public function __call($method, $args) - { - return call_user_func_array(array($this->_itip, $method), $args); - } - - /** - * Return the method of the iTip request. - * - * @return string The method of the request. - */ - public function getMethod() - { - return $this->_itip->getAttributeDefault('METHOD', 'REQUEST'); - } - - /** - * Return the uid of the iTip event. - * - * @return string The uid of the event. - */ - public function getUid() - { - return $this->_itip->getAttributeDefault('UID', ''); - } - - /** - * Return the organizer of the iTip event. - * - * @return string The organizer of the event. - */ - public function getOrganizer() - { - return preg_replace('/^mailto:\s*/i', '', $this->_itip->getAttributeDefault('ORGANIZER', '')); - } - - /** - * Return the summary of the iTip event. - * - * @return string The summary of the event. - */ - public function getSummary() - { - return $this->_itip->getAttributeDefault('SUMMARY', ''); - } - - /** - * Return the start of the iTip event. - * - * @return string The start of the event. - */ - public function getStart() - { - return $this->_itip->getAttributeDefault('DTSTART', 0); - } - - /** - * Return the end of the iTip event. - * - * @return string The end of the event. - */ - public function getEnd() - { - return $this->_itip->getAttributeDefault('DTEND', 0); - } - - public function getKolabObject() - { - $object = array(); - $object['uid'] = $this->_itip->getAttributeDefault('UID', ''); - - $org_params = $this->_itip->getAttribute('ORGANIZER', true); - if (!is_a( $org_params, 'PEAR_Error')) { - if (!empty($org_params[0]['CN'])) { - $object['organizer']['display-name'] = $org_params[0]['CN']; - } - $orgemail = $this->_itip->getAttributeDefault('ORGANIZER', ''); - if (preg_match('/mailto:(.*)/i', $orgemail, $regs )) { - $orgemail = $regs[1]; - } - $object['organizer']['smtp-address'] = $orgemail; - } - $object['summary'] = $this->_itip->getAttributeDefault('SUMMARY', ''); - $object['location'] = $this->_itip->getAttributeDefault('LOCATION', ''); - $object['body'] = $this->_itip->getAttributeDefault('DESCRIPTION', ''); - $dtend = $this->_itip->getAttributeDefault('DTEND', ''); - if (is_array($dtend)) { - $object['_is_all_day'] = true; - } - $start = new Horde_Kolab_Resource_Epoch($this->getStart()); - $object['start-date'] = $start->getEpoch(); - $end = new Horde_Kolab_Resource_Epoch($dtend); - $object['end-date'] = $end->getEpoch(); - - $attendees = $this->_itip->getAttribute('ATTENDEE'); - if (!is_a( $attendees, 'PEAR_Error')) { - $attendees_params = $this->_itip->getAttribute('ATTENDEE', true); - if (!is_array($attendees)) { - $attendees = array($attendees); - } - if (!is_array($attendees_params)) { - $attendees_params = array($attendees_params); - } - - $object['attendee'] = array(); - for ($i = 0; $i < count($attendees); $i++) { - $attendee = array(); - if (isset($attendees_params[$i]['CN'])) { - $attendee['display-name'] = $attendees_params[$i]['CN']; - } - - $attendeeemail = $attendees[$i]; - if (preg_match('/mailto:(.*)/i', $attendeeemail, $regs)) { - $attendeeemail = $regs[1]; - } - $attendee['smtp-address'] = $attendeeemail; - - if (!isset($attendees_params[$i]['RSVP']) - || $attendees_params[$i]['RSVP'] == 'FALSE') { - $attendee['request-response'] = false; - } else { - $attendee['request-response'] = true; - } - - if (isset($attendees_params[$i]['ROLE'])) { - $attendee['role'] = $attendees_params[$i]['ROLE']; - } - - if (isset($attendees_params[$i]['PARTSTAT'])) { - $status = strtolower($attendees_params[$i]['PARTSTAT']); - switch ($status) { - case 'needs-action': - case 'delegated': - $attendee['status'] = 'none'; - break; - default: - $attendee['status'] = $status; - break; - } - } - - $object['attendee'][] = $attendee; - } - } - - // Alarm - $valarm = $this->_itip->findComponent('VALARM'); - if ($valarm) { - $trigger = $valarm->getAttribute('TRIGGER'); - if (!is_a($trigger, 'PEAR_Error')) { - $p = $valarm->getAttribute('TRIGGER', true); - if ($trigger < 0) { - // All OK, enter the alarm into the XML - // NOTE: The Kolab XML format seems underspecified - // wrt. alarms currently... - $object['alarm'] = -$trigger / 60; - } - } else { - Horde::logMessage('No TRIGGER in VALARM. ' . $trigger->getMessage(), 'ERR'); - } - } - - // Recurrence - $rrule_str = $this->_itip->getAttribute('RRULE'); - if (!is_a($rrule_str, 'PEAR_Error')) { - require_once 'Horde/Date/Recurrence.php'; - $recurrence = new Horde_Date_Recurrence(time()); - $recurrence->fromRRule20($rrule_str); - $object['recurrence'] = $recurrence->toHash(); - } - - Horde::logMessage(sprintf('Assembled event object: %s', - print_r($object, true)), 'DEBUG'); - - return $object; - } - - public function setAccepted($resource) - { - // Update our status within the iTip request and send the reply - $this->_itip->setAttribute('STATUS', 'CONFIRMED', array(), false); - $attendees = $this->_itip->getAttribute('ATTENDEE'); - if (!is_array($attendees)) { - $attendees = array($attendees); - } - $attparams = $this->_itip->getAttribute('ATTENDEE', true); - foreach ($attendees as $i => $attendee) { - $attendee = preg_replace('/^mailto:\s*/i', '', $attendee); - if ($attendee != $resource) { - continue; - } - - $attparams[$i]['PARTSTAT'] = 'ACCEPTED'; - if (array_key_exists('RSVP', $attparams[$i])) { - unset($attparams[$i]['RSVP']); - } - } - - // Re-add all the attendees to the event, using our updates status info - $firstatt = array_pop($attendees); - $firstattparams = array_pop($attparams); - $this->_itip->setAttribute('ATTENDEE', $firstatt, $firstattparams, false); - foreach ($attendees as $i => $attendee) { - $this->_itip->setAttribute('ATTENDEE', $attendee, $attparams[$i]); - } - } - -} diff --git a/framework/Kolab_Resource/test/Horde/Kolab/Resource/AllTests.php b/framework/Kolab_Resource/test/Horde/Kolab/Resource/AllTests.php new file mode 100644 index 000000000..c47754ec5 --- /dev/null +++ b/framework/Kolab_Resource/test/Horde/Kolab/Resource/AllTests.php @@ -0,0 +1,45 @@ + + * @license http://www.fsf.org/copyleft/lgpl.html LGPL + * @link http://pear.horde.org/index.php?package=Kolab_Resource + */ + +/** + * Define the main method + */ +if (!defined('PHPUnit_MAIN_METHOD')) { + define('PHPUnit_MAIN_METHOD', 'Horde_Kolab_Resource_AllTests::main'); +} + +/** + * Prepare the test setup. + */ +require_once 'Horde/Test/AllTests.php'; + +/** + * All tests for the Kolab_Resource:: package. + * + * @category Kolab + * @package Kolab_Resource + * @subpackage UnitTests + * @author Gunnar Wrobel + * @license http://www.fsf.org/copyleft/lgpl.html LGPL + * @link http://pear.horde.org/index.php?package=Kolab_Resource + */ +class Horde_Kolab_Resource_AllTests extends Horde_Test_AllTests +{ +} + +Horde_Kolab_Resource_AllTests::init('Horde_Kolab_Resource', __FILE__); + +if (PHPUnit_MAIN_METHOD == 'Horde_Kolab_Resource_AllTests::main') { + Horde_Kolab_Resource_AllTests::main(); +} diff --git a/framework/Kolab_Resource/test/Horde/Kolab/Resource/Autoload.php b/framework/Kolab_Resource/test/Horde/Kolab/Resource/Autoload.php new file mode 100644 index 000000000..4c9c6cb1c --- /dev/null +++ b/framework/Kolab_Resource/test/Horde/Kolab/Resource/Autoload.php @@ -0,0 +1,26 @@ + + * @license http://www.fsf.org/copyleft/lgpl.html LGPL + * @link http://pear.horde.org/index.php?package=Kolab_Resource + */ + +require_once 'Horde/Kolab/Resource.php'; + +/** Do not catch strict standards */ +error_reporting(E_ALL | ~E_STRICT); + +/** Load the basic test definition */ +require_once dirname(__FILE__) . '/TestCase.php'; diff --git a/framework/Kolab_Resource/test/Horde/Kolab/Resource/fixtures/recur_invitation.eml b/framework/Kolab_Resource/test/Horde/Kolab/Resource/fixtures/recur_invitation.eml new file mode 100644 index 000000000..3dda6efe6 --- /dev/null +++ b/framework/Kolab_Resource/test/Horde/Kolab/Resource/fixtures/recur_invitation.eml @@ -0,0 +1,202 @@ +Received: from localhost (example.org [127.0.0.1]) + by example.org (Postfix) with ESMTP id 4E36AC2E001A + for ; Fri, 26 Sep 2008 10:54:08 +0200 (CEST) +X-Virus-Scanned: by amavisd-new at example.org +X-Spam-Flag: NO +X-Spam-Score: 3.704 +X-Spam-Level: *** +X-Spam-Status: No, score=3.704 tagged_above=3 required=6.3 tests=[AWL=-1.351, + HTML_IMAGE_ONLY_32=2.353, HTML_MESSAGE=0.001, MIME_BASE64_TEXT=2.701] +Received: from example.org ([127.0.0.1]) + by localhost (example.org [127.0.0.1]) (amavisd-new, port 10024) + with ESMTP id 151vjdIDehPR for ; + Fri, 26 Sep 2008 10:54:08 +0200 (CEST) +Received: from localhost (example.org [127.0.0.1]) + by example.org (Postfix) with ESMTP id 030C5C2E001C + for ; Fri, 26 Sep 2008 10:54:08 +0200 (CEST) +Received: from ug-out-1516.google.com (ug-out-1516.google.com [66.249.92.165]) + by example.org (Postfix) with ESMTP id D88AAC2E001A + for ; Fri, 26 Sep 2008 10:54:07 +0200 (CEST) +Received: by ug-out-1516.google.com with SMTP id 34so6700uge.3 + for ; Fri, 26 Sep 2008 01:54:07 -0700 (PDT) +DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; + d=google.com; s=beta; + h=domainkey-signature:mime-version:reply-to:sender:auto-submitted + :received:message-id:date:subject:from:to:content-type; + bh=NIbM6hZNgbcIAu3CGNdscvaw1JuMHR0cmVT+UvW5YdU=; + b=sGwxgD6sW0IDPFRSJcK9zvMtsS4jqziu+eF+p2fb7RsxCPFjU5FJFKbwhZQdVvA6I/ + rzueuvNP0EqBhfsdLVyA== +DomainKey-Signature: a=rsa-sha1; c=nofws; + d=google.com; s=beta; + h=mime-version:reply-to:sender:auto-submitted:message-id:date:subject + :from:to:content-type; + b=oo9wYH7lmDU5KDHTT4tpQ+BRlw/FYHBN2zt/an5FPuXE+dNM05UBVi8h87ig2c5Tvl + p53+hzDD2DoB/SlhqInA== +MIME-Version: 1.0 +Reply-To: Gunnar Wrobel +Sender: Google Kalender +Auto-Submitted: auto-generated +Received: by 10.210.130.14 with SMTP id c14mr120659ebd.11.1222419247313; Fri, + 26 Sep 2008 01:54:07 -0700 (PDT) +Message-ID: <0015174c3d6200b58f0457c8a9b5@google.com> +Date: Fri, 26 Sep 2008 01:54:07 -0700 +Subject: =?ISO-8859-1?B?W0VpbmxhZHVuZ10gdHJnIEAgVORnbGljaCB1bSAxMTowMCAocmVzQGRldi5wYXJkdXMu?= + =?ISO-8859-1?B?ZGUp?= +From: Gunnar Wrobel +To: "wrobel@example.org" +Content-Type: multipart/mixed; boundary=0015174c3d6200b57b0457c8a97d + +--0015174c3d6200b57b0457c8a97d +Content-Type: multipart/alternative; boundary=0015174c3d6200b5720457c8a97b + +--0015174c3d6200b5720457c8a97b +Content-Type: text/plain; charset=ISO-8859-1; format=flowed; delsp=yes +Content-Transfer-Encoding: base64 + +cmVzQGRldi5wYXJkdXMuZGUsIFNpZSB3dXJkZW4gZWluZ2VsYWRlbiB6dQ0KDQpUaXRlbDogdHJn +DQpaZWl0OiBU5GdsaWNoIHVtIDExOjAwIChaZWl0em9uZTogUm9tKQ0KS2FsZW5kZXI6IHJlc0Bk +ZXYucGFyZHVzLmRlDQoNClNpZSBr9m5uZW4gZGllc2VuIFRlcm1pbiBhbnplaWdlbiB1bnRlciAg +DQpodHRwOi8vd3d3Lmdvb2dsZS5jb20vY2FsZW5kYXIvZXZlbnQ/YWN0aW9uPVZJRVcmZWlkPWJX +czJiVzR6YUdGdWNEUTJhVGt3T0dWbGIyNHlaMmR1ZFdzZ2NtVnpRR1JsZGk1d1lYSmtkWE11WkdV +JnRvaz1NaklqWjNkeWIySmxiRUJuYjI5bmJHVnRZV2xzTG1OdmJUQTNaVGc1Tm1aaFpqZGxZVEE0 +WmpjM1pqYzBNMk16T0dSak5ETXlaVGc0WkRFeU0yVXpNV1EmY3R6PUV1cm9wZSUyRlJvbWUmaGw9 +ZGUNCg0KDQoNCkRpZXNlIEUtTWFpbCB3dXJkZSBhbiByZXNAZGV2LnBhcmR1cy5kZSBnZXNlbmRl +dCwgZGEgU2llIGVpbiBUZWlsbmVobWVyICANCmRpZXNlcyBUZXJtaW5zIHNpbmQuDQoNCkxlaG5l +biBTaWUgZGllc2VuIFRlcm1pbiBhYiwgdW0ga2VpbmUgd2VpdGVyZW4gTmFjaHJpY2h0ZW4genUg +ZGllc2VtIFRlcm1pbiAgDQp6dSBlcmhhbHRlbi4gU2llIGsmb3VtbDtubmVuIHNpY2ggYWx0ZXJu +YXRpdiBmJnV1bWw7ciBlaW4gR29vZ2xlLUtvbnRvICANCnVudGVyIGh0dHA6Ly93d3cuZ29vZ2xl +LmNvbS9jYWxlbmRhci8gYW5tZWxkZW4gdW5kIElocmUgIA0KQmVuYWNocmljaHRpZ3VuZ3NlaW5z +dGVsbHVuZ2VuIGYmdXVtbDtyIElocmVuIGdlc2FtdGVuIEthbGVuZGVyIHN0ZXVlcm4uDQo= +--0015174c3d6200b5720457c8a97b +Content-Type: text/html; charset=ISO-8859-1 +Content-Transfer-Encoding: 7bit + +
Google Kalender
+

wrobel@example.org, +Sie wurden eingeladen zu

+

trg

+

Täglich um 11:00 +
+(Zeitzone: +Rom) +
+ +
+Kalender: +wrobel@example.org

+

Weitere Termindetails»

+
Nehmen Sie teil?
+
+

 

+

Diese E-Mail wurde an wrobel@example.org gesendet, da Sie ein Teilnehmer dieses Termins sind.

Lehnen Sie diesen Termin ab, um keine weiteren Nachrichten zu diesem Termin zu erhalten. Sie können sich alternativ für ein Google-Konto unter http://www.google.com/calendar/ anmelden und Ihre Benachrichtigungseinstellungen für Ihren gesamten Kalender steuern.

+--0015174c3d6200b5720457c8a97b +Content-Type: text/calendar; charset=ISO-8859-1; method=REQUEST +Content-Transfer-Encoding: 7bit + +BEGIN:VCALENDAR +PRODID:-//Google Inc//Google Calendar 70.9054//EN +VERSION:2.0 +CALSCALE:GREGORIAN +METHOD:REQUEST +BEGIN:VTIMEZONE +TZID:Europe/Rome +X-LIC-LOCATION:Europe/Rome +BEGIN:DAYLIGHT +TZOFFSETFROM:+0100 +TZOFFSETTO:+0200 +TZNAME:CEST +DTSTART:19700329T020000 +RRULE:FREQ=YEARLY;BYMONTH=3;BYDAY=-1SU +END:DAYLIGHT +BEGIN:STANDARD +TZOFFSETFROM:+0200 +TZOFFSETTO:+0100 +TZNAME:CET +DTSTART:19701025T030000 +RRULE:FREQ=YEARLY;BYMONTH=10;BYDAY=-1SU +END:STANDARD +END:VTIMEZONE +BEGIN:VEVENT +DTSTART;TZID=Europe/Rome:20080926T110000 +DTEND;TZID=Europe/Rome:20080926T120000 +RRULE:FREQ=DAILY;WKST=SU +DTSTAMP:20080926T085407Z +ORGANIZER;CN=Gunnar Wrobel:mailto:test@example.org +UID:mk6mn3hanp46i908eeon2ggnuk@google.com +ATTENDEE;CUTYPE=INDIVIDUAL;ROLE=REQ-PARTICIPANT;PARTSTAT=NEEDS-ACTION;RSVP= + TRUE;CN=wrobel@example.org;X-NUM-GUESTS=0:mailto:wrobel@example.org +ATTENDEE;CUTYPE=INDIVIDUAL;ROLE=REQ-PARTICIPANT;PARTSTAT=ACCEPTED;RSVP=TRUE + ;CN=Gunnar Wrobel;X-NUM-GUESTS=0:mailto:test@example.org +CLASS:PRIVATE +CREATED:20080926T085406Z +DESCRIPTION:Zeigen Sie Ihren Termin unter http://www.google.com/calendar/ev + ent?action=VIEW&eid=bWs2bW4zaGFucDQ2aTkwOGVlb24yZ2dudWsgcmVzQGRldi5wYXJkdXM + uZGU&tok=MjIjZ3dyb2JlbEBnb29nbGVtYWlsLmNvbTA3ZTg5NmZhZjdlYTA4Zjc3Zjc0M2MzOG + RjNDMyZTg4ZDEyM2UzMWQ&ctz=Europe%2FRome&hl=de an. +LAST-MODIFIED:20080926T085406Z +LOCATION:Somewhere +SEQUENCE:0 +STATUS:CONFIRMED +SUMMARY:trg +TRANSP:OPAQUE +END:VEVENT +END:VCALENDAR + +--0015174c3d6200b5720457c8a97b-- +--0015174c3d6200b57b0457c8a97d +Content-Type: application/ics; name="invite.ics" +Content-Disposition: attachment; filename="invite.ics" +Content-Transfer-Encoding: 7bit + +BEGIN:VCALENDAR +PRODID:-//Google Inc//Google Calendar 70.9054//EN +VERSION:2.0 +CALSCALE:GREGORIAN +METHOD:REQUEST +BEGIN:VTIMEZONE +TZID:Europe/Rome +X-LIC-LOCATION:Europe/Rome +BEGIN:DAYLIGHT +TZOFFSETFROM:+0100 +TZOFFSETTO:+0200 +TZNAME:CEST +DTSTART:19700329T020000 +RRULE:FREQ=YEARLY;BYMONTH=3;BYDAY=-1SU +END:DAYLIGHT +BEGIN:STANDARD +TZOFFSETFROM:+0200 +TZOFFSETTO:+0100 +TZNAME:CET +DTSTART:19701025T030000 +RRULE:FREQ=YEARLY;BYMONTH=10;BYDAY=-1SU +END:STANDARD +END:VTIMEZONE +BEGIN:VEVENT +DTSTART;TZID=Europe/Rome:20080926T110000 +DTEND;TZID=Europe/Rome:20080926T120000 +RRULE:FREQ=DAILY;WKST=SU +DTSTAMP:20080926T085407Z +ORGANIZER;CN=Gunnar Wrobel:mailto:test@example.org +UID:mk6mn3hanp46i908eeon2ggnuk@google.com +ATTENDEE;CUTYPE=INDIVIDUAL;ROLE=REQ-PARTICIPANT;PARTSTAT=NEEDS-ACTION;RSVP= + TRUE;CN=wrobel@example.org;X-NUM-GUESTS=0:mailto:wrobel@example.org +ATTENDEE;CUTYPE=INDIVIDUAL;ROLE=REQ-PARTICIPANT;PARTSTAT=ACCEPTED;RSVP=TRUE + ;CN=Gunnar Wrobel;X-NUM-GUESTS=0:mailto:test@example.org +CLASS:PRIVATE +CREATED:20080926T085406Z +DESCRIPTION:Zeigen Sie Ihren Termin unter http://www.google.com/calendar/ev + ent?action=VIEW&eid=bWs2bW4zaGFucDQ2aTkwOGVlb24yZ2dudWsgcmVzQGRldi5wYXJkdXM + uZGU&tok=MjIjZ3dyb2JlbEBnb29nbGVtYWlsLmNvbTA3ZTg5NmZhZjdlYTA4Zjc3Zjc0M2MzOG + RjNDMyZTg4ZDEyM2UzMWQ&ctz=Europe%2FRome&hl=de an. +LAST-MODIFIED:20080926T085406Z +LOCATION: +SEQUENCE:0 +STATUS:CONFIRMED +SUMMARY:trg +TRANSP:OPAQUE +END:VEVENT +END:VCALENDAR + +--0015174c3d6200b57b0457c8a97d--