LoginSignup
2
2

More than 5 years have passed since last update.

Nuxt.jsとExpress.jsを使ってリマインダー機能をつくってみた

Last updated at Posted at 2019-03-15

Node製リマインダー機能

予約した内容を前日にリマインドするという機能をnodemailerでできないかと考えていたら、node schedulerを使うとできるみたいなことが書いてあったので作ってみた。

今回はVueファイル側でやることはないので、Expressを基本いじる感じになる。

環境

  • Nuxt.js v2.4.5
  • backpack-core
  • Express v4.16.4
  • nodemailer v5.1.1
  • nodemailer-smtp-transport v2.7.4
  • node-schedule v1.3.2
  • moment v2.24.0
  • mysql v2.16.0

インストール

対象のプロジェクト下で

yarn add nodemailer nodemailer-smtp-transport node-schedule moment mysql backpack-core

backpack-coreを設定

ES6を使えるようにする。
https://qiita.com/sauzar18/items/32a8553587e2bdcf3689

ここら辺見て設定してください。

SMTPの設定

server/config.js
const config = {
  transporter: {
    service: 'example.jp',
    port: 465, // ssl対応port
    auth: {
      user: 'yoyaku@example.jp',
      pass: 'passwordnyuryokusitekure'
    },
    use_authentication: true,
    tls: {
      rejectUnauthorized: false
    }
  }
}

export default config

ここを対象のサーバーの情報を入力してください

データベースをコネクト

今回はmysqlを使って行う。

server/mysql.js
import mysql from 'mysql'

const dbConfig = {
  host: 'localhost',
  user: 'example',
  database: 'reminder_db',
  password: 'examplepass',
  multipleStatements: true
}
const connection = mysql.createConnection(dbConfig)

export default connection

リマインドの設定

server/api/reminder.js
import { Router } from 'express'
import consola from 'consola'
import nodemailer from 'nodemailer'
import schedule from 'node-schedule'
import moment from 'moment'
import connection from '../mysql'
const config = require('../config').default
const router = Router()
// eslint-disable-next-line no-unused-vars
const job = schedule.scheduleJob({
  hour: 18,
  minute: 30
}, function () {
  const date = moment().add(1, 'days').format('YYYY-MM-DD')
  const emailQuery = `SELECT * FROM table WHERE reserve_date = "${date}" AND post_type NOT IN ('cancel')`
  connection.query(emailQuery, function (err, rows) {
    if (err) {
      consola.ready(err)
    } else {
      const transporter = nodemailer.createTransport(config.transporter)
      for (let i = 0; i < rows.length; i++) {
        const json = JSON.stringify(rows[i])
        const user = JSON.parse(json)
        const output = `予約システム

${user.username}様
予約前日になりました。
予約内容を確認の上、ご来店ください。

予約店:${user.company_name}
予約予定日時:${moment(user.start).format('YYYY年MM月DD日 h時mm日')}
予約内容:${user.title}

また、当日キャンセルにおいてはシステム上で行っても
受理されない可能性がありますので、店舗へご連絡の上ご確認ください。
`
        consola.ready(output)
        const mailOptions = {
          from: 'example.email.com',
          to: user.email,
          subject: '予約前日のお知らせ',
          text: output
        }
        transporter.sendMail(mailOptions, (error, info) => {
          if (error) {
            // eslint-disable-next-line no-undef
            consola.ready(error)
          } else {
            // eslint-disable-next-line no-undef
            consola.ready('success')
          }
        })
      }
    }
  })
})

export default router

これをapi読み込み

server/api/index.js
import { Router } from 'express'

import reminde from './reminder'

const router = Router()

router.use(reminde)

export default router

さらにapiも読み込んであげる

server/index.js
import api from './api'

app.use('/api', api)

今回DBから取得しているデータはこんな感じ

[
    { id: 0, company_name: '店舗1', reserve_date: '2019-03-16', start: '2019-03-16 07:00:00', end: '2019-03-16 07:30:00', title:'予約内容1', username: '田中太郎', email: 'example@example.com', post_type: 'new' },
    { id: 1, company_name: '店舗2', reserve_date: '2019-03-16', start: '2019-03-16 08:00:00', end: '2019-03-16 08:30:00', title:'予約内容2', username: '田中次郎', email: 'example2@example.com', post_type: 'cancel' },
    { id: 2, company_name: '店舗3', reserve_date: '2019-03-16', start: '2019-03-16 09:00:00', end: '2019-03-16 09:30:00', title:'予約内容3', username: '田中次郎', email: 'example3@example.com', post_type: 'new' }
]

やっていること

node schedulerでリマインドする時間を設定

const job = schedule.scheduleJob({
  hour: 18,
  minute: 30
}, function () {
    // script
})

毎日18時30分にスクリプトを実行する。

データベースから送信する情報を取得

予約日の一日前を対象としたデータを取得したいので、

moment.jsをつかって今日より一日追加してreserve_dateと同じ型に変換しWHEREで検索。

また、キャンセルしたユーザーを除外して取得。

const date = moment().add(1, 'days').format('YYYY-MM-DD')
const emailQuery = `SELECT * FROM table WHERE reserve_date = "${date}" AND post_type NOT IN ('cancel')`

mysqlにアクセスしてSELECTした内容をもとにループさせる

connection.query(emailQuery, function (err, rows) {
    if (err) {
        consola.ready(err)
    } else {
        const transporter = nodemailer.createTransport(config.transporter)
        for (let i = 0; i < rows.length; i++) {
        const json = JSON.stringify(rows[i])
        const user = JSON.parse(json)
        const output = `予約システム

${user.username}様
予約前日になりました。
予約内容を確認の上、ご来店ください。

予約店:${user.company_name}
予約予定日時:${moment(user.start).format('YYYY年MM月DD日 h時mm日')}
予約内容:${user.title}

また、当日キャンセルにおいてはシステム上で行っても
受理されない可能性がありますので、店舗へご連絡の上ご確認ください。
`
    consola.ready(output)
    const mailOptions = {
        from: 'example.email.com',
        to: user.email,
        subject: '予約前日のお知らせ',
        text: output
    }
    transporter.sendMail(mailOptions, (error, info) => {
        if (error) {
        // eslint-disable-next-line no-undef
        consola.ready(error)
        } else {
        // eslint-disable-next-line no-undef
        consola.ready('success')
        }
    })
    }
}
})

取得したデータをrowsに格納して、JSON形式に整形する。

ループ分のなかにnodemailerの設定と文章をつくる

各データに紐づく内容を文章に代入してあげ、対象のユーザーむけに送信をする。

これで設置が完了。

Expressサーバーが動いていれば、基本的に毎日、リマインド対象者を検索し、いれば送信してくれるようになります。

まとめ

node schedulerけっこういろんなところで使えそうだし、リマインダー機能つくるのが結構簡単につくれた。

2
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
2