简体   繁体   English

无法使用 EmailJS/React 发送 email

[英]Cannot send email with EmailJS/React

I've been working through a MERN stack tutorial, and I thought I'd challenge myself by using EmailJS.我一直在学习 MERN 堆栈教程,我想我会通过使用 EmailJS 来挑战自己。 What I'm trying to do is trigger EmailJS to send a confirmation email when a new user creates an account.我想要做的是在新用户创建帐户时触发 EmailJS 发送确认 email。 I'm using the correct EmailJS library, and have tried and tried and tried using their React example from their docs, which is below:我正在使用正确的 EmailJS 库,并且已经尝试并尝试使用他们文档中的 React 示例,如下所示:

import emailjs from '@emailjs/browser';

export const ContactUs = () => {
  const form = useRef();

  const sendEmail = (e) => {
    e.preventDefault();

    emailjs.sendForm('YOUR_SERVICE_ID', 'YOUR_TEMPLATE_ID', form.current, 'YOUR_PUBLIC_KEY')
      .then((result) => {
          console.log(result.text);
      }, (error) => {
          console.log(error.text);
      });
  };

  return (
    <form ref={form} onSubmit={sendEmail}>
      <label>Name</label>
      <input type="text" name="user_name" />
      <label>Email</label>
      <input type="email" name="user_email" />
      <label>Message</label>
      <textarea name="message" />
      <input type="submit" value="Send" />
    </form>
  );
};

This tutorial uses context and reducers—so I'm not sure whether this should go into the context or not (still learning context and reducers.), This is my onSubmit function within the form component—I removed the EmailJS code for the sake of getting my app running, but it's structured identically to the example, so const form = useRef() is being declared within onSubmit .本教程使用 context 和 reducer——所以我不确定这是否应该 go 进入上下文(仍在学习 context 和 reducers。),这是我在表单组件中的 onSubmit function——我删除了 EmailJS 代码为了让我的应用程序运行,但它的结构与示例相同,因此在onSubmit中声明了const form = useRef()

const onSubmit = (e) => {
    e.preventDefault();
    const { name, email, password, isMember } = values;
    if (!email || !password) {
      displayAlert();
      return;
    }
    const currentUser = { name, email, password };
    if (isMember) {
      setupUser({
        currentUser,
        endPoint: 'login',
        alertText: 'Login Successful! Redirecting...',
      });
    } else {
      setupUser({
        currentUser,
        endPoint: 'register',
        alertText: 'User Created! Redirecting...',
      });
    }
  };

I've been putting the EmailJS example after calling setupUser in onSubmit within the else block.else块中的onSubmit中调用setupUser之后,我一直在放置 EmailJS 示例。 I've also structured my form tag just like in the example.我还像示例中一样构造了我的form标签。 The one difference is that in the example, their onSubmit function is sendEmail and mine will be shared below.一个区别是,在示例中,他们的onSubmit function 是sendEmail ,我的将在下面共享。 According to the console, I'm getting an 'OK' as a response rather than an error—but no email is being sent.根据控制台,我收到“OK”作为响应而不是错误 — 但没有发送 email。 I've of course checked my EmailJS credentials and am not putting them in a .env just yet for testing purposes.我当然已经检查了我的 EmailJS 凭据,并且还没有将它们放入.env中以用于测试目的。 My setupUser function within my context file is:我的上下文文件中的setupUser function 是:

const setupUser = async ({ currentUser, endPoint, alertText }) => {
    dispatch({ type: SETUP_USER_BEGIN })
    try {
      const { data } = await axios.post(`/api/v1/auth/${endPoint}`, currentUser)

      const { user, token } = data
      dispatch({
        type: SETUP_USER_SUCCESS,
        payload: { user, token, alertText },
      })
      addUserToLocalStorage({ user, token })
    } catch (error) {
      dispatch({
        type: SETUP_USER_ERROR,
        payload: { msg: error.response.data.msg },
      })
    }
    clearAlert()
  }

I haven't tried putting anything EmailJS-related into the context file because I just got to a point where I was spinning my wheels.我还没有尝试将任何与 EmailJS 相关的东西放入上下文文件中,因为我刚刚到了我正在旋转轮子的地步。 My app also has an Express backend, so I thought about using their REST API, but again—was spinning my wheels and wanted to take a break.我的应用程序也有一个 Express 后端,所以我考虑过使用他们的 REST API,但又一次——我的车轮在旋转,想休息一下。

Does anyone have any ideas or suggestions?有人有什么想法或建议吗? I can provide more of my code if needed—I held back because it was lengthy, and I hope I provided enough information.如果需要,我可以提供更多我的代码——我之所以推迟是因为它太长了,我希望我提供了足够的信息。

You will need to learn more about handling forms in React.您将需要了解有关在 React 中处理 forms 的更多信息。

The emailJS library uses ref just to get the information from the form . emailJS 库使用ref只是为了从form中获取信息。 That's it.就是这样。 What it means is even if you don't have a form, you can pass the information directly into the emailJS lib itself (if you want)这意味着即使您没有表单,您也可以将信息直接传递到 emailJS 库本身(如果需要)

So you can start by learning how to handle a form in React.所以你可以从学习如何在 React 中处理表单开始。 Purely react.纯反应。 Up until the point where you can get all the information you want in your submitHandler.直到您可以在 submitHandler 中获得所需的所有信息。
From this point, you have all the infomration you need to pass down to emailJS, you can think of it just a function: EmailJS(your-form-info).从这一点开始,您拥有了需要传递给 emailJS 的所有信息,您可以将其视为 function:EmailJS(your-form-info)。 Of course, emailJS doesn't work that way but in it heart, it's just a function like that.当然,emailJS 不是那样工作的,但在本质上,它只是一个 function 那样的。

And there's no backend involve here, all you do is handle the form which is react, and emailjs is a service, which helps you send email, so your mentioned express is irrelevant here.而且这里没有后端涉及,您所做的只是处理响应的表单,而 emailjs 是一项服务,可帮助您发送 email,因此您提到的快递在这里无关紧要。

ETA: If necessary, I can share my context file and the <form> part of my code.预计到达时间:如有必要,我可以共享我的上下文文件和代码的<form>部分。

I finally figured this out and wanted to post my code just in case anyone runs into this same problem and hopefully you can avoid some of my mistakes.我终于弄明白了这一点,并想发布我的代码以防万一有人遇到同样的问题,希望你能避免我的一些错误。 First and foremost, the beginning of my problems started within EmailJS itself.首先,我的问题始于 EmailJS 本身。 I use their templates, and my variables weren't matching my updated code.我使用他们的模板,但我的变量与更新后的代码不匹配。

I was unable to get ref to work because my form was never structured like that.我无法让ref工作,因为我的表格从来没有像那样构造过。 I've used ref many times in the past successfully.我过去曾多次成功使用ref I also have a handleSubmit function tied to my form component.我还有一个handleSubmit function 绑定到我的表单组件。 I'm not sure whether that was part of the problem with ref since I was already identifying values in the form— value={values.email} , etc. Anyway—this might be a roundabout way of doing this, but it's been consistently working.我不确定这是否是ref问题的一部分,因为我已经确定了表单中的值—— value={values.email}等。无论如何——这可能是一种迂回的方式,但它一直是在职的。

So first, I went ahead and got my variables in EmailJS to match up with my code.所以首先,我继续在 EmailJS 中获取我的变量以匹配我的代码。 This is my full code from my Register component (minus the return and also needs some code cleanup):这是我的 Register 组件的完整代码(减去返回并且还需要一些代码清理):

import { useState, useEffect } from 'react';
import { Logo, FormRow, Alert } from '../components';
import Wrapper from '../assets/wrappers/RegisterPage';
import { useAppContext } from '../context/appContext';
import { useNavigate } from 'react-router-dom';
import emailjs from '@emailjs/browser';

const initialState = {
  name: '',
  email: '',
  password: '',
  isMember: true,
};

const Register = () => {
  const navigate = useNavigate();
  const [values, setValues] = useState(initialState);
  const { user, isLoading, showAlert, displayAlert, setupUser } =
    useAppContext();
  
  const obj = {
    userName: values.name,
    userEmail: values.email,
  };
  
  const sendNewAccountEmail = (obj) => {
    emailjs
      .send(
        'service id goes here',
        'template id goes here',
        obj,
        'public key goes here'
      )
      .then(
        (result) => {
          console.log(result.text);
        },
        (error) => {
          console.log(error.text);
        }
      );
  };

  const toggleMember = () => {
    setValues({ ...values, isMember: !values.isMember });
  };

  const handleChange = (e) => {
    setValues({ ...values, [e.target.name]: e.target.value });
  };
  const onSubmit = (e) => {
    e.preventDefault();
    const { name, email, password, isMember } = values;
    if (!email || !password) {
      displayAlert();
      return;
    }
    const currentUser = { name, email, password };
    if (isMember) {
      setupUser({
        currentUser,
        endPoint: 'login',
        alertText: 'Login Successful! Redirecting...',
      });
    } else {
      setupUser({
        currentUser,
        endPoint: 'register',
        alertText: 'User Created! Redirecting...',
      });
      sendNewAccountEmail();
    }
  };

  useEffect(() => {
    if (user) {
      setTimeout(() => {
        navigate('/');
      }, 3000);
    }
  }, [user, navigate]);

More mistakes, I wasn't using my form values correctly in my object—for example, I had更多的错误,我没有在我的对象中正确使用我的表单值——例如,我有

  const obj = {
    userName: name,
    userEmail: email,
  };

That threw an error because I wasn't supposed to use name , but the more I looked at it, I knew it was wrong.这引发了一个错误,因为我不应该使用name ,但我看得越多,我就知道这是错误的。 I then tried using然后我尝试使用

  const obj = {
    userName: user.name,
    userEmail: user.email,
  };

Silly me—I never defined user .愚蠢的我——我从来没有定义过user On top of that—I never set up the actual object yesterday!最重要的是——我昨天从未设置过实际的 object!

Another mistake was trying to write the sendNewAccountEmail within the onSubmit function. I'm pretty sure that I structured it wrong—so perhaps that part is possible.另一个错误是试图在onSubmit function 中编写sendNewAccountEmail 。我很确定我的结构是错误的——所以也许那部分是可能的。

Finally, my last mistake was calling sendNewAccountEmail();最后,我的最后一个错误是调用sendNewAccountEmail(); after the if/else statement.在 if/else 语句之后。 That got me feeling hopeful because it worked when I created a new user, BUT—in my code, you'll see that I'm using the setupUser function twice as it (for the most part) does the same thing when a user logs in—it just goes to different endPoint s.这让我感到充满希望,因为它在我创建新用户时有效,但是 - 在我的代码中,你会看到我使用了setupUser function 两次,因为它(大部分)在用户登录时做同样的事情in——它只是去不同的endPoint s。 And guess what happened—emails were sent at registration and login.猜猜发生了什么——电子邮件是在注册和登录时发送的。 Once I moved it into the else block and called it after setupUser , it finally worked as it should!一旦我将它移到else块并在setupUser之后调用它,它终于可以正常工作了!

If you made it this far, I really appreciate it, and I hope that it made sense can can be useful to others.如果你做到了这一点,我真的很感激,我希望它有意义可以对其他人有用。 I'm still working on my coding skills (lots to improve) and learning a lot as I go, so thanks for 1. reading this and 2. understanding my current skillset.我仍在努力提高我的编码技能(有很多需要改进的地方)并像我 go 一样学习很多东西,所以感谢 1. 阅读本文和 2. 了解我当前的技能。 :) Also if anything in my working code looks weird—I'd totally welcome feedback if it's relevant. :) 此外,如果我的工作代码中有任何内容看起来很奇怪——如果相关,我完全欢迎反馈。

And shoutout to Jimmy in the comments for leading me in the right direction.并在评论中向 Jimmy 大喊大叫,感谢他引导我朝着正确的方向前进。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM