Express.js에서 이메일 보내는 방법: SMTP 및 API 가이드

발행: (2025년 12월 15일 오후 04:52 GMT+9)
8 min read
원문: Dev.to

Source: Dev.to

사전 요구 사항

SendLayer 계정을 만든 후, 이메일 전송 가능성을 높이기 위해 발신 도메인을 인증하세요.

Express.js 서버 설정

# 프로젝트 폴더 생성
mkdir send-email
cd send-email

# npm 프로젝트 초기화
npm init -y

# 의존성 설치
npm install express dotenv

프로젝트 루트에 server.js 파일을 생성합니다:

// server.js
const express = require('express');
const dotenv = require('dotenv');

dotenv.config(); // 환경 변수 로드

const app = express();
const port = process.env.PORT || 3000;

// JSON 데이터 파싱 미들웨어
app.use(express.json());

app.listen(port, () => {
  console.log(`Server running on port ${port}`);
});

서버를 실행합니다:

node server.js

다음과 같이 표시됩니다:

Server running on port 3000

이제 http://localhost:3000에서 서버에 접근할 수 있습니다.

SMTP를 통한 이메일 전송

Nodemailer 설치

npm install nodemailer

환경 변수 설정

.env 파일을 만들고 SMTP 인증 정보를 추가합니다(예제는 SendLayer 사용):

SMTP_HOST=smtp.sendlayer.net
SMTP_PORT=587
SMTP_USER=your-smtp-username
SMTP_PASS=your-smtp-password
FROM_EMAIL=sender@example.com

Note: SendLayer의 경우, 발신 이메일은 인증된 도메인에 속해야 합니다(예: @example.com).

server.js에 이메일 로직 추가

// server.js (continued)
const nodemailer = require('nodemailer');

// SMTP를 통해 이메일을 보내는 함수
const sendEmail = async (to, subject, message) => {
  try {
    const transporter = nodemailer.createTransport({
      host: process.env.SMTP_HOST,
      port: Number(process.env.SMTP_PORT),
      secure: false, // TLS(587)일 경우 false, SSL(465)일 경우 true
      auth: {
        user: process.env.SMTP_USER,
        pass: process.env.SMTP_PASS,
      },
    });

    const mailOptions = {
      from: process.env.FROM_EMAIL,
      to,
      subject,
      text: message,
    };

    const info = await transporter.sendMail(mailOptions);
    console.log('Email sent:', info.messageId);
  } catch (error) {
    console.error('Error sending email:', error);
    throw error;
  }
};

// 이메일 전송을 트리거하는 POST 라우트
app.post('/send-email', async (req, res) => {
  const { to, subject, message } = req.body;

  if (!to || !subject || !message) {
    return res.status(400).json({ status: 'error', message: 'Missing required fields' });
  }

  try {
    await sendEmail(to, subject, message);
    res.status(200).json({ status: 'success', message: 'Email sent successfully' });
  } catch (err) {
    res.status(500).json({ status: 'error', message: 'Failed to send email' });
  }
});

첨부 파일 전송 (선택 사항)

mailOptionsattachments 배열을 추가합니다:

const mailOptions = {
  from: process.env.FROM_EMAIL,
  to,
  subject,
  text: message,
  attachments: [
    {
      filename: 'example.pdf',
      path: './path/to/example.pdf', // 올바른 경로로 업데이트
    },
  ],
};

엔드포인트 테스트

서버 시작:

node server.js

cURL이나 Postman을 사용해 http://localhost:3000/send-email에 JSON 본문을 POST합니다:

{
  "to": "recipient@example.com",
  "subject": "Test Email",
  "message": "Hello from Express.js!"
}

성공적인 응답 예시:

{
  "status": "success",
  "message": "Email sent successfully"
}

수신자의 받은편지함을 확인해 전송 여부를 확인하세요.

여러 수신자에게 보낼 경우, to 필드에 이메일 주소를 쉼표로 구분하면 됩니다.

API를 통한 이메일 전송

이 섹션에서는 SMTP 대신 이메일 서비스의 HTTP API(예: SendLayer)를 사용하는 방법을 설명합니다. 이 접근 방식은 대량 전송 시 전송 성공률과 확장성을 높여줍니다.

Axios(또는 다른 HTTP 클라이언트) 설치

npm install axios

.env에 API 자격 증명 추가

SENDLAYER_API_KEY=your-api-key

API 기반 전송 구현

// server.js (continued)
const axios = require('axios');

const sendEmailViaAPI = async (to, subject, message) => {
  try {
    const response = await axios.post(
      'https://api.sendlayer.com/v1/email',
      {
        from: process.env.FROM_EMAIL,
        to,
        subject,
        text: message,
      },
      {
        headers: {
          Authorization: `Bearer ${process.env.SENDLAYER_API_KEY}`,
          'Content-Type': 'application/json',
        },
      }
    );

    console.log('API email sent:', response.data);
    return response.data;
  } catch (error) {
    console.error('API error:', error.response?.data || error.message);
    throw error;
  }
};

// API 방식을 사용하는 예시 라우트
app.post('/send-email-api', async (req, res) => {
  const { to, subject, message } = req.body;

  if (!to || !subject || !message) {
    return res.status(400).json({ status: 'error', message: 'Missing required fields' });
  }

  try {
    await sendEmailViaAPI(to, subject, message);
    res.status(200).json({ status: 'success', message: 'Email sent via API' });
  } catch (err) {
    res.status(500).json({ status: 'error', message: 'Failed to send email via API' });
  }
});

API 방식은 SMTP 연결을 관리할 필요가 없으며, 템플릿, 추적, 속도 제한 등 더 풍부한 기능을 제공하는 경우가 많습니다.

일반적인 오류 해결

증상가능한 원인해결 방법
Error: self signed certificateTLS 인증 실패개발 환경에서만 secure: false 로 설정하고 tls: { rejectUnauthorized: false } 를 transporter 설정에 추가합니다.
550 5.1.1 (recipient not found)잘못된 to 주소이메일 주소 형식을 확인하고 도메인이 존재하는지 검증합니다.
401 Unauthorized from API잘못된 또는 누락된 API 키SENDLAYER_API_KEY 가 정확하고 Authorization 헤더에 포함되어 있는지 확인합니다.
No email received이메일이 스팸함에 들어감도메인의 SPF/DKIM 레코드를 확인하고 인증된 발신 주소를 사용합니다.
Server crashes on sendMail처리되지 않은 프로미스 거부sendEmail 호출을 try/catch 로 감싸고 적절한 HTTP 상태 코드를 반환합니다.

자주 묻는 질문

Q: SMTP와 이메일 API 중 어느 것을 사용해야 하나요?
A: 간단하거나 저용량일 경우 Nodemailer와 SMTP가 충분합니다. 대량 전송, 높은 전송 성공률, 템플릿·분석·추적 같은 고급 기능이 필요하면 이메일 API 사용을 권장합니다.

Q: HTML 이메일을 어떻게 보내나요?
A: mailOptionshtml 속성을 추가하거나 API 페이로드에 html을 포함하면 됩니다.

const mailOptions = {
  from: process.env.FROM_EMAIL,
  to,
  subject,
  html: '
## Hello

This is an HTML email.
',
};

Q: 이메일을 예약 전송할 수 있나요?
A: Nodemailer와 대부분의 이메일 API는 내장된 예약 기능을 제공하지 않습니다. node-cron 같은 작업 스케줄러나 Bull 같은 작업 큐를 사용해 원하는 시점에 전송을 트리거하세요.

Q: 속도 제한을 어떻게 처리하나요?
A: 이메일 제공자가 문서화한 제한을 준수하세요. 지수 백오프를 적용한 재시도 로직을 구현하거나, 대량 메일 전송 시 배치 요청을 사용합니다.

Back to Blog

관련 글

더 보기 »

Java Spring Boot를 사용한 기본 CRUD

Spring Boot란 무엇인가? Spring Boot는 웹 및 백엔드 애플리케이션을 쉽게 구축할 수 있도록 도와주는 Java 프레임워크입니다. 대부분의 설정과 구성을 자동으로 처리해 줍니다.