workflows: add support for complex data templates for mail attachments (#49884)
This commit is contained in:
parent
f747428404
commit
a1548ab4c5
|
@ -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]
|
||||
|
|
|
@ -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())
|
||||
|
|
|
@ -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'),
|
||||
|
|
|
@ -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)
|
||||
|
|
Loading…
Reference in New Issue