obnizを使用して、ドアセンサーを作った[メール送信クライアント編]

今回は、作ったドアセンサーの通知メール送信クライアントの話

以前 nodemailer で記事書いた時とは、少し仕様が変わったらしく
その辺で困りもしたがどうにか完成した。

それでは本題。

目次

コード

mqtt クライアント動作し、mqtt のメッセージに基づいてメールを送信するアプリケーションとして 4 ファイルを作成した。

  • mail.js(メール送信処理)
  • mailparam.js(メール処理パラメータ)
  • mqttparam.js(mqtt 処理パラメータ)
  • obnizmail.js(アプリケーション本体)

実行対象は obnizmail.js です。
node obnizmail.jsで実行します。
本番運用は、foreverを使用して実行しています。

それではコードです。
コードはすべてセキュリティにかかわるものはマスクしてあります。

mail.js(メール送信処理)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
//メール送信用
const Mailer = require("nodemailer");
let mailparam = require("./mailparam");
let smtpTransport = require("nodemailer-smtp-transport");

//SMTPの設定
const MailParam = {
service: "Gmail",
auth: {
user: mailparam.user,
pass: mailparam.pass,
},
tls: {
rejectUnauthorized: false,
},
};

//SMTP接続の作成
let Smtp = Mailer.createTransport(smtpTransport(MailParam));

//データ配信用メール内容
const MailOptions = {
from: "[送信元メールアドレス]",
to: "[送信先メールアドレス]",
subject: "ドア状態",
html: "",
text: "",
};

//ドアが開いた通知用メール作成関数。
const GetMailTextOPEN = (msg) => {
//メールオブジェクトを複製
MailData = Object.assign({}, MailOptions);

//メールオブジェクトに本文を追加
MailData.text = `
ドアが${msg}に開きました。
`;
return MailData;
};

//ドアが閉じた通知用メール作成関数。
const GetMailTextCLOSE = (msg) => {
//メールオブジェクトを複製
MailData = Object.assign({}, MailOptions);

//メールオブジェクト本文を追加
MailData.text = `
ドアが閉じました。
${msg}開いていました。
`;
return MailData;
};

//メール送信を関数定義
let Send = async (msg, type) => {
return new Promise((resolve, reject) => {
Smtp.sendMail(
type == "Open" ? GetMailTextOPEN(msg) : GetMailTextCLOSE(msg),
//MailData,
function (err, res) {
if (err) {
//送信に失敗したとき
console.log("送信失敗\n=>");
console.log(err);
reject("送信失敗\n=>" + err);
} else {
//送信に成功したとき
console.log("送信成功\n=>");
console.log(res);
resolve("送信成功\n=>" + res.message);
}
}
);
});
};

exports.Send = Send;
mailparam.js(メール処理パラメータ)
1
2
3
4
5
6
let mailparam = {
user: "[メール転送元アドレス]",
pass: "[アプリケーションパスワード]",
};

module.exports = mailparam;
mqttparam.js(mqtt処理パラメータ)
1
2
3
4
5
6
7
8
let mqttparam = {
server: "mqtt://[サーバーアドレス]:[ポート]",
clientId: "[クライアントID]",
username: "[クライアント名]",
password: "[パスワード]",
};

module.exports = mqttparam;
obnizmail.js(アプリケーション本体)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
let mqtt = require("mqtt");
let mqttparam = require("./mqttparam.js");
let mail = require("./mail");
const moment = require("moment");

//mqttサーバー接続
let client = mqtt.connect(mqttparam.server, {
clientId: mqttparam.clientId,
username: mqttparam.username,
password: mqttparam.password,
});

client.on("connect", function () {
client.subscribe("topic-door");
});

let state = false;
let opentime = "";
let closetime = "";

//時刻文字列作成関数
let gettime = () => {
let resultstring = "";
let now = moment().utcOffset("+0900");

resultstring = now.format("YYYY年MM月DD日 HH:mm s秒");

return resultstring;
};

//経過時間文字列作成関数
let getintervalstring = (a, b) => {
return `${a}から\n${b}まで`;
};

//多重送信回避用フラグ
let flag = true;

//メッセージ受信時処理
client.on("message", async function (topic, message) {
if (flag) {
flag = false;
let temp = JSON.parse(message.toString()).data.door;

//ドアが開いた
if (state != temp && state == "CLOSE") {
console.log("開いた");
opentime = gettime();
await mail.Send(opentime, "Open");
}
//ドアが閉じた
if (state != temp && state == "OPEN") {
console.log("閉じた");
closetime = gettime();
await mail.Send(getintervalstring(opentime, closetime), "Cloce");
}
//ドアが閉じている
if (state == temp && state == "CLOSE") {
opentime = "";
closetime = "";
}
//状態更新
state = temp;

//多重送信回避フラグ解放
flag = true;
}
});

こちらを実行すると、mqtt の通知に基づいてメールが送信されます。

困った話

こちらを作成していたとき、
去年まで動いていた nodemailer での gmail を介したメール送信が動かなくなりました。
以前別のものを作ったときに使っていたので、
「何でだよ!!!!」ってなっていました。

これについては、nodemailer-smtp-transportを使うことで回避できました。

参考になったのはstackoverflow Nodemailer with Gmail and NodeJS
英語は得意ではないけど、コードと並んでいればどうにか読めるかなという感じ。
じーっとコードを見ていたら、見慣れないnodemailer-smtp-transportを見つけて、
深堀りし始めたりしていました。
どうやら、nodemailerパッケージのバージョンが新しいものから、
転送にはnodemailer-smtp-transportを使ってほしいということだそう。

いい感じに作れたなと思ってましたが、
送信メッセージが開け閉め 2 種類だけになってるので、使いまわせないことが、改良点かな?と思ってます。

次は状況確認 WEB ページ編です。

ではでは。