Is there a way to send HTML emails?

Hi,

I’m trying to send and email using Kirby’s built-in email function, but the email body, which contains some HTML, is rendered as plain text by default, it is fine but unfortunately it doesn’t cover my case. Is there a way or just an option to set the content-type to text/html?

This is just an example of a possible option to achieve the goal:

$email = new Email(array(
  'to'      => 'mail@example.com',
  'from'    => 'john@doe.com',
  'subject' => 'Yay, Kirby sends mails',
  'body'    => 'Hey, this is a <strong>test email!</strong>'
  'options' => array(
     'isHtml' => true
  )
));

The toolkit docs say you can create your own adapter. I believe this is the only way to bypass the default header. You can try copying the default adapter and changing the header in the new service.

http://getkirby.com/docs/toolkit/sending-email#how-to-write-your-own-adaptor

email::$services['html_email'] = function($email) {

  $headers = array(
    'From: ' . $email->from,
    'Reply-To: ' . $email->replyTo,
    'Return-Path: ' . $email->replyTo,
    'Message-ID: <' . time() . '-' . $email->from . '>',
    'X-Mailer: PHP v' . phpversion(),
    'Content-Type: text/html; charset=utf-8',
    'Content-Transfer-Encoding: 8bit',
  );

  ini_set('sendmail_from', $email->from);
  $send = mail($email->to, str::utf8($email->subject), str::utf8($email->body), implode(PHP_EOL, $headers));
  ini_restore('sendmail_from');

  if(!$send) {
    throw new Error('The email could not be sent');
  }

};

Now, I’m not sure if this works when added in a plugin, to a page controller, or if it has to be added to the core e-mail file. The docs don’t specify. Perhaps @bastianallgeier or someone else can specify.

To specify the service try

$email = new Email(array(
  'to'      => 'mail@example.com',
  'from'    => 'john@doe.com',
  'service' => 'html_email',
  'subject' => 'Yay, Kirby sends mails',
  'body'    => 'Hey, this is a test email!'
));

if($email->send()) {
  echo 'The email has been sent';
} else {
  echo $email->error()->message();
}
4 Likes

Thank you @Luke, this seems the right solution. I will try to turn the service in a plugin.

Is there an ‘HTML Email Plugin’ anywhere? I really need this! :frowning:

The @Luke solution works fine. Put the content of the first snippet of his post in a file and move it in your Kirby ‘plugins’ folder. To use it, follow the second snippet.

For anyone looking, here is an up to date custom email driver for HTML email that works with Kirby 2.5.2

email::$services['html-mail'] = function($email) {
  $headers = header::create([
    'From'                      => $email->from,
    'Reply-To'                  => $email->replyTo,
    'Cc'                        => $email->cc,
    'Bcc'                       => $email->bcc,
    'Return-Path'               => $email->replyTo,
    'Message-ID'                => '<' . time() . '-' . $email->from . '>',
    'X-Mailer'                  => 'PHP v' . phpversion(),
    'Content-Type'              => 'text/html; charset=utf-8',
    'Content-Transfer-Encoding' => '8bit',
  ]);
  ini_set('sendmail_from', $email->from);
  $send = mail(
    $email->to,
    str::utf8($email->subject),
    str::utf8($email->body),
   $headers
  );
  ini_restore('sendmail_from');
  if(!$send) {
    throw new Error('The email could not be sent');
  }
};

To use with PHP mail():

$email = email(array(
  'to'      => 'mail@example.com',
  'from'    => 'john@doe.com',
  'subject' => 'Yay, Kirby sends mails',
  'body'    => 'Hey, this is a test email!',
  'service' => 'html-mail',
));

if($email->send()) {
  echo 'The email has been sent';
} else {
  echo $email->error()->message();
}

To use with Uniform plugin:

if (r::is('POST')) {
  $form->emailAction([
    'to'      => 'mail@example.com',
    'from'    => 'john@doe.com',
    'service' => 'html-mail',
    'replyTo' => 'john@doe.com',
    'subject' => 'Yay, Kirby sends mails',
    'snippet' => 'email',
  ]);
}
4 Likes