def create_or_update(self): with api.env.adopt_roles(['Manager']): obj_file = self.obj_file # namedblobfile object the_file = self.existing_file # dmsfile if the_file is None: log.error('file not found (scan_id: {0})'.format(self.scan_fields.get('scan_id'))) return params = {'PD': False, 'PC': False, 'PVS': False} # PD = no date, PC = no closing, PVS = no new file if the_file.scan_user: for param in the_file.scan_user.split('|'): params[param] = True # the_file.scan_user = None # Don't remove for next generation self.document = the_file.aq_parent # search for signed file result = self.site.portal_catalog( portal_type='dmsommainfile', scan_id=self.scan_fields.get('scan_id'), signed=True ) if result: # Is there a new version because export failing or really a new sending # Check if we are in a time delta of 20 hours: < = export failing else new sending signed_file = result[0].getObject() if (signed_file.scan_date and self.scan_fields['scan_date'] and self.scan_fields['scan_date'] - signed_file.scan_date) < datetime.timedelta(0, 72000): self.update(result[0].getObject(), obj_file) elif not params['PVS']: # make a new file self.create(obj_file) else: log.error('file not considered: existing signed but PVS (scan_id: {0})'.format( self.scan_fields.get('scan_id'))) elif not params['PVS']: # make a new file self.create(obj_file) else: # register scan date on original model the_file.scan_date = self.scan_fields['scan_date'] if not params['PD']: self.document.outgoing_date = (self.scan_fields['scan_date'] and self.scan_fields['scan_date'] or datetime.datetime.now()) self.document.reindexObject(idxs=('in_out_date')) if not params['PC']: # close trans = { 'created': ['set_scanned', 'mark_as_sent'], 'scanned': [], 'proposed_to_service_chief': ['propose_to_be_signed', 'mark_as_sent'], 'to_be_signed': ['mark_as_sent'], 'to_print': ['propose_to_be_signed', 'mark_as_sent'] } transitions(self.document, trans.get(api.content.get_state(self.document), []))
def test_get_state_infos(self): self.portal.portal_workflow.setChainForPortalTypes( ('Document', ), ('intranet_workflow', )) obj = api.content.create(container=self.portal.folder, id='mydoc', title='My document', type='Document') self.assertDictEqual(get_state_infos(obj), { 'state_title': u'Internal draft', 'state_name': 'internal' }) transitions(obj, 'submit') self.assertDictEqual(get_state_infos(obj), { 'state_title': u'Pending review', 'state_name': 'pending' })
def set_Members(self): if 'Members' in self.portal: return _createObjectByType('Folder', self.portal, id='Members', title='Users', description="Site Users") util = getUtility(ITranslationDomain, 'plonefrontpage') members = getattr(self.portal, 'Members') members.setTitle( util.translate(u'members-title', target_language='fr', default='Users')) members.setDescription( util.translate(u'members-description', target_language='fr', default="Site Users")) members.unmarkCreationFlag() members.setLanguage('fr') members.setExcludeFromNav(True) members.setConstrainTypesMode(1) members.setLocallyAllowedTypes([]) members.setImmediatelyAddableTypes([]) members.reindexObject() self.portal.portal_membership.memberareaCreationFlag = 0 self.portal.portal_membership.setMemberAreaType('member_area') transitions(members, 'show_internally') # add index_html to Members area if 'index_html' not in members.objectIds(): addPy = members.manage_addProduct[ 'PythonScripts'].manage_addPythonScript addPy('index_html') index_html = getattr(members, 'index_html') index_html.write(member_indexhtml) index_html.ZPythonScript_setTitle('User Search') # Block all right column portlets by default manager = getUtility(IPortletManager, name='plone.rightcolumn') if manager is not None: assignable = queryMultiAdapter((members, manager), ILocalPortletAssignmentManager) assignable.setBlacklistStatus('context', True) assignable.setBlacklistStatus('group', True) assignable.setBlacklistStatus('content_type', True)
def various_update(self): # replace front-page frontpage = getattr(self.portal, 'front-page') frontpage.title = _translate("front_page_title") frontpage.description = _translate("front_page_descr") frontpage.text = richtextval(_translate("front_page_text")) transitions(frontpage, ('retract', 'publish_internally')) frontpage.reindexObject() self.portal.templates.layout = 'dg-templates-listing' # plonegroup-organization pgo = get_own_organization() behaviour = ISelectableConstrainTypes(pgo) behaviour.setConstrainTypesMode(1) behaviour.setLocallyAllowedTypes([]) behaviour.setImmediatelyAddableTypes([]) ISelectableConstrainTypes(pgo['echevins']).setConstrainTypesMode(0) ISelectableConstrainTypes(pgo['services']).setConstrainTypesMode(0)
def various_update(self): # replace front-page frontpage = getattr(self.portal, 'front-page') frontpage.title = _translate("front_page_title") frontpage.description = _translate("front_page_descr") frontpage.text = richtextval(_translate("front_page_text")) transitions(frontpage, ('retract', 'publish_internally')) frontpage.reindexObject() self.portal.templates.layout = 'dg-templates-listing' self.portal.contacts.exclude_from_nav = True self.portal.contacts.reindexObject(['exclude_from_nav']) #Hiding folder contents self.portal.manage_permission('List folder contents', ('Manager', 'Site Administrator'), acquire=0) paob = self.portal.portal_actions.object_buttons for act in ('faceted.sync', 'faceted.disable', 'faceted.enable', 'faceted.search.disable', 'faceted.search.enable', 'faceted.actions.disable', 'faceted.actions.enable', 'ical_import_enable', 'ical_import_disable'): if act in paob: paob[act].visible = False
def various_update(self): # Adapt default portal: adaptDefaultPortal(self.portal) # remove local roles on project spaces (old ones too) for brain in self.pc(portal_type='projectspace'): obj = brain.getObject() obj.manage_delLocalRoles( ["pst_managers", "pst_editors", "pst_readers"]) transitions(obj, ['publish_internally']) try: api.group.delete(groupname="pst_managers") except: pass # replace front-page frontpage = getattr(self.portal, 'front-page') frontpage.setTitle(_translate("front_page_title")) frontpage.setDescription(_translate("front_page_descr")) frontpage.setText(_translate("front_page_text"), mimetype='text/html') transitions(frontpage, ('retract', 'publish_internally')) frontpage.reindexObject()
def archive(self): """ """ portal = api.portal.get() new_pst = api.content.copy(self.context, portal, 'pst-tmp', False) self.context = api.content.rename(self.context, 'pst-2012-2018') self.context.title = u'PST 2013-2018' self.context.reindexObject() new_pst = api.content.rename(new_pst, 'pst') new_pst.title = u'PST 2019-2024' new_pst.manage_addLocalRoles("pst_editors", ( 'Reader', 'Editor', 'Reviewer', 'Contributor', )) new_pst.reindexObject() new_pst.reindexObjectSecurity() new_pst.budget_years = [2019, 2020, 2021, 2022, 2023, 2024] del_view = new_pst.restrictedTraverse('clean_budget/delete') for fld in SUMMARIZED_FIELDS: del_view(fld) transitions(new_pst, ['publish_internally']) return self.request.RESPONSE.redirect(new_pst.absolute_url())
def test_transitions(self): self.portal.portal_workflow.setChainForPortalTypes(('Document', ), ('intranet_workflow', )) obj = api.content.create(container=self.portal.folder, id='mydoc', type='Document') self.assertEqual(api.content.get_state(obj), 'internal') # apply one transition transitions(obj, 'submit') self.assertEqual(api.content.get_state(obj), 'pending') # apply multiple transitions transitions(obj, ['publish_internally', 'publish_externally']) self.assertEqual(api.content.get_state(obj), 'external') transitions(obj, ['submit', 'retract', 'hide']) self.assertEqual(api.content.get_state(obj), 'private')
def test_transitions(self): self.portal.portal_workflow.setChainForPortalTypes( ('Document', ), ('intranet_workflow', )) obj = api.content.create(container=self.portal.folder, id='mydoc', type='Document') self.assertEqual(api.content.get_state(obj), 'internal') # apply one transition transitions(obj, 'submit') self.assertEqual(api.content.get_state(obj), 'pending') # apply multiple transitions transitions(obj, ['publish_internally', 'publish_externally']) self.assertEqual(api.content.get_state(obj), 'external') transitions(obj, ['submit', 'retract', 'hide']) self.assertEqual(api.content.get_state(obj), 'private')
def various_update(self): # doc message for id in ('doc1-0', 'doc'): if id in self.portal['messages-config']: api.content.delete(self.portal['messages-config'][id]) if ('indispo' in self.portal['messages-config'] and api.content.get_state( self.portal['messages-config']['indispo']) == 'activated'): api.content.transition(self.portal['messages-config']['indispo'], 'deactivate') if 'doc' not in self.portal['messages-config']: add_message( 'doc', 'Documentation', u'<p>Vous pouvez consulter la ' u'<a href="https://docs.imio.be/imio-doc/ia.pst/" target="_blank">documentation en ligne de la ' u'dernière version</a>, ainsi que <a href="https://www.imio.be/nos-applications/ia-pst/' u'les-actus-de-pst/ia-pst-1-3" target="_blank">les nouveautés</a>.</p>', msg_type='significant', can_hide=True, req_roles=['Authenticated'], activate=True) # activate user external edit pref change_user_properties(self.portal, kw='ext_editor:True', dochange='1') # replace front-page frontpage = getattr(self.portal, 'front-page') frontpage.title = _tr("front_page_title") frontpage.description = _tr("front_page_descr") frontpage.text = richtextval(_tr("front_page_text")) transitions(frontpage, ('retract', 'publish_internally')) frontpage.reindexObject() # remove portlets on pst for brain in self.catalog( object_provides='imio.project.pst.interfaces.IImioPSTProject'): ann = IAnnotations(brain.getObject()) if 'plone.portlets.contextassignments' in ann: if 'plone.leftcolumn' in ann[ 'plone.portlets.contextassignments']: for name in ('portlet_dashboard', 'navigation', 'portlet_actions'): if name in ann['plone.portlets.contextassignments'][ 'plone.leftcolumn']: del ann['plone.portlets.contextassignments'][ 'plone.leftcolumn'][name] if not len(ann['plone.portlets.contextassignments'] ['plone.leftcolumn']): del ann['plone.portlets.contextassignments'][ 'plone.leftcolumn'] if not len(ann['plone.portlets.contextassignments']): del ann['plone.portlets.contextassignments'] # registry api.portal.set_registry_record( 'collective.contact.core.interfaces.IContactCoreParameters.' 'display_below_content_title_on_views', True) registry = getUtility(IRegistry) record = registry.records.get( 'imio.pm.wsclient.browser.settings.IWS4PMClientSettings.generated_actions' ) if record is not None: val = api.portal.get_registry_record( 'imio.pm.wsclient.browser.settings.IWS4PMClientSettings.' 'generated_actions') if val is not None: event.notify(RecordModifiedEvent(record, val, val)) # update dashboard criterias for brain in self.catalog( object_provides='imio.project.pst.interfaces.IImioPSTProject'): pst = brain.getObject() mapping = { 'strategicobjectives': 'strategicobjective', 'operationalobjectives': 'operationalobjective', 'pstactions': 'pstaction', 'tasks': 'task' } for col_folder_id, content_type in mapping.iteritems(): col_folder = pst[col_folder_id] reimport_faceted_config(col_folder, xml='{}.xml'.format(content_type), default_UID=col_folder['all'].UID()) # rename pst titles = { u'PST (2012-2018)': u'PST 2013-2018', u'PST (2018-2024)': u'PST 2019-2024', u'PST (2019-2024)': u'PST 2019-2024', u'PST': u'PST 2019-2024' } values = titles.values() for brain in self.catalog( object_provides='imio.project.pst.interfaces.IImioPSTProject'): pst = brain.getObject() for tit in titles: if pst.title == tit: pst.title = titles[tit] modified(pst) break else: if pst.title not in values: logger.warning("PST rename: not replaced '{}'".format( pst.title.encode('utf8'))) # update ckeditor to remove format and avoid html <h> tags cke_props = self.portal.portal_properties.ckeditor_properties custom = ( u"[\n['AjaxSave'],\n['Cut','Copy','Paste','PasteText','PasteFromWord','-'," u"'Scayt'],\n['Undo','Redo','-','RemoveFormat'],\n['Bold','Italic','Underline','Strike'],\n" u"['NumberedList','BulletedList','-','Outdent','Indent','Blockquote'],\n['JustifyLeft'," u"'JustifyCenter', 'JustifyRight','JustifyBlock'],\n['Table','SpecialChar','Link','Unlink'],\n'/'," u"\n['Styles'],\n['Maximize', 'ShowBlocks', 'Source']\n]") cke_props.toolbar_Custom = custom if cke_props.menuStyles.find(CKEDITOR_MENUSTYLES_CUSTOMIZED_MSG) == -1: enc = self.portal.portal_properties.site_properties.getProperty( 'default_charset') msg_highlight_red = _tr('ckeditor_style_highlight_in_red').encode( 'utf-8') msg_highlight_blue = _tr( 'ckeditor_style_highlight_in_blue').encode('utf-8') msg_highlight_green = _tr( 'ckeditor_style_highlight_in_green').encode('utf-8') msg_highlight_yellow = _tr( 'ckeditor_style_highlight_in_yellow').encode('utf-8') msg_x_small = _tr('ckeditor_style_x_small').encode('utf-8') msg_small = _tr('ckeditor_style_small').encode('utf-8') msg_large = _tr('ckeditor_style_large').encode('utf-8') msg_x_large = _tr('ckeditor_style_x_large').encode('utf-8') msg_indent = _tr('ckeditor_style_indent_first_line').encode( 'utf-8') msg_table_no_optimization = _tr( 'ckeditor_style_table_no_optimization').encode('utf-8') menuStyles = unicode( "[\n{0}\n{{ name : '{1}'\t\t, element : 'span', attributes : {{ 'class' : 'highlight-red' }} }},\n" "{{ name : '{2}'\t\t, element : 'span', attributes : {{ 'class' : 'highlight-blue' }} }},\n" "{{ name : '{3}'\t\t, element : 'span', attributes : {{ 'class' : 'highlight-green' }} }},\n" "{{ name : '{4}'\t\t, element : 'span', attributes : {{ 'class' : 'highlight-yellow' }} }},\n" "{{ name : '{5}'\t\t, element : 'p', attributes : {{ 'class' : 'xSmallText' }} }},\n" "{{ name : '{6}'\t\t, element : 'p', attributes : {{ 'class' : 'smallText' }} }},\n" "{{ name : '{7}'\t\t, element : 'p', attributes : {{ 'class' : 'largeText' }} }},\n" "{{ name : '{8}'\t\t, element : 'p', attributes : {{ 'class' : 'xLargeText' }} }},\n" "{{ name : '{9}'\t\t, element : 'table', styles : {{ 'table-layout' : 'fixed' }} }},\n" "{{ name : '{10}'\t\t, element : 'p', attributes : {{ 'style' : 'text-indent: 40px;' }} }},\n]\n" .format(CKEDITOR_MENUSTYLES_CUSTOMIZED_MSG, msg_highlight_red, msg_highlight_blue, msg_highlight_green, msg_highlight_yellow, msg_x_small, msg_small, msg_large, msg_x_large, msg_table_no_optimization, msg_indent), enc) cke_props.menuStyles = menuStyles
def update_site(self): # documentgenerator config set_oo_port() set_uno_path() # add templates configuration add_templates(self.portal) # set som objects as not next/prev navigable for obj in (self.portal['front-page'], self.portal['contacts'], self.portal['templates']): if not INextPrevNotNavigable.providedBy(obj): alsoProvides(obj, INextPrevNotNavigable) # publish outgoing-mail folder if api.content.get_state(self.omf) != 'internally_published': transitions(self.omf, ["show_internally"]) # add group if api.group.get('expedition') is None: api.group.create('expedition', '1 Expédition courrier sortant') self.portal['outgoing-mail'].manage_addLocalRoles('expedition', ['Contributor']) self.portal['contacts'].manage_addLocalRoles('expedition', ['Contributor', 'Editor', 'Reader']) api.group.add_user(groupname='expedition', username='******') # dir_general can add outgoing mails self.portal['outgoing-mail'].manage_addLocalRoles('dir_general', ['Contributor']) # rename group title encodeurs = api.group.get('encodeurs') if encodeurs.getProperty('title') != '1 Encodeurs courrier entrant': self.portal.portal_groups.editGroup('encodeurs', title='1 Encodeurs courrier entrant') # update im mail-searches # alsoProvides(self.imf['mail-searches'], ICollectionCategories) # add new collection to_treat_in_my_group createIMailCollections(self.imf['mail-searches']) reimport_faceted_config(self.imf['mail-searches'], xml='im-mail-searches.xml', default_UID=self.imf['mail-searches']['all_mails'].UID()) # update permissions for perm in ("imio.dms.mail: Write mail base fields", "imio.dms.mail: Write treating group field", "imio.dms.mail: Write userid field"): if 'Site Administrator' not in [dic['name'] for dic in self.portal.rolesOfPermission(perm) if dic['selected'] == 'SELECTED']: self.portal.manage_permission(perm, ('Manager', 'Site Administrator'), acquire=0) # configure external edition self.portal.portal_memberdata.manage_changeProperties(ext_editor=True) self.registry['externaleditor.ext_editor'] = True if 'Image' in self.registry['externaleditor.externaleditor_enabled_types']: self.registry['externaleditor.externaleditor_enabled_types'] = ['PODTemplate', 'ConfigurablePODTemplate', 'DashboardPODTemplate', 'SubTemplate', 'StyleTemplate', 'dmsommainfile'] change_user_properties(self.portal, kw='ext_editor:True', dochange='1') # searched types changeSearchedTypes(self.portal) # add documentation message add_message('doc2-0', 'Documentation 2.0', u'<p>Vous pouvez consulter la <a href="http://www.imio.be/' u'support/documentation/topic/cp_app_ged" target="_blank">documentation en ligne de la ' u'version 2.0</a>, ainsi que d\'autres documentations liées.</p>', msg_type='significant', can_hide=True, req_roles=['Authenticated'], activate=True) val = api.portal.get_registry_record('imio.actionspanel.browser.registry.IImioActionsPanelConfig.transitions') if 'dmsoutgoingmail.back_to_agent|' not in val: val += ['dmsoutgoingmail.back_to_agent|', 'dmsoutgoingmail.back_to_creation|', 'dmsoutgoingmail.back_to_service_chief|', 'dmsoutgoingmail.back_to_print|', 'dmsoutgoingmail.back_to_be_signed|', 'dmsoutgoingmail.back_to_scanned|'] api.portal.set_registry_record('imio.actionspanel.browser.registry.IImioActionsPanelConfig.transitions', val) # update front-page frontpage = self.portal['front-page'] if frontpage.Title() == 'Gestion du courrier 1.1': frontpage.setTitle(_("front_page_title")) frontpage.setDescription(_("front_page_descr")) frontpage.setText(_("front_page_text"), mimetype='text/html')
def import_scanned(self, number=2, only='', ptype='dmsincomingmail', redirect='1'): # i_e ok """ Import some incoming mail for demo site """ if ptype not in ('dmsincomingmail', 'dmsincoming_email'): return "ptype parameter must be in ('dmsincomingmail', 'dmsincoming_email') values" now = datetime.now() portal = getToolByName(self, "portal_url").getPortalObject() pc = portal.portal_catalog contacts = portal.contacts intids = getUtility(IIntIds) onlys = only.split(',') docs = { 'dmsincomingmail': { # i_e ok '59.PDF': { 'c': {'mail_type': 'courrier', 'file_title': '010500000000001.pdf', 'recipient_groups': []}, 'f': {'scan_id': '010500000000001', 'pages_number': 1, 'scan_date': now, 'scan_user': '******', 'scanner': 'Ricola'} }, '60.PDF': { 'c': {'mail_type': 'courrier', 'file_title': '010500000000002.pdf', 'recipient_groups': []}, 'f': {'scan_id': '010500000000002', 'pages_number': 1, 'scan_date': now, 'scan_user': '******', 'scanner': 'Ricola'} }, }, 'dmsincoming_email': OrderedDict([ ('email3.pdf', {'c': {'title': u'Organisation de la braderie annuelle début septembre', 'mail_type': u'courrier', 'file_title': u'email.pdf', 'recipient_groups': [], 'orig_sender_email': u'*****@*****.**', 'tg': ['evenements'], 'user': '******'}, 'f': {'scan_id': '', 'pages_number': 1, 'scan_date': now, 'scan_user': '', 'scanner': ''}, 's': 'proposed_to_agent'}), ('email4.pdf', {'c': {'title': u'Facture 3P XX12345', 'mail_type': u'courrier', 'file_title': u'email.pdf', 'recipient_groups': [], 'orig_sender_email': u'*****@*****.**'}, 'f': {'scan_id': '', 'pages_number': 1, 'scan_date': now, 'scan_user': '', 'scanner': ''}, 'a': ['facture-3P-XX12345.pdf']}), ('email1.pdf', {'c': {'title': u'Réservation de la salle Le Foyer', 'mail_type': u'courrier', 'file_title': u'email.pdf', 'recipient_groups': [], 'orig_sender_email': u'*****@*****.**', 'tg': ['direction-generale', 'secretariat'], 'user': '******'}, 'f': {'scan_id': '', 'pages_number': 1, 'scan_date': now, 'scan_user': '', 'scanner': ''}, 's': 'proposed_to_agent'}), ('email2.pdf', {'c': {'title': u'Où se situe votre entité par rapport aux Objectifs de développement durable ?', 'mail_type': u'courrier', 'file_title': u'email.pdf', 'recipient_groups': [], 'orig_sender_email': u'*****@*****.**'}, 'f': {'scan_id': '', 'pages_number': 1, 'scan_date': now, 'scan_user': '', 'scanner': ''}}), ]) } # update config with tg, user, sender for fil in docs[ptype]: if 'tg' in docs[ptype][fil]['c']: org, user = get_org_user(contacts, docs[ptype][fil]['c'].pop('tg'), docs[ptype][fil]['c'].pop('user')) if org: docs[ptype][fil]['c'].update({'treating_groups': org.UID(), 'assigned_user': user}) if 'orig_sender_email' in docs[ptype][fil]['c']: results = pc.unrestrictedSearchResults(email=docs[ptype][fil]['c']['orig_sender_email'], portal_type=['organization', 'person', 'held_position']) if results: docs[ptype][fil]['c']['sender'] = [RelationValue(intids.getId(brain._unrestrictedGetObject())) for brain in results] docs_cycle = cycle(docs[ptype]) folder = portal['incoming-mail'] count = 1 limit = int(number) while count <= limit: doc = docs_cycle.next() if only and doc not in onlys: time.sleep(0.5) continue with open(add_path('Extensions/%s' % doc), 'rb') as fo: file_object = NamedBlobFile(fo.read(), filename=unicode(doc)) irn = internalReferenceIncomingMailDefaultValue(DummyView(portal, portal.REQUEST)) doc_metadata = copy.copy(docs[ptype][doc]['c']) doc_metadata['internal_reference_no'] = irn (document, main_file) = createDocument( DummyView(portal, portal.REQUEST), create_period_folder(folder, datetime.now()), ptype, '', file_object, owner='scanner', metadata=doc_metadata) for key, value in docs[ptype][doc]['f'].items(): setattr(main_file, key, value) main_file.reindexObject(idxs=('scan_id', 'internal_reference_number')) # transaction.commit() # commit here to be sure to index preceding when using collective.indexing # change has been done in IdmSearchableExtender to avoid using catalog document.reindexObject(idxs=('SearchableText', )) # attachments for attachment in docs[ptype][doc].get('a', []): with open(add_path('Extensions/%s' % attachment), 'rb') as fo: file_object = NamedBlobFile(fo.read(), filename=unicode(doc)) createContentInContainer(document, 'dmsappendixfile', title=attachment, file=file_object) # state if 's' in docs[ptype][doc]: to_state = docs[ptype][doc]['s'] state = api.content.get_state(document) i = 0 while state != to_state and i < 10: transitions(document, ['propose_to_agent', 'propose_to_n_plus_1', 'propose_to_n_plus_2', 'propose_to_n_plus_3', 'propose_to_n_plus_4', 'propose_to_n_plus_5', 'propose_to_manager', 'propose_to_pre_manager']) state = api.content.get_state(document) i += 1 count += 1 if redirect: return portal.REQUEST.response.redirect(folder.absolute_url())
def __call__(self): # 1 send email body = self.context.email_body msg = create_html_email(body.raw) for a_uid in self.context.email_attachments or []: a_obj = uuidToObject(a_uid, unrestricted=True) if a_obj: title = a_obj.title if a_obj.file.filename: title = a_obj.file.filename if PMH_ENABLED: title = unidecode(title) add_attachment(msg, title, content=a_obj.file.data) mailhost = get_mail_host(check=False) replyto_key = 'imio.dms.mail.browser.settings.IImioDmsMailConfig.omail_replyto_email_send' if mailhost.smtp_host == u'localhost' and not PMH_ENABLED: api.portal.show_message(_( 'Your email has not been sent: ${error}.', mapping={'error': _(u'Cannot use localhost as smtp')}), self.request, type='error') return elif api.portal.get_registry_record(replyto_key, default=False): ret, error = send_email(msg, self.context.email_subject, mailhost.smtp_uid, self.context.email_recipient, self.context.email_cc, replyto=self.context.email_sender) else: ret, error = send_email(msg, self.context.email_subject, self.context.email_sender, self.context.email_recipient, self.context.email_cc) if ret: api.portal.show_message(_('Your email has been sent.'), self.request) else: api.portal.show_message(_( 'Your email has not been sent: ${error}.', mapping={'error': error}), self.request, type='error') return # 2 Update status on omail now = datetime.strftime(datetime.now(), '%Y-%m-%d %H:%M') status = _tr(u'Email sent at ${date_hour}.', mapping={'date_hour': now}) if not self.context.email_status: self.context.email_status = status else: self.context.email_status += u' {}'.format(status) modified(self.context) # 3 Close if necessary close = api.portal.get_registry_record( 'imio.dms.mail.browser.settings.IImioDmsMailConfig.' 'omail_close_on_email_send') if close: trans = { 'created': [ 'mark_as_sent', 'propose_to_be_signed', 'set_validated', 'propose_to_n_plus_1' ], 'scanned': ['mark_as_sent'], 'proposed_to_n_plus_1': ['mark_as_sent', 'propose_to_be_signed', 'set_validated'], 'to_be_signed': ['mark_as_sent'], 'validated': ['propose_to_be_signed', 'mark_as_sent'] } state = api.content.get_state(self.context) i = 0 while state != 'sent' and i < 10: transitions(self.context, trans.get(state, [])) state = api.content.get_state(self.context) i += 1