const MailListener = require("mail-listener2") const ImapSimple = require('imap-simple') const mailparser = require('mailparser') const fs = require('fs') if (!fs.existsSync('./credentials.json')) fs.copyFileSync('./credentials.default.json', './credentials.json') let $ImapConnection const config = require('./config.json') const credentials = require('./credentials.json') const nodemailer = require("nodemailer") config.smtp = Object.assign({}, credentials, credentials.smtp) let smtpTransporter = nodemailer.createTransport({ host: config.smtp.host, port: config.smtp.port, secure: config.smtp.tls, auth: { user: config.smtp.user, // generated ethereal user pass: config.smtp.password, // generated ethereal password }, }) config.imap = Object.assign({}, credentials, credentials.imap) config.imap.username = config.imap.user //config.onmail = () => ScanUnread() const io = require("socket.io-client") const axios = require('axios') const socket = io(new URL(config.pager.url).origin) const mailListener = new MailListener({ ...config.imap, connTimeout: 10000, authTimeout: 10000, //debug: console.log, tlsOptions: { rejectUnauthorized: false }, mailbox: "INBOX", searchFilter: ["UNSEEN"], markSeen: true, fetchUnreadOnStart: true, }) const searchCriteria = ['UNSEEN'] const fetchOptions = { bodies: ['HEADER', 'TEXT', ''], markSeen: true, struct: true, } const ignoreImapIDs = [] function main() { /* ImapSimple .connect(config) .then((connection) => { $ImapConnection = connection }) .then(ScanUnread) */ } const ingressMap = {} socket.on('msgmgr:event', async (eventType, eventData) => { console.log(eventType, eventData) switch (eventType) { case 'status': { const [msgId, uuid, status] = eventData if (!!ingressMap[msgId]) ingressMap[ msgId ][2].push(`${ uuid } is ${ status }`) } break; case 'read': if (!!ingressMap[ eventData ]) ingressMap[ eventData ][2].push('read') break; case 'response': { const [msgId, response] = eventData if (!!ingressMap[msgId]) { ingressMap[ msgId ][2].push(`response ${ response }`) //const [ replyTo, subject, logArray ] = ingressMap[msgId] let info = await smtpTransporter.sendMail({ from: `"msg-email--smartpager 👻" <${ config.smtp.user }>`, to: ingressMap[msgId][ 0 ], subject: `Response [${ ingressMap[msgId][ 1 ] }] ${ response.toString() }`, text: `Response: ${ response.toString() }\n${ ingressMap[msgId][ 2 ].join('\n') }`, inReplyTo: ingressMap[msgId][ 3 ] }); console.log("Message sent: %s", info.messageId, ingressMap[ msgId ]); } } break; } }) async function sendPage(payload) { console.log(payload) return (await axios.post(config.pager.url, Object.assign({ ...config.pager.params }, { payload }))) } function checkMatch(mail, cmd) { if (!!cmd.subjectContains && !(mail.subject.indexOf(cmd.subjectContains) > -1)) return 0 // subjectContains does not match if (!!cmd.mxdomainExact && !(mail.from.value[0].address)) return 0 if (!!cmd.mxdomainContains && !(mail.from.value[0].address.indexOf(cmd.mxdomainContains) > -1)) return 0 // mxdomainContains does not match return !!cmd.ignore ? 1 : 2 // if ignore is set, lets break with 1, otherwise send page with 2 } async function processMail(mail) { for (processCommand of config.handling.processing) { let res = checkMatch(mail, processCommand) if (res) { if (!!processCommand.format && !processCommand.ignore) { console.log(mail) let payload = processCommand.format payload = payload.replace("[subject]", mail.subject) payload = payload.replace("[from]", mail.from.text) payload = payload.replace("[fromName]", mail.from[0].name || mail.from[0].address) payload = payload.replace("[fromAddress]", mail.from[0].address) sendPage(payload) .then(result => { if (!!processCommand.duplexReply) { ingressMap[ result.data ] = [ mail.from[0].address, mail.subject, [], mail.messageId ] console.log('Duplex Handling Active', result.data, mail.from[0].address) return } }) } } } } /* function ScanUnread() { return $ImapConnection.openBox('INBOX') .then(() => $ImapConnection.search(searchCriteria, fetchOptions)) .then((emails) => { console.log('unreadCount:', emails.length) if (emails.length > 0 && config.handling.onlySimpleCounter === true) { sendPage(config.handling.onlySimpleCounterFormat.replace("[unreadCount]", emails.length)) } else { for (let mail of emails) { const all = mail.parts.filter(x => x.which == '')[ 0 ] const idHeader = `Imap-Id: ${mail.attributes.uid}\r\n` if (ignoreImapIDs.indexOf(mail.attributes.uid) > -1) continue // Skip already notified mails ignoreImapIDs.push(mail.attributes.uid) mailparser.simpleParser(idHeader + all.body).then(processMail) } } }) } */ mailListener.on("server:connected", () => { console.log("imapConnected") }) mailListener.on("server:disconnected", () => { console.log("imapDisconnected") require('process').exit() }) mailListener.on("error", (err) => { console.log(err) }) mailListener.on("mail", async (mail, seqno, attributes) => { //if (mail.headers.from == "eBay Kleinanzeigen " && mail.headers.subject == "Aktiviere jetzt dein eBay Kleinanzeigen Konto") { console.log("emailParsed", mail.headers.subject, mail.headers.to) processMail(mail) //await fuckEcho(mail.html, mail.headers.to) // await registrator.handleMail(mail.html, mail.headers.to) //} }) mailListener.start() main() const express = require('express') const appConfig = express() appConfig.use(express.json()) appConfig.use(express.static('html')) /** CONFIG Routes */ appConfig.get('/config', async (req, res) => { return res.json(JSON.parse(fs.readFileSync('config.json'))) }) appConfig.post('/config', async (req, res) => { if (!(!!req.body.pager)) return res.status(403).json(false) if (!(!!req.body.handling)) return res.status(403).json(false) console.log(req.body) fs.writeFileSync('config.json', JSON.stringify(req.body, null, "\t")) return res.json(true) }) appConfig.get('/credentials', async (req, res) => { return res.json(JSON.parse(fs.readFileSync('credentials.json'))) }) appConfig.post('/credentials', async (req, res) => { fs.writeFileSync('credentials.json', JSON.stringify(req.body, null, "\t")) return res.json(true) }) appConfig.post('/restart', (req, res) => { process.exit(1) }) appConfig.listen(3010, '0.0.0.0' || config.host || '127.0.0.1')