Sending email
The shop sends emails about orders and registration by itself. A module can send its own — for example, tell the shop owner about a new review. The Mail::Send() method does that: it takes a mail template, substitutes variables into it and sends it through the shop's mail settings.
Where templates live
A module's mail templates are kept in the mails folder, one subfolder per language. Every email needs two files with the same name: an HTML version and a text one. Create them by hand:
modules/acmehello/
├── acmehello.php
├── mails/
│ └── en/
│ ├── review_added.html
│ └── review_added.txt
└── ...The subfolder name is the language code: en, ru, fr. Always keep the en folder: if there is no template for the email's language, the engine takes the English one.
The template
<!-- modules/acmehello/mails/en/review_added.html -->
<h2>New review</h2>
<p>Product: {product}</p>
<p>Author: {author}</p>
<p>Rating: {rating} out of 5</p>New review
Product: {product}
Author: {author}
Rating: {rating} out of 5The second block is the content of the review_added.txt file. A mail template is not Smarty: it has no conditions or loops, only placeholders in curly braces that are replaced with values.
Sending
// modules/acmehello/acmehello.php
private function notifyAboutReview(string $productName, string $author, int $rating): bool
{
return (bool) Mail::Send(
(int) $this->context->language->id,
'review_added',
$this->trans('New product review', [], 'Modules.Acmehello.Admin'),
[
'{product}' => $productName,
'{author}' => $author,
'{rating}' => $rating,
],
Configuration::get('PS_SHOP_EMAIL'),
null,
null,
null,
null,
null,
$this->getLocalPath() . 'mails/'
);
}The method sends an email to the shop address and returns true on success.
Arguments of Mail::Send
| In order | What is passed |
|---|---|
| 1 | The language id: it selects the template subfolder |
| 2 | The template name without the extension |
| 3 | The subject |
| 4 | The array of variables: the key is the placeholder with its braces |
| 5 | The recipient address |
| 6 | The recipient name |
| 7, 8 | The sender address and name; null means the shop settings |
| 9 | An attachment |
| 10 | Internal, left as null |
| 11 | The templates folder. For a module — its mails folder |
Without the eleventh argument the engine looks for the template in the shop's common mails folder and does not find it. getLocalPath() returns the path of the module folder on disk.
Calling it after a review is saved
// modules/acmehello/acmehello.php, the addReview method
if (!$review->add()) {
return false;
}
$product = new Product($productId, false, $this->context->language->id);
$this->notifyAboutReview($product->name, $author, $rating);
return true;The email goes out after the review is saved. The sending result does not affect saving: a review must not be lost because of broken mail.
How to see the result
Send a review through the form on the reviews page and open "Advanced Parameters → E-mail" in the back office. At the bottom of the page there is a log of sent emails: a line with the review_added template appears there. The same page is where the sending method is configured and a test email is sent.
On a local machine mail usually does not leave the computer. It is handy to point the SMTP settings at a local mail catcher such as Mailpit: the emails show up in its window.
Ready variables
The engine adds several placeholders to every email by itself.
| Placeholder | What is substituted |
|---|---|
{shop_name} | The shop name |
{shop_url} | The shop address |
{shop_logo} | The logo |
Common mistake
Only the .html file is created and the .txt one is forgotten. Mail::Send() returns false, the email is not sent, and there is no error on screen. Every email needs both files with the same name in the folder of every language.