silverstripe-framework: email templating broken
Affected Version
4.2.2
Description
None of the email templating works according to the docs… https://docs.silverstripe.org/en/4/developer_guides/email/
- you can’t override the default email template as described.
- if you use setBody() or pass in anything as a body, the entire template is replaced by that body, ignoring any setHTMLTemplate directive.
- there’s no automatic plaintext render if the body is set.
- the generic template expects something called $EmailContent, so can’t use setBody($body), must use addData(‘EmailContent’,$body)
- the plaintext render leaves behind artifacts such as line breaks & spacing, and prints the contents of <script> and <style> tags
Steps to Reproduce
Just try the password reset email, it’s unstyled and the plaintext version doesn’t include the link.
Or try coding a simple email:
Email::create('test1@here.com', 'test2@here.com', 'hello')->setBody('this is <a href="http://google.com">my google</a>')->send();
The results are… inconsistent? Do the docs need updating?
About this issue
- Original URL
- State: open
- Created 6 years ago
- Comments: 15 (14 by maintainers)
This is still an issue in 4.4.4. I managed to work around it by changing
$email->setBody($body)
to:I encountered some of these problems today. Partly it’s a documentation issue but also the built in templates have problems.
SilverStripe/Email/GenericEmail.ss
template which doesn’t exist. There is aSilverStripe/Control/Email.ss
which presumably is what replaced this template.mail($from, $to, $subject, $body)
format, then goes on to talk about theGenericEmail
template. Even if that template existed, if you pass a$body
argument then that template would not be used,$body
is taken as the entire html body (as noted earlier).Email.ss
template is structured as a wrapper, with a$EmailContent
placeholder. Presumably it’s intended that you can pass inner html to this wrapper, so you can work just with content and not worry about the html shell. Indeed theForgotPasswordEmail.ss
andChangePasswordEmail.ss
templates contain only paragraph tags so it looks like the intention is for those to be rendered out and passed in toEmail.ss
as$EmailContent
. This doesn’t happen though. Those emails call e.g.->setHTMLTemplate('SilverStripe\\Control\\Email\\ChangePasswordEmail')
so the result is an html email with no body tag or other boilerplate.Email.ss
template, there are no references toEmailContent
anywhere in the SilverStripe Framework/CMS codebase or docs. If you call->setData()
on an Email without specifying a template then that template will be used, but you would have to know by digging in to the code to pass your content in aEmailContent
property.One solution would be to:
SilverStripe/Control/Email.ss
template and tell people they can use it like$email->setData('EmailContent' => DBField::create_field('HTMLFragment', '<p>Some content</p>')
Email.ss
template.This should correct the html markup that is going to people’s email clients, and would allow SS developers to provided their own branded
SilverStripe/Control/Email.ss
template and know that it will be applied to these system emails.A drawback to that (and possibly making it a breaking change) would be that if a developer has already overridden the password templates and added a html/body shell to it, then you’ll get broken markup - a double shell. It also ultimately gives you less flexibility for modifying those emails since you could only edit the inner content. Perhaps that could be offset by letting developers set a template for these emails through config that could be used in place of
Email.ss
if they wish.Maybe an idea for SilverStripe 5 would be to extend the
Page.ss
+Layout/Page.ss
approach to emails? It’s essentially the same problem and developers are used to that solution.BTW:
These issues may have been fixed as
$email = new Email('noreply@example.com', 'example@example.com', 'test subject', '<!doctype html><html><body><style>style</style><script>script</script><p>test</p></body></html>'); $email->send();
worked fine for me, the plain text component was justtest
.Regarding CSS markup appearing in plaintext, you can suppress it by adding HTML comment tags! It doesn’t seem to affect the rendering of the HTML version and the plaintext version dutifully removes the fake comment.
My quick and dirty test code
PageController.php
:templates/Includes/email/MemberEmail.ss
:Reproduces the issue.
However I feel this is a little different to the issue suggested by the OP.