nodejs实践录:测试连接性及邮件通知

本文给出一个与服务器测试连通性的示例,具备邮件通知功能,可以以此为基础添加需要的测试项。

代码功能如下:

  • 测试程序与服务器连接,发送指定报文(由内部指定),服务端收到指定报文,回复testOK,客户端接收,认为测试通过。
  • 否则,测试失败(如果连接不到服务,也认为失败)。
  • 当成功或失败时,将结果写到文件(因为nodejs是异步操作,无法保证顺序),然后读取之,再发送邮件给相应的收件人。
  • 发送邮件函数比测试函数延后3秒进行,保证测试完毕后才发邮件。

后续改善功能:

  • 测试函数调用频率提高,确保第一时间发现问题。
  • 每天凌晨发送结果邮件,当错误发生时,立即发送邮件。

代码片段如下:

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
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
/*
内部测试,将结果通过邮件通知给收件人
*/

const net = require('net');
const nodemailer = require("nodemailer");
var fs =require('fs');

var g_cnt = 0;
var g_err = 0;
const g_filename = "inntest.txt";

function getTimestamp()
{
var now = new Date();
var y = now.getFullYear();
var m = now.getMonth() + 1;
var d = now.getDate();
var hour = now.getHours();
var min = now.getMinutes();
var sec = now.getSeconds();
var msec = now.getMilliseconds();
return "[" + y + "-" + (m < 10 ? "0" + m : m) +
"-" + (d < 10 ? "0" + d : d) +
" " + (hour < 10 ? "0" + hour : hour) +
":" + (min < 10 ? "0" + min : min) +
":" + (sec < 10 ? "0" + sec : sec) +
"." + (msec < 100 ? (msec < 10 ? "00" + msec : '0' + msec) : msec) + "] ";
}

function printf(fmt, ...extras)
{
console.log(getTimestamp(), fmt, ...extras);
}

// 以追加的形式写到文件
// 注:如果写入内容不一致,最好自行转换成一致再调用
function write(filename, fmt)
{
fs.writeFile(filename, getTimestamp() + fmt + '\r\n', {flag:'a', encoding:'utf-8', mode:'0644'}, function(err){});
}

function read(filename)
{
var buf = '';
buf = fs.readFileSync(filename, 'utf8');
fs.unlink(filename, (err) =>{});
return buf;
}

function nl2br(str, isXhtml) {
var breakTag = (isXhtml || typeof isXhtml === 'undefined') ? '<br />' : '<br>';
var str = (str + '').replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;").replace(/"/g, "&quot;").replace(/'/g, "&apos;");
return (str + '').replace(/([^>\r\n]?)(\r\n|\n\r|\r|\n)/g, '$1' + breakTag + '$2');
};

function sendMail(from, aliasName, tos, subject, msg)
{
const smtpTransport = nodemailer.createTransport({
host: 'smtp.exmail.qq.com',
secureConnection: true, // use SSL
secure: true,
port: 465,
auth: {
user: from,
pass: '1qaz@WSX',
}
});

smtpTransport.sendMail({
//from : '标题别名 <foobar@latelee.org>',
from : aliasName + ' ' + '<' + from + '>',
to : tos,
subject : subject,//邮件主题
html : nl2br(msg)
}, function(err, res) {
if (err)
{
printf('error: ', err);
}
});
}


function clientmain1(HOST, PORT, msg)
{
var client = new net.Socket();

//printf("connect to ", HOST);
client.connect(PORT, HOST, function()
{
var buffer = Buffer.from(msg, 'hex');
client.write(buffer);
});
// 服务端返回数据处理
client.on('data',function(data){
//printf('got from server: ' + data.toString('hex'));
if (data == 'quit') {
client.destroy();
//printf('server quit, bye');
}
else if (data == 'testOK') {
//printf("test OK");
// printf("test cnt: ", g_cnt, PORT);
g_cnt++;
write(g_filename, "test OK");
client.destroy();
}
});

client.on('error',function(error){
// 当无法连接或其它错误时,在本函数
//printf(`error code: ${error.code}, port: ${error.port}`);
write(g_filename, "test: failed: " + error.code);
client.destroy(); // 调用此函数,会产生close事件
});

client.on('close',function(){
//正常关闭连接
// printf('Connection closed');
//process.exit(0);
});
}

function clientmain2()
{
clientmain1('127.0.0.1', 10086, "test0002147284end"); // packet OK
}

function send2Mail()
{
var context = read(g_filename);
printf('will send email');

sendMail('test@latelee.org', 'my test', 'li@latelee.org', 'my test', context);
}

function clientmain()
{
var Interval = 10;
//send2Mail();
setTimeout(clientmain2, 1000*Interval)
setTimeout(send2Mail, 1000*Interval + 1000*2);
}

// clientmain();

var cron = require('node-cron');

// cron.schedule('* * * * *', () => { // 每分钟 OK
cron.schedule('0 * * * *', () => { // 每小时 OK
// cron.schedule('0 23 * * *', () => { // 每天23点钟
console.log('running a task every hour');
clientmain();
});

说明:本文所用的发送邮箱已被笔者用于gitlab提交邮件通知(用于工作)、其它CI通知,如有需要,可以直接使用,只需将sendMail第三个参数修改为收件人邮箱即可。请不要修改密码,不然会造成影响。

李迟 2019.3.12 周三 中午