def test_attachment_properties(self): binary_file_content = u'Hello from unicode æøå'.encode('utf-8') att1 = FileAttachment(name='my_file_1.txt', content=binary_file_content) self.assertIn("name='my_file_1.txt'", str(att1)) att1.content = binary_file_content # Test property setter self.assertEqual(att1.content, binary_file_content) # Test property getter att1.attachment_id = 'xxx' self.assertEqual(att1.content, binary_file_content ) # Test property getter when attachment_id is set att1._content = None with self.assertRaises(ValueError): print(att1.content ) # Test property getter when we need to fetch the content attached_item1 = self.get_test_item(folder=self.test_folder) att2 = ItemAttachment(name='attachment1', item=attached_item1) self.assertIn("name='attachment1'", str(att2)) att2.item = attached_item1 # Test property setter self.assertEqual(att2.item, attached_item1) # Test property getter self.assertEqual(att2.item, attached_item1) # Test property getter att2.attachment_id = 'xxx' self.assertEqual( att2.item, attached_item1) # Test property getter when attachment_id is set att2._item = None with self.assertRaises(ValueError): print(att2.item ) # Test property getter when we need to fetch the item
def test_recursive_attachments(self): # Test that we can handle an item which has an attached item, which has an attached item... item = self.get_test_item(folder=self.test_folder) attached_item_level_1 = self.get_test_item(folder=self.test_folder) attached_item_level_2 = self.get_test_item(folder=self.test_folder) attached_item_level_3 = self.get_test_item(folder=self.test_folder) attached_item_level_3.save() attachment_level_3 = ItemAttachment(name='attached_item_level_3', item=attached_item_level_3) attached_item_level_2.attach(attachment_level_3) attached_item_level_2.save() attachment_level_2 = ItemAttachment(name='attached_item_level_2', item=attached_item_level_2) attached_item_level_1.attach(attachment_level_2) attached_item_level_1.save() attachment_level_1 = ItemAttachment(name='attached_item_level_1', item=attached_item_level_1) item.attach(attachment_level_1) item.save() self.assertEqual( item.attachments[0].item.attachments[0].item.attachments[0].item. subject, attached_item_level_3.subject) # Also test a fresh item new_item = self.test_folder.get(id=item.id, changekey=item.changekey) self.assertEqual( new_item.attachments[0].item.attachments[0].item.attachments[0]. item.subject, attached_item_level_3.subject)
def test_item_attachments(self): item = self.get_test_item(folder=self.test_folder) attached_item1 = self.get_test_item(folder=self.test_folder) att1 = ItemAttachment(name='attachment1', item=attached_item1) # Test __init__(attachments=...) and attach() on new item self.assertEqual(len(item.attachments), 0) item.attach(att1) self.assertEqual(len(item.attachments), 1) item.save() fresh_item = self.get_item_by_id(item) self.assertEqual(len(fresh_item.attachments), 1) fresh_attachments = sorted(fresh_item.attachments, key=lambda a: a.name) self.assertEqual(fresh_attachments[0].name, 'attachment1') self.assertEqual(fresh_attachments[0].item.subject, attached_item1.subject) self.assertEqual(fresh_attachments[0].item.body, attached_item1.body) # Same as 'body' because 'body' doesn't contain HTML self.assertEqual(fresh_attachments[0].item.text_body, attached_item1.body) # Test attach on saved object att2 = ItemAttachment(name='attachment2', item=attached_item1) self.assertEqual(len(item.attachments), 1) item.attach(att2) self.assertEqual(len(item.attachments), 2) fresh_item = self.get_item_by_id(item) self.assertEqual(len(fresh_item.attachments), 2) fresh_attachments = sorted(fresh_item.attachments, key=lambda a: a.name) self.assertEqual(fresh_attachments[0].name, 'attachment1') self.assertEqual(fresh_attachments[0].item.subject, attached_item1.subject) self.assertEqual(fresh_attachments[0].item.body, attached_item1.body) self.assertEqual(fresh_attachments[1].name, 'attachment2') self.assertEqual(fresh_attachments[1].item.subject, attached_item1.subject) self.assertEqual(fresh_attachments[1].item.body, attached_item1.body) # Test detach item.detach(att1) self.assertTrue(att1.attachment_id is None) self.assertTrue(att1.parent_item is None) fresh_item = self.get_item_by_id(item) self.assertEqual(len(fresh_item.attachments), 1) fresh_attachments = sorted(fresh_item.attachments, key=lambda a: a.name) self.assertEqual(fresh_attachments[0].name, 'attachment2') self.assertEqual(fresh_attachments[0].item.subject, attached_item1.subject) self.assertEqual(fresh_attachments[0].item.body, attached_item1.body)
def test_item_attachment_properties(self): attached_item1 = self.get_test_item(folder=self.test_folder) att1 = ItemAttachment(name='attachment1', item=attached_item1) self.assertIn("name='attachment1'", str(att1)) att1.item = attached_item1 # Test property setter self.assertEqual(att1.item, attached_item1) # Test property getter self.assertEqual(att1.item, attached_item1) # Test property getter att1.attachment_id = 'xxx' self.assertEqual( att1.item, attached_item1) # Test property getter when attachment_id is set att1._item = None with self.assertRaises(ValueError): print(att1.item ) # Test property getter when we need to fetch the item
def test_parse_incident_from_item_with_attachments(): """ Given: - Message item with attachment that contains email attachments When: - Parsing incident from item Verify: - Parsing runs successfully """ content = b'ARC-Seal: i=1; a=rsa-sha256; s=arcselector9901;' \ b' d=microsoft.com; cv=none;b=ES/YXpFlV19rlN1iV+ORg5RzID8GPSQL' \ b'nUT26MNdeTzcQSwK679doIz5Avpv8Ps2H/aBkBamwRNOCJBkl7iCHyy+04yRj3ghikw3u/ufIFHi0sQ7QG95mO1PVPLibv9A==' message = Message( datetime_created=EWSDate(year=2021, month=1, day=25), to_recipients=[], attachments=[ ItemAttachment( item=Item(mime_content=content, headers=[]), attachment_id=AttachmentId(), last_modified_time=EWSDate(year=2021, month=1, day=25), ), ], ) incident = parse_incident_from_item(message) assert incident['attachment']
def test_parse_incident_from_item(): """ Given: - Message item with attachment that contains non UTF-8 encoded char When: - Parsing incident from item Verify: - Parsing runs successfully - Incidnet attachment is not empty """ message = Message( datetime_created=EWSDate(year=2021, month=1, day=25), to_recipients=[], attachments=[ ItemAttachment( item=Item(mime_content=b'\xc400'), attachment_id=AttachmentId(), last_modified_time=EWSDate(year=2021, month=1, day=25), ), ], ) incident = parse_incident_from_item(message) assert incident['attachment']
def test_both_attachment_types(self): item = self.get_test_item(folder=self.test_folder) attached_item = self.get_test_item(folder=self.test_folder).save() item_attachment = ItemAttachment(name="item_attachment", item=attached_item) file_attachment = FileAttachment(name="file_attachment", content=b"file_attachment") item.attach(item_attachment) item.attach(file_attachment) item.save() fresh_item = self.get_item_by_id(item) self.assertSetEqual({a.name for a in fresh_item.attachments}, {"item_attachment", "file_attachment"})
def test_both_attachment_types(self): item = self.get_test_item(folder=self.test_folder) attached_item = self.get_test_item(folder=self.test_folder).save() item_attachment = ItemAttachment(name='item_attachment', item=attached_item) file_attachment = FileAttachment(name='file_attachment', content=b'file_attachment') item.attach(item_attachment) item.attach(file_attachment) item.save() fresh_item = list(self.account.fetch(ids=[item]))[0] self.assertSetEqual({a.name for a in fresh_item.attachments}, {'item_attachment', 'file_attachment'})
def test_item_attachment_properties(self): attached_item1 = self.get_test_item(folder=self.test_folder) att1 = ItemAttachment(name="attachment1", item=attached_item1) self.assertIn("name='attachment1'", str(att1)) att1.item = attached_item1 # Test property setter with self.assertRaises(TypeError) as e: att1.item = "XXX" self.assertEqual(e.exception.args[0], "'value' 'XXX' must be of type <class 'exchangelib.items.item.Item'>") self.assertEqual(att1.item, attached_item1) # Test property getter self.assertEqual(att1.item, attached_item1) # Test property getter att1.attachment_id = "xxx" self.assertEqual(att1.item, attached_item1) # Test property getter when attachment_id is set att1._item = None with self.assertRaises(ValueError): print(att1.item) # Test property getter when we need to fetch the item
def test_raw_service_call(self): item = self.get_test_item(folder=self.test_folder) attached_item1 = self.get_test_item(folder=self.test_folder) attached_item1.body = HTMLBody("<html><body>Hello HTML</body></html>") att1 = ItemAttachment(name="attachment1", item=attached_item1) item.attach(att1) item.save() with self.assertRaises(ValueError): # Bad body_type GetAttachment(account=att1.parent_item.account).get( items=[att1.attachment_id], include_mime_content=True, body_type="XXX", filter_html_content=None, additional_fields=[], ) # Test body_type attachment = GetAttachment(account=att1.parent_item.account).get( items=[att1.attachment_id], include_mime_content=True, body_type="Text", filter_html_content=None, additional_fields=[FieldPath(field=self.ITEM_CLASS.get_field_by_fieldname("body"))], ) self.assertEqual(attachment.item.body, "Hello HTML\r\n") # Test filter_html_content. I wonder what unsafe HTML is. attachment = GetAttachment(account=att1.parent_item.account).get( items=[att1.attachment_id], include_mime_content=False, body_type="HTML", filter_html_content=True, additional_fields=[FieldPath(field=self.ITEM_CLASS.get_field_by_fieldname("body"))], ) self.assertEqual( attachment.item.body, '<html>\r\n<head>\r\n<meta http-equiv="Content-Type" content="text/html; charset=utf-8">\r\n' "</head>\r\n<body>\r\nHello HTML\r\n</body>\r\n</html>\r\n", )
def test_item_attachments(self): item = self.get_test_item(folder=self.test_folder) item.attachments = [] attached_item1 = self.get_test_item(folder=self.test_folder) attached_item1.attachments = [] attached_item1.save() attachment1 = ItemAttachment(name='attachment1', item=attached_item1) item.attach(attachment1) self.assertEqual(len(item.attachments), 1) item.save() fresh_item = list(self.account.fetch(ids=[item]))[0] self.assertEqual(len(fresh_item.attachments), 1) fresh_attachments = sorted(fresh_item.attachments, key=lambda a: a.name) self.assertEqual(fresh_attachments[0].name, 'attachment1') self.assertIsInstance(fresh_attachments[0].item, self.ITEM_CLASS) for f in self.ITEM_CLASS.FIELDS: with self.subTest(f=f): # Normalize some values we don't control if f.is_read_only: continue if self.ITEM_CLASS == CalendarItem and f in CalendarItem.timezone_fields( ): # Timezone fields will (and must) be populated automatically from the timestamp continue if isinstance(f, ExtendedPropertyField): # Attachments don't have these values. It may be possible to request it if we can find the FieldURI continue if f.name == 'is_read': # This is always true for item attachments? continue if f.name == 'reminder_due_by': # EWS sets a default value if it is not set on insert. Ignore continue if f.name == 'mime_content': # This will change depending on other contents fields continue old_val = getattr(attached_item1, f.name) new_val = getattr(fresh_attachments[0].item, f.name) if f.is_list: old_val, new_val = set(old_val or ()), set(new_val or ()) self.assertEqual(old_val, new_val, (f.name, old_val, new_val)) # Test attach on saved object attached_item2 = self.get_test_item(folder=self.test_folder) attached_item2.attachments = [] attached_item2.save() attachment2 = ItemAttachment(name='attachment2', item=attached_item2) item.attach(attachment2) self.assertEqual(len(item.attachments), 2) fresh_item = list(self.account.fetch(ids=[item]))[0] self.assertEqual(len(fresh_item.attachments), 2) fresh_attachments = sorted(fresh_item.attachments, key=lambda a: a.name) self.assertEqual(fresh_attachments[0].name, 'attachment1') self.assertIsInstance(fresh_attachments[0].item, self.ITEM_CLASS) for f in self.ITEM_CLASS.FIELDS: with self.subTest(f=f): # Normalize some values we don't control if f.is_read_only: continue if self.ITEM_CLASS == CalendarItem and f in CalendarItem.timezone_fields( ): # Timezone fields will (and must) be populated automatically from the timestamp continue if isinstance(f, ExtendedPropertyField): # Attachments don't have these values. It may be possible to request it if we can find the FieldURI continue if f.name == 'reminder_due_by': # EWS sets a default value if it is not set on insert. Ignore continue if f.name == 'is_read': # This is always true for item attachments? continue if f.name == 'mime_content': # This will change depending on other contents fields continue old_val = getattr(attached_item1, f.name) new_val = getattr(fresh_attachments[0].item, f.name) if f.is_list: old_val, new_val = set(old_val or ()), set(new_val or ()) self.assertEqual(old_val, new_val, (f.name, old_val, new_val)) self.assertEqual(fresh_attachments[1].name, 'attachment2') self.assertIsInstance(fresh_attachments[1].item, self.ITEM_CLASS) for f in self.ITEM_CLASS.FIELDS: # Normalize some values we don't control if f.is_read_only: continue if self.ITEM_CLASS == CalendarItem and f in CalendarItem.timezone_fields( ): # Timezone fields will (and must) be populated automatically from the timestamp continue if isinstance(f, ExtendedPropertyField): # Attachments don't have these values. It may be possible to request it if we can find the FieldURI continue if f.name == 'reminder_due_by': # EWS sets a default value if it is not set on insert. Ignore continue if f.name == 'is_read': # This is always true for item attachments? continue if f.name == 'mime_content': # This will change depending on other contents fields continue old_val = getattr(attached_item2, f.name) new_val = getattr(fresh_attachments[1].item, f.name) if f.is_list: old_val, new_val = set(old_val or ()), set(new_val or ()) self.assertEqual(old_val, new_val, (f.name, old_val, new_val)) # Test detach item.detach(attachment2) self.assertTrue(attachment2.attachment_id is None) self.assertTrue(attachment2.parent_item is None) fresh_item = list(self.account.fetch(ids=[item]))[0] self.assertEqual(len(fresh_item.attachments), 1) fresh_attachments = sorted(fresh_item.attachments, key=lambda a: a.name) for f in self.ITEM_CLASS.FIELDS: with self.subTest(f=f): # Normalize some values we don't control if f.is_read_only: continue if self.ITEM_CLASS == CalendarItem and f in CalendarItem.timezone_fields( ): # Timezone fields will (and must) be populated automatically from the timestamp continue if isinstance(f, ExtendedPropertyField): # Attachments don't have these values. It may be possible to request it if we can find the FieldURI continue if f.name == 'reminder_due_by': # EWS sets a default value if it is not set on insert. Ignore continue if f.name == 'is_read': # This is always true for item attachments? continue if f.name == 'mime_content': # This will change depending on other contents fields continue old_val = getattr(attached_item1, f.name) new_val = getattr(fresh_attachments[0].item, f.name) if f.is_list: old_val, new_val = set(old_val or ()), set(new_val or ()) self.assertEqual(old_val, new_val, (f.name, old_val, new_val)) # Test attach with non-saved item attached_item3 = self.get_test_item(folder=self.test_folder) attached_item3.attachments = [] attachment3 = ItemAttachment(name='attachment2', item=attached_item3) item.attach(attachment3) item.detach(attachment3)
def test_magic(self): for item in (FileAttachment(name="XXX"), ItemAttachment(name="XXX")): self.assertIn("name=", str(item)) self.assertIn(item.__class__.__name__, repr(item))