机车 CMS(托管):在提交内容类型(模型)表格后发送电子邮件

Locomotive CMS (hosted): send email upon submission of Content Type (Model) form

我正在使用托管版的 Locomotive CMS。

机车 CMS 提供 means by which to collect form submissions and a means by which to send an email using the Actions API.

我想收集表单提交,然后发送电子邮件给提交表单的人。

我有 3 个注意事项:

  1. 我希望在 content type 中收集表单数据(启用 public 次提交)
  2. 我想使用 Google reCAPTCHA v3
  3. 我想submit the form using AJAX

上述所有项目在托管版本的 Locomotive CMS 中都是开箱即用的。但是,我不知道如何通过 AJAX 同时发送电子邮件来提交带有 Google reCAPTCHA 的内容类型表单。发送电子邮件功能需要一个专用页面上的 action,我认为需要加载该页面才能执行 运行 操作。此外,我不知道如何从表单提交到发送电子邮件操作 运行s.

的页面获取数据

如何通过 AJAX 提交 Locomotive CMS 内容类型表单并启用 Google reCAPTCHA 发送包含表单提交数据给表单提交者?

几个先决条件:

  1. 设置metafields_schema.yml以包含发送电子邮件的必要信息:

    smtp_settings:
      label: Outgoing Email
      fields:
    
        server:
          label: SMTP Server
          type: string
          localized: false
    
        username:
          label: Username
          type: string
          localized: false
    
        password:
          label: Password
          type: string
          localized: false
    
        port:
          label: Port
          type: string
          hint: TLS
          localized: false
    
  2. 设置电子邮件模板:

    邮箱-template.liquid:

    <p>Dear {{ entryData.first_name }},</p>
    <!-- include form submission data via entryData.form_field_name -->
    

如果去掉使用 Google reCAPTCHA 的条件,任务就相对简单了。

我们“简单地”将表单数据传递到自定义页面,我们在其中发送电子邮件并使用操作创建内容条目 API。

设置如下:

  1. 手动 创建一个表单来收集内容类型数据。请注意表单操作指向自定义页面:

    <form method="POST" enctype="multipart/form-data" class="form" action="{% path_to 'page-with-send-email-and-create-content-entry-action' %}">
        <!-- form fields here -->
    </form>
    
    <script defer src="{{ 'form-submit.js' | javascript_url }}"></script>
    
  2. 提交表单 AJAX:

    形式-submit.js:

    $('.form').on('submit', function(e) {
        e.preventDefault();
        var form = $(this);
    
        // error handling functions removed for brevity
    
        $.ajax({
            type: 'POST',
            url: form.attr('action'),
            data: form.serialize(),
            dataType: 'json',
            success: function(data) {
                console.log('Success:', data);
            },
            error: function(xhr, status, error) {
                console.log('Status:', status);
                console.log('Error:', error);
                var errors = jQuery.parseJSON(xhr.responseText).errors;
                console.log(errors);
                for (error in errors) { 
                    myError = error;
                    console.log(myError);
                }
            }
        });
    
    });
    
  3. Send an email and create a content type entry 使用操作 API:

    带发送电子邮件和创建内容条目的页面-action.liquid:

    {% action "send email and create content type entry" %}
    
        var SMTPsettings = getProp('site').metafields.smtp_settings;
        var entryData = getProp('params'); // params holds the data passed to the page via AJAX
    
        // save entryData into a Liquid variable to be called in the Email Template
        setProp('entryData',entryData);
    
        sendEmail({
    
            to: formData.email_address, // must match the name attribute of the field used to collect the email address 
            from: SMTPsettings.username,
            subject: '[Email Subject]',
            page_handle: 'email-template', // template page for email
    
            smtp: {
                address: SMTPsettings.server,
                port: SMTPsettings.port,
                user_name: SMTPsettings.username,
                password: SMTPsettings.password,
                authentication: 'plain',
                enable_starttls_auto: true
            }
    
        });
    
        createEntry('content_entry_name', {
            content_type_field_name: formData.form_field_name,
            // comma-separated list - last item has no comma
        });
    
    {% endaction %}
    
    {"success":true}
    

如果需要Google reCAPTCHA,则任务比较复杂。

我认为没有办法在启用 Google reCAPTCHA 的情况下在 Locomotive CMS 中手动创建表单,这意味着上述方法将不起作用。

Google reCAPTCHA 可通过默认 内容类型表单设置在 Locomotive CMS 中使用:

{% model_form 'content_type_slug', class: 'form', json: true, recaptcha: true %}
    // form fields here
{% endmodel_form %}

<script src="https://www.google.com/recaptcha/api.js?render={{ site.metafields.google.recaptcha_site_key }}"></script>

<script>
    grecaptcha.ready(function() {
        grecaptcha.execute('{{ site.metafields.google.recaptcha_site_key }}', {
            action: 'enquiry'
        })
        .then(function(token) {
            document.getElementById('g-recaptcha-response').value  = token;
        });
    });
</script>

<script defer src="{{ 'form-submit.js' | javascript_url }}"></script>

注意:属性recaptcha_required需要在content_typeyml文件中设置为true

在这种情况下,我们无法为表单操作设置自定义 url。此外,reCAPTCHA 验证意味着我们需要让表单通过常规流程提交和创建内容条目,并单独发送电子邮件。

为此,我们需要获取在提交表单时创建的内容条目的 ID。然后我们可以 运行 一个额外的 AJAX 请求并将 ID 传递到包含发送电子邮件操作的自定义页面。在自定义页面上,我们将使用 ID 来引用内容条目并获取数据以填充电子邮件。

设置如下:

  1. 通过上面的默认方法创建表单。

  2. 使用 AJAX 提交表格。成功提交后,获取内容条目 ID 并将其传递给辅助 AJAX 请求:

    形式-submit.js:

    $('.form').on('submit', function(e) {
        e.preventDefault();
        var form = $(this);
    
        // error handling functions removed for brevity
    
        $.ajax({
            type: 'POST',
            url: form.attr('action'),
            data: form.serialize(),
            dataType: 'json',
            success: function(data) {
                console.log('Success:', data);
    
                // get the content entry ID
                var entryID = data._id;
                // set up the data to be sent in the correct format
                var newData = 'id=' + entryID;
    
                // set up our secondary AJAX request
                function sendEmail() {
    
                    $.ajax({
                        type: 'POST',
                        url: 'page-with-send-email-action',
                        data: newData,
                        dataType: 'json',
                        success: function(data) {
                            console.log('Success:', data);
                        },
                        error: function(xhr, status, error) {
                            console.log('Status:', status);
                            console.log('Error:', error);
                            var errors = jQuery.parseJSON(xhr.responseText).errors;
                            console.log(errors);
    
                            for (error in errors) { 
                                myError = error;
                                console.log(myError);
                            }
                        }
                    });
    
                }
    
                sendEmail();
                showSuccess();
    
            },
            error: function(xhr, status, error) {
                console.log('Status:', status);
                console.log('Error:', error);
                var errors = jQuery.parseJSON(xhr.responseText).errors;
                console.log(errors);
    
                for (error in errors) { 
                    myError = error;
                    console.log(myError);
                    showError();
                }
            }
        });
    });
    
  3. 找到提交的内容条目并使用操作发送电子邮件 API:

    带发送电子邮件的页面-action.liquid:

    {% action "send email" %}
    
        var SMTPsettings = getProp('site').metafields.smtp_settings;
        var entryID = getProp('params').id;
        var entryData = findEntry('content_type_slug', entryID);
    
        // save entryData into a Liquid variable to be called in the Email Template
        setProp('entryData',entryData);
    
        sendEmail({
    
            to: entryData.email_address,
            from: SMTPsettings.username,
            subject: '[Email Subject]',
            page_handle: 'email-template',
    
            smtp: {
                address: SMTPsettings.server,
                port: SMTPsettings.port,
                user_name: SMTPsettings.username,
                password: SMTPsettings.password,
                authentication: 'plain',
                enable_starttls_auto: true
            }
    
        });
    
    {% endaction %}
    
    {"success":true}