8/9/2018 - 12:47 PM

Simple Contact-Form in Kirby 3

Simple Contact-Form in Kirby 3

As a starting point I've used the latest Starterkit (Beta 4) combined with the core from the latest Nightly Build (18-08-06).

First, set email-properties in your config. I would recommend using a mail-service like Mailgun (via SMTP) because setting everything up on your own server is cumbersome, error-prone, and unsecure. But of course, it's up to you.



return [

  'debug'  => true,

    'email' => [

      'transport' => [
        'type' => 'smtp',
        'port' => 465,
        'ssl' => true,
        'host' => 'smtp.server.com',
        // If authentification is needed
            'auth' => true,
        'username' => '...',
        'password' => '...',

      'presets' => [
        'contact-form' => [
          'template'=> 'contact-form',
          'from'    => 'no-reply@your-domain.com',
              // Replace this with your email
          'to'    => 'you@your-mail.com',



Then we setup a contact template. Because that's already done in the Starterkit I've added a new section and put the actual form in a snippet.





  <?php if(param('success')): ?>

    <!-- Success -->
    <p>Message successfully sent.</p>

  <?php elseif(isset($alerts) && $alerts): ?>

    <!-- Errors -->
    <p>Fix the following errors:
        <?php foreach($alerts as $alert): ?>
          <li><?= html($alert) ?></li>
        <?php endforeach ?>

  <?php endif ?>

  <!-- Actual Form -->
  <?= snippet('contact-form') ?>




<form method="post">

    <label for="name">Name</label><br>
    <input type="text" id="name" name="name" required autofocus>

    <label for="email">E-Mail</label><br>
    <input type="email" id="email" name="email" required>

    <label for="message">Message</label><br>
    <textarea id="message" name="message" required></textarea>

  <button type="submit" name="submit" value="submit">Submit</button>


With the current size of the form a snippet does not really make sense but with more fields, classes and wrappers it'll propably become a beast, so I would recommend using a snippet ;)

The actual logic of the form lives inside a controller which must be named exactly like our template (contact).



return function($site, $pages, $page) {
  if(!get('submit')) return;

  $successUrl = url($page->url(), [ 'params' => 'success:true' ]);
  $alerts = null;

  // Gather form-data
  $form = kirby()->request()->data();

  // TODO
  // Validate form-data here..
  // Propably use `Kirby\Toolkit\V::input` here like suggested by @CelineDesign

  // Try to send the mail
  try {

    kirby()->email('contact-form', [
      'subject' => "Message by {$form['name']}",
      'replyTo' => $form['email'],
      'data' => [ 'form' => $form ]


  } catch (Exception $error) {
    return [ 'alerts' => [ $error ] ];


And finally we need the actual email-templates which are going to be sent. We called it contact-form in the config so lets create two(!) files:

  • site/emails/contact-form.html.php
  • site/emails/contact-form.text.php

Within these templates you can write all the template-code you are used to and also use global objects like site() or kirby().


  Name: <?= $form['name'] ?>

  E-Mail: <?= $form['email'] ?>

  Message: <?= $form['message'] ?>


Name: <?= $form['name'] ?>

E-Mail: <?= $form['email'] ?>

Message: <?= $form['message'] ?>

What could be improved

  • Add a simple Honeypot
  • Add Form-Validation
  • Use JavaScript for a loading animation when the form gets send
  • Or make the form completely AJAXish
  • Send a second mail as a confirmation for the user..
  • Better form markup (for autocomplete and accessibility)