If someone is interested, and as I can’t find any documentation on this implementation, here is my solution for a simple (or less simple) contact form with uniform + a phpmailer driver. (I’m a graphic designer so I don’t tell you that it’s the best solution, but it’s the only one I found online, feel free to add corrections)
Why phpmailer? Because as they say themselves:
Formatting email correctly is surprisingly difficult. There are myriad overlapping RFCs, requiring tight adherence to horribly complicated formatting and encoding rules - the vast majority of code that you’ll find online that uses the mail() function directly is just plain wrong! Please don’t be tempted to do it yourself - if you don’t use PHPMailer, there are many other excellent libraries that you should look at before rolling your own - try SwiftMailer, Zend_Mail, eZcomponents etc.
Kirby (and uniform) are based on the simple mail()
function, so after a lot of research (I’m not a developper) I ended to do this:
- Install the uniform plugin
- Install the phpmailer driver
- set up my controller
- set up my template
In /site/plugins
create a phpmailer-driver
folder, and copy the official class.phpmailer.php
you can found it on the official phpmailer github repo. This give you the base functions of phpmailer.
add a phpmailer-driver.php
with this content:
<?php
email::$services['phpmailer'] = function($email) {
require_once(__DIR__ . DS . 'class.phpmailer.php');
$mail = new PHPMailer;
$mail->CharSet = 'UTF-8';
$mail->setFrom($email->from);
$mail->addReplyTo($email->replyTo);
$mail->addAddress($email->to);
if ($email->attachment != null) {
$mail->addAttachment($email->attachment);
}
$mail->isHTML(true);
$mail->Subject = $email->subject;
$mail->Body = $email->body;
if (!$mail->send()) {
throw new Error('PHPMailer error: ' . $mail->ErrorInfo);
}
}
?>
Then, add a controller to your contact page, in /site/controllers
(a php file with the same name of the template you put the form in). The content of the controller depends on what you want to do, read the Uniform documentation. You can put this code directly in your template file but a controller is cleaner.
A simple example of contact form with copy sended to sender:
<?php
use Uniform\Form;
return function ($site, $pages, $page) {
$to = page('about')->email(); //or your email in a string 'your@email.com', or the email set in config.php
$subject = 'Contact from website '.$_POST['name'];
$from_email = $_POST['email'];
$message = $_POST['message'];
if(isset($_POST['receive_copy'])):
$receivecopy = true;
endif;
$form = new Form([
'email' => [
'rules' => ['required', 'email'],
'message' => "Email seems invalid.",
],
'name' => [],
'message' => [
'rules' => ['required'],
'message' => "The message is missing",
],
'receive_copy' => [],
]);
if (r::is('POST')) {
$form->emailAction([
'to' => $to,
'from' => $to, //use an email of your company, here the same email is used
'subject' => $subject,
'receive-copy' => $receivecopy,
'service' => 'phpmailer'
]);
}
return compact('form');
};
And the form himself in html/php, you can embed this directly in your template too, but a snippet is cleaner.
<form id="contact" method="post" action="#contact">
<fieldset>
<h3>Contact me</h3>
<?php if ($form->success()): ?>
<p class="success">Message sent</p>
<?php else: ?>
<?php snippet('uniform/errors', ['form' => $form]) ?>
<?php endif; ?>
<p>
<label for="name">Enter your name (optional) :</label>
<input id="name" <?php if ($form->error('name')): ?> class="error"
<?php endif; ?> name="name" type="text" value="<?php echo $form->old('name') ?>">
</p>
<p>
<label for="email">Enter your email* :</label>
<input id="email" <?php if ($form->error('email')): ?> class="error"
<?php endif; ?> name="email" type="email" value="<?php echo $form->old('email') ?>">
</p>
<p>
<label for="message">Write your message* :</label>
<textarea id="message" <?php if ($form->error('message')): ?> class="error"<?php endif; ?> name="message"><?php echo $form->old('message') ?></textarea>
</p>
<!-- The following field is for robots only, invisible to humans: -->
<p aria-hidden=”true” class="visually-hidden" id="pot">
<?php echo csrf_field() ?>
<?php echo honeypot_field() ?>
</p>
<p>
<label for="copy"><input id="copy" name="receive_copy" type="checkbox" value="true" checked="true">Receive a copy of your message.</label>
*Mandatory fields
</p>
<p>
<input type="submit" value="Send !" class="submit" />
</p>
</fieldset>
</form>
In your CSS, to hide the honeypot and csrf fields:
.visually-hidden, .uniform__potty {
position: absolute !important;
border: 0 !important;
height: 1px !important;
width: 1px !important;
padding: 0 !important;
overflow: hidden !important;
clip: rect(0, 0, 0, 0) !important;
}
I hope it can help some people who try to achieve this. Next step: do this without uniform, and implement advanced phpmailer functions as SMTP.