express.jsでメールを送るAPIを作りテストサーバーを立ち上げる

# express.jsでメールを送るAPIを作りテストサーバーを立ち上げる
# 概要
- express.js
- smtp test server(schickling/mailcatcher)

# やり方
## 事前準備
nodeやnpm、npx、docker、docker-compose をインストールする。

## まずはAPIを作りましょう。
```
npx create-express-api api
cp api
npm install nodemailer
```

## app.jsにbodyparserを追加する。
```javascript:api/src/app.js
const express = require("express");
const morgan = require("morgan");
const helmet = require("helmet");
const cors = require("cors");
var bodyParser = require("body-parser");

require("dotenv").config();

const middlewares = require("./middlewares");
const api = require("./api");

const app = express();

// parse application/x-www-form-urlencoded application/json
app.use(bodyParser.urlencoded());
app.use(bodyParser.json());

app.use(morgan("dev"));
app.use(helmet());
app.use(cors());
app.use(express.json());

app.use("/api/v1", api);
app.use("/", api);

app.use(middlewares.notFound);
app.use(middlewares.errorHandler);

module.exports = app;

```

## メールを送るルーターを追加する
```javascript:api/src/api/sendmail.js
const express = require("express");
const router = express.Router();
const nodemailer = require("nodemailer");

const host = process.env.SMTP_HOST || "localhost";
const port = parseInt(process.env.SMTP_PORT) || 25;
const from = process.env.MAIL_ADDRESS || "test@test.com";

const smtp = nodemailer.createTransport({
  host,
  port,
});

router.post("/", async (req, res) => {
  try {
    console.log(req.body);
    const { to, message, subject } = req.body;
    if (!to) throw new Error("to is required");
    if (!message) throw new Error("message is required");
    if (!subject) throw new Error("subject is required");

    const option = { from, to, subject, text: message };
    const result = await smtp.sendMail(option);

    res.json({
      message: "message has been sent",
    });
  } catch (e) {
    console.error(e);
    res.status(400).json({ error: true, message: e.message });
  }
});

module.exports = router;

```
## メールを送るルーターをindexに追加する
```javascript:api/src/api/index.js
const express = require("express");

const emojis = require("./emojis");
const sendmail = require("./sendmail");

const router = express.Router();

router.get("/", (req, res) => {
  res.send("<a href='https://www.postman.com/'>use postman</a>");
});

router.use("/emojis", emojis);
router.use("/sendmail", sendmail);

module.exports = router;
```

## dockerfileを準備
```Dockerfile:api/Dockerfile
FROM node:16.13.0
WORKDIR /usr/src/app
COPY package*.json ./
RUN npm install --only=production
COPY . .
EXPOSE 5000
CMD [ "npm", "start" ]

```

## docker-composeを用意する
```yml:docker-compose.yml
version: "3"
services:
  smtp:
    image: schickling/mailcatcher
    ports:
      - "1080:1080"
      - "25:1025"
  api:
    build:
      context: ./api
    environment:
      - SMTP_HOST=smtp
      - SMTP_PORT=1025
    ports:
      - "3000:5000"
```

## 起動
```bash:bash
docker-compose up
```

# 使ってみる
このAPIにリクエストを送ると、メールが送られます
http://localhost:1080 にアクセスすればメールが擬似的に送られたことを確認できると思います。

```bash
curl --location --request POST 'http://localhost:3000/sendmail' \
--header 'Content-Type: application/x-www-form-urlencoded' \
--data-urlencode 'to=test@test.com' \
--data-urlencode 'subject=件名' \
--data-urlencode 'message=これはテストです。'
```

# 参考文献
- [Node.js Web アプリケーションを Docker 化する](https://nodejs.org/ja/docs/guides/nodejs-docker-webapp/)
- [create express api](https://www.npmjs.com/package/create-express-api)
- [compose-postfix](https://github.com/khezen/compose-postfix/blob/master/docker-compose.yml)