1

Description

I am using the contact form and it works in my Brave browser but in Safari and Chrome the form will not send. It used to work fine, so I don't know what has changed. If there is a quick work around without having to wait for a plugin update, that would be great, since it seems to be a browser specific issue. I am getting the following error: Unable to verify your data submission.

in /htdocs/vendor/yiisoft/yii2/web/Controller.phpat line 220
211212213214215216217218219220221222223224225226227228229    }
 
    /**
     * {@inheritdoc}
     */
    public function beforeAction($action)
    {
        if (parent::beforeAction($action)) {
            if ($this->enableCsrfValidation && Yii::$app->getErrorHandler()->exception === null && !$this->request->validateCsrfToken()) {
                throw new BadRequestHttpException(Yii::t('yii', 'Unable to verify your data submission.'));
            }
 
            return true;
        }
 
        return false;
    }
 
    /**
2. in /htdocs/vendor/craftcms/cms/src/web/Controller.php at line 171– [yii\web\Controller::beforeAction](https://www.yiiframework.com/doc-2.0/yii-web-controller.html#beforeAction()-detail)(yii\base\InlineAction)
165166167168169170171172173174175176177    {
        // Don't enable CSRF validation for Live Preview requests
        if ($this->request->getIsLivePreview()) {
            $this->enableCsrfValidation = false;
        }
 
        if (!parent::beforeAction($action)) {
            return false;
        }
 
        $this->_enforceAllowAnonymous($action);
 
        return true;
3. in /htdocs/vendor/yiisoft/yii2/base/Controller.php at line 176– craft\web\Controller::beforeAction(yii\base\InlineAction)
4. in /htdocs/vendor/yiisoft/yii2/base/Module.php at line 552– [yii\base\Controller::runAction](https://www.yiiframework.com/doc-2.0/yii-base-controller.html#runAction()-detail)('', ['p' => 'academy'])
5. in /htdocs/vendor/craftcms/cms/src/web/Application.php at line 305– [yii\base\Module::runAction](https://www.yiiframework.com/doc-2.0/yii-base-module.html#runAction()-detail)('contact-form/send', ['p' => 'academy'])
299300301302303304305306307308309310311     * @param string $route
     * @param array $params
     * @return Response|null The result of the action, normalized into a Response object
     */
    public function runAction($route, $params = []): ?BaseResponse
    {
        $result = parent::runAction($route, $params);
 
        if ($result === null || $result instanceof Response) {
            return $result;
        }
 
        $response = $this->getResponse();
6. in /htdocs/vendor/craftcms/cms/src/web/Application.php at line 608– craft\web\Application::runAction('contact-form/send', ['p' => 'academy'])
602603604605606607608609610611612613614        if ($request->getIsActionRequest()) {
            $route = implode('/', $request->getActionSegments());
 
            try {
                Craft::debug("Route requested: '$route'", __METHOD__);
                $this->requestedRoute = $route;
                return $this->runAction($route, $_GET);
            } catch (Throwable $e) {
                $this->_unregisterDebugModule();
                if ($e instanceof InvalidRouteException) {
                    throw new NotFoundHttpException(Craft::t('yii', 'Page not found.'), $e->getCode(), $e);
                }
                throw $e;
7. in /htdocs/vendor/craftcms/cms/src/web/Application.php at line 284– craft\web\Application::_processActionRequest(craft\web\Request)
278279280281282283284285286287288289290                    throw new ForbiddenHttpException();
                }
            }
        }
 
        // If this is an action request, call the controller
        if (($response = $this->_processActionRequest($request)) !== null) {
            return $response;
        }
 
        // If we’re still here, finally let Yii do its thing.
        try {
            return parent::handleRequest($request);
8. in /htdocs/vendor/yiisoft/yii2/base/Application.php at line 384– craft\web\Application::handleRequest(craft\web\Request)
9. in /htdocs/web/index.php at line 23– [yii\base\Application::run](https://www.yiiframework.com/doc-2.0/yii-base-application.html#run()-detail)()
17181920212223}
 
// Load and run Craft
define('CRAFT_ENVIRONMENT', getenv('ENVIRONMENT') ?: 'production');
/** @var craft\web\Application $app */
$app = require CRAFT_VENDOR_PATH.'/craftcms/cms/bootstrap/web.php';
$app->run();
$_GET = [
    'p' => 'academy',
];

$_POST = [
    'CRAFT_CSRF_TOKEN' => 'I8Ge6gfYDwDFoAfCHuyYidPquFiomw6sN2dsqw4gYnih9e0aJVgbCfcdAE4wF-F_f8gTQJBEgIv1Za5vqlpPsDVpgIE7ZISp92faioddTwJ32ZrGxWneVU_Vw2Ixm2XRUVdDPw1WCf6mhqAai3WHdeqLxkeLreYEsfjO1HJ--rZFJUXXTQYnzZaTfMzdO_LpX2ShTKenmEzvTDicmTSQKKDQ3eCB9zHp_UDmAjcZz0hCVx3nnro3dBl5JIt7NH0JJtNMTqtwJqR8s-iXV5wKnmx71QQMseAOUeaflVDtsrFsLTJO6Kr1oFzvbC6z81RQ_gPpMGB6Cj1vb8_C6cYj-T6wNtLS_3TZm6pM5culmxs_nPgPEBWiKUBF-PPVF5vwarOLchiQ',
    'action' => 'contact-form/send',
    'fromName' => 'Mat',
    'message' => [
        'lastName' => 'Test',
        'Address' => 'Street 4',
        'Phone' => '3234',
        'body' => 'Test',
        'subject' => '13a2d79f3d0502dda6a739b25c62590dde66c880f8d028d2e05d9b3b215ae838Ihr Anmeldung für die KWMM Academy',
    ],
    'fromEmail' => 'arentsen@tuta.io',
    'subject' => 'Anmeldung Academy',
];

$_COOKIE = [
    '_ga' => 'GA1.1.1886405093.1700471866',
    '_ga_6CHHVG88Y8' => 'GS1.1.1700471865.1.1.1700471905.0.0.0',
    'CraftSessionId' => '24a3f6c5aa12f1ba61593ec364728aab',
    '1031b8c41dfff97a311a7ac99863bdc5_identity' => '65d3e26ed3ae6f779769ad79d26e3ee83755c26a530cae8b8f3a5b49e20b4c14a:2:{i:0;s:41:"1031b8c41dfff97a311a7ac99863bdc5_identity";i:1;s:162:"[1,"[\\"9SA8TkDCAzXaxPtZTVeMf3Uk0rgfkJ6O09GSsPwoxuZrG_uCtTqmDebVSLUwHIHJkYxPFEjbjVKmH3JkAIAz54Qp8_awxGuQph75\\",null,\\"eede85db4b43e095858cc613d9c48e11\\"]",1209600]";}',
    'CRAFT_CSRF_TOKEN' => '11221cc31f3076f3b553cfafe50b5b0e8f53b56263aeed5124310007ed4588cea:2:{i:0;s:16:"CRAFT_CSRF_TOKEN";i:1;s:147:"_dvJ4tSSzIr92BTAZQ0iZ3R_V08c950-EzUVKsPf|65484ce0f5020c859afbc82f5e02fd8a7c43d6eb49629c0dedf9cd472178e251_dvJ4tSSzIr92BTAZQ0iZ3R_V08c950-EzUVKsPf|1";}',
    '1031b8c41dfff97a311a7ac99863bdc5_username' => 'ec3ef95ad492bdba655f6007f92ecb3fce265bc3943934474a8a8e4f2f1ed1dba:2:{i:0;s:41:"1031b8c41dfff97a311a7ac99863bdc5_username";i:1;s:5:"admin";}',
];

$_SESSION = [
    'bd62416aa8538ede709019a5e113eea5__flash' => [],
    '1031b8c41dfff97a311a7ac99863bdc5__token' => '9SA8TkDCAzXaxPtZTVeMf3Uk0rgfkJ6O09GSsPwoxuZrG_uCtTqmDebVSLUwHIHJkYxPFEjbjVKmH3JkAIAz54Qp8_awxGuQph75',
    '1031b8c41dfff97a311a7ac99863bdc5__id' => 1,
    '__authKey' => '["9SA8TkDCAzXaxPtZTVeMf3Uk0rgfkJ6O09GSsPwoxuZrG_uCtTqmDebVSLUwHIHJkYxPFEjbjVKmH3JkAIAz54Qp8_awxGuQph75",null,"eede85db4b43e095858cc613d9c48e11"]',
    '1031b8c41dfff97a311a7ac99863bdc5__expire' => 1701681559,
    '__duration' => 1209600,
];

My template is as follows:

{% macro errorList(errors) %}
    {% if errors %}
        {{ ul(errors, {class: 'errors'}) }}
    {% endif %}
{% endmacro %}

{% set message = message ?? null %}

{% if craft.app.session.hasFlash('notice') %}
    <p class="message notice">{{ craft.app.session.getFlash('notice')|t }}</p>
{% elseif craft.app.session.hasFlash('error') %}
    <p class="message error">{{ craft.app.session.getFlash('error')|t }}</p>
{% endif %}

{% if craft.app.session.hasFlash('notice') %}
{% else %}
    
    <form method="post" action="" accept-charset="UTF-8" id="academy-form">
        {{ csrfInput() }}
        {{ actionInput('contact-form/send') }}
        {#{ redirectInput('contact/thanks') }#}

        <div class="w-full flex flex-wrap">
            <div class="w-full md:w-1/2 mb-2 pr-2">
                <label for="from-name">* {{ "Vorname"|t }}</label>
                {{ input('text', 'fromName', message.fromName ?? '', {
                    id: 'from-name',
                    autocomplete: 'name',
                    class: 'border-2 p-1 w-full',
                    required: true,
                }) }}
                {{ message ? _self.errorList(message.getErrors('firstName')) }}
            </div>
            <div class="w-full md:w-1/2 mb-2 pr-2">
                <label for="lastName">* {{ "Nachname"|t }}</label>
                <input class='border-2 p-1 w-full' id="lastName" type="text" name="message[lastName]" REQUIRED value="">
            </div>
            <div class="w-full mb-2 pr-2">
                <label for="phone">* {{ "Adresse"|t }}</label>
                <input class='border-2 p-1 w-full' id="phone" type="text" name="message[Address]" REQUIRED value="">
            </div>

            <div class="w-full md:w-1/2 mb-2 pr-2">
                <label for="from-email">* Email</label>
                {{ input('email', 'fromEmail', message.fromEmail ?? '', {
                    id: 'from-email',
                    autocomplete: 'email',
                    class: 'border-2 p-1 w-full',
                    required : true,
                }) }}
                {{ message ? _self.errorList(message.getErrors('fromEmail')) }}
            </div>
            <div class="w-full md:w-1/2 mb-2 pr-2">
                <label for="phone">* {{ "Telefon"|t }}</label>
                <input class='border-2 p-1 w-full' id="phone" type="text" REQUIRED name="message[Phone]" value="">
            </div>

            <div class="w-full mb-4 pr-2 mt-2">
                {# I sign up for #}
                <div class="mb-0">{{ entry.signupText|default }}</div>

                {% for row in entry.checkboxOptions %}  
                    <div class="w-full "><label class="ml-2 inline-block cursor-pointer"><input class="cursor-pointer px-2 w-3 h-3 text-kworange-400 bg-gray-100 border-gray-300 rounded focus:ring-kworange-400 dark:focus:ring-kworange-400 dark:ring-offset-gray-800 focus:ring-2 dark:bg-gray-700 dark:border-gray-600" style="accent-color:#FE4D11;" type="checkbox" name="message[Courses][]" value="{{ row.col1 ? row.col1 }}"> {{ row.col1 ? row.col1 }}</label></div>
                {% endfor %}

                {{ message ? _self.errorList(message.getErrors('message')) }}
            </div>
            <div class="w-full mb-2 pr-2">
                <label for="message">* {{ entry.messageText }}</label>
                <textarea class="border-2 p-1 w-full" rows="5" cols="40" id="message" name="message[body]" REQUIRED>{{ message.message.body ?? '' }}</textarea>
            </div>
            
        {{ input('hidden', 'subject', "Anmeldung" ?? '', {
            id: 'subject',
        }) }}

        <input type="hidden" name="message[subject]" value="{{ 'Ihr Anmeldung'|hash }}">
            <div class="w-full mb-2 pr-2"><button class='border-2 px-2 py-1 hover:bg-kworange-400 hover:text-white hover:border-kworange-400' type="submit">{{ "Senden"|t }}</button></div>
        </div>
    </form>
{% endif %}
<div class="w-full pt-4">{{ entry.formAfterText|default }}</div>
 <div class="w-full" id="thanks"></div>

Versions

Craft: 4.5.10
Contact-form: 3.0.1
Contact-form extensions: 4.2.2

3
  • 2
    Are you using any caching? Nov 20 at 11:48
  • Yes, that's it, now it works, thanks so much!
    – Matthias
    Nov 24 at 21:43
  • Ok cool, I'll add it as an answer so we can close out properly. Nov 27 at 9:24

1 Answer 1

2

If you're using any kind of caching such as Nginx fastCGI static caching/Blitz/Craft's {% cache %} tags/Varnish etc, then you'll need to find a way to generate a fresh CSRF token in the hidden CSRF input in each form for each unique site visitor. Typically you'd do this by making a JS fetch request to an uncached template that returns the CSRF token on each page load and then inject the value into all the CSRF inputs. Here's an example from my boilerplate: https://github.com/cld-agency/craftwind-boilerplate/blob/craft-4/src/js/main.js#L27

For the sake of completeness, if you're using Freeform, you'll also need to refresh the form hash as per Solspace's instructions here: https://docs.solspace.com/craft/freeform/v4/templates/caching/

1

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.