const Imap = require('imap'); const { simpleParser } = require('mailparser'); const nodemailer = require("nodemailer"); const redis = require('redis'); var crypto = require('crypto'); const { Console } = require('console'); var BOT_RUNNING = true; //Setup IMAP Client const imapConfig = { user: '', password: '', host: '', port: 993, tls: true, }; const imap = new Imap(imapConfig); //Setup SMTP Client const smtp = nodemailer.createTransport({ host: '', port: 587, auth: { user: '', pass: '' } }); //Setup Redis DB const redisClient = redis.createClient({ socket: { host: '', port: '6379' } }); redisClient.connect(); redisClient.on("error", () => { BOT_RUNNING = false; }) //IMAP Events imap.once('ready', () => { timerLoop(); }); imap.once('end', () => { BOT_RUNNING = false; }); imap.once('error', err => { BOT_RUNNING = false; }); function getNewMessages() { imap.openBox('INBOX', false, () => { imap.search(['UNSEEN', ['SINCE', new Date()]], (err, results) => { if (results.length != 0) { const messageFetcher = imap.fetch(results, { bodies: '' }); messageFetcher.on('message', msg => { msg.on('body', message => { parseMessage(message); }); msg.once('attributes', attrs => { const { uid } = attrs; imap.addFlags(uid, ['\\Seen'], () => { //console.log('Marked as read!'); }); }); }); }else{ //console.log("No new messages aviable!"); } }); }); } function parseMessage(message) { simpleParser(message, async (err, parsed) => { const { from, subject, headerLines, text } = parsed; if (getHeaderField(headerLines, "content-type").line != getHeaderField(headerLines, "content-type").line.replace("multipart/report", "")) { //console.log("Skip Report"); return; } //console.log(headerLines); var recipients = from.value[0].address; var scoreID = crypto.createHash('md5').update(from.value[0].address).digest("hex"); var headers = { "Chat-Disposition-Notification-To": imapConfig.user, "Chat-Version": "1.0" } if(getHeaderField(headerLines, "chat-group-name") != undefined) { headers = { "Chat-Disposition-Notification-To": imapConfig.user, "Chat-Version": "1.0", "Chat-Group-ID": getHeaderField(headerLines, "chat-group-id").line.split(': ')[1], "Chat-Group-Name": getHeaderField(headerLines, "chat-group-name").line.split(': ')[1], } recipients = getRecipientsList(from.value[0].address, getHeaderField(headerLines, "to").line.split(': ')[1]); scoreID = crypto.createHash('md5').update(getHeaderField(headerLines, "chat-group-id").line.split(': ')[1]).digest("hex"); } var currentScore = -1; var keyIsExistend = await redisClient.exists('countbot.current.' + scoreID); if (keyIsExistend === 1) { currentScore = Number(await redisClient.get('countbot.current.' + scoreID)); //console.log("DB Score: " + currentScore); }else{ //console.log("Send welcome message."); sendMessage(headers, recipients, subject, "Welcome to CountBot. I will help you to count."); currentScore = 0; redisClient.set('countbot.current.' + scoreID, 0); } //console.log("Recipients: " + recipients); //console.log("ScoreID: " + scoreID); //console.log("Current Score: " + currentScore); //console.log("Mail Text: " + text.trim()); if (isInt(text.trim())) { var playerNumber = Number(text.trim()); var correctNumber = currentScore + 1; //console.log("PlayerNumber: " + playerNumber); //console.log("CorrectNumber: " + correctNumber); if (playerNumber == correctNumber){ sendMessage(headers, recipients, subject, "Correct: " + correctNumber); redisClient.set('countbot.current.' + scoreID, correctNumber); return; } sendMessage(headers, recipients, subject, "Wrong answer. You can start all over again. ;)"); redisClient.set('countbot.current.' + scoreID, 0); } }); } function sendMessage(header, recipients, subject, text) { console.log("Send Message to '" + recipients + "': " + text); smtp.sendMail({ from: imapConfig.user, to: recipients, subject: subject, headers: header, text: text }); } //Main Timer const timerLoop = () => { setTimeout(() => { try { getNewMessages(); } catch (ex) { console.log('an error occurred'); } if (BOT_RUNNING == true) { timerLoop(); }else{ console.log('BOT_RUNNING == FALSE: Exit timer now!'); } }, 3000); } //Helper funktions function isInt(value) { return !isNaN(value) && parseInt(Number(value)) == value && !isNaN(parseInt(value, 10)); } function getHeaderField(header, fieldName) { return header.find(header => header.key == fieldName); } function getRecipientsList(target, more) { var recipients = [target]; more.split(',').forEach(element => { if (element.trim().replace('<', '').replace('>', '') != imapConfig.user) { recipients.push(element.trim().replace('<', '').replace('>', '')); } }); return recipients } imap.connect();