[CalendarServer-changes] [14963] CalendarServer/branches/release/CalendarServer-5.4-dev/txdav/caldav /datastore/scheduling/imip

source_changes at macosforge.org source_changes at macosforge.org
Tue Jul 14 14:01:30 PDT 2015


Revision: 14963
          http://trac.calendarserver.org//changeset/14963
Author:   cdaboo at apple.com
Date:     2015-07-14 14:01:30 -0700 (Tue, 14 Jul 2015)
Log Message:
-----------
Fix iMIP send failures when organizer CN is missing or contains non-ascii characters. Make sure iMIP message-ids use the configured server host name as the domain portion of the id.

Modified Paths:
--------------
    CalendarServer/branches/release/CalendarServer-5.4-dev/txdav/caldav/datastore/scheduling/imip/inbound.py
    CalendarServer/branches/release/CalendarServer-5.4-dev/txdav/caldav/datastore/scheduling/imip/outbound.py
    CalendarServer/branches/release/CalendarServer-5.4-dev/txdav/caldav/datastore/scheduling/imip/smtpsender.py
    CalendarServer/branches/release/CalendarServer-5.4-dev/txdav/caldav/datastore/scheduling/imip/test/test_outbound.py

Modified: CalendarServer/branches/release/CalendarServer-5.4-dev/txdav/caldav/datastore/scheduling/imip/inbound.py
===================================================================
--- CalendarServer/branches/release/CalendarServer-5.4-dev/txdav/caldav/datastore/scheduling/imip/inbound.py	2015-07-14 20:58:41 UTC (rev 14962)
+++ CalendarServer/branches/release/CalendarServer-5.4-dev/txdav/caldav/datastore/scheduling/imip/inbound.py	2015-07-14 21:01:30 UTC (rev 14963)
@@ -28,7 +28,6 @@
 from twisted.internet import protocol, defer, ssl
 from twisted.internet.defer import inlineCallbacks, returnValue, succeed
 from twisted.mail import pop3client, imap4
-from twisted.mail.smtp import messageid
 
 from twistedcaldav.config import config
 from twistedcaldav.ical import Property, Component
@@ -349,7 +348,7 @@
             del msg["To"]
             msg["To"] = toAddr
             log.warn("Mail gateway forwarding reply back to organizer")
-            yield smtpSender.sendMessage(fromAddr, toAddr, messageid(), msg.as_string())
+            yield smtpSender.sendMessage(fromAddr, toAddr, SMTPSender.betterMessageID(), msg.as_string())
             returnValue(self.REPLY_FORWARDED_TO_ORGANIZER)
 
         # Process the imip attachment; inject to calendar server

Modified: CalendarServer/branches/release/CalendarServer-5.4-dev/txdav/caldav/datastore/scheduling/imip/outbound.py
===================================================================
--- CalendarServer/branches/release/CalendarServer-5.4-dev/txdav/caldav/datastore/scheduling/imip/outbound.py	2015-07-14 20:58:41 UTC (rev 14962)
+++ CalendarServer/branches/release/CalendarServer-5.4-dev/txdav/caldav/datastore/scheduling/imip/outbound.py	2015-07-14 21:01:30 UTC (rev 14963)
@@ -32,7 +32,7 @@
 from twext.enterprise.queue import WorkItem
 from twext.python.log import Logger
 from twisted.internet.defer import inlineCallbacks, returnValue
-from twisted.mail.smtp import messageid, rfc822date
+from twisted.mail.smtp import rfc822date
 from twisted.web.microdom import Text as DOMText, Element as DOMElement
 from twisted.web.microdom import parseString
 from twisted.web.template import XMLString, TEMPLATE_NAMESPACE, Element, renderer, flattenString, tags
@@ -449,6 +449,8 @@
             orgEmail = organizerMailto[7:]
 
             orgCN = calendar.getOrganizerProperty().parameterValue('CN', None)
+            if orgCN:
+                orgCN = orgCN.decode("utf-8")
             addressWithToken = formattedFrom
 
         # At the point we've created the token in the db, which we always
@@ -552,7 +554,7 @@
         msg["Reply-To"] = replyToAddress
         msg["To"] = toAddress
         msg["Date"] = rfc822date()
-        msgId = messageid()
+        msgId = SMTPSender.betterMessageID()
         msg["Message-ID"] = msgId
 
         msgAlt = MIMEMultipart("alternative")
@@ -654,8 +656,9 @@
         # template stuff, and once again, it's just a 'mailto:'.
         # tags.a(href="mailto:"+email)[cn]
         if orgEmail:
-            details['htmlOrganizer'] = tags.a(href="mailto:%s" % (orgEmail,))(
-                orgCN)
+            if not orgCN:
+                orgCN = orgEmail
+            details['htmlOrganizer'] = tags.a(href="mailto:%s" % (orgEmail,))(orgCN)
         else:
             details['htmlOrganizer'] = orgCN
 

Modified: CalendarServer/branches/release/CalendarServer-5.4-dev/txdav/caldav/datastore/scheduling/imip/smtpsender.py
===================================================================
--- CalendarServer/branches/release/CalendarServer-5.4-dev/txdav/caldav/datastore/scheduling/imip/smtpsender.py	2015-07-14 20:58:41 UTC (rev 14962)
+++ CalendarServer/branches/release/CalendarServer-5.4-dev/txdav/caldav/datastore/scheduling/imip/smtpsender.py	2015-07-14 21:01:30 UTC (rev 14963)
@@ -24,7 +24,8 @@
 from twext.internet.gaiendpoint import GAIEndpoint
 from twext.python.log import Logger
 from twisted.internet import defer, ssl, reactor as _reactor
-from twisted.mail.smtp import ESMTPSenderFactory
+from twisted.mail.smtp import ESMTPSenderFactory, messageid
+from twistedcaldav.config import config
 
 log = Logger()
 
@@ -74,3 +75,15 @@
         deferred.addCallback(_success, msgId, fromAddr, toAddr)
         deferred.addErrback(_failure, msgId, fromAddr, toAddr)
         return deferred
+
+
+    @staticmethod
+    def betterMessageID():
+        """
+        Strip out the domain in the default Twisted Message-ID value and replace with our configured
+        server host name. That will avoid leaking internal app-server host names in a multi-host setup.
+
+        @return: our safe message-id value
+        @rtype: L{str}
+        """
+        return "{}@{}>".format(messageid().split("@")[0], config.ServerHostName)

Modified: CalendarServer/branches/release/CalendarServer-5.4-dev/txdav/caldav/datastore/scheduling/imip/test/test_outbound.py
===================================================================
--- CalendarServer/branches/release/CalendarServer-5.4-dev/txdav/caldav/datastore/scheduling/imip/test/test_outbound.py	2015-07-14 20:58:41 UTC (rev 14962)
+++ CalendarServer/branches/release/CalendarServer-5.4-dev/txdav/caldav/datastore/scheduling/imip/test/test_outbound.py	2015-07-14 21:01:30 UTC (rev 14963)
@@ -57,7 +57,7 @@
 DESCRIPTION:awesome description with "<" and "&"
 END:VEVENT
 END:VCALENDAR
-"""
+""".encode("utf-8")
 
 inviteTextNoTimezone = u"""BEGIN:VCALENDAR
 VERSION:2.0
@@ -80,7 +80,7 @@
 DESCRIPTION:awesome description with "<" and "&"
 END:VEVENT
 END:VCALENDAR
-"""
+""".encode("utf-8")
 
 inviteTextWithTimezone = u"""BEGIN:VCALENDAR
 VERSION:2.0
@@ -246,7 +246,7 @@
 DESCRIPTION:awesome description with "<" and "&"
 END:VEVENT
 END:VCALENDAR
-"""
+""".encode("utf-8")
 
 ORGANIZER = "urn:uuid:C3B38B00-4166-11DD-B22C-A07C87E02F6A"
 ATTENDEE = "mailto:attendee at example.com"
@@ -391,63 +391,63 @@
 
             # Update
             (
-                """BEGIN:VCALENDAR
+                u"""BEGIN:VCALENDAR
 VERSION:2.0
 METHOD:REQUEST
 BEGIN:VEVENT
 UID:CFDD5E46-4F74-478A-9311-B3FF905449C3
 DTSTART:20100325T154500Z
 DTEND:20100325T164500Z
-ATTENDEE;CN=The Attendee;CUTYPE=INDIVIDUAL;PARTSTAT=NEEDS-ACTION;RSVP=TRUE:
+ATTENDEE;CN=Th\xe9 Attendee;CUTYPE=INDIVIDUAL;PARTSTAT=NEEDS-ACTION;RSVP=TRUE:
  mailto:attendee at example.com
-ATTENDEE;CN=The Organizer;CUTYPE=INDIVIDUAL;EMAIL=organizer at example.com;PAR
+ATTENDEE;CN=Th\xe9 Organizer;CUTYPE=INDIVIDUAL;EMAIL=organizer at example.com;PAR
  TSTAT=ACCEPTED:urn:uuid:C3B38B00-4166-11DD-B22C-A07C87E02F6A
-ORGANIZER;CN=The Organizer;EMAIL=organizer at example.com:urn:uuid:C3B38B00-41
+ORGANIZER;CN=Th\xe9 Organizer;EMAIL=organizer at example.com:urn:uuid:C3B38B00-41
  66-11DD-B22C-A07C87E02F6A
-SUMMARY:testing outbound( ) *update*
+SUMMARY:t\xe9sting outbound( ) *update*
 END:VEVENT
 END:VCALENDAR
-""",
+""".encode("utf-8"),
                 "CFDD5E46-4F74-478A-9311-B3FF905449C3",
                 "urn:uuid:C3B38B00-4166-11DD-B22C-A07C87E02F6A",
                 "mailto:attendee at example.com",
                 "update",
                 "organizer at example.com",
-                "The Organizer",
+                u"Th\xe9 Organizer",
                 [
-                    (u'The Attendee', u'attendee at example.com'),
-                    (u'The Organizer', u'organizer at example.com')
+                    (u'Th\xe9 Attendee', u'attendee at example.com'),
+                    (u'Th\xe9 Organizer', u'organizer at example.com')
                 ],
-                "The Organizer <organizer at example.com>",
-                "The Organizer <organizer at example.com>",
+                u"Th\xe9 Organizer <organizer at example.com>",
+                "=?utf-8?q?Th=C3=A9_Organizer_=3Corganizer=40example=2Ecom=3E?=",
                 "attendee at example.com",
             ),
 
             # Reply
             (
-                """BEGIN:VCALENDAR
+                u"""BEGIN:VCALENDAR
 VERSION:2.0
 METHOD:REPLY
 BEGIN:VEVENT
 UID:DFDD5E46-4F74-478A-9311-B3FF905449C4
 DTSTART:20100325T154500Z
 DTEND:20100325T164500Z
-ATTENDEE;CN=The Attendee;CUTYPE=INDIVIDUAL;EMAIL=attendee at example.com;PARTST
+ATTENDEE;CN=Th\xe9 Attendee;CUTYPE=INDIVIDUAL;EMAIL=attendee at example.com;PARTST
  AT=ACCEPTED:urn:uuid:C3B38B00-4166-11DD-B22C-A07C87E02F6A
-ORGANIZER;CN=The Organizer;EMAIL=organizer at example.com:mailto:organizer at exam
+ORGANIZER;CN=Th\xe9 Organizer;EMAIL=organizer at example.com:mailto:organizer at exam
  ple.com
-SUMMARY:testing outbound( ) *reply*
+SUMMARY:t\xe9sting outbound( ) *reply*
 END:VEVENT
 END:VCALENDAR
-""",
+""".encode("utf-8"),
                 None,
                 "urn:uuid:C3B38B00-4166-11DD-B22C-A07C87E02F6A",
                 "mailto:organizer at example.com",
                 "reply",
                 "organizer at example.com",
-                "The Organizer",
+                u"Th\xe9 Organizer",
                 [
-                    (u'The Attendee', u'attendee at example.com'),
+                    (u'Th\xe9 Attendee', u'attendee at example.com'),
                 ],
                 "attendee at example.com",
                 "attendee at example.com",
@@ -621,6 +621,59 @@
         self.assertEquals(actualTypes, expectedTypes)
 
 
+    def test_generateEmail_noOrganizerCN(self):
+        """
+        L{MailHandler.generateEmail} generates a MIME-formatted email when
+        the organizer property has no CN parameter.
+        """
+        calendar = Component.fromString(initialInviteText)
+        _ignore_msgID, msgTxt = self.sender.generateEmail(
+            inviteState='new',
+            calendar=calendar,
+            orgEmail=u"user01 at localhost",
+            orgCN=None,
+            attendees=[(u"Us\xe9r One", "user01 at localhost"),
+                       (u"User 2", "user02 at localhost")],
+            fromAddress="user01 at localhost",
+            replyToAddress="imip-system at localhost",
+            toAddress="user03 at localhost",
+        )
+        message = email.message_from_string(msgTxt)
+        self.assertTrue(message is not None)
+
+
+    def test_generateEmail_noAttendeeCN(self):
+        """
+        L{MailHandler.generateEmail} generates a MIME-formatted email when
+        the attendee property has no CN parameter.
+        """
+        calendar = Component.fromString(initialInviteText)
+        _ignore_msgID, msgTxt = self.sender.generateEmail(
+            inviteState='new',
+            calendar=calendar,
+            orgEmail=u"user01 at localhost",
+            orgCN=u"User Z\xe9ro One",
+            attendees=[(None, "user01 at localhost"),
+                       (None, "user02 at localhost")],
+            fromAddress="user01 at localhost",
+            replyToAddress="imip-system at localhost",
+            toAddress="user03 at localhost",
+        )
+        message = email.message_from_string(msgTxt)
+        self.assertTrue(message is not None)
+
+
+    def test_messageID(self):
+        """
+        L{SMTPSender.betterMessageID} generates a Message-ID domain matching
+        the L{config.ServerHostName} value.
+        """
+        self.patch(config, "ServerHostName", "calendar.example.com")
+        msgID, message = self.generateSampleEmail()
+        self.assertEquals(message['Message-ID'], msgID)
+        self.assertEqual(msgID[:-1].split("@")[1], config.ServerHostName)
+
+
     def test_alwaysIncludeTimezones(self):
         """
         L{MailHandler.generateEmail} generates a MIME-formatted email with a
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.macosforge.org/pipermail/calendarserver-changes/attachments/20150714/505fbef3/attachment-0001.html>


More information about the calendarserver-changes mailing list