4.2.2
None of the email templating works according to the docs...
https://docs.silverstripe.org/en/4/developer_guides/email/
@ScopeyNZ is this what I was experiencing the other day?
I feel like it might be.
For context, pretend we're trying to send an email with some customisations:
$extraData = ['Important' => 'value'];
// $this is a DataObject
$data = $this->customise($extraData);
// Imagine $template references a template containing "<p>An important $Important</p>"
$email->setHTMLTemplate($template);
$email->setData($data);
$email->send();
// receive: "<p>An important </p>"
Does it work if you pass ArrayData::create($extraData) @NightJar ?
Sorry I didn't find the time to try, but suspect the same result. These methods have worked this way in the past, so suddenly not would be either a bug, or a BC break - the latter being of interest as to _when_ they stopped working, and why that's different to the documentation.
DataObject inherits from ViewableData so should already be compatible, and customise returns a ViewableData_Customised, so in any of the cases I'd expect this to work. If the fault sits elsewhere (e.g. customise not being able to accept an array) then I'd still argue that while this is just a manifestation it is still relevant.
I'm not 100% sure these are the same issue, unfortunately I found @mikeyc7m 's post a bit confusing as to what the actual problem was. But reading the template section of the Email docs specifically, that's _almost_ equivalent to what I've listed out above - the only difference I see is that I'm not using a simple array, at least not as the data parameter to the email.
My quick and dirty test code
PageController.php:
private static $allowed_actions = [
'thing'
];
public function thing(HTTPRequest $request)
{
$member = Security::getCurrentUser();
$email = Email::create('[email protected]', '[email protected]', 'This is a subject');
$data = $member->customise([]);
$email->setHTMLTemplate('Includes/email/MemberEmail');
$email->setData($data);
$email->send();
}
templates/Includes/email/MemberEmail.ss:
<div>
<h1>Hi $FirstName</h1>
<p>Your email is <em>$Email</em></p>
</div>
Reproduces the issue.
However I feel this is a little different to the issue suggested by the OP.
In anycase if this issue is systemic, as opposed to custom code in @ScopeyNZ and I's examples, and the default "reset password" is broken in core because of it, this is a major issue.
Particularly as that particular use-case will be a blocker to MFA work.
@mikeyc7m The work around for this issue (at least in my case) is to use $email->setCustomisedObj($customisedObject)
I'm unsure if it'll work with e.g. ArrayData or plain arrays.
I can reproduce that passing a ViewableData as the data for an email won't work in template variable calls, e.g.:
$email->setData(['FirstName' => 'Test']); // works when you call $FirstName in template
$member->customise([])->FirstName; // returns "default admin"
$member->customise([]); $email->setData($member); // empty when calling $FirstName in template
Email::setData() accepts a ViewableData object, which is where this bug is, so we need to fix that. This is related or perhaps the same problem as https://github.com/silverstripe/silverstripe-framework/issues/8302, which is "fixed".
I haven't had a chance yet to validate the other claims in the OP.
- if you use setBody() or pass in anything as a body, the entire template is replaced by that body, ignoring any setHTMLTemplate directive.
Just spent >1.5 hours trying to work out why an e-mail template wasn't working after upgrading to SilverStripe 4, now I know! Well, at least it wasn't me. What's the latest on this?
Reset password and other things are working for me now in 4.4.x-dev, however I've not had the time to go and re-check the specific reproduction steps listed above.
I don't know when/why/how this was fixed, and cannot be certain it is. If you could report back with what versions of the core modules you're using @purplespider that could help :)
- if you use setBody() or pass in anything as a body, the entire template is replaced by that body, ignoring any setHTMLTemplate directive.
This is still an issue in 4.4.4. I managed to work around it by changing $email->setBody($body) to:
php
$email->setData([
'Body' => DBField::create_field('HTMLFragment', $body),
]);
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 a SilverStripe/Control/Email.ss which presumably is what replaced this template.mail($from, $to, $subject, $body) format, then goes on to talk about the GenericEmail 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 the ForgotPasswordEmail.ss and ChangePasswordEmail.ss templates contain only paragraph tags so it looks like the intention is for those to be rendered out and passed in to Email.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 to EmailContent 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 a EmailContent 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:
there's no automatic plaintext render if the body is set. The plaintext render (...) prints the contents of