Subversion Repositories web.active

Rev

Blame | Last modification | View Log

<?php

/**
 * Simple and secure contact form using Ajax, validations inputs, SMTP protocol and Google reCAPTCHA v3 in PHP.
 * 
 * @see      https://github.com/raspgot/AjaxForm-PHPMailer-reCAPTCHA
 * @package  PHPMailer | reCAPTCHA v3
 * @author   Gauthier Witkowski <contact@raspgot.fr>
 * @link     https://raspgot.fr
 * @version  1.1.0
 */

use PHPMailer\PHPMailer\PHPMailer;
use PHPMailer\PHPMailer\Exception;
use PHPMailer\PHPMailer\SMTP;

# https://www.php.net/manual/fr/timezones.php
date_default_timezone_set('Europe/Amsterdam');

require __DIR__ . '/vendor/PHPMailer/Exception.php';
require __DIR__ . '/vendor/PHPMailer/PHPMailer.php';
require __DIR__ . '/vendor/PHPMailer/SMTP.php';
require __DIR__ . '/vendor/recaptcha/autoload.php';

class Ajax_Form {

    # Constants to redefined
    # Check this for more configurations: https://blog.mailtrap.io/phpmailer
    const HOST        = '192.168.2.104:25'; # SMTP server
    const USERNAME    = 'info@rldactive.nl'; # SMTP username
    const PASSWORD    = ''; # SMTP password
    const SECRET_KEY  = '6LdH8WUiAAAAAKWxUOxNDjrHegr6klQpD64iVU72'; # GOOGLE secret key
    const SMTP_SECURE = ''; #PHPMailer::ENCRYPTION_STARTTLS; //ENCRYPTION_STARTTLS;
    const SMTP_AUTH   = false;
    const PORT        = 25;
    const SUBJECT     = 'Nieuw bericht van webbezoeker !';
    const HANDLER_MSG = [
        'success'       => '✔️ Je bericht is verstuurd !',
        'token-error'   => '❌ Fout met recaptcha controle.',
        'enter_name'    => '❌ Je moet een naam invullen.',
        'enter_email'   => '❌ Vul een geldig email adres in.',
        'enter_message' => '❌ Je mag je bericht niet leeg laten.',
        'bad_ip'        => '❌ Adresseringsfout mail- en/of web-server',
        'ajax_only'     => '❌ Asynchronous anonymous.',
        'bot'           => '❌ Spam.',
        'email_body'    => '
            <h1>{{subject}}</h1>
            <p><b>Date</b>: {{date}}</p>
            <p><b>Name</b>: {{name}}</p>
            <p><b>E-Mail</b>: {{email}}</p>
            <p><b>Message</b>: {{message}}</p>
            <p><b>IP</b>: {{ip}}</p>
        '
    ];

    /**
     * Ajax_Form constructor
     */
    public function __construct()
    {
        # Check if request is Ajax request
        if (!empty($_SERVER['HTTP_X_REQUESTED_WITH']) && $_SERVER['HTTP_X_REQUESTED_WITH'] !== 'XMLHttpRequest') {
            $this->statusHandler('ajax_only');
        }

        # var_dump($_SERVER);
        # Check if fields has been entered and valid
        if ($_SERVER['REQUEST_METHOD'] === 'POST') {
            $name    = filter_var($this->secure($_POST['name']), FILTER_SANITIZE_STRING) ?? $this->statusHandler('enter_name');
            $email   = filter_var($this->secure($_POST['email']), FILTER_SANITIZE_EMAIL) ?? $this->statusHandler('enter_email');
            $message = filter_var($this->secure($_POST['message']), FILTER_SANITIZE_STRING) ?? $this->statusHandler('enter_message');
            $token   = filter_var($this->secure($_POST['recaptcha-token']), FILTER_SANITIZE_STRING) ?? $this->statusHandler('token-error');
            $ip      = filter_var($_SERVER['REMOTE_ADDR'], FILTER_VALIDATE_IP) ?? $this->statusHandler('bad_ip');
            $date    = new DateTime();
            $nhoning = (!empty($_POST['contact_me_by_fax_only']) && (bool) $_POST['contact_me_by_fax_only'] == TRUE);
            //$nhoning = TRUE;
        }
        
        # Prepare email body
        $email_body = self::HANDLER_MSG['email_body'];
        $email_body = $this->template($email_body, [
            'subject' => self::SUBJECT,
            'date'    => $date->format('j/m/Y H:i:s'),
            'name'    => $name,
            'email'   => $email,
            'ip'      => $ip,
            'message' => $message
        ]);

        # check honeypot
        //$honeypot = FALSE;
        //if (!empty($_REQUEST['contact_me_by_fax_only']) && (bool) $_REQUEST['contact_me_by_fax_only'] == TRUE) {
        //    $honeypot = TRUE;
        //  log_spambot($_REQUEST);
        //    # treat as spambot
        //}
        
        # Verifying the user's response
        $recaptcha = new \ReCaptcha\ReCaptcha(self::SECRET_KEY);
        $resp = $recaptcha
            ->setExpectedHostname($_SERVER['SERVER_NAME'])
            ->verify($token, $_SERVER['REMOTE_ADDR']);
        
        if (($resp->isSuccess()) && (!$nhoning)) {
        //if (true) {
            # Instanciation of PHPMailer
            $mail = new PHPMailer(true);
            $mail->setLanguage('nl', __DIR__ . '/forms/vendor/PHPMailer/language/');

            try {
                # Server settings
                $mail->SMTPDebug  = SMTP::DEBUG_OFF;   # Enable verbose debug outputSMTP::DEBUG_SERVER
                $mail->isSMTP();                       # Set mailer to use SMTP
                $mail->Host        = self::HOST;       # Specify main and backup SMTP servers
                $mail->SMTPAuth    = self::SMTP_AUTH;  # Enable SMTP authentication
                $mail->SMTPAutoTLS = self::SMTP_AUTH;  # Enable SMTP authentication
                $mail->Username   = self::USERNAME;    # SMTP username
                $mail->Password   = self::PASSWORD;    # SMTP password
                $mail->SMTPSecure = self::SMTP_SECURE; # Enable TLS encryption, `ssl` also accepted
                $mail->Port       = self::PORT;        # TCP port
                //$mail->SMTPSecure = '';
                # Recipients
                $mail->setFrom($email, $name);
                $mail->addAddress(self::USERNAME, 'info rldactive');
                $mail->addReplyTo(self::USERNAME, 'info rldactive');

                # Content
                $mail->isHTML(true);
                $mail->CharSet = 'UTF-8';
                $mail->Subject = self::SUBJECT;
                $mail->Body    = $email_body;
                $mail->AltBody = strip_tags($email_body);

                # Send email
                $mail->send();
                $this->statusHandler('success');

            } catch (Exception $e) {
                die(json_encode($mail->ErrorInfo));
            }
        } elseif (!($resp->isSuccess())) {
            die(json_encode($resp->getErrorCodes()));
        } else {
            //die('');
            $this->statusHandler('bot');
        }
    }

    /**
     * Template string values
     *
     * @param string $string
     * @param array $vars
     * @return string
     */
    public function template(string $string, array $vars): string
    {
        foreach ($vars as $name => $val) {
            $string = str_replace("{{{$name}}}", $val, $string);
        }

        return $string;
    }

    /**
     * Secure inputs fields
     *
     * @param string $post
     * @return string
     */
    public function secure(string $post): string
    {
        $post = htmlspecialchars($post);
        $post = stripslashes($post);
        $post = trim($post);

        return $post;
    }

    /**
     * Error or success message
     *
     * @param string $message
     * @return json
     */
    public function statusHandler(string $message): json
    {
       die(json_encode(self::HANDLER_MSG[$message]));
    }

}

# Instanciation 
new Ajax_Form();