【Next.js】Resendでメール送信

## Resendとは
Resendは、開発者がアプリケーションから
メールを簡単に送信できるようにするためのメールAPIサービスで、
シンプルな実装でメール送信機能を実装できます。

## Resendの環境構築
1. アカウント作成とセットアップ
[Resend](https://resend.com/)でアカウント作成を行い、APIキーを取得する
- API Keysを選択
![スクリーンショット 2025-05-18 17.31.04.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3983478/779dea67-65d3-4203-8dd7-d144a84f30c2.png)
- Create API Keyを押下
![スクリーンショット 2025-05-18 17.31.20.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3983478/6d487db8-a0b6-45b2-8079-2eef1ee29e2b.png)
- nameを記入してAddを押下
![スクリーンショット 2025-05-18 17.34.14.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3983478/38369bd3-809a-4b3c-94d2-3781f768d143.png)
- 生成されたAPIKeyをコピーしてDoneを押下
※こちらで必ずコピーして環境変数に設定するかローカルに保存しておくこと。
![スクリーンショット 2025-05-18 17.37.59.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3983478/5e1b057e-9ee9-4f14-99a9-0204bc8d38ab.png)

2. パッケージインストール
`npm install resend`
3. 環境変数に1.で生成したAPIキーを設定
`RESEND_API_KEY=`
4. 実装例
#### メール送信用フォーム
```tsx:MailForm.tsx
import React, { useState } from 'react'

const SimpleMailForm = () => {
  const [email, setEmail] = useState('')
  const [subject, setSubject] = useState('')
  const [content, setContent] = useState('')
  const [message, setMessage] = useState('')
  const [imageFile, setImageFile] = useState(null);

  const handleSubmit = async (e: React.FormEvent) => {
    e.preventDefault()
    setMessage('')
    
    const formData = new FormData()
    formData.append('email', email)
    formData.append('subject', subject)
    formData.append('content', content)
    
    if (imageFile) formData.append('imageFile', imageFile)
    
    const res = await fetch(`${process.env.NEXT_PUBLIC_BASE}/api/send`, {
      method: 'POST',
      headers: { 'Content-Type': 'application/json' },
      body: formData,
    })
    if (res.ok) {
      setMessage('送信しました')
      setEmail('')
      setSubject('')
      setContent('')
    } else {
      setMessage('送信に失敗しました')
    }
  }

  return (
    <form onSubmit={handleSubmit}>
      <div>
        <label>メールアドレス</label>
        <input value={email} onChange={e => setEmail(e.target.value)} required />
      </div>
      <div>
        <label>件名</label>
        <input value={subject} onChange={e => setSubject(e.target.value)} required />
      </div>
      <div>
        <label>本文</label>
        <textarea value={content} onChange={e => setContent(e.target.value)} required />
      </div>
      <div>
        <label>画像ファイル</label>
        <input
          type="file"
          accept="image/*"
          onChange={e => setImageFile(e.target.files[0])}
        />
  </div>
      <button type="submit">送信</button>
      <div>{message}</div>
    </form>
  )
}

export default SimpleMailForm
```

#### メール送信用API
```ts:/api/send/route.ts
import { NextRequest, NextResponse } from 'next/server'
import { Resend } from 'resend'

const resend = new Resend(process.env.RESEND_API_KEY)

export async function POST(req: NextRequest) {
  const formData = await req.formData()
  const email = formData.get('email') as string
  const subject = formData.get('subject') as string
  const content = formData.get('content') as string
  const imageFile = formData.get('imageFile') as File | null

  let attachments = []
  if (imageFile) {
    const arrayBuffer = await imageFile.arrayBuffer()
    const buffer = Buffer.from(arrayBuffer)
    attachments.push({ filename: imageFile.name, content: buffer })
  }

  try {
    const data = await resend.emails.send({
      from: 'Acme <onboarding@resend.dev>',
      to: email,
      subject,
      html: `<p>${content}</p>`,
      attachments
    })
    return NextResponse.json({ success: true, data })
  } catch (error) {
    return NextResponse.json({ success: false, error: String(error) }, { status: 500 })
  }
}
```
:::note info
注意点として、送信先のメールアドレスは
Resendアカウントのメールアドレスしか送信できません。
任意のメールアドレスを指定して送信したい場合は、
独自ドメインの設定が必要となります。
:::