summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorThomas Bruederli <bruederli@kolabsys.com>2014-07-07 19:34:07 -0400
committerThomas Bruederli <bruederli@kolabsys.com>2014-07-07 19:34:07 -0400
commit317c074fc70c972ed068c01e658925512abbc28a (patch)
treed636ce437c6f3ddfeb1428ebd8c45e2ef738a09b
parenta674289628249f45ec46c3096b1c476692943ff3 (diff)
downloadpykolab-317c074fc70c972ed068c01e658925512abbc28a.tar.gz
Catch potential exceptions while sending iTip replies; set recipient parstat=needs-action when saving new/re-scheduled invitations directly to calendar
-rw-r--r--pykolab/itip/__init__.py31
-rw-r--r--tests/functional/test_wallace/test_007_invitationpolicy.py31
-rw-r--r--wallace/module_invitationpolicy.py16
3 files changed, 58 insertions, 20 deletions
diff --git a/pykolab/itip/__init__.py b/pykolab/itip/__init__.py
index f32cad4..43646df 100644
--- a/pykolab/itip/__init__.py
+++ b/pykolab/itip/__init__.py
@@ -197,13 +197,9 @@ def send_reply(from_address, itip_events, response_text, subject=None):
"""
import smtplib
- smtp = smtplib.SMTP("localhost", 10027)
conf = pykolab.getConf()
- if conf.debuglevel > 8:
- smtp.set_debuglevel(True)
-
if isinstance(itip_events, dict):
itip_events = [ itip_events ]
@@ -217,12 +213,25 @@ def send_reply(from_address, itip_events, response_text, subject=None):
if subject is not None:
subject = subject % { 'summary':event_summary, 'status':_(participant_status), 'name':attendee.get_name() }
- message = itip_event['xml'].to_message_itip(from_address,
- method="REPLY",
- participant_status=participant_status,
- message_text=message_text,
- subject=subject
- )
- smtp.sendmail(message['From'], message['To'], message.as_string())
+ try:
+ message = itip_event['xml'].to_message_itip(from_address,
+ method="REPLY",
+ participant_status=participant_status,
+ message_text=message_text,
+ subject=subject
+ )
+ except Exception, e:
+ log.error(_("Failed to compose iTip reply message: %r") % (e))
+ return
+
+ smtp = smtplib.SMTP("localhost", 10027)
+
+ if conf.debuglevel > 8:
+ smtp.set_debuglevel(True)
+
+ try:
+ smtp.sendmail(message['From'], message['To'], message.as_string())
+ except Exception, e:
+ log.error(_("SMTP sendmail error: %r") % (e))
smtp.quit()
diff --git a/tests/functional/test_wallace/test_007_invitationpolicy.py b/tests/functional/test_wallace/test_007_invitationpolicy.py
index 3b68aef..0d2875c 100644
--- a/tests/functional/test_wallace/test_007_invitationpolicy.py
+++ b/tests/functional/test_wallace/test_007_invitationpolicy.py
@@ -150,7 +150,6 @@ class TestWallaceInvitationpolicy(unittest.TestCase):
self.john = {
'displayname': 'John Doe',
'mail': 'john.doe@example.org',
- 'sender': 'John Doe <john.doe@example.org>',
'dn': 'uid=doe,ou=People,dc=example,dc=org',
'preferredlanguage': 'en_US',
'mailbox': 'user/john.doe@example.org',
@@ -161,7 +160,6 @@ class TestWallaceInvitationpolicy(unittest.TestCase):
self.jane = {
'displayname': 'Jane Manager',
'mail': 'jane.manager@example.org',
- 'sender': 'Jane Manager <jane.manager@example.org>',
'dn': 'uid=manager,ou=People,dc=example,dc=org',
'preferredlanguage': 'en_US',
'mailbox': 'user/jane.manager@example.org',
@@ -172,7 +170,6 @@ class TestWallaceInvitationpolicy(unittest.TestCase):
self.jack = {
'displayname': 'Jack Tentative',
'mail': 'jack.tentative@example.org',
- 'sender': 'Jack Tentative <jack.tentative@example.org>',
'dn': 'uid=tentative,ou=People,dc=example,dc=org',
'preferredlanguage': 'en_US',
'mailbox': 'user/jack.tentative@example.org',
@@ -486,7 +483,32 @@ class TestWallaceInvitationpolicy(unittest.TestCase):
def test_005_invite_rescheduling_reject(self):
- pass
+ self.purge_mailbox(self.john['mailbox'])
+ self.purge_mailbox(self.jack['kolabtargetfolder'])
+
+ start = datetime.datetime(2014,8,9, 17,0,0, tzinfo=pytz.timezone("Europe/Berlin"))
+ uid = self.send_itip_invitation(self.jack['mail'], start)
+
+ response = self.check_message_received(self.itip_reply_subject % { 'summary':'test', 'status':_('TENTATIVE') }, self.jack['mail'])
+ self.assertIsInstance(response, email.message.Message)
+
+ # send update with new but conflicting date and incremented sequence
+ self.create_calendar_event(datetime.datetime(2014,8,10, 10,30,0, tzinfo=pytz.timezone("Europe/Berlin")), user=self.jack)
+ new_start = datetime.datetime(2014,8,10, 9,30,0, tzinfo=pytz.timezone("Europe/Berlin"))
+ self.send_itip_update(self.jack['mail'], uid, new_start, summary="test (updated)", sequence=1)
+
+ response = self.check_message_received(self.itip_reply_subject % { 'summary':'test', 'status':_('DECLINED') }, self.jack['mail'])
+ self.assertEqual(response, None)
+
+ # verify re-scheduled copy in jack's calendar with NEEDS-ACTION
+ event = self.check_user_calendar_event(self.jack['kolabtargetfolder'], uid)
+ self.assertIsInstance(event, pykolab.xml.Event)
+ self.assertEqual(event.get_start(), new_start)
+ self.assertEqual(event.get_sequence(), 1)
+
+ attendee = event.get_attendee(self.jack['mail'])
+ self.assertTrue(attendee.get_rsvp())
+ self.assertEqual(attendee.get_participant_status(), kolabformat.PartNeedsAction)
def test_006_invitation_reply(self):
@@ -563,3 +585,4 @@ class TestWallaceInvitationpolicy(unittest.TestCase):
notification_text = str(notification.get_payload());
self.assertIn(self.jack['mail'], notification_text)
self.assertNotIn(_("PENDING"), notification_text)
+
diff --git a/wallace/module_invitationpolicy.py b/wallace/module_invitationpolicy.py
index 7375d2d..41917da 100644
--- a/wallace/module_invitationpolicy.py
+++ b/wallace/module_invitationpolicy.py
@@ -283,10 +283,11 @@ def execute(*args, **kw):
if done == MESSAGE_PROCESSED:
log.debug(_("iTip message %r consumed by the invitationpolicy module") % (message.get('Message-ID')), level=5)
os.unlink(filepath)
- filepath = None
+ cleanup()
+ return None
- cleanup()
- return filepath
+ # accept message into the destination inbox
+ accept(filepath)
def process_itip_request(itip_event, policy, recipient_email, sender_email, receiving_user):
@@ -357,7 +358,8 @@ def process_itip_request(itip_event, policy, recipient_email, sender_email, rece
subject=_('"%(summary)s" has been %(status)s'))
elif policy & ACT_SAVE_TO_CALENDAR:
- # copy the invitation into the user's calendar with unchanged PARTSTAT
+ # copy the invitation into the user's calendar with PARTSTAT=NEEDS-ACTION
+ itip_event['xml'].set_attendee_participant_status(receiving_attendee, 'NEEDS-ACTION')
save_event = True
else:
@@ -801,7 +803,11 @@ def send_reply_notification(event, receiving_user):
if conf.debuglevel > 8:
smtp.set_debuglevel(True)
- smtp.sendmail(orgemail, receiving_user['mail'], msg.as_string())
+ try:
+ smtp.sendmail(orgemail, receiving_user['mail'], msg.as_string())
+ except Exception, e:
+ log.error(_("SMTP sendmail error: %r") % (e))
+
smtp.quit()