Problem/Motivation

$message['body'][] = (string) \Drupal::service('renderer')->renderPlain($build);

That breaks sending HTML mails for example with swift mailer, which tries to be correct and escapes non-safe HTML.

Proposed resolution

Remove the string casts.

Remaining tasks

User interface changes

API changes

Data model changes

Support from Acquia helps fund testing for Drupal Acquia logo

Comments

Berdir created an issue. See original summary.

tduong’s picture

Assigned: Unassigned » tduong
Status: Active » Needs review
FileSize
1.32 KB

Removed string cast.

Wim Leers’s picture

Wim Leers’s picture

Initially, that patch did not add this string cast. Only since #2506581-44: Remove SafeMarkup::set() from Renderer::doRender, it does. Because since that iteration of the patch, renderPlain() is returning SafeStringInterface (by now MarkupInterface).

The only reason AFAICT that we added that string cast, is to keep BC.

But perhaps in this particular instance, that was not necessary.

We should get Alex Pott's thoughts on this.

Wim Leers’s picture

But overall, +1, because That breaks sending HTML mails for example with swift mailer, which tries to be correct and escapes non-safe HTML. sounds sensible, and due to this string cast, that mailer cannot detect that this is in fact already considered safe.

Berdir’s picture

Assigned: tduong » Unassigned
Status: Needs review » Reviewed & tested by the community

Setting to RTBC to get feedback from @alexpott.

I was thinking about tests but I'm not sure it is worth it or even possible. We'd need a HTML test mailer that checks for this, but note that there's also #2223967: Do not decode a contact message twice and it might not be possible to have a useful test without that, which we're currently working around that issue with a custom view builder in a custom module, but we can't work around this problem.

I'd also be OK with just doing this in 8.1.x if we think it's too much of a change for 8.0.x

Wim Leers’s picture

Agreed with #6.

catch’s picture

Assigned: Unassigned » alexpott

Assigning to @alexpott so he knows this is waiting on him.

alexpott’s picture

Isn't there an issue with what is considered safe for email being different from html. As far as I can remember, these string casts occurred so that there was no unnecessary API change - maybe something will break now this is an object?

alexpott’s picture

Status: Reviewed & tested by the community » Needs work

Thinking so more - I'm generally happy that we should delay the string casting. But this needs to be documented on hook_mail(). In an ideal world mail sending would leverage the render system and then we'd delay everything including the render here.

Berdir’s picture

Something like this?

Leaving at 8.0.x for now, but I guess this will be 8.1.x only?

alexpott’s picture

@Berdir thanks that is exactly what I was expecting.

It is shame we don't have anywhere we document some of the expectations around the API but it is not up to this issue to fix that.

Berdir’s picture

Version: 8.0.x-dev » 8.1.x-dev
Assigned: alexpott » Unassigned

Discussed with alex that 8.0.x probably isn't going to happen since this is a tiny change to how it worked before.

But, I can't imagine anyone relying on that right now and for almost all cases, you shouldn't even notice if something is a string or Markup object. Someone might do Markup::create() in an alter hook to fix this, but this will continue to work, it will just no longer be required to do that.

Given that and that this is a bugfix, I think this would still be acceptable for 8.1 beta, so changing the version to that.

Wim Leers’s picture

Status: Needs review » Reviewed & tested by the community
+++ b/core/core.api.php
@@ -1947,9 +1947,10 @@ function hook_queue_info_alter(&$queues) {
+ *     An array of strings or objects that implement MarkupIntrface containing

s/MarkupIntrface/MarkupInterface/

Can be fixed on commit.

alexpott’s picture

Status: Reviewed & tested by the community » Fixed

I fixed up the docs to have fqcn...

diff --git a/core/core.api.php b/core/core.api.php
index 5dcb798..27bc96d 100644
--- a/core/core.api.php
+++ b/core/core.api.php
@@ -1947,10 +1947,10 @@ function hook_queue_info_alter(&$queues) {
  *     Subject of the email to be sent. This must not contain any newline
  *     characters, or the email may not be sent properly.
  *  - 'body':
- *     An array of strings or objects that implement MarkupIntrface containing
- *     the message text. The message body is created by concatenating the
- *     individual array strings into a single text string using "\n\n" as a
- *     separator.
+ *     An array of strings or objects that implement
+ *     \Drupal\Component\Render\MarkupInterface containing the message text. The
+ *     message body is created by concatenating the individual array strings
+ *     into a single text string using "\n\n" as a separator.
  *  - 'headers':
  *     Associative array containing mail headers, such as From, Sender,
  *     MIME-Version, Content-Type, etc.
@@ -2000,7 +2000,8 @@ function hook_mail_alter(&$message) {
  *   - body: An array of lines containing the message to be sent. Drupal will
  *     format the correct line endings for you. MailManagerInterface->mail()
  *     sets this to an empty array when the hook is invoked. The array may
- *     contain either strings or objects implementing MarkupInterface.
+ *     contain either strings or objects implementing
+ *     \Drupal\Component\Render\MarkupInterface.
  *   - from: The address the message will be marked as being from, which is
  *     set by MailManagerInterface->mail() to either a custom address or the
  *     site-wide default email address when the hook is invoked.

Discussed with @xjm and @catch and we agreed this was eligible for inclusion in 8.1.x.

Committed 2ef41bb and pushed to 8.1.x and 8.2.x. Thanks!

  • alexpott committed 05c382e on 8.2.x
    Issue #2666160 by Berdir, tduong: contact_mail() casts rendered markup...

  • alexpott committed 2ef41bb on 8.1.x
    Issue #2666160 by Berdir, tduong: contact_mail() casts rendered markup...

Status: Fixed » Closed (fixed)

Automatically closed - issue fixed for 2 weeks with no activity.