# Contact form validation

**URL:** <https://forum.getkirby.com/t/contact-form-validation/26033>\
**Category:** Questions\
**Tags:** v3\
**Created:** [July 20, 2022, 7:29pm UTC](https://forum.getkirby.com/t/contact-form-validation/26033 "2022-07-20T19:29:24Z")\
**Posts on this page:** 5\
**Page:** 1

<div class="post-metadata">

**Author:** ![gerico](https://avatars.discourse-cdn.com/v4/letter/g/ecb155/32.png) [@gerico](https://forum.getkirby.com/u/gerico)\
**Post date:** [July 20, 2022, 7:29pm UTC](https://forum.getkirby.com/t/contact-form-validation/26033/1 "2022-07-20T19:29:24Z")

</div>

Hi there,

I followed the example in the documents for a simple contact form. Upon testing the form is was failing to submit and I was getting a generic mailer error that told me nothing. I search the forum and found an old post where a suggestion was made to edit that controller to see if the form data is being captured.

For clarity I am using Kirby in Docker with Mailhog setup. I have got mailhog configured in my config.php as per the docs.

My controller:

```auto
<?php
return function($kirby, $pages, $page) {

    $alert = null;

    if($kirby->request()->is('POST') && get('submit')) {
dump($_POST); // check if you get into this if-statement at all
        // check the honeypot
        if(empty(get('website')) === false) {
            go($page->url());
            exit;
        }

        $data = [
            'name' => get('name'),
            'email' => get('email'),
            'text' => get('text')
        ];

        $rules = [
            'name' => ['required', 'minLength' => 3],
            'email' => ['required', 'email'],
            'text' => ['required', 'minLength' => 3, 'maxLength' => 3000],
        ];

        $messages = [
            'name' => 'Please enter a valid name',
            'email' => 'Please enter a valid email address',
            'text' => 'Please enter a text between 3 and 3000 characters'
        ];

        // some of the data is invalid
        if($invalid = invalid($data, $rules, $messages)) {
            $alert = $invalid;

            // the data is fine, let's send the email
        } else {
        dump($data);
            try {
                $kirby->email([
                    //...
                    
                ]);

            } catch (Exception $error) {
                if(option('debug')):
                    $alert['error'] = 'The form could not be sent: ' . $error->getMessage();
                else:
                    $alert['error'] = 'The form could not be sent!';
                endif;
            }

            // no exception occurred, let's send a success message
            if (empty($alert) === true) {
                $success = 'Your message has been sent, thank you. We will get back to you soon!';
                $data = [];
            }
        }
    }

    return [
        'alert' => $alert,
        'data' => $data ?? false,
        'success' => $success ?? false
    ];
};

```

and my contact.php

```auto
<?php if($success): ?>
            <div class="alert success">
                <p><?= $success ?></p>
            </div>
            <?php else: ?>
            <?php if (isset($alert['error'])): ?>
                <div><?= $alert['error'] ?></div>
            <?php endif ?>
            <form method="post" action="<?= $page->url() ?>">
            <fieldset class="[flow]">
                <div class="honeypot [visually-hidden]">
                    <label for="website">Website <abbr title="required">*</abbr></label>
                    <input type="url" id="website" name="website" tabindex="-1">
                </div>
                <div class="field">
                    <legend class="visually-hidden">Name</legend>
                    <label for="name">
                        Name <abbr title="required">*</abbr>
                    </label>
                    <input type="text" id="name" name="name" value="<?= esc($data['name'] ?? '', 'attr') ?>" required>
                    <?= isset($alert['name']) ? '<span class="alert error">' . esc($alert['name']) . '</span>' : '' ?>
                </div>
                <div class="field">
                    <legend class="visually-hidden">Telephone</legend>
                    <label for="tel">
                        Telephone <abbr title="required">*</abbr>
                    </label>
                    <input type="text" id="tel" name="tel" value="<?= esc($data['tel'] ?? '', 'attr') ?>" required>
                    <?= isset($alert['tel']) ? '<span class="alert error">' . esc($alert['tel']) . '</span>' : '' ?>
                </div>
                <div class="field">
                    <legend class="visually-hidden">Email</legend>
                    <label for="email">
                        Email <abbr title="required">*</abbr>
                    </label>
                    <input type="email" id="email" name="email" value="<?= esc($data['email'] ?? '', 'attr') ?>" required>
                    <?= isset($alert['email']) ? '<span class="alert error">' . esc($alert['email']) . '</span>' : '' ?>
                </div>
                <div class="field">
                    <legend class="visually-hidden">Message</legend>
                    <label for="text">
                        Message <abbr title="required">*</abbr>
                    </label>
                    <textarea id="text" name="text" rows="10" required>
                        <?= esc($data['text'] ?? '') ?>
                    </textarea>
                    <?= isset($alert['text']) ? '<span class="alert error">' . esc($alert['text']) . '</span>' : '' ?>
                </div>
                <input type="submit" name="submit" value="Submit">
            </fieldset>
            </form>
            <?php endif ?>

```

At the top I can see the form field data being dumped.

```auto
Array
(
    [website] => 
    [name] => Mathew
    [tel] => 5464565464564
    [email] => myemail@gmail.com
    [text] => sdf fdsfsd sd fsd fsdsdfsdf
    [submit] => Submit
)

Array
(
    [name] => Mathew
    [email] => myemail@gmail.com
    [text] => sdf fdsfsd sd fsd fsdsdfsdf
)

```

The error I then get in the from the form is now:

> The form could not be sent: The property “body” is required

---

<div class="post-metadata">

**Author:** ![texnixe](https://dub1.discourse-cdn.com/flex017/user_avatar/forum.getkirby.com/texnixe/32/5754_2.png) [@texnixe](https://forum.getkirby.com/u/texnixe)\
**Post date:** [July 20, 2022, 8:43pm UTC](https://forum.getkirby.com/t/contact-form-validation/26033/2 "2022-07-20T20:43:20Z")

</div>

What does your email configuration look like?

You left out the parameters in $kirby-\>email() and your email template, but the error points towards something there.

---

<div class="post-metadata">

**Author:** ![gerico](https://avatars.discourse-cdn.com/v4/letter/g/ecb155/32.png) [@gerico](https://forum.getkirby.com/u/gerico)\
**Post date:** [July 20, 2022, 9:08pm UTC](https://forum.getkirby.com/t/contact-form-validation/26033/3 "2022-07-20T21:08:31Z")

</div>

Hey @texnixe,

For clarity here is my working form template:

```auto
<?php if($success): ?>
            <div class="alert success">
                <p><?= $success ?></p>
            </div>
            <?php else: ?>
            <?php if (isset($alert['error'])): ?>
                <div><?= $alert['error'] ?></div>
            <?php endif ?>
            <form method="post" action="<?= $page->url() ?>">
            <fieldset class="[flow]">
                <div class="honeypot [visually-hidden]">
                    <label for="website">Website <abbr title="required">*</abbr></label>
                    <input type="url" id="website" name="website" tabindex="-1">
                </div>
                <div class="field">
                    <legend class="visually-hidden">Name</legend>
                    <label for="name">
                        Name <abbr title="required">*</abbr>
                    </label>
                    <input type="text" id="name" name="name" value="<?= esc($data['name'] ?? '', 'attr') ?>" required>
                    <?= isset($alert['name']) ? '<span class="alert error">' . esc($alert['name']) . '</span>' : '' ?>
                </div>
                <div class="field">
                    <legend class="visually-hidden">Telephone</legend>
                    <label for="tel">
                        Telephone <abbr title="required">*</abbr>
                    </label>
                    <input type="text" id="tel" name="tel" value="<?= esc($data['tel'] ?? '', 'attr') ?>" required>
                    <?= isset($alert['tel']) ? '<span class="alert error">' . esc($alert['tel']) . '</span>' : '' ?>
                </div>
                <div class="field">
                    <legend class="visually-hidden">Email</legend>
                    <label for="email">
                        Email <abbr title="required">*</abbr>
                    </label>
                    <input type="email" id="email" name="email" value="<?= esc($data['email'] ?? '', 'attr') ?>" required>
                    <?= isset($alert['email']) ? '<span class="alert error">' . esc($alert['email']) . '</span>' : '' ?>
                </div>
                <div class="field">
                    <legend class="visually-hidden">Message</legend>
                    <label for="text">
                        Message <abbr title="required">*</abbr>
                    </label>
                    <textarea id="text" name="text" rows="10" required>
                        <?= esc($data['text'] ?? '') ?>
                    </textarea>
                    <?= isset($alert['text']) ? '<span class="alert error">' . esc($alert['text']) . '</span>' : '' ?>
                </div>
                <input type="submit" name="submit" value="Submit">
            </fieldset>
            </form>
            <?php endif ?>

```

config:

```auto
return [
    'debug' => true,
    'panel' => [
        'slug' => 'admin-area'
    ],
    'email' => [
        'transport' => [
          'type' => 'smtp',
          'host' => 'localhost',
          'port' => 1025,
          'security' => false,
        ]
      ],
];

```

and my contact controller (copied from the docs, I’ve not yet added my telephone field in here. But it makes no different removing it from my template):

```auto
<?php
return function($kirby, $pages, $page) {

    $alert = null;

    if($kirby->request()->is('POST') && get('submit')) {

        // check the honeypot
        if(empty(get('website')) === false) {
            go($page->url());
            exit;
        }

        $data = [
            'name' => get('name'),
            'email' => get('email'),
            'text' => get('text')
        ];

        $rules = [
            'name' => ['required', 'minLength' => 3],
            'email' => ['required', 'email'],
            'text' => ['required', 'minLength' => 3, 'maxLength' => 3000],
        ];

        $messages = [
            'name' => 'Please enter a valid name',
            'email' => 'Please enter a valid email address',
            'text' => 'Please enter a text between 3 and 3000 characters'
        ];

        // some of the data is invalid
        if($invalid = invalid($data, $rules, $messages)) {
            $alert = $invalid;

            // the data is fine, let's send the email
        } else {
            try {
                $kirby->email([
                    'template' => 'email',
                    'from' => 'yourcontactform@yourcompany.com',
                    'replyTo' => $data['email'],
                    'to' => 'you@yourcompany.com',
                    'subject' => esc($data['name']) . ' sent you a message from your contact form',
                    'data' => [
                        'text' => esc($data['text']),
                        'sender' => esc($data['name'])
                    ]
                ]);

            } catch (Exception $error) {
                if(option('debug')):
                    $alert['error'] = 'The form could not be sent: <strong>' . $error->getMessage() . '</strong>';
                else:
                    $alert['error'] = 'The form could not be sent!';
                endif;
            }

            // no exception occurred, let's send a success message
            if (empty($alert) === true) {
                $success = 'Your message has been sent, thank you. We will get back to you soon!';
                $data = [];
            }
        }
    }

    return [
        'alert' => $alert,
        'data' => $data ?? false,
        'success' => $success ?? false
    ];
};

```

With this in place, I get the error:

```auto
The form could not be sent: SMTP connect() failed. https://github.com/PHPMailer/PHPMailer/wiki/Troubleshooting

```

As I mentioned I am using Docker and Mailhog. I am starting to wonder if this is something in my setup rather than a problem in Kirby. Although that leaves me even more stumped. I can access the mailhog client via `http://localhost:8025/` withouth issues and I can see in Docker that mailhog is running and bound to the relevant ports.

Is there any way to get a more detailed error message from the mailer to detect what is actually causing the problems?

---

<div class="post-metadata">

**Author:** ![gerico](https://avatars.discourse-cdn.com/v4/letter/g/ecb155/32.png) [@gerico](https://forum.getkirby.com/u/gerico)\
**Post date:** [July 20, 2022, 9:16pm UTC](https://forum.getkirby.com/t/contact-form-validation/26033/4 "2022-07-20T21:16:03Z")

</div>

@texnixe I just stumbled upon a fix. I came across an old post someone made where they stated they needed to use `'host'` with a value of `host.docker.internal`. Making this change fixes my issue… Not quite sure I understand whats happening, but thankful nonetheless.

---

<div class="post-metadata">

**Author:** ![texnixe](https://dub1.discourse-cdn.com/flex017/user_avatar/forum.getkirby.com/texnixe/32/5754_2.png) [@texnixe](https://forum.getkirby.com/u/texnixe)\
**Post date:** [July 20, 2022, 9:37pm UTC](https://forum.getkirby.com/t/contact-form-validation/26033/5 "2022-07-20T21:37:00Z")

</div>

> [@gerico](#):
>
> `host.docker.internal`

Yes, that’s right.

Alternatively, when you use docker-compose, you can use a named host, see my Docker recipe: [Kirby meets Docker | Kirby CMS](https://getkirby.com/docs/cookbook/setup/kirby-meets-docker#example-4-docker-compose__add-mailhog-service)

Using localhost or 127.0.0.1 works if you run Mailhog in a container but your website runs in a local webserver.
