【问题标题】:Getting duplicate emails from contact form in rails/react app从 rails/react 应用程序中的联系表单获取重复的电子邮件
【发布时间】:2021-07-14 19:19:39
【问题描述】:

我使用 Sendgrid 向我的 rails/react 应用程序添加了一个联系表单。一切正常,但每次通过联系表格提交内容时,我都会收到 3-5 封电子邮件。他们中的一些人缺少联系表中的数据。我无法在我的代码中发现这些重复的电子邮件。

前端的联系方式:

import React, { useState } from "react";
import { Redirect } from "react-router-dom";
import _ from "lodash";

import ErrorList from "../utilities/ErrorList";

export const ContactForm = () => {
  let defaultFields = {
    name: "",
    email: "",
    subject: "",
    message: "",
  };

  const [message, setMessage] = useState(defaultFields);
  const [errors, setErrors] = useState({});
  const [successMessage, setSuccessMessage] = useState();

  if (successMessage) {
    return <Redirect to="/success" />;
  }

  const newMessage = (formData) => {
    fetch("/api/v1/contact", {
      method: "POST",
      body: JSON.stringify(formData),
      credentials: "same-origin",
      headers: {
        Accept: "application/json",
        "Content-Type": "application/json",
      },
    })
      .then((response) => {
        if (response.ok) {
          return response;
        } else {
          let errorMessage = `${response.status} (${response.statusText})`,
            error = new Error(errorMessage);
          throw error;
        }
      })
      .then((response) => response.json())
      .then((body) => {
        if (body.sent) {
          setSuccessMessage(true);
        } else {
          setSuccessMessage(false);
        }
      })
      .catch((error) => console.error(`Error in fetch: ${error.message}`));
  };

  const handleChange = (event) => {
    setMessage({
      ...message,
      [event.currentTarget.name]: event.currentTarget.value,
    });
  };

  const validForSubmission = () => {
    let submitErrors = {};
    const requiredFields = ["name", "email", "subject", "message"];
    requiredFields.forEach((field) => {
      if (
        message[field].trim() === "" ||
        message[field].trim() === "" ||
        message[field].trim() === "" ||
        message[field].trim() === ""
      ) {
        submitErrors = {
          ...submitErrors,
          [field]: "is blank",
        };
      }
    });
    setErrors(submitErrors);
    return _.isEmpty(submitErrors);
  };

  const handleSubmit = (event) => {
    event.preventDefault();
    if (validForSubmission()) {
      newMessage(message);
      newMessage(defaultFields);
    }
  };

  return (
    <section className="section">
      <div className="container">
        <form onSubmit={handleSubmit} className="new-post-form callout">
          <ErrorList errors={errors} />
          <div className="field">
            <label className="label">
              Name:
              <div className="control">
                <input
                  className="input"
                  type="text"
                  placeholder="Please enter your name"
                  name="name"
                  id="name"
                  onChange={handleChange}
                  value={message.name}
                />
              </div>
            </label>
          </div>

          <div className="field">
            <label className="label">
              Email:
              <div className="control">
                <input
                  className="input"
                  type="text"
                  placeholder="Please enter your email address"
                  name="email"
                  id="email"
                  onChange={handleChange}
                  value={message.email}
                />
              </div>
            </label>
          </div>

          <div className="field">
            <label className="label">
              Subject:
              <div className="control">
                <input
                  className="input"
                  type="text"
                  placeholder="Please add a message subject"
                  name="subject"
                  id="subject"
                  onChange={handleChange}
                  value={message.subject}
                />
              </div>
            </label>
          </div>

          <div className="field">
            <label className="label">
              Message:
              <div className="control">
                <textarea
                  className="textarea"
                  placeholder="Add your message here"
                  name="message"
                  id="message"
                  onChange={handleChange}
                  value={message.message}
                ></textarea>
              </div>
            </label>
          </div>

          <div className="field is-grouped">
            <div className="control">
              <button className="button is-link">Submit</button>
            </div>
            <div className="control">
              <button className="button is-link is-light">Cancel</button>
            </div>
          </div>
        </form>
        {successMessage === false && (
          <div className="blog-flex">
            <p>Sorry your message couldn&apos;t be sent. Please try again and make sure all fields are filled out.</p>
          </div>
        )}
      </div>
    </section>
  );
};

export default ContactForm;

从联系表单提交的数据点击contact_controller

require 'pry'

class Api::V1::ContactController < ApiController

  before_action :contact_params, only: [:create]

  def create
    @message = contact_params
    ContactForm.send_message_email(@message).deliver
    
    if ContactForm.send_message_email(@message).deliver
      render json: {sent: true}
    else
      render json: {sent: false}
    end
  end
  
  protected

  def contact_params
    params.require(:contact).permit([:name, :email, :subject, :message])
  end

end

应用程序/邮件中的联系人表单

require 'pry'

class ContactForm < ApplicationMailer

  default :from => 'info@maddoxgreyauthor.com'

  # send email from contact form
  def send_message_email(message)
    @message = message
    mail( :to => 'info@maddoxgreyauthor.com',
    :subject => 'New Message From Maddox Grey Author' )
  end
end

最后是电子邮件的布局。这是在 app/views/contact_forms/send_message_email.html.erb

<!DOCTYPE html>
<html>
  <head>
    <meta content='text/html; charset=UTF-8' http-equiv='Content-Type' />
  </head>
  <body>
    <h1>New message received from <%= @message["name"] %>!</h1>
    <p>Email: <%= @message["email"] %></p>
    <p>Subject: <%= @message["subject"] %></p>
    <p>Message: <%= @message["message"] %></p>
  </body>
</html>

【问题讨论】:

    标签: ruby-on-rails sendgrid sendgrid-ruby sendgrid-rails


    【解决方案1】:

    在这里您发送了两次电子邮件:

      def create
        @message = contact_params
        ContactForm.send_message_email(@message).deliver #<--- once
        
        if ContactForm.send_message_email(@message).deliver #<--- twice
          render json: {sent: true}
        else
          render json: {sent: false}
        end
      end
    

    执行以下操作至少可以帮助处理其中一封重复的电子邮件:

      def create
        @message = contact_params
        send_email = ContactForm.send_message_email(@message).deliver 
        
        if send_email 
          render json: {sent: true}
        else
          render json: {sent: false}
        end
      end
    

    或者更节省空间的解决方案:

      def create
          render json: {sent: !!ContactForm.send_message_email(contact_params).deliver}
      end
    

    其次,在这里你还要调用 API 函数两次:

      const handleSubmit = (event) => {
        event.preventDefault();
        if (validForSubmission()) {
          newMessage(message); //<-- Once
          newMessage(defaultFields); //<-- Twice
        }
      };
    

    【讨论】:

    • 谢谢!我想知道即使第二个是 if 语句是否触发了另一个发送。我有点不确定如何对其进行返工,以便它仍会将{sent: true} 发送回前端。只删除第一个并将那个包裹在 if 语句中是否有意义?
    • 每次你调用一个函数,在任何地方,它都会被执行。我关于如何解决它的示例正是这样做的。 !! 确保 ContactForm.send_message_email(contact_params).deliver 返回的任何内容都将转换为 truefalse
    • 我已将解决方案更新为您的代码。希望这能更清楚地说明这一点。
    • 非常感谢!不敢相信我错过了前端的第二个电话。我修改了代码,它现在按预期工作。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2020-09-30
    • 2014-01-27
    • 1970-01-01
    • 2014-01-13
    • 1970-01-01
    • 1970-01-01
    • 2012-06-06
    相关资源
    最近更新 更多