workflows: add support for complex data templates for mail attachments (#49884)

This commit is contained in:
Frédéric Péters 2021-01-05 14:22:34 +01:00
parent f747428404
commit a1548ab4c5
4 changed files with 68 additions and 17 deletions

View File

@ -631,12 +631,12 @@ def test_workflows_edit_email_action(pub):
# attachments without backoffice fields: python expressions
resp = app.get(item_url)
assert "Attachments (Python expressions)" in resp.text
assert "Attachments (templates or Python expressions)" in resp.text
resp.form['attachments$element0'] = 'form_var_upload_raw'
resp = resp.form.submit('submit')
assert resp.location
resp = app.get(item_url)
assert "Attachments (Python expressions)" in resp.text
assert "Attachments (templates or Python expressions)" in resp.text
assert resp.form['attachments$element0'].value == 'form_var_upload_raw'
sendmail = Workflow.get(workflow.id).get_status(st1.id).items[0]
assert sendmail.attachments == ['form_var_upload_raw']
@ -652,7 +652,7 @@ def test_workflows_edit_email_action(pub):
workflow.store()
resp = app.get(item_url)
assert "Attachments" in resp.text
assert "Attachments (Python expressions)" not in resp.text
assert "Attachments (templates or Python expressions)" not in resp.text
assert resp.form['attachments$element0$choice'].value == 'form_var_upload_raw'
assert len(resp.form['attachments$element0$choice'].options) == 5
resp = resp.form.submit('attachments$add_element') # add one
@ -697,7 +697,7 @@ def test_workflows_edit_email_action(pub):
workflow.backoffice_fields_formdef.fields = []
workflow.store()
resp = app.get(item_url)
assert "Attachments (Python expressions)" in resp.text
assert "Attachments (templates or Python expressions)" in resp.text
resp = resp.form.submit('submit')
assert resp.location
sendmail = Workflow.get(workflow.id).get_status(st1.id).items[0]

View File

@ -1493,6 +1493,37 @@ def test_email_attachments(pub, emails):
assert payload1.get_payload(decode=True) == b"Hello world"
assert json.loads(force_text(payload2.get_payload(decode=True))) == {'hello': 'world'}
# check with templates
emails.empty()
sendmail.attachments = ['{{form_var_backoffice_file1_raw}}']
sendmail.perform(formdata)
get_response().process_after_jobs()
assert emails.count() == 1
assert emails.emails['foobar']['msg'].is_multipart()
assert emails.emails['foobar']['msg'].get_content_subtype() == 'mixed'
assert emails.emails['foobar']['msg'].get_payload()[0].get_content_type() == 'text/html'
assert emails.emails['foobar']['msg'].get_payload()[1].get_content_type() == 'image/jpeg'
emails.empty()
sendmail.attachments = ['{{form_var_backoffice_file2}}']
sendmail.perform(formdata)
get_response().process_after_jobs()
assert emails.count() == 1
assert emails.emails['foobar']['msg'].is_multipart()
assert emails.emails['foobar']['msg'].get_content_subtype() == 'mixed'
assert emails.emails['foobar']['msg'].get_payload()[0].get_content_type() == 'text/html'
assert emails.emails['foobar']['msg'].get_payload()[1].get_content_type() == 'text/plain'
emails.empty()
sendmail.attachments = ['{% firstof form_var_frontoffice_file form_var_backoffice_file2 %}']
sendmail.perform(formdata)
get_response().process_after_jobs()
assert emails.count() == 1
assert emails.emails['foobar']['msg'].is_multipart()
assert emails.emails['foobar']['msg'].get_content_subtype() == 'mixed'
assert emails.emails['foobar']['msg'].get_payload()[0].get_content_type() == 'text/html'
assert emails.emails['foobar']['msg'].get_payload()[1].get_content_type() == 'image/jpeg'
def test_webservice_call(http_requests, pub):
pub.substitutions.feed(MockSubstitutionVariables())

View File

@ -102,7 +102,7 @@ class MailTemplatePage(Directory):
)
form.add(WidgetList, 'attachments',
title=_('Attachments (Python expressions)'),
title=_('Attachments (templates or Python expressions)'),
element_type=StringWidget,
value=self.mail_template.attachments,
add_element_label=_('Add attachment'),

View File

@ -1871,7 +1871,7 @@ class WorkflowStatusItem(XmlSerialisable):
element_kwargs={'render_br': False, 'options': attachments_options})
else:
form.add(WidgetList, '%sattachments' % prefix,
title=_('Attachments (Python expressions)'),
title=_('Attachments (templates or Python expressions)'),
element_type=StringWidget,
value=attachments,
add_element_label=_('Add attachment'),
@ -2165,6 +2165,25 @@ class WorkflowStatusItem(XmlSerialisable):
attachments.extend(self.attachments or [])
attachments.extend(extra_attachments or [])
# 1. attachments defined as templates
with get_publisher().complex_data():
for attachment in attachments[:]:
if '{%' not in attachment and '{{' not in attachment:
continue
attachments.remove(attachment)
try:
attachment = WorkflowStatusItem.compute(attachment, allow_complex=True, raises=True)
except:
get_publisher().notify_of_exception(sys.exc_info(),
context='[workflow/attachments]')
else:
if attachment:
complex_value = get_publisher().get_cached_complex_data(attachment)
if complex_value:
uploads.append(complex_value)
# 2. python expressions
if attachments:
global_eval_dict = get_publisher().get_global_eval_dict()
local_eval_dict = get_publisher().substitutions.get_context_variables()
@ -2185,19 +2204,20 @@ class WorkflowStatusItem(XmlSerialisable):
if not picklableupload:
continue
if not isinstance(picklableupload, PicklableUpload):
try:
# convert any value to a PicklableUpload; it will ususally
# be a dict like one provided by qommon/evalutils:attachment()
picklableupload = FileField.convert_value_from_anything(picklableupload)
except ValueError:
get_publisher().notify_of_exception(sys.exc_info(),
context='[workflow/attachments]')
continue
uploads.append(picklableupload)
return uploads
# 3. convert any value to a PicklableUpload; this allows for
# dicts like those provided by qommon/evalutils:attachment()
for upload in uploads:
if not isinstance(upload, PicklableUpload):
try:
upload = FileField.convert_value_from_anything(upload)
except ValueError:
get_publisher().notify_of_exception(sys.exc_info(),
context='[workflow/attachments]')
continue
yield upload
def __repr__(self):
return '<%s %s>' % (self.__class__.__name__, self.id)