def validate(self, value): """The document must either have a digital file or be preserved in paper form. XXX: This validator is a hack, since it validates field values across schemata using request.form instead of `value`. """ # Bail if not called during a regular add form if self.request.form == {}: return # Mails are always available in digital form if IMail.providedBy(self.context): return form = self.view.parentForm if getattr(form, 'skip_validate_file_field', False): return if not any([self.has_file(), self.is_preserved_as_paper(), self.has_referenced_document()]): raise Invalid( _(u'error_file_and_preserved_as_paper', default=u"You don't select a file and document is also not " u"preserved in paper_form, please correct it."))
def cancel(self, obj): """Cancels a single document checkout. """ if IMail.providedBy(obj): msg = _(u'msg_cancel_checkout_on_mail_not_possible', default=u'Could not cancel checkout on document ${title}, ' 'mails does not support the checkin checkout process.', mapping={'title': obj.Title().decode('utf-8')}) api.portal.show_message(message=msg, request=self.request, type='error') return # check out the document manager = getMultiAdapter((obj, self.request), ICheckinCheckoutManager) # is cancel allowed for this document? if not manager.is_cancel_allowed(): msg = _(u'Could not cancel checkout on document ${title}.', mapping=dict(title=obj.Title().decode('utf-8'))) api.portal.show_message(message=msg, request=self.request, type='error') else: manager.cancel() # notify the user msg = _(u'Cancel checkout: ${title}', mapping={'title': obj.Title().decode('utf-8')}) api.portal.show_message(message=msg, request=self.request, type='info')
def validate(self, value): """The document must either have a digital file or be preserved in paper form. XXX: This validator is a hack, since it validates field values across schemata using request.form instead of `value`. """ # Bail if not called during a regular add form if self.request.form == {}: return # Mails are always available in digital form if IMail.providedBy(self.context): return form = self.view.parentForm if getattr(form, 'skip_validate_file_field', False): return if not any([ self.has_file(), self.is_preserved_as_paper(), self.has_referenced_document() ]): raise Invalid( _(u'error_file_and_preserved_as_paper', default=u"You don't select a file and document is also not " u"preserved in paper_form, please correct it."))
def cancel(self, obj): """Cancels a single document checkout. """ if IMail.providedBy(obj): msg = _(u'msg_cancel_checkout_on_mail_not_possible', default=u'Could not cancel checkout on document ${title}, ' 'mails does not support the checkin checkout process.', mapping={'title': obj.Title().decode('utf-8')}) api.portal.show_message( message=msg, request=self.request, type='error') return # check out the document manager = getMultiAdapter((obj, self.request), ICheckinCheckoutManager) # is cancel allowed for this document? if not manager.is_cancel_allowed(): msg = _(u'Could not cancel checkout on document ${title}', mapping=dict(title=obj.Title().decode('utf-8'))) api.portal.show_message( message=msg, request=self.request, type='error') else: manager.cancel() # notify the user msg = _(u'Cancel checkout: ${title}', mapping={'title': obj.Title().decode('utf-8')}) api.portal.show_message( message=msg, request=self.request, type='info')
def create_mail(self, text='', objs=[], only_links=''): """Create the mail and attach the the files. For object without a file it include a Link to the Object in to the message""" attachment_parts = [] msg = MIMEMultipart() msg['Date'] = formatdate(localtime=True) # iterate over object list (which can include documents and mails), # create attachement parts for them and prepare docs_links docs_links = '%s:\r\n' % (translate( _('label_documents', default=u'Documents'), context=self.request)) for obj in objs: if IMail.providedBy(obj): obj_file = obj.message else: obj_file = obj.file if only_links or not obj_file: # rewrite the url with clients public url url = '%s/%s' % (get_current_client().public_url, '/'.join( obj.getPhysicalPath()[2:])) docs_links = '%s\r\n - %s (%s)' % (docs_links, obj.title, url) continue docs_links = '%s\r\n - %s (%s)' % ( docs_links, obj.title, translate(_('label_see_attachment', default=u'see attachment'), context=self.request)) mimetype = obj_file.contentType if not mimetype: mimetype = 'application/octet-stream' maintype, subtype = obj_file.contentType.split('/', 1) part = MIMEBase(maintype, subtype) part.set_payload(obj_file.data) Encoders.encode_base64(part) part.add_header('Content-Disposition', 'attachment; filename="%s"' % obj_file.filename) attachment_parts.append(part) # First, create the text part and attach it to the message ... text = '%s\r\n\r\n%s\r\n' % (text.encode( CHARSET, 'ignore'), docs_links.encode(CHARSET)) if not isinstance(text, unicode): text = text.decode('utf8') msg.attach(MIMEText(text, 'plain', CHARSET)) # ... then attach all the attachment parts for part in attachment_parts: msg.attach(part) return msg
def create_mail(self, text="", objs=[], only_links=""): """Create the mail and attach the the files. For object without a file it include a Link to the Object in to the message""" attachment_parts = [] msg = MIMEMultipart() msg["Date"] = formatdate(localtime=True) # iterate over object list (which can include documents and mails), # create attachement parts for them and prepare docs_links docs_links = "%s:\r\n" % (translate(_("label_documents", default=u"Documents"), context=self.request)) for obj in objs: if IMail.providedBy(obj): obj_file = obj.message else: obj_file = obj.file if only_links or not obj_file: # rewrite the url with clients public url url = "%s/%s" % (get_current_client().public_url, "/".join(obj.getPhysicalPath()[2:])) docs_links = "%s\r\n - %s (%s)" % (docs_links, obj.title, url) continue docs_links = "%s\r\n - %s (%s)" % ( docs_links, obj.title, translate(_("label_see_attachment", default=u"see attachment"), context=self.request), ) mimetype = obj_file.contentType if not mimetype: mimetype = "application/octet-stream" maintype, subtype = obj_file.contentType.split("/", 1) part = MIMEBase(maintype, subtype) part.set_payload(obj_file.data) Encoders.encode_base64(part) part.add_header("Content-Disposition", 'attachment; filename="%s"' % obj_file.filename) attachment_parts.append(part) # First, create the text part and attach it to the message ... text = "%s\r\n\r\n%s\r\n" % (text.encode(CHARSET, "ignore"), docs_links.encode(CHARSET)) if not isinstance(text, unicode): text = text.decode("utf8") msg.attach(MIMEText(text, "plain", CHARSET)) # ... then attach all the attachment parts for part in attachment_parts: msg.attach(part) return msg
def validate(self, value): if value: if self.request.get( 'form.widgets.documents_as_links') != ['selected']: registry = queryUtility(IRegistry) reg_proxy = registry.forInterface(ISendDocumentConf) total = 0 for obj in value: #check if its a mail if IMail.providedBy(obj): total += obj.message.getSize() elif obj.file: total += obj.file.getSize() if total > (reg_proxy.max_size * 1000000): raise FilesTooLarge() else: raise schema.interfaces.RequiredMissing()
def _handle_store_batch(self, brains): """This function stores the documents and their versions in bumblebee. It decides if a document has to be updated depending on its conversion timestamp and updates the timestamp after storing the document. Track the checksums locally by batch first and only add them to the global set once the transaction has been commited. Otherwise we would skip storing objects in case a conflict occurs. """ batch_checksums = set() objs_to_store = [] for brain in brains: obj = brain.getObject() if not self.needs_update(obj, self.timestamp): continue self._prepare_store_batch(obj, objs_to_store, batch_checksums) # don't attempt to store versions for mails, mails should not have # versions. in some cases they do nevertheless and then iterating # over versions may fail utterly. we don't like that thus we # avoid that it happens. # XXX should be fixed properly by making sure mails don't have # versions, ever. if IMail.providedBy(obj): continue for versiondata in self.prtool.getHistory(obj): self._prepare_store_batch(versiondata.object, objs_to_store, batch_checksums) self._store_batch(objs_to_store) for obj in objs_to_store: self.set_conversion_timestamp(obj, self.timestamp) return batch_checksums
def _handle_store_batch(self, brains): """This function stores the documents and their versions in bumblebee. It decides if a document has to be updated depending on its conversion timestamp and updates the timestamp after storing the document. Track the checksums locally by batch first and only add them to the global set once the transaction has been commited. Otherwise we would skip storing objects in case a conflict occurs. """ batch_checksums = set() objs_to_store = [] for brain in brains: obj = brain.getObject() if not self.needs_update(obj, self.timestamp): continue self._prepare_store_batch(obj, objs_to_store, batch_checksums) # don't attempt to store versions for mails, mails should not have # versions. in some cases they do nevertheless and then iterating # over versions may fail utterly. we don't like that thus we # avoid that it happens. # XXX should be fixed properly by making sure mails don't have # versions, ever. if IMail.providedBy(obj): continue for versiondata in self.prtool.getHistory(obj): self._prepare_store_batch( versiondata.object, objs_to_store, batch_checksums) self._store_batch(objs_to_store) for obj in objs_to_store: self.set_conversion_timestamp(obj, self.timestamp) return batch_checksums
def recursive_find_uncatalogued_mails(parent, catalog, max_depth=None, depth=0): """Recursively traverse content starting at parent and find uncatalogued mails. """ if max_depth and depth > max_depth: return if not hasattr(parent, 'objectItems'): return try: items = parent.objectItems() except: return for ident, item in items: if IMail.providedBy(item): path = '/'.join(item.getPhysicalPath()) nof_results = len(catalog.unrestrictedSearchResults({'path': path})) if nof_results != 1: print "{} result(s) for: {}".format(nof_results, path) recursive_find_uncatalogued_mails(item, catalog, max_depth=max_depth, depth=depth+1)
def test_factory(self): fti = queryUtility(IDexterityFTI, name='ftw.mail.mail') factory = fti.factory new_object = createObject(factory) self.failUnless(IMail.providedBy(new_object)) self.assertEquals(u'no_subject', new_object.title)
def test_adding(self): mail = create(Builder('mail')) self.failUnless(IMail.providedBy(mail)) self.assertEquals(u'no_subject', mail.title)
def create_mail(self, text='', objs=[], only_links=''): """Create the mail and attach the the files. For object without a file it include a Link to the Object in to the message""" attachment_parts = [] msg = MIMEMultipart() msg['Date'] = formatdate(localtime=True) # iterate over object list (which can include documents and mails), # create attachement parts for them and prepare docs_links docs_links = '%s:\r\n' % (translate( _('label_documents', default=u'Documents'), context=self.request)) for obj in objs: if IMail.providedBy(obj): obj_file = obj.message else: obj_file = obj.file if only_links or not obj_file: # rewrite the url with current adminunit's public url url = '%s/%s' % ( get_current_admin_unit().public_url, '/'.join(obj.getPhysicalPath()[2:])) docs_links = '%s\r\n - %s (%s)' % ( docs_links, obj.title, url) continue docs_links = '%s\r\n - %s (%s)' % ( docs_links, obj.title, translate( _('label_see_attachment', default=u'see attachment'), context=self.request)) mimetype = obj_file.contentType if not mimetype: mimetype = 'application/octet-stream' maintype, subtype = obj_file.contentType.split('/', 1) part = MIMEBase(maintype, subtype) part.set_payload(obj_file.data) if mimetype != 'message/rfc822': Encoders.encode_base64(part) part.add_header('Content-Disposition', 'attachment; filename="%s"' % obj_file.filename) attachment_parts.append(part) # First, create the text part and attach it to the message ... text = '%s\r\n\r\n%s\r\n' % ( text.encode(CHARSET, 'ignore'), docs_links.encode(CHARSET)) if not isinstance(text, unicode): text = text.decode('utf8') msg.attach(MIMEText(text, 'plain', CHARSET)) # ... then attach all the attachment parts for part in attachment_parts: msg.attach(part) return msg