How to apply template (tpl) file for email message body - php

I've this mail function in my custom module
function mymodule_mail($key, &$message, $params) {
switch ($key) {
case 'notification':
$message['headers']['Content-Type'] = 'text/html; charset=UTF-8; format=flowed';
$message['subject'] = $params['subject'];
$message['body'] = t('<table style="border:2px solid black;"><tr><td>MESSAGE BODY </td><td><b>'.$params['msg'].'</b></td></tr></table>');
break;
}
}
Here you can clearly see that for message body i'm using some html tags.
Below code invoke the mail function, which is written in my block.
$params = array(
'subject' => 'email subject',
'msg' => 'message body',
);
drupal_mail('mymodule', 'notification', 'email address', language_default(), $params);
I want to know, is there any easy way to apply a template (.tpl.php) file for my message body so that i can put my all css styling within that tpl file.
Any suggestion would be greatly appreciated.

You'll need to set up a theme call for it
function mymodule_theme() {
$path = drupal_get_path('module', 'mymodule') . '/templates';
return array(
'mymodule_mail_template' => array(
'template' => 'your-template-file', //note that there isn't an extension on here, it assumes .tpl.php
'arguments' => array('message' => ''), //the '' is a default value
'path' => $path,
),
);
}
Now that you have that, you can change the way you're assigning the body
$message['body'] = theme('mymodule_mail_template', array('message' => $params['msg']);
The key message needs to match the argument you supplied in mymodule_theme(), which it does.
Now you can just create your-template-file.tpl.php in the module's templates/ folder (you'll have to make that) and you can use the variable $message in your template to do whatever you'd like. The variable name matches your theme argument name.
After your module is set up properly, make sure to flush the cache. I can't tell you how long it took me to realize that the first time I started working with Drupal, and how much time I wasted trying to fix non-existent bugs.

The HTML Mail module does just that :-)

Related

Codeigniter 4 Email sending with HTML as message

can you help me figure out a way to use the email class of CI4 to send an email with an HTML as the message?
in Codeigniter 3 it is simple and goes like this:
$email->message($this->load->view('html_page_to_send_from_view_folder',$data,true));
but in Codeigniter 4 I tried doing this:
$email->setMessage(echo view('html_page_to_send_from_view_folder',$data,true));
It gives out an error:
syntax error, unexpected echo(T_ECHO), expecting ')'
I also tried putting the view in a variable like so:
$echo_page = echo view('html_page_to_send_from_view_folder',$data,true);
$email->setMessage($echo_page);
but it just throws the same error, I was searching all over the internet and the documentation but couldn't find a way to do this. Help please.
I tried this but got no error, and also got no email :'(
$echo_page = view('html_page_to_send_from_view_folder',$data,true);
$email->setMessage($echo_page);
According to this, if you want to use some template as your message body, you should do something like this:
// Using a custom template
$template = view("email-template", []);
$email->setMessage($template);
CodeIgniter 4 documentation states:
setMessage($body)
Parameters: $body (string) – E-mail message body
Returns: CodeIgniter\Email\Email instance (method chaining)
Return type: CodeIgniter\Email\Email
Sets the e-mail message body:
$email->setMessage('This is my message');
Okay I got it now I made it work by adding this code $email->setNewLine("\r\n"); at the end just after the setMessage:
$email->setMessage($my_message);
$email->setNewLine("\r\n");
and also I set the SMTP port 587 instead of 465:
$config['SMTPPort']= 587;
ALSO, for the setMessage, I did it like this:
$my_message = view('html_page_to_send_from_view_folder',["id" => $data['id']]);
$email->setMessage($my_message);
really weird man....
A. Firstly,
Instead of:❌
$echo_page = echo view('html_page_to_send_from_view_folder',$data,true);
Use this:✅
$echo_page = view('html_page_to_send_from_view_folder',$data);
Notice the luck of an echo statement and not passing true as the third argument of the view(...) hepler function.
B. Secondly, to submit HTML-based emails, ensure that you've set the mailType property to html. This can be achieved by using the setMailType() method on the Email instance. I.e:
$email->setMailType('html');
Alternatively, you could set the "mail type" by passing an array of preference values to the email initialize() method. I.e:
public function sendMail(): bool
{
$email = \Config\Services::email();
$email->initialize([
'SMTPHost' => 'smtp.mailtrap.io',
'SMTPPort' => 2525,
'SMTPUser' => '479d7c109ae335',
'SMTPPass' => '0u6f9d18ef3256',
'SMTPCrypto' => 'tls',
'protocol' => 'smtp',
'mailType' => 'html',
'mailPath' => '/usr/sbin/sendmail',
'SMTPAuth' => true,
'fromEmail' => 'from#example.com',
'fromName' => 'DEMO Company Name',
'subject' => 'First Email Test',
]);
$email->setTo('to#example.com');
$email->setMessage(view('blog_view'));
$response = $email->send();
$response ? log_message("error", "Email has been sent") : log_message("error", $email->printDebugger());
return $response;
}

$t function does not work in lithium email template

I have a email template onecode.mail.php
Which I call from
$body = $view->render(
'template',
compact('users','oneCode','username'),
array(
'controller' => 'users',
'template'=>'onecode',
'type' => 'mail',
'layout' => false
)
);
$transport = Swift_MailTransport::newInstance();
$mailer = Swift_Mailer::newInstance($transport);
$message = Swift_Message::newInstance();
$message->setSubject("Sign in password");
$message->setFrom(array(NOREPLY => 'Sign in password'));
$message->setTo($email);
$message->setBody($body,'text/html');
$mailer->send($message);
onecode.mail.php contains
<?=$t('Login Email Password')?>
<?=$oneCode?>
I get an error while processing this request as:
<b>Fatal error</b>: Function name must be a string in <b>app\resources
\tmp\cache\templates
\template_views_users_onecode.mail_0_1460392715_2266.php</b> on line <b>1</b><br/>
Translation works perfect in all the .html.php files but not in the template of .email.php
What should be done? Any suggestions, thanks for the help.
Please add the following lines in your template:
<?php
use lithium\g11n\Message;
extract(Message::aliases());
?>
<?=$t('Login Email Password')?>
You should be able to get the translation in your desired language

CakePHP Paypal IPN Plugin email not working

I'm using this plugin in a CakePHP Application. Everything seems to work except sending emails.
I have the following code in AppController.php
function afterPaypalNotification($txnId)
{
//Here is where you can implement code to apply the transaction to your app.
//for example, you could now mark an order as paid, a subscription, or give the user premium access.
//retrieve the transaction using the txnId passed and apply whatever logic your site needs.
$transaction = ClassRegistry::init('PaypalIpn.InstantPaymentNotification')->findById($txnId);
$this->log($transaction['InstantPaymentNotification']['id'], 'paypal');
//Tip: be sure to check the payment_status is complete because failure
// are also saved to your database for review.
if ($transaction['InstantPaymentNotification']['payment_status'] == 'Completed')
{
//Yay! We have monies!
ClassRegistry::init('PaypalIpn.InstantPaymentNotification')->email(array(
'id' => $txnId,
'subject' => 'Thanks!',
'message' => 'Thank you for the transaction!'
));
}
else
{
//Oh no, better look at this transaction to determine what to do; like email a decline letter.
ClassRegistry::init('PaypalIpn.InstantPaymentNotification')->email(array(
'id' => $txnId,
'subject' => 'Failed!',
'message' => 'Please review your transaction'
));
}
}
But the data returned from Paypal is saved in the instant_payment_notifications table but for some reason the emails are not sent. Has anybody tried this plugin before and did the email fonctionality work?
Do I need to enable email.php in app/Config for the emails to work? I read somewhere on Cake's website that I don't need that file for emails to work, so I guess that's not where the problem is.
Any help will be appreciated.
Thanks.
In CakePhp 2.5 you should use CakeEmail
Create the file /app/Config/email.php with the class EmailConfig. The /app/Config/email.php.default has an example of this file.
Add following line in /app/Controller/AppController.php before class declaration
App::uses('CakeEmail', 'Network/Email');
In afterPaypalNotification function replace
ClassRegistry::init('PaypalIpn.InstantPaymentNotification')->email(array(
'id' => $txnId,
'subject' => 'Thanks!',
'message' => 'Thank you for the transaction!'
));
with (fast e-mail, no style)
CakeEmail::deliver('customer#example.com', 'Thanks!', 'Thank you for the transaction!', array('from' => 'you#example.com'));
or
$Email = new CakeEmail();
$Email->template('email_template', 'email_layout')
->emailFormat('html')
->to('customer#example.com')
->from('you#domain.com')
->viewVars(array('id' => $txnId))
->send();
Email template goes to /app/View/Emails/html/email_template.ctp
Email layouts goes to /app/View/Layouts/Emails/html/email_layout.ctp

Cakephp not redirecting after sending email through CakeEmail

In CakePHP 2.X, for one of my controller actions, I am trying to send an email to all user's every time a new record is created.
Updated with drmonkeyninja's suggestions:
// NewslettersContoller.php
public function add() {
if($this->request->is('post')) {
$this->Newsletter->create();
if($this->Newsletter->save($this->request->data)) {
$this->Session->setFlash(__('Your newsletter has been submited.'));
$this->redirect(array('action' => 'view', $this->Newsletter->id));
}
else {
$this->Session->setFlash(__('Unable to add your post.'));
return $this->redirect(array('action' => 'add'));
}
}
}
// Newsletter.php
public function afterSave($created, $options = []) {
parent::afterSave($created, $options);
if ($created === true) {
$newsletter = $this->findById($this->id);
// Get all users with an email address.
$emails = ClassRegistry::init('User')->find(
'list',
array(
'fields' => array(
'User.id',
'User.email'
),
'conditions' => array(
'User.email <>' => null
)
)
);
$Email = new CakeEmail('gmail');
$Email->from(array('me#example.com' => 'Caprock Portal'));
$Email->to($emails);
$Email->subject($newsletter['Newsletter']['title']);
$Email->message($newsletter['Newsletter']['content']);
try {
$Email->send();
} catch (Exception $exception) {
$this->log($exception);
}
}
}
As you can see from the code snippet, I use CakeEmail to send every user an email containing the newsletter created in the action. Unfortunately for some reason, every time CakeEmail finishes sending the email, CakePHP ignores my redirect request and proceeds to render a blank view (route is still add). I have verified that it is the CakeEmail function by commenting it and verifying that redirection starts to work again. Nothing is caught in the try-catch block either.
One of my assumptions for the cause of this problem is that the email headers are interfering with the redirect headers for my action. I inspected the network requests through my browser, but nothing seems to be sent out, except from the original post request to the add function.
It would be better to send the email from the Newsletter model in the afterSave() callback:-
// app/Model/Newsletter.php
App::uses('CakeEmail', 'Network/Email');
public function afterSave($created, $options = []) {
parent::afterSave($created, $options);
if ($created === true) {
$newsletter = $this->findById($this->id);
// Get all users with an email address.
$emails = ClassRegistry::init('User')->find(
'list',
array(
'fields' => array(
'User.id',
'User.email'
),
'conditions' => array(
'User.email <>' => null
)
)
);
$Email = new CakeEmail('gmail');
$Email->from(array('me#example.com' => 'Caprock Portal'));
$Email->to($emails);
$Email->subject($newsletter['Newsletter']['title']);
$Email->message($newsletter['Newsletter']['content']);
try {
$Email->send();
} catch (Exception $exception) {
$this->log($exception);
}
}
}
Your controller action would then just be:-
// app/Controller/NewslettersController.php
public function add() {
if ($this->request->is('post')) {
$this->Newsletter->create();
if ($this->Newsletter->save($this->request->data)) {
return $this->redirect(array('action' => 'view', $this->Newsletter->id));
} else {
$this->Session->setFlash(__('Unable to add your post.'));
return $this->redirect(array('action' => 'add'));
}
}
}
If the view is still not rendering then temporarily disable the afterSave() callback to check that the Controller part of the code is working as expected when saving your newsletter.
Note that you can filter out the users without an email address when you retrieve the users from the database. By using find('list') you don't need to mess with a foreach loop.
You also don't need to use $this->Newsletter->getLastInsertId(); as $this->Newsletter->id should have already been set to this at the time of save.
Cake's debug() method is better to use when debugging variables than var_dump() which incidentally won't work in your example as your are redirecting after it has been output!
You can also try specifying the controller in the url array:
if($Email->send()) {
return $this->redirect(
array('controller' => 'controller_name', 'action' => 'view', $id)
);
} else {
return $this->redirect(
array('controller' => 'controller_name', 'action' => 'add')
);
}
Remove the var_dump. It breaks HTTP protocol if you try to send header information (for the redirect) after content has already been sent.
Another alternative is to send the emails out as a Shell/Console using a Cronjob.
This is a link to the book where you can find a bunch of information about creating shells.
CakePHP 3.x
http://book.cakephp.org/3.0/en/console-and-shells.html
CakePHP 2.x
http://book.cakephp.org/2.0/en/console-and-shells.html
This eliminates blocking your processing. If you send emails in controller or model, your app is still waiting for the emails to be sent before the page is rendered or redirected. So by moving to a cronjob the user has as faster better experience because the are not waiting for emails to be sent out.
So how do you know what to send out via the shell??? Well that depends on your use case but I flag records that need sent with a database column for this purpose, find all the ones that haven't been sent, mark those found records with another flag as being processed, the second flag in the database prevents two cron tasks from reading and sending the same records while the first cronjob is still processing. I like to set my cronjobs for mailing as low as possible for transaction type emails, however that can depend on the hosting provider and their settings.

SendGrid SMTP API for Applying Template

I'm trying to apply the sendgrid templates by building the SendGrid X-SMTPAPI headers in my index.php.
This is an abstract of my index.php code:
// Start Sendgrid
$sendgrid = new SendGrid('userid', 'pwd');
$header = new Smtpapi\Header();
$filter = array(
'templates' => array(
'settings' => array(
'enabled' => 1,
'template_id' => 'f2c99ace-87af-2618-8390-c19e2ad2805f'
)
)
);
$header->setFilters($filter);
$emailwelcome = new SendGrid\Email();
$emailwelcome->addTo($email)->
setFrom('hello#world.com')->
setFromName('Welcome to World')->
setSubject('Your Invitation')->
setText('Hello World!')->
setHtml('<strong>Hello World!</strong>');
$sendgrid->send($emailwelcome);
To apply the templates, as copied from the SendGrid documentation:
"Enabling a Template
To use a Template Engine template when you send, enable the templates filter and set the template_id to one of your Template Engine templates.
Example
{
"filters": {
"templates": {
"settings": {
"enable": 1,
"template_id": "5997fcf6-2b9f-484d-acd5-7e9a99f0dc1f"
}
}
}
}
You can use this JSON in the X-SMTPAPI header of an SMTP message, or in the x-smtpapi parameter of a mail.send API call."
Question is... where is the X-SMTPAPI header of my SMTP message? In my composer.json or index.php or in the vendor files?
Thanks for your help.
Okay, so apparently. All you need to do is add these 2 lines of code in the index.php:
addFilter('templates', 'enable', 1)->
addFilter('templates', 'template_id', 'f2c99ace-87af-3618-8390-c19e2ad2805f');
Weeeeeeeee~

Categories