forked from smartpager/msg-email
added duplex response handling
This commit is contained in:
parent
4f16309647
commit
a853f223b5
4 changed files with 143 additions and 16 deletions
|
@ -1,8 +1,15 @@
|
|||
{
|
||||
"user": "mail@domein.tld",
|
||||
"password": "wachtwoord",
|
||||
"host": "imap.domein.tld",
|
||||
"port": 993,
|
||||
"tls": true,
|
||||
"imap": {
|
||||
"host": "imap.domein.tld",
|
||||
"port": 993,
|
||||
"tls": true
|
||||
},
|
||||
"smtp": {
|
||||
"host": "smtp.domein.tld",
|
||||
"port": 465,
|
||||
"tls": true
|
||||
},
|
||||
"authTimeout": 5000
|
||||
}
|
|
@ -21,7 +21,7 @@
|
|||
<v-form>
|
||||
<v-tabs v-model="configTab" next-icon="mdi-arrow-right-bold-box-outline" prev-icon="mdi-arrow-left-bold-box-outline" show-arrows>
|
||||
<v-tabs-slider></v-tabs-slider>
|
||||
<v-tab key="credentials">IMAP Credentials</v-tab>
|
||||
<v-tab key="credentials">Credentials</v-tab>
|
||||
<v-tab key="mailProcessing">Mail Processing Chain</v-tab>
|
||||
<v-tab key="notificationConfig">Notification Configuration</v-tab>
|
||||
</v-tabs>
|
||||
|
@ -36,15 +36,28 @@
|
|||
<v-text-field label="Password" type="password" v-model="credentialsData.password"></v-text-field>
|
||||
</v-col>
|
||||
</v-row>
|
||||
<b>IMAP:</b>
|
||||
<v-row>
|
||||
<v-col cols="12" sm="12" md="6">
|
||||
<v-text-field label="Host" v-model="credentialsData.host"></v-text-field>
|
||||
<v-text-field label="Host" v-model="credentialsData.imap.host"></v-text-field>
|
||||
</v-col>
|
||||
<v-col cols="6" sm="4" md="2">
|
||||
<v-checkbox label="TLS" v-model="credentialsData.tls"></v-checkbox>
|
||||
<v-checkbox label="TLS" v-model="credentialsData.imap.tls"></v-checkbox>
|
||||
</v-col>
|
||||
<v-col cols="6" sm="4" md="2">
|
||||
<v-text-field label="Port" min="1" max="65535" type="number" v-model="credentialsData.port"></v-text-field>
|
||||
<v-text-field label="Port" min="1" max="65535" type="number" v-model="credentialsData.imap.port"></v-text-field>
|
||||
</v-col>
|
||||
</v-row>
|
||||
<b>SMTP:</b>
|
||||
<v-row>
|
||||
<v-col cols="12" sm="12" md="6">
|
||||
<v-text-field label="Host" v-model="credentialsData.smtp.host"></v-text-field>
|
||||
</v-col>
|
||||
<v-col cols="6" sm="4" md="2">
|
||||
<v-checkbox label="TLS" v-model="credentialsData.smtp.tls"></v-checkbox>
|
||||
</v-col>
|
||||
<v-col cols="6" sm="4" md="2">
|
||||
<v-text-field label="Port" min="1" max="65535" type="number" v-model="credentialsData.smtp.port"></v-text-field>
|
||||
</v-col>
|
||||
</v-row>
|
||||
<v-row>
|
||||
|
@ -68,6 +81,7 @@
|
|||
<v-row v-for="(processingCmd, index) in configData.handling.processing" :key="processingCmd._id" style="border-bottom: 2px solid black;">
|
||||
<pre>Index: {{ index }}</pre>
|
||||
<v-col cols="12" sm="12" md="12">
|
||||
<v-checkbox label="Send Reply(Breakpoint)" v-model="processingCmd.duplexReply"></v-checkbox>
|
||||
<v-checkbox label="Ignore/Breakpoint" v-model="processingCmd.ignore"></v-checkbox>
|
||||
<v-btn color="error" @click="configData.handling.processing.splice(index, 1)" icon><v-icon>mdi-delete</v-icon></v-btn>
|
||||
<v-btn color="warning" :disabled="index == 0" @click="moveProcessingCMD(index, true)" icon>
|
||||
|
@ -79,7 +93,7 @@
|
|||
</v-col>
|
||||
<v-col cols="12" sm="12" md="12">
|
||||
<pre>possible Placeholders: [from] [fromName] [fromAddress] [subject]</pre>
|
||||
<v-text-field v-model="processingCmd.format" label="Format"></v-text-field>
|
||||
<v-text-field v-model="processingCmd.format" label="Format"></v-text-field>
|
||||
</v-col>
|
||||
<v-col cols="6" sm="6" md="4">
|
||||
<v-text-field v-model="processingCmd.subjectContains" label="Subject Contains (leave empty if unused)"></v-text-field>
|
||||
|
@ -204,6 +218,7 @@
|
|||
storeConfig.handling.processing = storeConfig.handling.processing.map(x => {
|
||||
let y = { }
|
||||
if (!!x.ignore && x.ignore == true) y.ignore = true
|
||||
if (!!x.duplexReply && x.duplexReply == true) y.duplexReply = true
|
||||
if (!!x.format && x.format.length > 0) y.format = x.format
|
||||
for (n of ['format', 'subjectContains', 'mxdomainExact', 'mxdomainContains']) // only copy if not empty
|
||||
if (!!x[n] && x[n].length > 0) y[n] = x[n]
|
||||
|
|
116
index.js
116
index.js
|
@ -1,32 +1,98 @@
|
|||
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')
|
||||
config.imap = require('./credentials.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: false,
|
||||
markSeen: true,
|
||||
struct: true,
|
||||
}
|
||||
const ignoreImapIDs = []
|
||||
function main() {
|
||||
ImapSimple
|
||||
/* 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
|
||||
ingressMap[ msgId ][2].push(`${ uuid } is ${ status }`)
|
||||
} break;
|
||||
case 'read':
|
||||
ingressMap[ eventData ][2].push('read')
|
||||
break;
|
||||
case 'response': {
|
||||
const [msgId, response] = eventData
|
||||
if (!!ingressMap[msgId]) {
|
||||
ingressMap[ msgId ][2].push(`${ uuid } 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)
|
||||
await axios.post(config.pager.url, Object.assign({ ...config.pager.params }, { 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
|
||||
|
@ -40,16 +106,30 @@ async function processMail(mail) {
|
|||
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.value[0].name || mail.from.value[0].address)
|
||||
payload = payload.replace("[fromAddress]", mail.from.value[0].address)
|
||||
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))
|
||||
|
@ -68,6 +148,28 @@ function ScanUnread() {
|
|||
}
|
||||
})
|
||||
}
|
||||
*/
|
||||
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()
|
||||
|
||||
|
||||
|
@ -105,4 +207,4 @@ appConfig.post('/restart', (req, res) => {
|
|||
process.exit(1)
|
||||
})
|
||||
|
||||
appConfig.listen(3010)
|
||||
appConfig.listen(3010, '0.0.0.0' || config.host || '127.0.0.1')
|
||||
|
|
|
@ -20,7 +20,10 @@
|
|||
"axios": "^0.21.1",
|
||||
"express": "^4.17.1",
|
||||
"imap-simple": "^5.0.0",
|
||||
"mail-listener2": "^0.3.1",
|
||||
"mailparser": "^3.1.0",
|
||||
"node-imap": "^0.9.6"
|
||||
"node-imap": "^0.9.6",
|
||||
"nodemailer": "^6.4.18",
|
||||
"socket.io-client": "^4.4.1"
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue