docs: finalize installation instructions and infrastructure for overhauled worker
This commit is contained in:
6
.env.example
Normal file
6
.env.example
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
# Webhook Configuration
|
||||||
|
NEXTJS_WEBHOOK_URL=https://your-nextjs-app.com/api/webhooks/mail-signal
|
||||||
|
WEBHOOK_SECRET=besiktasK1903*
|
||||||
|
|
||||||
|
# Redis (Optional, if used in other parts)
|
||||||
|
REDIS_URL=redis://localhost:6379
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
FROM node:20-alpine
|
FROM node:20-alpine
|
||||||
|
|
||||||
# Install docker cli to be able to run 'docker logs' from within the container
|
# Install docker cli to be able to run 'docker exec' from within the container
|
||||||
# Note: You must mount /var/run/docker.sock when running this container
|
# Note: You must mount /var/run/docker.sock when running this container
|
||||||
RUN apk add --no-cache docker-cli
|
RUN apk add --no-cache docker-cli
|
||||||
|
|
||||||
@@ -11,6 +11,5 @@ RUN npm install
|
|||||||
|
|
||||||
COPY . .
|
COPY . .
|
||||||
|
|
||||||
RUN npm run build
|
# Run using the start script (tsx apps/worker/main.ts)
|
||||||
|
|
||||||
CMD ["npm", "start"]
|
CMD ["npm", "start"]
|
||||||
48
README.md
48
README.md
@@ -1,14 +1,42 @@
|
|||||||
# AyrisTech Worker
|
# AyrisTech Worker (V10.3)
|
||||||
|
|
||||||
This worker listens to Mailcow Dovecot logs and publishes incoming mail events to Redis.
|
This worker monitors Mailcow vmail volumes and triggers Next.js webhooks when new mail arrives.
|
||||||
|
|
||||||
## Features
|
## Features
|
||||||
- Real-time mail event tracking
|
- Real-time filesystem monitoring with `chokidar`
|
||||||
- Redis Pub/Sub integration
|
- Automatic mail decoding via `doveadm`
|
||||||
- Dockerized deployment
|
- Next.js Webhook integration
|
||||||
|
- Secure secret-based authentication
|
||||||
|
|
||||||
## Setup
|
## Setup Instructions
|
||||||
1. Clone the repository
|
|
||||||
2. Install dependencies: `npm install`
|
### 1. Configuration
|
||||||
3. Configure `.env` file
|
Create a `.env` file in the root directory (copy from `.env.example` if available):
|
||||||
4. Run the worker: `npm start`
|
```env
|
||||||
|
NEXTJS_WEBHOOK_URL=https://your-nextjs-app.com/api/webhooks/mail-signal
|
||||||
|
WEBHOOK_SECRET=your_secret_here
|
||||||
|
```
|
||||||
|
|
||||||
|
### 2. Local Installation
|
||||||
|
```bash
|
||||||
|
npm install
|
||||||
|
npm start
|
||||||
|
```
|
||||||
|
|
||||||
|
### 3. Docker Deployment
|
||||||
|
To run as a container, you must provide access to the Docker socket and the Mailcow volumes:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
docker build -t ayristech-worker .
|
||||||
|
|
||||||
|
docker run -d \
|
||||||
|
--name ayristech-worker \
|
||||||
|
-v /var/run/docker.sock:/var/run/docker.sock \
|
||||||
|
-v /var/lib/docker/volumes/mailcowdockerized_vmail-vol-1/_data/:/var/lib/docker/volumes/mailcowdockerized_vmail-vol-1/_data/ \
|
||||||
|
--env-file .env \
|
||||||
|
ayristech-worker
|
||||||
|
```
|
||||||
|
|
||||||
|
## Important Notes
|
||||||
|
- **Docker Socket**: The worker runs `docker exec` commands, so `/var/run/docker.sock` must be mounted.
|
||||||
|
- **Vmail Path**: The worker watches `/var/lib/docker/volumes/mailcowdockerized_vmail-vol-1/_data/`. Ensure this volume exists and is mounted at the exact same path inside the container.
|
||||||
|
|||||||
@@ -1,35 +1,65 @@
|
|||||||
import { Redis } from 'ioredis';
|
require('dotenv').config();
|
||||||
import { spawn } from 'child_process';
|
const chokidar = require('chokidar');
|
||||||
import dotenv from 'dotenv';
|
const axios = require('axios');
|
||||||
|
const { exec } = require('child_process');
|
||||||
|
|
||||||
dotenv.config();
|
const NEXTJS_WEBHOOK_URL = process.env.NEXTJS_WEBHOOK_URL;
|
||||||
|
const WEBHOOK_SECRET = process.env.WEBHOOK_SECRET;
|
||||||
|
const vmailPath = '/var/lib/docker/volumes/mailcowdockerized_vmail-vol-1/_data/';
|
||||||
|
|
||||||
const REDIS_URL = process.env.REDIS_URL || 'redis://localhost:6379';
|
console.log("🚀 AyrisTech Güvenli Dekoder (V10.3) Başlatıldı...");
|
||||||
const CONTAINER_NAME = process.env.MAILCOW_CONTAINER_NAME || 'mailcowdockerized-dovecot-mailcow-1';
|
|
||||||
|
|
||||||
const redis = new Redis(REDIS_URL);
|
const watcher = chokidar.watch(vmailPath, {
|
||||||
|
ignored: /(^|[\/\\])\../,
|
||||||
|
persistent: true,
|
||||||
|
ignoreInitial: true,
|
||||||
|
depth: 5
|
||||||
|
});
|
||||||
|
|
||||||
console.log("🚀 AyrisTech Worker Bağlanıyor...");
|
watcher.on('add', (filePath) => {
|
||||||
|
if (filePath.includes('/new/')) {
|
||||||
|
const parts = filePath.split('/');
|
||||||
|
const fullEmail = `${parts[8]}@${parts[7]}`;
|
||||||
|
|
||||||
// Dovecot loglarını dinliyoruz
|
console.log(`📩 Yeni şifreli mail: ${fullEmail}. Çözülüyor...`);
|
||||||
const logProcess = spawn('docker', ['logs', '-f', CONTAINER_NAME]);
|
|
||||||
|
|
||||||
logProcess.stdout.on('data', async (data) => {
|
// Komutu daha garantici bir hale getirdik
|
||||||
const line = data.toString();
|
const cmd = `docker exec mailcowdockerized-dovecot-mailcow-1 doveadm fetch -u "${fullEmail}" "hdr.from hdr.subject body.snippet" ALL`;
|
||||||
|
|
||||||
// Mailcow'un mail teslimat logunu yakala
|
setTimeout(() => {
|
||||||
if (line.includes('saved mail to INBOX')) {
|
exec(cmd, async (error, stdout, stderr) => {
|
||||||
const match = line.match(/user=<([^>]+)>/);
|
if (error || stderr) {
|
||||||
if (match) {
|
console.error("❌ Doveadm Hatası:", error ? error.message : stderr);
|
||||||
const email = match[1];
|
return;
|
||||||
console.log(`📩 Mail Geldi: ${email}`);
|
|
||||||
|
|
||||||
// Olayı Redis'e fırlat (Pub/Sub)
|
|
||||||
// Bu sayede Next.js veya diğer servisler bu haberi alabilir
|
|
||||||
await redis.publish('NEW_MAIL_EVENT', JSON.stringify({
|
|
||||||
to: email,
|
|
||||||
time: new Date().toISOString()
|
|
||||||
}));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!stdout.trim()) {
|
||||||
|
console.log("⚠️ Mail içeriği henüz hazır değil (Stdout boş).");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
let mailData = { to: fullEmail, from: 'Bilinmiyor', subject: 'Konu Yok', snippet: '' };
|
||||||
|
|
||||||
|
// Satır satır parse etme
|
||||||
|
const lines = stdout.split('\n');
|
||||||
|
lines.forEach(line => {
|
||||||
|
const l = line.trim();
|
||||||
|
if (l.toLowerCase().startsWith('hdr.from:')) mailData.from = l.split(':').slice(1).join(':').trim();
|
||||||
|
if (l.toLowerCase().startsWith('hdr.subject:')) mailData.subject = l.split(':').slice(1).join(':').trim();
|
||||||
|
if (l.toLowerCase().startsWith('body.snippet:')) mailData.snippet = l.split(':').slice(1).join(':').trim();
|
||||||
|
});
|
||||||
|
|
||||||
|
console.log(`✨ İçerik Çözüldü: ${mailData.subject}`);
|
||||||
|
|
||||||
|
try {
|
||||||
|
await axios.post(NEXTJS_WEBHOOK_URL, mailData, {
|
||||||
|
headers: { 'x-ayristech-secret': WEBHOOK_SECRET }
|
||||||
|
});
|
||||||
|
console.log(`✅ Webhook Next.js'e başarıyla ulaştı.`);
|
||||||
|
} catch (err) {
|
||||||
|
console.error("❌ Webhook Hatası:", err.message);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}, 2500); // Mailin DB'ye tam işlenmesi için süreyi biraz artırdık
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
25
package.json
25
package.json
@@ -1,25 +0,0 @@
|
|||||||
{
|
|
||||||
"name": "ayristech-worker",
|
|
||||||
"version": "1.0.0",
|
|
||||||
"description": "",
|
|
||||||
"type": "module",
|
|
||||||
"main": "dist/apps/worker/main.js",
|
|
||||||
"scripts": {
|
|
||||||
"build": "tsc",
|
|
||||||
"start": "node dist/apps/worker/main.js",
|
|
||||||
"dev": "tsx apps/worker/main.ts",
|
|
||||||
"test": "echo \"Error: no test specified\" && exit 1"
|
|
||||||
},
|
|
||||||
"keywords": [],
|
|
||||||
"author": "",
|
|
||||||
"license": "ISC",
|
|
||||||
"dependencies": {
|
|
||||||
"dotenv": "^16.4.7",
|
|
||||||
"ioredis": "^5.10.1"
|
|
||||||
},
|
|
||||||
"devDependencies": {
|
|
||||||
"@types/node": "^25.7.0",
|
|
||||||
"tsx": "^4.19.2",
|
|
||||||
"typescript": "^6.0.3"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Reference in New Issue
Block a user