Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 18 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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.
105 changes: 105 additions & 0 deletions message_processor.js
Original file line number Diff line number Diff line change
@@ -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();
18 changes: 18 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
@@ -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"
}
}
32 changes: 16 additions & 16 deletions user_settings.json
Original file line number Diff line number Diff line change
@@ -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"
}
}