def test_internaldate_style(self): self.check_normalised_and_not( b' 9-Feb-2007 17:08:08 -0430', datetime(2007, 2, 9, 17, 8, 8, 0, FixedOffset(-4 * 60 - 30))) self.check_normalised_and_not( b'19-Feb-2007 17:08:08 0400', datetime(2007, 2, 19, 17, 8, 8, 0, FixedOffset(4 * 60)))
def test_dots_for_time_separator(self): # As reported in issue #154. self.check_normalised_and_not( b'Sat, 8 May 2010 16.03.09 +0200', datetime(2010, 5, 8, 16, 3, 9, 0, FixedOffset(120))) self.check_normalised_and_not( b'Tue, 18 May 2010 16.03.09 -0200', datetime(2010, 5, 18, 16, 3, 9, 0, FixedOffset(-120))) self.check_normalised_and_not( b'Wednesday,18 August 2010 16.03.09 -0200', datetime(2010, 8, 18, 16, 3, 9, 0, FixedOffset(-120)))
def test_INTERNALDATE(self): def check(date_str, expected_dt): output = parse_fetch_response(['3 (INTERNALDATE "%s")' % date_str], normalise_times=False) actual_dt = output[3]['INTERNALDATE'] self.assertEqual(actual_dt, expected_dt) check(' 9-Feb-2007 17:08:08 -0430', datetime(2007, 2, 9, 17, 8, 8, 0, FixedOffset(-4 * 60 - 30))) check('12-Feb-2007 17:08:08 +0200', datetime(2007, 2, 12, 17, 8, 8, 0, FixedOffset(2 * 60))) check(' 9-Dec-2007 17:08:08 +0000', datetime(2007, 12, 9, 17, 8, 8, 0, FixedOffset(0)))
def test_ENVELOPE(self): envelope_str = ('1 (ENVELOPE ( ' '"Sun, 24 Mar 2013 22:06:10 +0200" ' '"subject" ' '(("name" NIL "address1" "domain1.com")) ' '((NIL NIL "address2" "domain2.com")) ' '(("name" NIL "address3" "domain3.com")) ' 'NIL' '((NIL NIL "address4" "domain4.com") ' '("person" NIL "address4b" "domain4b.com")) ' 'NIL "<reply-to-id>" "<msg_id>"))') output = parse_fetch_response([envelope_str], normalise_times=False) self.assertSequenceEqual( output[1]['ENVELOPE'], Envelope(datetime(2013, 3, 24, 22, 6, 10, tzinfo=FixedOffset(120)), "subject", (Address("name", None, "address1", "domain1.com"), ), (Address(None, None, "address2", "domain2.com"), ), (Address("name", None, "address3", "domain3.com"), ), None, (Address(None, None, "address4", "domain4.com"), Address("person", None, "address4b", "domain4b.com")), None, "<reply-to-id>", "<msg_id>"))
def test_for_system_DST_active(self, localtime): localtime_mock = Mock() localtime_mock.tm_isdst = True localtime.return_value = localtime_mock offset = FixedOffset.for_system() self.assertEqual(offset.tzname(None), '-1500')
def test_INTERNALDATE_normalised(self): output = parse_fetch_response([b'3 (INTERNALDATE " 9-Feb-2007 17:08:08 -0430")']) dt = output[3][b'INTERNALDATE'] self.assertTrue(dt.tzinfo is None) # Returned date should be in local timezone expected_dt = datetime_to_native( datetime(2007, 2, 9, 17, 8, 8, 0, FixedOffset(-4 * 60 - 30))) self.assertEqual(dt, expected_dt)
def test_ENVELOPE(self): envelope_str = ( b'1 (ENVELOPE ( ' b'"Sun, 24 Mar 2013 22:06:10 +0200" ' b'"subject" ' b'(("name" NIL "address1" "domain1.com")) ' # from (name and address) b'((NIL NIL "address2" "domain2.com")) ' # sender (just address) b'(("name" NIL "address3" "domain3.com") NIL) ' # reply to b'NIL' # to (no address) b'((NIL NIL "address4" "domain4.com") ' # cc b'("person" NIL "address4b" "domain4b.com")) ' b'NIL ' # bcc b'"<reply-to-id>" ' b'"<msg_id>"))') output = parse_fetch_response([envelope_str], normalise_times=False) self.assertSequenceEqual( output[1][b'ENVELOPE'], Envelope(datetime(2013, 3, 24, 22, 6, 10, tzinfo=FixedOffset(120)), b"subject", (Address(b"name", None, b"address1", b"domain1.com"), ), (Address(None, None, b"address2", b"domain2.com"), ), (Address(b"name", None, b"address3", b"domain3.com"), ), None, (Address(None, None, b"address4", b"domain4.com"), Address(b"person", None, b"address4b", b"domain4b.com")), None, b"<reply-to-id>", b"<msg_id>"))
def test_INTERNALDATE(self): out = parse_fetch_response( [b'1 (INTERNALDATE " 9-Feb-2007 17:08:08 -0430")'], normalise_times=False) self.assertEqual( out[1][b'INTERNALDATE'], datetime(2007, 2, 9, 17, 8, 8, 0, FixedOffset(-4 * 60 - 30)))
def test_INTERNALDATE_normalised(self): def check(date_str, expected_dt): output = parse_fetch_response(['3 (INTERNALDATE "%s")' % date_str]) actual_dt = output[3]['INTERNALDATE'] self.assertTrue(actual_dt.tzinfo is None) # Returned date should be in local timezone expected_dt = datetime_to_native(expected_dt) self.assertEqual(actual_dt, expected_dt) check(' 9-Feb-2007 17:08:08 -0430', datetime(2007, 2, 9, 17, 8, 8, 0, FixedOffset(-4 * 60 - 30))) check('12-Feb-2007 17:08:08 +0200', datetime(2007, 2, 12, 17, 8, 8, 0, FixedOffset(2 * 60))) check(' 9-Dec-2007 17:08:08 +0000', datetime(2007, 12, 9, 17, 8, 8, 0, FixedOffset(0)))
def test_with_msg_time(self, datetime_to_INTERNALDATE): datetime_to_INTERNALDATE.return_value = 'somedate' self.client._imap.append.return_value = ('OK', [b'Good']) msg = b'bye' self.client.append('foobar', msg, ['FLAG', 'WAVE'], datetime(2009, 4, 5, 11, 0, 5, 0, FixedOffset(2 * 60))) self.assertTrue(datetime_to_INTERNALDATE.called) self.client._imap.append.assert_called_with( b'"foobar"', '(FLAG WAVE)', '"somedate"', msg)
def test_fetch(self): # Generate a fresh message-id each time because Gmail is # clever and will treat appends of messages with # previously seen message-ids as the same message. This # breaks our tests when the test message is updated. msg_id_header = make_msgid() msg = ("Message-ID: %s\r\n" % msg_id_header) + MULTIPART_MESSAGE self.client.select_folder(self.base_folder) self.append_msg(msg) self.client.normalise_times = False fields = ["RFC822", b"FLAGS", "INTERNALDATE", "ENVELOPE"] msg_id = self.client.search()[0] resp = self.client.fetch(msg_id, fields) self.assertEqual(len(resp), 1) msginfo = resp[msg_id] extra_fields = [b"SEQ"] if self.condstore_enabled: extra_fields.append(b"MODSEQ") self.assertSetEqual( set(msginfo.keys()), set([to_bytes(f) for f in fields] + extra_fields), ) self.assertEqual(msginfo[b"SEQ"], 1) self.assertEqual(msginfo[b"RFC822"], to_bytes(msg)) self.assertIsInstance(msginfo[b"INTERNALDATE"], datetime) self.assertIsInstance(msginfo[b"FLAGS"], tuple) self.assertSequenceEqual( msginfo[b"ENVELOPE"], Envelope( datetime(2010, 3, 16, 16, 45, 32, tzinfo=FixedOffset(0)), b"A multipart message", (Address(b"Bob Smith", None, b"bob", b"smith.com"), ), (Address(b"Bob Smith", None, b"bob", b"smith.com"), ), (Address(b"Bob Smith", None, b"bob", b"smith.com"), ), ( Address(b"Some One", None, b"some", b"one.com"), Address(None, None, b"foo", b"foo.com"), ), None, None, None, to_bytes(msg_id_header), ), )
def _append(self, folder, msg, flags=(), msg_time=None): # TODO """ FORKED FORM IMAPCLIENT """ if msg_time: if not msg_time.tzinfo: # pragma: no cover msg_time = msg_time.replace(tzinfo=FixedOffset.for_system()) # pragma: no cover time_val = '"{0}"'.format(msg_time.strftime("%d-%b-%Y %H:%M:%S %z")) time_val = imapclient.imapclient.to_unicode(time_val) else: time_val = None return self.conn._command_and_check('append', self.conn._normalise_folder(folder), imapclient.imapclient.seq_to_parenstr(flags), time_val, Helper.str_to_bytes(msg), unpack=True)
def test_mixed_types(self): self.assertEqual( parse_fetch_response([ (b'1 (INTERNALDATE " 9-Feb-2007 17:08:08 +0100" RFC822 {21}', b'Subject: test\r\n\r\nbody'), b')' ]), { 1: { b'INTERNALDATE': datetime_to_native( datetime(2007, 2, 9, 17, 8, 8, 0, FixedOffset(60))), b'RFC822': b'Subject: test\r\n\r\nbody', b'SEQ': 1 } })
def test_fetch(self): # Generate a fresh message-id each time because Gmail is # clever and will treat appends of messages with # previously seen message-ids as the same message. This # breaks our tests when the test message is updated. msg_id_header = make_msgid() msg = ('Message-ID: %s\r\n' % msg_id_header) + MULTIPART_MESSAGE self.client.select_folder(self.base_folder) self.append_msg(msg) self.client.normalise_times = False fields = ['RFC822', b'FLAGS', 'INTERNALDATE', 'ENVELOPE'] msg_id = self.client.search()[0] resp = self.client.fetch(msg_id, fields) self.assertEqual(len(resp), 1) msginfo = resp[msg_id] extra_fields = [b'SEQ'] if self.condstore_enabled: extra_fields.append(b'MODSEQ') self.assertSetEqual( set(msginfo.keys()), set([to_bytes(f) for f in fields] + extra_fields), ) self.assertEqual(msginfo[b'SEQ'], 1) self.assertEqual(msginfo[b'RFC822'], to_bytes(msg)) self.assertIsInstance(msginfo[b'INTERNALDATE'], datetime) self.assertIsInstance(msginfo[b'FLAGS'], tuple) self.assertSequenceEqual( msginfo[b'ENVELOPE'], Envelope( datetime(2010, 3, 16, 16, 45, 32, tzinfo=FixedOffset(0)), b'A multipart message', (Address(b'Bob Smith', None, b'bob', b'smith.com'), ), (Address(b'Bob Smith', None, b'bob', b'smith.com'), ), (Address(b'Bob Smith', None, b'bob', b'smith.com'), ), (Address(b'Some One', None, b'some', b'one.com'), Address(None, None, b'foo', b'foo.com')), None, None, None, to_bytes(msg_id_header)))
def test_for_system_DST(self): offset = FixedOffset.for_system() self.assert_(offset.tzname(None) == '-1500')
def test_for_system_no_DST(self): offset = FixedOffset.for_system() self.assertEqual(offset.tzname(None), '+1500')
check(' 9-Feb-2007 17:08:08 -0430', datetime(2007, 2, 9, 17, 8, 8, 0, FixedOffset(-4*60 - 30))) check('12-Feb-2007 17:08:08 +0200', datetime(2007, 2, 12, 17, 8, 8, 0, FixedOffset(2*60))) check(' 9-Dec-2007 17:08:08 +0000', datetime(2007, 12, 9, 17, 8, 8, 0, FixedOffset(0))) def test_mixed_types(self): self.assertEquals(parse_fetch_response([('1 (INTERNALDATE " 9-Feb-2007 17:08:08 +0100" RFC822 {21}', 'Subject: test\r\n\r\nbody'), ')']), {1: {'INTERNALDATE': datetime_to_native(datetime(2007, 2, 9, 17, 8, 8, 0, FixedOffset(60))), 'RFC822': 'Subject: test\r\n\r\nbody', 'SEQ': 1}}) def add_crlf(text): return CRLF.join(text.splitlines()) + CRLF system_offset = FixedOffset.for_system() def datetime_to_native(dt): return dt.astimezone(system_offset).replace(tzinfo=None)
def test_GMT(self): self._check(FixedOffset(0), timedelta(0), '+0000')
def test_positive(self): self._check(FixedOffset(30), timedelta(minutes=30), '+0030') self._check(FixedOffset(2 * 60), timedelta(hours=2), '+0200') self._check(FixedOffset(11 * 60 + 30), timedelta(hours=11, minutes=30), '+1130')
check(' 9-Dec-2007 17:08:08 +0000', datetime(2007, 12, 9, 17, 8, 8, 0, FixedOffset(0))) def test_mixed_types(self): self.assertEqual( parse_fetch_response([ ('1 (INTERNALDATE " 9-Feb-2007 17:08:08 +0100" RFC822 {21}', 'Subject: test\r\n\r\nbody'), ')' ]), { 1: { 'INTERNALDATE': datetime_to_native( datetime(2007, 2, 9, 17, 8, 8, 0, FixedOffset(60))), 'RFC822': 'Subject: test\r\n\r\nbody', 'SEQ': 1 } }) def add_crlf(text): return CRLF.join(text.splitlines()) + CRLF system_offset = FixedOffset.for_system() def datetime_to_native(dt): return dt.astimezone(system_offset).replace(tzinfo=None)
def test_negative(self): self._check(FixedOffset(-30), timedelta(minutes=-30), '-0030') self._check(FixedOffset(-2 * 60), timedelta(hours=-2), '-0200') self._check(FixedOffset(-11 * 60 - 30), timedelta(minutes=(-11 * 60) - 30), '-1130')
def test_without_timezone(self, for_system): dt = datetime(2009, 1, 2, 3, 4, 5, 0) for_system.return_value = FixedOffset(-5 * 60) self.assertEqual(datetime_to_INTERNALDATE(dt), '02-Jan-2009 03:04:05 -0500')
def test_with_timezone(self): dt = datetime(2009, 1, 2, 3, 4, 5, 0, FixedOffset(2 * 60 + 30)) self.assertEqual(datetime_to_INTERNALDATE(dt), '02-Jan-2009 03:04:05 +0230')
def test_rfc822_style(self): self.check_normalised_and_not( b'Sun, 24 Mar 2013 22:06:10 +0200', datetime(2013, 3, 24, 22, 6, 10, 0, FixedOffset(120)))