diff --git a/README.md b/README.md index c41b323..b101ec2 100644 --- a/README.md +++ b/README.md @@ -24,3 +24,21 @@ This project accomplishs the following functions user_settings.json 9. Performs regular clean on Parent Folder and deletes any messages older than 2 days + +--- + +## Node.js Version + +`message_processor.js` is an Express based server that keeps a persistent +IMAP session and periodically forwards unseen messages. Install the +dependencies and start the server with Node.js: + +```bash +npm install +node message_processor.js +``` + +The script reads `user_settings.json` for defaults and prompts for any +missing values before scanning the mailbox at the configured interval. +Once running, the server listens on port 3000 and exposes a `/status` +endpoint to confirm it is alive. diff --git a/message_processor.js b/message_processor.js new file mode 100644 index 0000000..1c4ea99 --- /dev/null +++ b/message_processor.js @@ -0,0 +1,105 @@ +const fs = require('fs'); +const path = require('path'); +const readline = require('readline'); +const { ImapFlow } = require('imapflow'); +const nodemailer = require('nodemailer'); +const express = require('express'); + +const USER_SETTINGS_PATH = path.join(__dirname, 'user_settings.json'); + +function loadSettings() { + try { + const data = fs.readFileSync(USER_SETTINGS_PATH, 'utf8'); + return JSON.parse(data); + } catch (err) { + console.error('Unable to load user settings:', err); + process.exit(1); + } +} + +function saveSettings(settings) { + try { + fs.writeFileSync(USER_SETTINGS_PATH, JSON.stringify(settings, null, 4)); + } catch (err) { + console.error('Unable to save user settings:', err); + } +} + +async function promptSettings(settings) { + const rl = readline.createInterface({ input: process.stdin, output: process.stdout }); + function ask(question, defaultValue) { + return new Promise(resolve => { + rl.question(`${question} (${defaultValue}): `, answer => { + resolve(answer || defaultValue); + }); + }); + } + + settings.SendFrom = await ask('Enter the email address you want to send from', settings.SendFrom); + settings.SendTo = await ask('Enter the email address you want to send to', settings.SendTo); + settings.Smtp = await ask('Enter the SMTP server to use', settings.Smtp); + settings.Encryption = await ask('Select the encryption type: Unencrypted or Encrypted', settings.Encryption); + settings.Interval = parseInt(await ask('Enter the interval (minutes) between scans', settings.Interval), 10); + rl.close(); + saveSettings(settings); + return settings; +} + +async function startProcessing(settings) { + const imap = new ImapFlow({ + host: settings.Smtp, + port: settings.Encryption === 'Encrypted' ? 993 : 143, + secure: settings.Encryption === 'Encrypted', + auth: { + user: settings.SendFrom, + pass: settings.RI + } + }); + + const transporter = nodemailer.createTransport({ + host: settings.Smtp, + secure: settings.Encryption === 'Encrypted', + auth: { + user: settings.SendFrom, + pass: settings.RI + } + }); + + await imap.connect(); + await imap.mailboxOpen('INBOX'); + + async function scanMailbox() { + const messages = await imap.search({ seen: false }); + for await (let msg of imap.fetch(messages, { source: true })) { + const mailOptions = { + from: settings.SendFrom, + to: settings.SendTo, + subject: msg.envelope.subject, + text: `HEADER\n\n${msg.source.toString()}\n\nFOOTER` + }; + await transporter.sendMail(mailOptions); + await imap.messageFlagsAdd(msg.uid, ['\\Seen']); + } + } + + // initial scan then repeat at interval without closing the connection + await scanMailbox(); + setInterval(() => { + scanMailbox().catch(err => console.error('Failed to process emails:', err)); + }, settings.Interval * 60000); +} + +async function main() { + let settings = loadSettings(); + settings = await promptSettings(settings); + + const app = express(); + app.get('/status', (req, res) => res.send('running')); + + await startProcessing(settings); + app.listen(3000, () => { + console.log('Message processor server running on port 3000'); + }); +} + +main(); diff --git a/package.json b/package.json new file mode 100644 index 0000000..ea2968c --- /dev/null +++ b/package.json @@ -0,0 +1,18 @@ +{ + "name": "message_processor", + "version": "1.0.0", + "description": "Free to Use and Licensed under GNU GPLv3", + "main": "message_processor.js", + "scripts": { + "test": "echo \"Error: no test specified\" && exit 1" + }, + "keywords": [], + "author": "", + "license": "GPL-3.0", + "type": "commonjs", + "dependencies": { + "imapflow": "^1.0.0", + "nodemailer": "^6.9.11", + "express": "^4.19.2" + } +} diff --git a/user_settings.json b/user_settings.json index 207c7ee..0534c48 100644 --- a/user_settings.json +++ b/user_settings.json @@ -1,16 +1,16 @@ -{ - "SendFrom": "email@email.com", - "SendTo": "email@email.com", - "Smtp": "smtp.gmail.com", - "Encryption": "Unencrypted", - "Interval": 1, - "RI": "", - }, - "comments": { - "description": "Email Message Processor - User Settings File", - "version": "v2.0.6.3", - "author": "Written by Culpur.net, An Armored Ninja Company", - "license": "Free to use, Licensed under GNU GPLv3" - "questions": "Need Help, contact us at msgpro [at] culpur.net" - "last update": "Script last updates on 23.03.2023 [at] 20:27" -} +{ + "SendFrom": "email@email.com", + "SendTo": "email@email.com", + "Smtp": "smtp.gmail.com", + "Encryption": "Unencrypted", + "Interval": 1, + "RI": "", + "comments": { + "description": "Email Message Processor - User Settings File", + "version": "v2.0.6.3", + "author": "Written by Culpur.net, An Armored Ninja Company", + "license": "Free to use, Licensed under GNU GPLv3", + "questions": "Need Help, contact us at msgpro [at] culpur.net", + "last update": "Script last updates on 23.03.2023 [at] 20:27" + } +}