Hello guys,
I have two forms on a website and I am trying to get the first one to work. I have a one-pager-website and the code for the form itself is in a snippet called site/snippets/contact_form.php
:
<div class="">
<div class="relative mx-auto px-1 py-1">
<div class="">
<?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 action="<?= $page->url() ?>" method="POST" id="contactform" class="grid grid-cols-1 gap-y-6 sm:grid-cols-2 sm:gap-x-8">
<div class="absolute -left-full">
<label for="website">Website <abbr title="required">*</abbr></label>
<input type="url" id="website" name="website" tabindex="-1">
</div>
<div>
<div class="mt-1">
<input required placeholder="Ihr Name *" type="text" name="name" id="name" value="<?= esc($data['name'] ?? '', 'attr') ?>" autocomplete="name" class="py-3 px-4 block w-full shadow-sm border border-transparent focus:outline-none focus:ring-2 focus:border-mixed-one focus:ring-mixed-one border-gray-300 rounded-sm">
<?= isset($alert['name']) ? '<span class="alert error">' . esc($alert['name']) . '</span>' : '' ?>
</div>
</div>
<div>
<div class="mt-1">
<input required placeholder="Ihre E-Mail-Adresse *" type="email" name="email" id="email" autocomplete="email" class="py-3 px-4 block w-full shadow-sm border border-transparent focus:outline-none focus:ring-2 focus:border-mixed-one focus:ring-mixed-one border-gray-300 rounded-sm" value="<?= esc($data['email'] ?? '', 'attr') ?>">
<?= isset($alert['email']) ? '<span class="alert error">' . esc($alert['email']) . '</span>' : '' ?>
</div>
</div>
<div class="sm:col-span-2">
<div class="mt-1"> <select class="py-3 px-4 block w-full shadow-sm border border-transparent focus:outline-none focus:ring-2 focus:border-mixed-one focus:ring-mixed-one border-gray-300 rounded-sm">
<option disabled selected="true">Ich bin ...</option>
<option>Option 1</option>
<option>Option 2</option>
<option>...</option>
</select> </div>
</div>
<div class="sm:col-span-2">
<div class="mt-1">
<textarea placeholder="Ihre Nachricht" id="message" name="message" rows="4" maxrows="10" class="py-3 px-4 block w-full shadow-sm border border-transparent focus:outline-none focus:ring-2 focus:border-mixed-one focus:ring-mixed-one border-gray-300 rounded-sm">
<?= esc($data['message'] ?? '') ?>
</textarea>
<?= isset($alert['message']) ? '<span class="alert error">' . esc($alert['message']) . '</span>' : '' ?>
</div>
</div>
<!-- ------------------------- Datenschutz Switch -------------------------- -->
<div class="sm:col-span-2">
<div class="flex items-start">
<div class="flex-shrink-0"> <button type="button" class="relative inline-flex flex-shrink-0 h-6 w-11 border-2 border-transparent rounded-full cursor-pointer transition-colors ease-in-out duration-200 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-mixed-one bg-mixed-one"
x-data="{ on: false }" role="switch" aria-checked="true" :aria-checked="on.toString()" @click="on = !on" x-state:on="Enabled" x-state:off="Not Enabled" :class="{ 'bg-mixed-one': on, 'bg-gray-300': !(on) }">
<span class="sr-only">Datenschutz</span>
<span aria-hidden="true" class="inline-block h-5 w-5 rounded-full bg-white shadow transform ring-0 transition ease-in-out duration-200 translate-x-5" x-state:on="Enabled" x-state:off="Not Enabled" :class="{ 'translate-x-5': on, 'translate-x-0': !(on) }"></span>
</button> </div>
<div class="ml-3">
<p class="text-base text-gray-500">text text text</p>
</div>
</div>
</div>
<!-- ------------------------- Newsletter -------------------------- -->
<div class="sm:col-span-2">
<div class="flex items-start">
<div class="flex-shrink-0"> <button type="button" class="relative inline-flex flex-shrink-0 h-6 w-11 border-2 border-transparent rounded-full cursor-pointer transition-colors ease-in-out duration-200 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-mixed-one bg-mixed-one"
x-data="{ on2: false }" role="switch" aria-checked="true" :aria-checked="on2.toString()" @click="on2 = !on2" x-state:on="Enabled" x-state:off="Not Enabled" :class="{ 'bg-mixed-one': on2, 'bg-gray-300': !(on2) }">
<span class="sr-only">Optional: Newsletter</span>
<span aria-hidden="true" class="inline-block h-5 w-5 rounded-full bg-white shadow transform ring-0 transition ease-in-out duration-200 translate-x-5" x-state:on="Enabled" x-state:off="Not Enabled" :class="{ 'translate-x-5': on2, 'translate-x-0': !(on2) }"></span>
</button> </div>
<div class="ml-3">
<p class="text-base text-gray-500"> text text text</p>
</div>
</div>
</div>
<!-- ---------------------------- ende switches ---------------------------- -->
<!-- ------------------------------- captcha ------------------------------- -->
<div class="sm:col-span-2">
<div class="mt-1">
<div>
<div class="mt-6 sm:mt-5 space-y-6 sm:space-y-5">
<div class="flex justify-center"> <span class="text-sm text-gray-500" id="title-optional">Spam-Abwehr: Bitte Aufgabe lösen *</span> </div>
<div class="flex justify-center"> <label for="validator" class="submit__control block text-sm font-medium text-gray-700">
<span class="text-sm text-gray-500" id="validator"></span>
<div class="mt-1 submit__generated"></div>
<!-- <i class="fas fa-sync"></i> -->
<svg xmlns="http://www.w3.org/2000/svg" class="syncIcon h-10 w-10" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M4 4v5h.582m15.356 2A8.001 8.001 0 004.582 9m0 0H9m11 11v-5h-.581m0 0a8.003 8.003 0 01-15.357-2m15.357 2H15" />
</svg>
</label> </div>
</div>
</div>
<div class="gotcha-wrapper"> <input class="w-full px-4 py-4 border" name="gotcha" id="gotcha" value="" placeholder="If you see this invest in better CSS - ignore me" /> </div>
</div>
</div>
<!-- ---------------------------- ende captcha ----------------------------- -->
<div class="sm:col-span-2">
<button type="submit" name="submit" class="w-full inline-flex items-center justify-center px-6 py-3 border border-transparent rounded-sm shadow-sm text-base font-medium text-white bg-contrast focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-contrast">
Nachricht absenden
</button>
</div>
<small>* Pflichtfeld</small>
</form>
<?php endif ?>
</div>
</div>
</div>
The email-validation is copied from the cookbook: site/controllers/contact_form.php
:
<?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'),
'message' => get('message')
];
$rules = [
'name' => ['required', 'minLength' => 1],
'email' => ['required', 'email'],
'message' => ['required', 'minLength' => 3, 'maxLength' => 3000],
];
$messages = [
'name' => 'Error Name',
'email' => 'Error Email',
'message' => 'Error Message'
];
// 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' => 'info@xxx.com',
'replyTo' => $data['email'],
'to' => 'myemail@gmail.com',
'subject' => esc($data['name']) . ' sent you a message from your contact form',
'data' => [
'message' => esc($data['message']),
'sender' => esc($data['name'])
],
// new feature that you can try with copy paste here
'beforeSend' =>function ($mailer) {
$mailer->SMTPOptions = [
'ssl' => [
'verify_peer' => false,
'verify_peer_name' => false,
'allow_self_signed' => true
]
];
return $mailer;
}
]);
} 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 = 'Ihre Nachricht wurde gesendet. Vielen Dank! Wir werden uns in Kürze bei Ihnen melden.';
$data = [];
}
}
}
return [
'alert' => $alert,
'data' => $data ?? false,
'success' => $success ?? false
];
};
And finally the email config from site/config/config.php
:
<?php
return [
'panel' =>[
'install' => true
],
'debug' => true,
'email' => [
'transport' => [
'type' => 'smtp',
'host' => 'smtp.office365.com',
'port' => 587,
'security' => 'starttls',
'auth' => true,
'username' => 'email',
'password' => 'password',
]
],
];
I have nothing found about starttls together with kirby. As far as I know office only supports starttls. Does anybody here has any experience with that?
When I submit the form the page just reloads. Inside the dev-tools in the network-tab I can see that it tries to get the index.php
file which always returns a 404 although the file exists. Might that cause an error? I am on nginx with docker.
My files are:
drwxr-xr-x 5 www-data www-data 4096 Aug 27 10:29 assets
-rw-r--r-- 1 www-data www-data 900 Aug 27 10:29 composer.json
drwxr-xr-x 9 www-data www-data 4096 Aug 31 18:02 content
-rw-r--r-- 1 www-data www-data 67 Aug 27 10:29 index.php
drwxr-xr-x 14 www-data www-data 4096 Aug 27 10:34 kirby
drwxr-xr-x 3 www-data www-data 4096 Sep 2 10:11 media
drwxr-xr-x 2 root root 4096 Aug 27 10:29 .metals
-rw-r--r-- 1 www-data www-data 718 Aug 27 10:29 package.json
-rw-r--r-- 1 www-data www-data 177829 Aug 27 10:29 package-lock.json
-rw-r--r-- 1 www-data www-data 184 Aug 27 10:29 postcss.config.js
-rw-r--r-- 1 www-data www-data 888 Aug 27 10:29 README.md
drwxr-xr-x 11 www-data www-data 4096 Sep 2 12:39 site
-rw-r--r-- 1 www-data www-data 2426 Aug 27 10:29 tailwind.config.js
I know that my structure is not perfect yet and that I have some security issues which I will be addressing once the contact-form works.
Thank you any help is appreciated.