You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

211 lines
6.6 KiB
JavaScript

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 <noreply@ebay-kleinanzeigen.de>" && 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')