无法使用 EmailJS/React 发送电子邮件

Cannot send email with EmailJS/React

我一直在学习 MERN 堆栈教程,我想我会通过使用 EmailJS 来挑战自己。我想要做的是在新用户创建帐户时触发 EmailJS 发送确认电子邮件。我正在使用正确的 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>
  );
};

本教程使用上下文和缩减器——所以我不确定这是否应该进入上下文(仍在学习上下文和缩减器!)。这是我在表单组件中的 onSubmit 函数——为了获取我的应用 运行,我删除了 EmailJS 代码,但它的结构与示例相同,因此 const form = useRef() 在 [=15= 中声明].

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...',
      });
    }
  };

onSubmit 中调用 setupUser 之后,我一直在将 EmailJS 示例放在 else 块中。我还像示例中一样构造了我的 form 标签。一个区别是在示例中,他们的 onSubmit 函数是 sendEmail 而我的将在下面共享。根据控制台,我收到 'OK' 作为响应而不是错误 — 但没有发送电子邮件。我当然已经检查了我的 EmailJS 凭据,并且还没有将它们放入 .env 中以用于测试目的。我的上下文文件中的 setupUser 函数是:

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()
  }

我还没有尝试将任何与 EmailJS 相关的东西放入上下文文件中,因为我刚刚到了我正在旋转轮子的地步。我的应用程序也有一个 Express 后端,所以我考虑过使用他们的 REST API,但又一次——我的轮子一直在转动,想休息一下。

有没有人有什么想法或建议?如果需要,我可以提供更多我的代码——我之所以推迟是因为它太长了,我希望我提供了足够的信息。

您将需要了解有关在 React 中处理表单的更多信息。

emailJS 库使用 ref 只是为了从 form 获取信息。而已。这意味着即使你没有表单,你也可以将信息直接传递到 emailJS 库本身(如果你愿意的话)

所以你可以从学习如何在 React 中处理表单开始。纯反应。直到您可以在 submitHandler 中获得所需的所有信息。
从这一点开始,您拥有了需要传递给 emailJS 的所有信息,您可以将其视为一个函数:EmailJS(your-form-info)。当然,emailJS 不是那样工作的,但在本质上,它只是一个类似的函数。

而且这里没有后端,你做的只是处理react的表单,emailjs是一个服务,它可以帮助你发送电子邮件,所以你提到的快递在这里是无关紧要的。

ETA:如有必要,我可以共享我的上下文文件和我的代码的 <form> 部分。

我终于弄明白了,想 post 我的代码以防万一有人遇到同样的问题,希望你能避免我的一些错误。首先,我的问题始于 EmailJS 本身。我使用他们的模板,但我的变量与更新后的代码不匹配。

我无法让 ref 工作,因为我的表格从来没有像那样构造过。我过去曾多次成功使用 ref。我还有一个绑定到我的表单组件的 handleSubmit 函数。我不确定这是否是 ref 问题的一部分,因为我已经确定了表单中的值 — value={values.email} 等。无论如何 — 这可能是一种迂回的方式,但它是一直在工作。

所以首先,我继续在 EmailJS 中获取我的变量以匹配我的代码。这是我的 Register 组件的完整代码(减去 return 并且还需要一些代码清理):

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]);

更多错误!我没有在我的对象中正确使用我的表单值——例如,我有

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

这引发了一个错误,因为我不应该使用 name,但我看得越多,我就知道这是错误的。然后我尝试使用

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

愚蠢的我——我从来没有定义过 user。最重要的是——我昨天从未设置过实际对象!

另一个错误是试图在 onSubmit 函数中编写 sendNewAccountEmail。我很确定我的结构是错误的——所以也许那部分是可能的。

最后,我的最后一个错误是在 if/else 语句之后调用 sendNewAccountEmail();。这让我感到充满希望,因为它在我创建新用户时起作用了!但是——在我的代码中,你会看到我使用了 setupUser 函数两次,因为它(在大多数情况下)在用户登录时做同样的事情——它只是转到不同的 endPoints。猜猜发生了什么——电子邮件是在注册和登录时发送的。一旦我将它移入 else 块并在 setupUser 之后调用它,它终于可以正常工作了!

如果你能做到这一点,我真的很感激,我希望它有意义可以对其他人有用。我仍在努力提高我的编码技能(有很多需要改进的地方)并且在我前进的过程中学到了很多东西,所以感谢您 1. 阅读本文和 2. 了解我当前的技能。 :) 另外,如果我的工作代码中有任何地方看起来很奇怪——如果相关,我完全欢迎反馈。

并在评论中向 Jimmy 大喊大叫,因为他引导我朝着正确的方向前进。