Problem/Motivation

Send plaintext emails. I don't know if there's something I did not quite get.
But I have no problem sending HTML formatted emails. But in some use cases, I need to send plaintext emails.

When I try the following kind of snippet, the email I receive contains the outer template (header, footer, etc) from the HTML email template in my theme. And the body of the email is empty.

I was expecting just a plain text email, no HTML template at all.

I just think that is just that I don't know how to proceed :-)

Thanks,
Cheers,
Jérémy

Steps to reproduce

    /** @var \Drupal\symfony_mailer\EmailFactory $factory */
    $factory = Drupal::service('email_factory');

    $email = $factory->newModuleEmail('my_module', 'plaintext');

    $email->setTo('john@bar.com');
    $email->setSubject('My plaintext email subject');
    //$email->setBody($build); // This would be rendered as HTML by Drupal renderer.
    $email->setTextBody('Some basic plain text input'); // I just figured I should use this method...
    $ret = $email->send();

Proposed resolution

Create new class SendAsPlainEmailAdjuster in namespace Drupal\symfony_mailer\Plugin\EmailAdjuster, id=email_as_plain, weight = 850
function postRender() contains one line $email->setHtmlBody(NULL);

At start of InlineCssEmailAdjuster::postRender() return if $email->getHtmlBody() is empty.

Remaining tasks

x

User interface changes

x

API changes

x

Data model changes

x

Command icon Show commands

Start within a Git clone of the project using the version control instructions.

Or, if you do not have SSH keys set up on git.drupalcode.org:

    Comments

    jchatard created an issue. See original summary.

    jchatard’s picture

    Issue summary: View changes
    adamps’s picture

    Title: How to send plaintext email? » Send email as plaintext
    Component: Documentation » Code
    Category: Support request » Feature request

    OK, I can understand the confusion, as the required code doesn't really exist yet!

    I added a new section to the FAQ

    This module is deeply based on Twig templates and rendering. These of course are HTML-based and they will persistently escape any plain text passed to them. So what we do is generate an HTML email then subsequently convert it to plain text.

    Already the HtmlToTextEmailAdjuster generates the plain text alternative. So all that is left is to remove the HTML body, which is easy, just call setHtmlBody(NULL). You can do that in a postRender() function, but you must make sure your weight is >800 to come after HtmlToTextEmailAdjuster.

    I have converted this to a "feature request". The task is to create a new EmailAdjuster implementation that does the above. Then it will be possible via the GUI with a policy element.

    With the above, you would just call setBody(). I agree setTextBody() is tempting, but it has the following comment:

    * By default, the text body will be generated from the unrendered body using
    * EmailInterface::getBody(). This function can be used to set a custom
    * plain-text alternative,

    thtas’s picture

    I've solved this for now using a hook:

    In code, creating the email with

    $email->setBody('Some basic plain text input');
    

    Then the hook to remove the html and add the plain text.

    /**
     * Implements hook_mailer_post_render().
     */
    function MY_MODULE_mailer_post_render(\Drupal\symfony_mailer\EmailInterface $email) {
      // Only send as plain text.
      if ($email->getSubType() == 'SUBTYPE') {
        $email->setTextBody($email->getHtmlBody());
        $email->setHtmlBody(NULL);
      }
    }
    
    jons’s picture

    There is a variable is_html in the swiftmailer template (swiftmailer.html.twig)
    I used this to manage HTML/plain text output in the template.
    This is not set for the new email.html.twig
    It was populated in the SwiftMailer.php plugin code.

    It would be good to set this for symfony_mailer both for backward compatibility and native use.
    However I can't see how a client module, via hooks, can get hold of both email object (to make a decision on whether to set is_html) and $variables at the same time (to set it)?

    adamps’s picture

    email.html.twig is similar to simplenews-newsletter-body.html.twig or commerce-order-receipt.html.twig - it creates a base email body

    swiftmailer.html.twig is different - it wraps the above base email which is available as {{ body }}. It is similar to the template that would be added as part of #3271797: Wrap email body which would have the is_html variable.

    jons’s picture

    Thanks @AdamPS
    Lots of layers of this to try to figure out!

    I've built a native implementation and added code as in #4

    The symfony _mailer still sends text/plain and text/html sections (though the text/html is empty) (overall multipart/alternative).
    My email client shows the empty body by default. Should the text/html be omitted if content is empty?

    --5rFB3OrX
    Content-Type: text/plain; charset=utf-8
    Content-Transfer-Encoding: quoted-printable
    
    =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
    test body
    =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
    
    --5rFB3OrX
    Content-Type: text/html; charset=utf-8
    Content-Transfer-Encoding: quoted-printable
    
    --5rFB3OrX--
    adamps’s picture

    Should the text/html be omitted if content is empty?

    I guess that it is a matter of timing. Your hook will run run the default weight = 500. One of the adjusters such as AbsoluteUrlEmailAdjuster (weight = 700) runs afterwards and puts in an empty body.

    You should make your code run with weight > 800, which makes it after HtmlToTextEmailAdjuster, then the plain text is already there (but better, as it calls Html2Text) and you can just call $email->setHtmlBody(NULL);. This way you will still get absolute URLs, which can be important. To create a hook with a specific weight, write a hook_mailer_TYPE__SUBTYPE_init() which calls email->addProcessor().

    jons’s picture

    @AdamPS thanks
    I see the issue but not sure how to change the weight.
    I assume its my hook mymodule_mailer_post_render() code that needs to run later - but it sounds like its not the module weight you are referring to but the processor weight - which would be my EmailBuilderBase plugin?
    I cant see how to do this with the hook you mention (ie on the $email object ).

    adamps’s picture

    Issue summary: View changes

    it sounds like its not the module weight you are referring to but the processor weight -

    Correct

    I cant see how to do this with the hook you mention

    It's not possible with the post_render hook. The easiest way is to create an email adjuster. I added an explanation to the issue summary "proposed resolution" section. It would be great if you could upload a patch if you get it working.

    adamps’s picture

    Status: Active » Needs review
    StatusFileSize
    new1.38 KB

    • AdamPS committed de06491 on 1.x
      Issue #3264279 by AdamPS: Send email as plaintext
      
    adamps’s picture

    Status: Needs review » Fixed
    adamps’s picture

    This EmailAdjuster has been disabled - the setting is now on WrapAndConvertEmailAdjuster.

    Edit: see #3271797: Wrap email body

    Status: Fixed » Closed (fixed)

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