def test_nested_remove_attachments(self): """A forwarded mail with attachments results in nested multipart payloads - this should also be handled by remove_attachments. """ msg = deepcopy(self.msg_nested_attachments) self.assertNotEquals(msg, self.msg_nested_attachments) # we have two attachments (which are nested) self.assertEquals([{'position': 4, 'size': 137588, 'content-type': 'image/jpg', 'filename': '1703693_0412c29a4f.jpg'}, {'position': 5, 'size': 223504, 'content-type': 'image/jpg', 'filename': '3512536451_e1310bf568.jpg'}], utils.get_attachments(msg)) # lets remove one attachment new_msg = utils.remove_attachments(msg, (5,)) # we get the same message back.. self.assertEquals(msg, new_msg) # .. but without the removed attachment self.assertEquals([{'position': 4, 'size': 137588, 'content-type': 'image/jpg', 'filename': '1703693_0412c29a4f.jpg'}], utils.get_attachments(new_msg))
def test_get_attachments(self): self.assertEquals([], utils.get_attachments(self.msg_ascii)) self.assertEquals([{'position': 1, 'size': 7, 'content-type': 'text/plain', 'filename': 'Bücher.txt'}], utils.get_attachments(self.msg_attachment))
def render_attachment_table(self): """Renders a ftw-table of attachments. """ columns = ( {'column': 'position', 'column_title': _(u'column_attachment_checkbox', default=u''), 'transform': attachment_checkbox_helper}, {'column': 'content-type', 'column_title': _(u'column_attachment_type', default=u'Type'), 'transform': content_type_helper}, {'column': 'filename', 'column_title': _(u'column_attachment_filename', default=u'Filename'), 'transform': downloadable_filename_helper(self.context)}, {'column': 'size', 'column_title': _(u'column_attachment_size', default=u'Size'), 'transform': human_readable_filesize_helper(self.context)}, ) items = get_attachments(self.context.msg) generator = getUtility(ITableGenerator, 'ftw.tablegenerator') return generator.generate(items, columns, sortable=False)
def __call__(self): items = get_attachments(self.context.msg) if not len(items): msg = _(u'error_no_attachments_to_extract', default=u'This mail has no attachments to extract.') IStatusMessage(self.request).addStatusMessage(msg, type='warning') return self.request.RESPONSE.redirect( self.context.absolute_url()) elif self.request.get('form.cancelled'): return self.request.RESPONSE.redirect( self.context.absolute_url()) elif self.request.get('form.submitted'): attachments = self.request.get('attachments') if not attachments: msg = _(u'error_no_attachments_selected', default=u'You have not selected any attachments.') IStatusMessage(self.request).addStatusMessage(msg, type='error') else: attachments = [int(pos) for pos in attachments] delete_action = self.request.get('delete_action', 'nothing') if delete_action not in self.allowed_delete_actions: raise ValueError('Expected delete action to be one of ' + str(self.allowed_delete_actions)) self.extract_attachments(attachments, delete_action) dossier = self.find_parent_dossier() return self.request.RESPONSE.redirect( os.path.join(dossier.absolute_url(), '#documents')) return grok.View.__call__(self)
def render_attachment_table(self): """Renders a ftw-table of attachments. """ columns = ( { 'column': 'position', 'column_title': _(u'column_attachment_checkbox', default=u''), 'transform': attachment_checkbox_helper }, { 'column': 'content-type', 'column_title': _(u'column_attachment_type', default=u'Type'), 'transform': content_type_helper }, { 'column': 'filename', 'column_title': _(u'column_attachment_filename', default=u'Filename'), 'transform': downloadable_filename_helper(self.context) }, { 'column': 'size', 'column_title': _(u'column_attachment_size', default=u'Size'), 'transform': human_readable_filesize_helper(self.context) }, ) items = get_attachments(self.context.msg) generator = getUtility(ITableGenerator, 'ftw.tablegenerator') return generator.generate(items, columns, sortable=False)
def __call__(self): items = get_attachments(self.context.msg) if not len(items): msg = _(u'error_no_attachments_to_extract', default=u'This mail has no attachments to extract.') IStatusMessage(self.request).addStatusMessage(msg, type='warning') return self.request.RESPONSE.redirect(self.context.absolute_url()) elif self.request.get('form.cancelled'): return self.request.RESPONSE.redirect(self.context.absolute_url()) elif self.request.get('form.submitted'): attachments = self.request.get('attachments') if not attachments: msg = _(u'error_no_attachments_selected', default=u'You have not selected any attachments.') IStatusMessage(self.request).addStatusMessage(msg, type='error') else: attachments = [int(pos) for pos in attachments] delete_action = self.request.get('delete_action', 'nothing') if delete_action not in self.allowed_delete_actions: raise ValueError('Expected delete action to be one of ' + str(self.allowed_delete_actions)) self.extract_attachments(attachments, delete_action) dossier = self.find_parent_dossier() return self.request.RESPONSE.redirect( os.path.join(dossier.absolute_url(), '#documents')) return grok.View.__call__(self)
def test_remove_attachments(self): # we dont want to change the message itselve, so lets copy it msg = deepcopy(self.msg_attachment) self.assertNotEquals(msg, self.msg_attachment) # our message has one attachment self.assertEquals([{'position': 1, 'size': 7, 'content-type': 'text/plain', 'filename': 'Bücher.txt'}], utils.get_attachments(msg)) # lets remove the attachment new_msg = utils.remove_attachments(msg, (1,)) # we get the same message back self.assertEquals(msg, new_msg) self.assertEquals([], utils.get_attachments(new_msg))
def test_deleting_after_extracting(self, browser): browser.login().open(self.mail, view='extract_attachments') browser.fill({'attachments:list': ['1'], 'delete_action': ['all']}).submit() self.assertEquals( len(get_attachments(self.mail.msg)), 0, 'The attachment deleting after extracting, \ does not work correctly.')
def test_deleting_after_extracting(self): mail = self.create_mail(MESSAGE_TEXT) self.browser.open('%s/extract_attachments' % mail.absolute_url()) self.browser.getControl(name='attachments:list').value = [1] self.browser.getControl(name='delete_action').value = ['all'] self.browser.getControl(name='form.submitted').click() self.assertEquals( len(get_attachments(mail.msg)), 0, 'The attachment deleting after extracting, \ does not work correctly.')
def attachments(self): context = aq_inner(self.context) attachments = utils.get_attachments(context.msg) for attachment in attachments: lookup = self.lookup_mimetype_registry(attachment) if lookup: attachment['class'] = self.get_css_class(lookup) attachment['type-name'] = lookup.name() else: attachment['class'] = '' attachment['type-name'] = 'File' return attachments
def attachments(self): context = aq_inner(self.context) attachments = utils.get_attachments(context.msg) for attachment in attachments: lookup = self.lookup_mimetype_registry(attachment) if lookup: attachment["class"] = self.get_css_class(lookup) attachment["type-name"] = lookup.name() else: attachment["class"] = "" attachment["type-name"] = "File" return attachments
def attachments(self): context = aq_inner(self.context) attachments = utils.get_attachments(context.msg) for attachment in attachments: lookup = self.lookup_mimetype_registry(attachment) if lookup: attachment['class'] = self.get_attachment_css_class(lookup) attachment['type-name'] = lookup.name() else: attachment['class'] = '' attachment['type-name'] = 'File' return attachments
def test_nested_get_attachments(self): """A forwarded mail with attachments results in nested multipart payloads - this should also be handled by get_attachments method. """ self.assertEquals([{'position': 4, 'size': 137588, 'content-type': 'image/jpg', 'filename': '1703693_0412c29a4f.jpg'}, {'position': 5, 'size': 223504, 'content-type': 'image/jpg', 'filename': '3512536451_e1310bf568.jpg'}], utils.get_attachments(self.msg_nested_attachments))
def attachments(self): normalize = getUtility(IIDNormalizer).normalize context = aq_inner(self.context) attachments = utils.get_attachments(context.msg) mtr = getToolByName(context, 'mimetypes_registry') for attachment in attachments: icon = 'mimetype-plain' type_name = 'File' if attachment.get('content-type') == 'application/octet-stream': lookup = mtr.globFilename(attachment.get('filename')) else: lookup = mtr.lookup(attachment['content-type']) if lookup: if isinstance(lookup, list) or isinstance(lookup, tuple): lookup = lookup[0] icon = "mimetype-%s" % normalize(lookup.minor()) type_name = lookup.name() attachment['icon'] = icon attachment['type-name'] = type_name return attachments
def assert_attachment(self, mail, filename, content_type): attachments = get_attachments(mail) self.assertEquals(1, len(attachments)) self.assertEquals(filename, attachments[0].get('filename')) self.assertEquals(content_type, attachments[0].get('content-type'))
def extract_attachments(self, positions, delete_action): dossier = self.find_parent_dossier() attachments_to_extract = filter( lambda att: att.get('position') in positions, get_attachments(self.context.msg)) # create documents from the selected attachments for att in attachments_to_extract: pos = att.get('position') filename = att.get('filename') # remove line breaks from the filename filename = re.sub('\s{1,}', ' ', filename) kwargs = {'title': filename[:filename.rfind('.')].decode('utf-8'), 'file': self.get_attachment_as_namedfile(pos), 'keywords': (), 'digitally_available': True} doc = createContentInContainer(dossier, 'opengever.document.document', **kwargs) for schemata in iterSchemata(doc): for name, field in getFieldsInOrder(schemata): if name not in kwargs.keys(): default = queryMultiAdapter(( doc, doc.REQUEST, # request None, # form field, None, # Widget ), IValue, name='default') if default is not None: default = default.get() if default is None: default = getattr(field, 'default', None) if default is None: try: default = field.missing_value except: pass field.set(field.interface(doc), default) # add a reference from the attachment to the mail intids = getUtility(IIntIds) iid = intids.getId(self.context) # prevent circular dependencies from opengever.document.behaviors import IRelatedDocuments IRelatedDocuments(doc).relatedItems = [RelationValue(iid)] msg = _(u'info_extracted_document', default=u'Created document ${title}', mapping={'title': doc.Title().decode('utf-8')}) IStatusMessage(self.request).addStatusMessage(msg, type='info') # reindex the new document to index also all the default values doc.reindexObject() # delete the attachments from the email message, if needed if delete_action in ('all', 'selected'): if delete_action == 'selected': pos_to_delete = positions else: # all pos_to_delete = [int(att['position']) for att in get_attachments(self.context.msg)] # set the new message file msg = remove_attachments(self.context.msg, pos_to_delete) self.context.message = NamedFile( data=msg.as_string(), contentType=self.context.message.contentType, filename=self.context.message.filename)
def _update_attachment_infos(self): self._attachment_infos = tuple(utils.get_attachments(self.msg))
def extract_attachments(self, positions, delete_action): dossier = self.find_parent_dossier() attachments_to_extract = filter( lambda att: att.get('position') in positions, get_attachments(self.context.msg)) # create documents from the selected attachments for att in attachments_to_extract: pos = att.get('position') filename = att.get('filename') # remove line breaks from the filename filename = re.sub('\s{1,}', ' ', filename) kwargs = { 'title': filename[:filename.rfind('.')].decode('utf-8'), 'file': self.get_attachment_as_namedfile(pos), 'keywords': (), 'digitally_available': True } doc = createContentInContainer(dossier, 'opengever.document.document', **kwargs) for schemata in iterSchemata(doc): for name, field in getFieldsInOrder(schemata): if name not in kwargs.keys(): default = queryMultiAdapter( ( doc, doc.REQUEST, # request None, # form field, None, # Widget ), IValue, name='default') if default is not None: default = default.get() if default is None: default = getattr(field, 'default', None) if default is None: try: default = field.missing_value except: pass field.set(field.interface(doc), default) # add a reference from the attachment to the mail intids = getUtility(IIntIds) iid = intids.getId(self.context) # prevent circular dependencies from opengever.document.behaviors import IRelatedDocuments IRelatedDocuments(doc).relatedItems = [RelationValue(iid)] msg = _(u'info_extracted_document', default=u'Created document ${title}', mapping={'title': doc.Title().decode('utf-8')}) IStatusMessage(self.request).addStatusMessage(msg, type='info') # reindex the new document to index also all the default values doc.reindexObject() # delete the attachments from the email message, if needed if delete_action in ('all', 'selected'): if delete_action == 'selected': pos_to_delete = positions else: # all pos_to_delete = [ int(att['position']) for att in get_attachments(self.context.msg) ] # set the new message file msg = remove_attachments(self.context.msg, pos_to_delete) self.context.message = NamedFile( data=msg.as_string(), contentType=self.context.message.contentType, filename=self.context.message.filename)