Next.js 및 Nodemailer로 연락처 양식 작성

소개



웹 사이트 또는 앱에서 이메일 기능을 구현하는 데 도움이 되는 많은 패키지가 있습니다. 인기 있는nodemailer 라이브러리를 사용했는데 Next.js API 경로와 정말 잘 어울렸습니다.

문의 양식 구성 요소를 설명하는 것으로 시작하겠습니다. 다음으로 이메일 요청을 처리하기 위해 API 끝점을 구현한 방법에 대해 설명합니다. 마지막으로 양식을 끝점과 통합하여 닫겠습니다.

이 기사를 최대한 활용하려면 Javascript, React 및 Next.js에 익숙해야 합니다. 아래의 문의 양식 구성 요소를 검토하여 시작하겠습니다.

import useContactForm from '../hooks/useContactForm';

const ContactForm = () => {

  const {values, handleChange} = useContactForm();

  const handleSubmit = (e) => {
    e.preventDefault()
  }

  return (
      <form onSubmit={handleSubmit}>
          <label htmlFor='email'>Email</label>
          <input
              required
              id='email'
              value={values.email}
              onChange={handleChange}
              type='email'
          />

          <label htmlFor='subject'>Subject</label>
          <input
              required
              id='subject'
              value={values.subject}
              onChange={handleChange}
              type='text'
          />
          <label htmlFor='message'>Message</label>
          <textarea
              required
              value={values.message}
              onChange={handleChange}
              id='message'
              rows={8}
          />
        <button type='submit' value='Submit'>Send</button>
      </form>
  );
};

export default ContactForm;


양식 구성 요소



양식 구성 요소는 비교적 간단하지만 여기서 일어나는 일을 분석해 보겠습니다.

먼저 useContactForm라는 사용자 지정 후크를 가져옵니다(자세한 내용은 나중에 설명). 그런 다음 valueshandleChange를 분해합니다. values 객체는 양식 입력의 현재 상태를 나타내며 다음과 같은 속성과 초기 상태를 가집니다.

const values = {
    email: '',
    subject: '',
    message: '',
}


또한 양식 handleChange 이벤트를 처리하는 onChange 라는 함수를 얻습니다.

함수 본문에서 아래로 내려가면 양식 handleSubmit 이벤트를 처리하는 onSubmit 함수가 있습니다.
현재 수행하는 유일한 작업은 기본 양식 제출 동작을 방지하는 것입니다. 나중에 양식 데이터를 처리하기 위해 더 많은 논리를 추가할 것입니다. 지금은 useContactForm 사용자 지정 후크를 자세히 살펴보겠습니다.

import {useState} from 'react';

const useContactForm = () => {
  const [values, setValues] = useState({
    email: '',
    subject: '',
    message: '',
  });

  const handleChange = (e) => {
    setValues(prevState => {
      return {
        ...prevState,
        [e.target.id]: e.target.value,
      };
    });
  };

  return {values, handleChange};
};

export default useContactForm;


앞에서 언급했듯이 values ​​개체의 초기 상태에는 양식에 정의된 id로 정의된 속성이 포함되어 있습니다.
입력, 각각은 빈 문자열의 초기 값을 가집니다.

handleChange 함수는 spread syntax 을 사용하여 현재 상태의 모든 요소를 ​​포함하여 상태를 업데이트합니다. 마지막으로 e.target.id를 사용하여 대상 요소의 상태를 동적으로 업데이트합니다.

양식의 상태를 유지하는 다른 방법이 분명히 있습니다. 떠오르는 가장 일반적인 대안은 각 양식 입력에 대해 하나useState 후크를 사용하는 것입니다. useContactForm 후크를 사용하면 더 적은 코드를 사용하여 동일한 목표를 달성할 수 있습니다.

API로 이동하기 전에 axios을 사용하여 함수를 생성했습니다.
API에 요청을 보냅니다.

import axios from 'axios';

const sendEmail = async (email, subject, message) => {
  return axios({
    method: 'post',
    url: '/api/send-mail',
    data: {
      email: email,
      subject: subject,
      message: message,
    },
  });
};

export default sendEmail;


양식을 API와 연결할 때 이 문제로 다시 돌아오겠습니다.

API



내장된 Next.jsApi Routes로 API 엔드포인트를 생성했습니다. 다음 디렉토리를 생성하여 시작했습니다.
내 Next.js 프로젝트에서.

/blog/pages/api


끝점의 이름을 send-mail.js로 지정했습니다. 따라서 끝점의 URL은 다음과 같습니다.

http://localhost:3000/api/send-mail


끝점에 몇 가지 코드를 추가해 보겠습니다.

const nodemailer = require('nodemailer');

export default function handler(req, res) {

  const message = {
    from: req.body.email,
    to: process.env.GMAIL_EMAIL_ADDRESS,
    subject: req.body.subject,
    text: req.body.message,
    html: `<p>${req.body.message}</p>`,
  };

  let transporter = nodemailer.createTransport({
    service: 'Gmail',
    auth: {
      user: process.env.GMAIL_EMAIL_ADDRESS,
      pass: process.env.GMAIL_APP_PASSWORD,
    },
  });

  if (req.method === 'POST') {
    transporter.sendMail(message, (err, info) => {

      if (err) {
        res.status(404).json({
            error: `Connection refused at ${err.address}`
        });
      } else {
        res.status(250).json({
            success: `Message delivered to ${info.accepted}`
        });
      }
    });
  }
}


좋아, 여기서 많은 일이 벌어지고 있어. 먼저 nodemailer 라이브러리를 포함했습니다. 다음으로 req 및 res 매개변수가 있는 요청 핸들러인 handler 함수가 있습니다. 익숙하지 않은 경우 API Routes 문서를 확인하십시오.
req 및 res 객체와 함께.

다음으로 nodemailer message configuration 개체를 만듭니다. 나는 Gmail을 내 것으로 사용했습니다.
제공자이지만 여기에서 설명하는 몇 가지 주의 사항이 있습니다( using Gmail ).
좋은 소식은 nodemailer가 많은 대안을 지원한다는 것입니다. nodemailer docs은 환상적입니다. 라이브러리에 익숙하지 않은 경우 문서를 검토하는 것이 좋습니다.

메일 데이터를 보내기 위해 transporter 개체를 만듭니다. transporter 함수는 메시지 데이터와 선택적 콜백을 받아들입니다. 콜백은 내가 응답을 처리하는 데 사용하는 errorinfo 개체에 대한 액세스를 제공합니다.

이것이 API의 전부입니다. 이제 연락처 양식을 연결해 보겠습니다.

양식을 API에 연결



나머지 코드를 handleSubmit 함수에 추가해 보겠습니다.

import useContactForm from '../hooks/useContactForm';
import sendEmail from '../lib/sendEmail';
import {useState} from 'react';

const ContactForm = () => {

  const {values, handleChange} = useContactForm();
  const [responseMessage, setResponseMessage] = useState(
      {isSuccessful: false, message: ''});

  const handleSubmit = async (e) => {
    e.preventDefault();
    try {
      const req = await sendEmail(values.email, values.subject, values.message);
      if (req.status === 250) {
        setResponseMessage(
            {isSuccessful: true, message: 'Thank you for your message.'});
      }
    } catch (e) {
      console.log(e);
      setResponseMessage({
        isSuccessful: false,
        message: 'Oops something went wrong. Please try again.',
      });
    }
  };

  return (
      <form onSubmit={handleSubmit}>
          <label htmlFor='email'>Email</label>
          <input
              required
              id='email'
              value={values.email}
              onChange={handleChange}
              type='email'
          />

          <label htmlFor='subject'>Subject</label>
          <input
              required
              id='subject'
              value={values.subject}
              onChange={handleChange}
              type='text'
          />
          <label htmlFor='message'>Message</label>
          <textarea
              required
              value={values.message}
              onChange={handleChange}
              id='message'
              rows={8}
          />
        <button type='submit' value='Submit'>Send</button>
      </form>
  );
};

export default ContactForm;

handleSubmit 함수가 비동기 함수로 변환됩니다. 새 API 엔드포인트의 응답을 기다리기 위해 생성한 sendEmail 함수를 사용합니다. responseMessage 상태가 응답으로 업데이트됩니다.

결론



이제 responseMessage 상태가 변경되었으므로 이를 사용하여 UI를 업데이트할 수 있습니다. 일반적으로 여기에는 메시지 상태와 함께 사용자에게 경고를 표시하는 것이 포함됩니다.

좋은 웹페이지 즐겨찾기