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の設定
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を使って行う。
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
リマインドの設定
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読み込み
import { Router } from 'express'
import reminde from './reminder'
const router = Router()
router.use(reminde)
export default router
さらにapiも読み込んであげる
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けっこういろんなところで使えそうだし、リマインダー機能つくるのが結構簡単につくれた。