[CalendarServer-changes] [2821] CalendarServer/branches/users/sagen/mailgateway-implicit-2745/ twistedcaldav
source_changes at macosforge.org
source_changes at macosforge.org
Wed Aug 13 19:40:34 PDT 2008
Revision: 2821
http://trac.macosforge.org/projects/calendarserver/changeset/2821
Author: sagen at apple.com
Date: 2008-08-13 19:40:34 -0700 (Wed, 13 Aug 2008)
Log Message:
-----------
Refactoring DSN/reply processing a bit for testability
Modified Paths:
--------------
CalendarServer/branches/users/sagen/mailgateway-implicit-2745/twistedcaldav/mail.py
CalendarServer/branches/users/sagen/mailgateway-implicit-2745/twistedcaldav/test/test_mail.py
Modified: CalendarServer/branches/users/sagen/mailgateway-implicit-2745/twistedcaldav/mail.py
===================================================================
--- CalendarServer/branches/users/sagen/mailgateway-implicit-2745/twistedcaldav/mail.py 2008-08-13 21:56:59 UTC (rev 2820)
+++ CalendarServer/branches/users/sagen/mailgateway-implicit-2745/twistedcaldav/mail.py 2008-08-14 02:40:34 UTC (rev 2821)
@@ -284,7 +284,8 @@
def __init__(self, path):
- path = os.path.join(path, MailGatewayTokensDatabase.dbFilename)
+ if path != ":memory:":
+ path = os.path.join(path, MailGatewayTokensDatabase.dbFilename)
super(MailGatewayTokensDatabase, self).__init__(path, True)
def createToken(self, organizer, attendee):
@@ -515,13 +516,11 @@
return True, action, calBody
-
else:
# Not a DSN
return False, None, None
-
def _extractToken(self, text):
try:
pre, post = text.split('@')
@@ -530,50 +529,33 @@
except ValueError:
return None
+ def processDSN(self, calBody, msgId, fn):
+ calendar = ical.Component.fromString(calBody)
+ # Extract the token (from organizer property)
+ organizer = calendar.getOrganizer()
+ token = self._extractToken(organizer)
+ if not token:
+ self.log_error("Mail gateway can't find token in DSN %s" % (msgId,))
+ return
- def inbound(self, message):
- msg = email.message_from_string(message)
+ result = self.db.lookupByToken(token)
+ if result is None:
+ # This isn't a token we recognize
+ self.log_error("Mail gateway found a token (%s) but didn't recognize it in DSN %s" % (token, msgId))
+ return
- isDSN, action, calBody = self.checkDSN(msg)
- if isDSN:
- if action == 'failed' and calBody:
- # This is a DSN we can handle
- calendar = ical.Component.fromString(calBody)
- # Extract the token (from organizer property)
- organizer = calendar.getOrganizer()
- token = self._extractToken(organizer)
- if not token:
- self.log_error("Mail gateway can't find token in DSN %s" % (msg['Message-ID'],))
- return
+ organizer, attendee = result
+ organizer = str(organizer)
+ attendee = str(attendee)
+ calendar.removeAllButOneAttendee(attendee)
+ calendar.getOrganizerProperty().setValue(organizer)
+ calendar.addProperty(Property("REQUEST-STATUS",
+ "5.1;Service unavailable"))
- result = self.db.lookupByToken(token)
- if result is None:
- # This isn't a token we recognize
- self.log_error("Mail gateway found a token (%s) but didn't recognize it in DSN %s" % (token, msg['Message-ID']))
- return
+ self.log_error("Mail gateway processing DSN %s" % (msgId,))
+ return fn(organizer, attendee, calendar, msgId)
- organizer, attendee = result
- organizer = str(organizer)
- attendee = str(attendee)
- calendar.removeAllButOneAttendee(attendee)
- calendar.getOrganizerProperty().setValue(organizer)
- calendar.addProperty(Property("REQUEST-STATUS",
- "5.1;Service unavailable"))
-
- self.log_error("Mail gateway processing DSN %s" % (msg['Message-ID'],))
- return injectMessage(organizer, attendee, calendar,
- msg['Message-ID'])
-
- else:
- # It's a DSN without enough to go on
- self.log_error("Mail gateway can't process DSN %s" % (msg['Message-ID'],))
- return
-
- self.log_info("Mail gateway received message %s from %s to %s" %
- (msg['Message-ID'], msg['From'], msg['To']))
-
- # TODO: make sure this is an email message we want to handle
-
+ def processReply(self, msg, fn):
# extract the token from the To header
name, addr = email.utils.parseaddr(msg['To'])
if addr:
@@ -610,10 +592,29 @@
attendee = str(attendee)
calendar.removeAllButOneAttendee(attendee)
calendar.getOrganizerProperty().setValue(organizer)
- return injectMessage(organizer, attendee, calendar,
- msg['Message-ID'])
+ return fn(organizer, attendee, calendar, msg['Message-ID'])
+ def inbound(self, message, fn=injectMessage):
+ msg = email.message_from_string(message)
+
+ isDSN, action, calBody = self.checkDSN(msg)
+ if isDSN:
+ if action == 'failed' and calBody:
+ # This is a DSN we can handle
+ return self.processDSN(calBody, msg['Message-ID'], fn)
+ else:
+ # It's a DSN without enough to go on
+ self.log_error("Mail gateway can't process DSN %s" % (msg['Message-ID'],))
+ return
+
+ self.log_info("Mail gateway received message %s from %s to %s" %
+ (msg['Message-ID'], msg['From'], msg['To']))
+
+ return self.processReply(msg, fn)
+
+
+
def outbound(self, organizer, attendee, calendar):
# create token, send email
token = self.db.getToken(organizer, attendee)
@@ -646,6 +647,7 @@
attendee = attendee[7:]
message = message.replace("${toaddress}", attendee)
+ self.log_debug("Sending: %s" % (message,))
def _success(result, msgId, fromAddr, toAddr):
self.log_info("Mail gateway sent message %s from %s to %s" %
(msgId, fromAddr, toAddr))
@@ -674,6 +676,14 @@
msgId = messageid()
msg["Message-ID"] = msgId
+ # the icalendar attachment (putting this first because if we get a
+ # DSN failure in response, having this attachment in this position
+ # seems to increase the chance we will get it back in the DSN).
+ msgIcal = MIMEText(str(calendar), "calendar", "UTF-8")
+ msgIcal.add_header("Content-Disposition",
+ "attachment;filename=invitation.ics")
+ msg.attach(msgIcal)
+
msgAlt = MIMEMultipart("alternative")
msg.attach(msgAlt)
@@ -707,12 +717,6 @@
(imageName,))
msgHtmlRelated.attach(msgImage)
- # the icalendar attachment
- msgIcal = MIMEText(str(calendar), "calendar", "UTF-8")
- msgIcal.add_header("Content-Disposition",
- "attachment;filename=invitation.ics")
- msg.attach(msgIcal)
-
return msgId, msg.as_string()
def _generateCalendarSummary(self, calendar, organizer):
@@ -1045,7 +1049,7 @@
return
d = self.factory.handleMessage(messageData)
- if d:
+ if isinstance(d, defer.Deferred):
d.addCallback(self.cbFlagDeleted, messageList)
else:
# No deferred returned, so no need for addCallback( )
Modified: CalendarServer/branches/users/sagen/mailgateway-implicit-2745/twistedcaldav/test/test_mail.py
===================================================================
--- CalendarServer/branches/users/sagen/mailgateway-implicit-2745/twistedcaldav/test/test_mail.py 2008-08-13 21:56:59 UTC (rev 2820)
+++ CalendarServer/branches/users/sagen/mailgateway-implicit-2745/twistedcaldav/test/test_mail.py 2008-08-14 02:40:34 UTC (rev 2821)
@@ -44,3 +44,27 @@
file(os.path.join(self.dataDir, filename)).read()
)
self.assertEquals(self.handler.checkDSN(msg), expected)
+
+
+ def test_processDSN(self):
+
+ template = 'BEGIN:VCALENDAR\nVERSION:2.0\nCALSCALE:GREGORIAN\nMETHOD:REQUEST\nPRODID:-//example Inc.//iCal 3.0//EN\nBEGIN:VTIMEZONE\nTZID:US/Pacific\nBEGIN:STANDARD\nDTSTART:20071104T020000\nRRULE:FREQ=YEARLY;BYMONTH=11;BYDAY=1SU\nTZNAME:PST\nTZOFFSETFROM:-0700\nTZOFFSETTO:-0800\nEND:STANDARD\nBEGIN:DAYLIGHT\nDTSTART:20070311T020000\nRRULE:FREQ=YEARLY;BYMONTH=3;BYDAY=2SU\nTZNAME:PDT\nTZOFFSETFROM:-0800\nTZOFFSETTO:-0700\nEND:DAYLIGHT\nEND:VTIMEZONE\nBEGIN:VEVENT\nUID:1E71F9C8-AEDA-48EB-98D0-76E898F6BB5C\nDTSTART;TZID=US/Pacific:20080812T094500\nDTEND;TZID=US/Pacific:20080812T104500\nATTENDEE;CUTYPE=INDIVIDUAL;CN=User 01;PARTSTAT=ACCEPTED:mailto:user01 at exam\n ple.com\nATTENDEE;CUTYPE=INDIVIDUAL;RSVP=TRUE;ROLE=REQ-PARTICIPANT;PARTSTAT=NEEDS-A\n CTION;CN=nonexistant at example.com:mailto:nonexistant at example.com\nCREATED:20080812T191857Z\nDTSTAMP:20080812T191932Z\nORGANIZER;CN=User 01:mailto:xyzzy+%s at example.com\nSEQUENCE:2\nSUMMARY:New Event\nTRANSP:OPAQUE\nEND:VEVENT\nEND
:VCALENDAR\n'
+ calBody = template % "bogus_token"
+
+ def echo(*args):
+ return args
+
+ self.assertEquals(self.handler.processDSN(calBody, "xyzzy", echo),
+ None)
+
+ token = self.handler.db.createToken("mailto:user01 at example.com",
+ "mailto:user02 at example.com")
+
+ calBody = template % token
+
+ organizer, attendee, calendar, msgId = self.handler.processDSN(calBody,
+ "xyzzy", echo)
+ self.assertEquals(organizer, 'mailto:user01 at example.com')
+ self.assertEquals(attendee, 'mailto:user02 at example.com')
+ self.assertEquals(str(calendar), 'BEGIN:VCALENDAR\r\nVERSION:2.0\r\nCALSCALE:GREGORIAN\r\nMETHOD:REQUEST\r\nPRODID:-//example Inc.//iCal 3.0//EN\r\nBEGIN:VTIMEZONE\r\nTZID:US/Pacific\r\nBEGIN:STANDARD\r\nDTSTART:20071104T020000\r\nRRULE:FREQ=YEARLY;BYMONTH=11;BYDAY=1SU\r\nTZNAME:PST\r\nTZOFFSETFROM:-0700\r\nTZOFFSETTO:-0800\r\nEND:STANDARD\r\nBEGIN:DAYLIGHT\r\nDTSTART:20070311T020000\r\nRRULE:FREQ=YEARLY;BYMONTH=3;BYDAY=2SU\r\nTZNAME:PDT\r\nTZOFFSETFROM:-0800\r\nTZOFFSETTO:-0700\r\nEND:DAYLIGHT\r\nEND:VTIMEZONE\r\nREQUEST-STATUS:5.1\\;Service unavailable\r\nBEGIN:VEVENT\r\nUID:1E71F9C8-AEDA-48EB-98D0-76E898F6BB5C\r\nDTSTART;TZID=US/Pacific:20080812T094500\r\nDTEND;TZID=US/Pacific:20080812T104500\r\nCREATED:20080812T191857Z\r\nDTSTAMP:20080812T191932Z\r\nORGANIZER;CN=User 01:mailto:user01 at example.com\r\nSEQUENCE:2\r\nSUMMARY:New Event\r\nTRANSP:OPAQUE\r\nEND:VEVENT\r\nEND:VCALENDAR\r\n')
+ self.assertEquals(msgId, 'xyzzy')
-------------- next part --------------
An HTML attachment was scrubbed...
URL: http://lists.macosforge.org/pipermail/calendarserver-changes/attachments/20080813/3f067b5c/attachment-0001.html
More information about the calendarserver-changes
mailing list