lots of updates
This commit is contained in:
parent
59c7245010
commit
31cf4524bf
3
.cron
Normal file
3
.cron
Normal file
@ -0,0 +1,3 @@
|
||||
|
||||
0 * * * * /root/temp_mail/scripts/delete_messages_24h.sh >> /var/log/temp_mail/cleanup.log 2>&1
|
||||
0 0 * * * /root/temp_mail/scripts/delete_emails_14d.sh >> /var/log/temp_mail/cleanup.log 2>&1
|
||||
2
.env-example
Normal file
2
.env-example
Normal file
@ -0,0 +1,2 @@
|
||||
MYSQL_ADMIN_USER=admin
|
||||
MYSQL_ADMIN_PASSWORD=
|
||||
15
config/database-example.js
Normal file
15
config/database-example.js
Normal file
@ -0,0 +1,15 @@
|
||||
module.exports = {
|
||||
development: {
|
||||
client: 'mysql2',
|
||||
connection: {
|
||||
database: 'email_api',
|
||||
user: 'email_api',
|
||||
password: '',
|
||||
host: 'localhost',
|
||||
port: 3306
|
||||
},
|
||||
migrations: {
|
||||
directory: '../db/migrations'
|
||||
}
|
||||
}
|
||||
};
|
||||
23
package.json
23
package.json
@ -3,30 +3,43 @@
|
||||
"version": "1.0.0",
|
||||
"main": "app.js",
|
||||
"scripts": {
|
||||
"test": "echo \"Error: no test specified\" && exit 1",
|
||||
"start": "node app.js",
|
||||
"dev": "nodemon app.js"
|
||||
"start": "npm run setup && node app.js",
|
||||
"dev": "npm run setup && nodemon app.js",
|
||||
"lint": "eslint .",
|
||||
"lint:fix": "eslint --fix .",
|
||||
"setup": "bash setup.sh"
|
||||
},
|
||||
"keywords": [],
|
||||
"author": "",
|
||||
"author": "Ryahn",
|
||||
"license": "ISC",
|
||||
"description": "",
|
||||
"dependencies": {
|
||||
"bcrypt": "^5.1.1",
|
||||
"chokidar": "^4.0.3",
|
||||
"cors": "^2.8.5",
|
||||
"express": "^4.21.2",
|
||||
"favicon": "^0.0.2",
|
||||
"haraka": "^0.0.33",
|
||||
"haraka-plugin-dkim": "^1.0.9",
|
||||
"html-to-text": "^9.0.5",
|
||||
"jsonwebtoken": "^9.0.2",
|
||||
"knex": "^3.1.0",
|
||||
"moniker": "^0.1.2",
|
||||
"mysql2": "^3.12.0",
|
||||
"node-cron": "^3.0.3",
|
||||
"nodemailer": "^6.10.0",
|
||||
"objection": "^3.1.5",
|
||||
"sanitize-html": "^2.14.0",
|
||||
"serve-favicon": "^2.5.0",
|
||||
"swagger-jsdoc": "^6.2.8",
|
||||
"swagger-ui-express": "^5.0.1",
|
||||
"unique-names-generator": "^4.7.1"
|
||||
},
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "git@git.zonies.xyz:Ryahn/Temp-Email-Service.git"
|
||||
},
|
||||
"description": "",
|
||||
"devDependencies": {
|
||||
"eslint": "^9.21.0"
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,26 +1,27 @@
|
||||
const User = require('../src/db/models/User');
|
||||
const { Model } = require('objection');
|
||||
const Knex = require('knex');
|
||||
const knexConfig = require('../src/config/database');
|
||||
const User = require("../src/db/models/User");
|
||||
const { Model } = require("objection");
|
||||
const Knex = require("knex");
|
||||
const knexConfig = require("../src/config/database");
|
||||
const knex = Knex(knexConfig.development);
|
||||
Model.knex(knex);
|
||||
const Logger = require("../src/utils/logger");
|
||||
const log = new Logger();
|
||||
|
||||
const email = process.argv[2];
|
||||
const id = process.argv[3];
|
||||
|
||||
if (!email && !id) {
|
||||
console.error('Usage: node delete_user.js <email> || <id>');
|
||||
log.error("Usage: node delete_user.js <email> || <id>");
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
async function main() {
|
||||
let user;
|
||||
if (id) {
|
||||
user = await User.query().where('id', id).delete();
|
||||
await User.query().where("id", id).delete();
|
||||
} else {
|
||||
user = await User.query().where('email', email).delete();
|
||||
await User.query().where("email", email).delete();
|
||||
}
|
||||
console.log(`User deleted`);
|
||||
log.info(`User deleted`);
|
||||
process.exit(0);
|
||||
}
|
||||
|
||||
|
||||
@ -29,7 +29,7 @@ async function main() {
|
||||
);
|
||||
};
|
||||
|
||||
token = generateToken();
|
||||
const token = generateToken();
|
||||
await User.query().where("id", user.id).update({ api_key: token });
|
||||
console.log("Token generated and updated for user", user.email);
|
||||
console.log("Token:", token);
|
||||
|
||||
231
setup.sh
231
setup.sh
@ -1,21 +1,242 @@
|
||||
#! /bin/bash
|
||||
|
||||
# Color definitions
|
||||
GREEN='\033[0;32m'
|
||||
YELLOW='\033[1;33m'
|
||||
RED='\033[0;31m'
|
||||
NC='\033[0m' # No Color
|
||||
|
||||
# Logger functions
|
||||
log_info() {
|
||||
echo -e "${GREEN}[INFO]${NC} $1"
|
||||
}
|
||||
|
||||
log_warn() {
|
||||
echo -e "${YELLOW}[WARN]${NC} $1"
|
||||
}
|
||||
|
||||
log_error() {
|
||||
echo -e "${RED}[ERROR]${NC} $1"
|
||||
}
|
||||
|
||||
CURRENT_DIR=$(pwd)
|
||||
SERVICE_FILE="haraka.service"
|
||||
SERVICE_PATH="/etc/systemd/system/$SERVICE_FILE"
|
||||
LOCAL_SERVICE_PATH="$CURRENT_DIR/$SERVICE_FILE"
|
||||
|
||||
# Load environment variables
|
||||
if [ -f "$CURRENT_DIR/.env" ]; then
|
||||
export $(cat "$CURRENT_DIR/.env" | grep -v '^#' | xargs)
|
||||
else
|
||||
log_error ".env file not found"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Check if MYSQL_ADMIN_PASSWORD is set
|
||||
if [ -z "$MYSQL_ADMIN_PASSWORD" ]; then
|
||||
log_error "MYSQL_ADMIN_PASSWORD not found in .env file"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [ -z "$MYSQL_ADMIN_USER" ]; then
|
||||
log_error "MYSQL_ADMIN_USER not found in .env file"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Database configuration
|
||||
DB_NAME="email_api1"
|
||||
DB_USER="email_api1"
|
||||
DB_PASS=$(openssl rand -base64 12) # Generate random password
|
||||
|
||||
# Check if mysql-server is installed
|
||||
if ! command -v mysql &> /dev/null; then
|
||||
log_warn "MySQL Server not found. Installing..."
|
||||
sudo apt-get update >> /dev/null 2>&1
|
||||
sudo apt-get install -y mysql-server >> /dev/null 2>&1
|
||||
else
|
||||
log_info "MySQL Server is already installed"
|
||||
fi
|
||||
|
||||
# Wait for MySQL to be ready
|
||||
log_info "Waiting for MySQL to be ready..."
|
||||
while ! mysqladmin ping -h "localhost" -u admin -p"${MYSQL_ADMIN_PASSWORD}" --silent; do
|
||||
sleep 1
|
||||
done
|
||||
|
||||
# Create database and user
|
||||
log_info "Setting up MySQL database and user..."
|
||||
mysql -u admin -p"${MYSQL_ADMIN_PASSWORD}" -e "CREATE DATABASE IF NOT EXISTS ${DB_NAME};"
|
||||
|
||||
# Check if user exists
|
||||
USER_EXISTS=$(mysql -u "${MYSQL_ADMIN_USER}" -p"${MYSQL_ADMIN_PASSWORD}" -s -N -e "SELECT COUNT(*) FROM mysql.user WHERE User = '${DB_USER}' AND Host = 'localhost';")
|
||||
|
||||
if [ "$USER_EXISTS" -eq 0 ]; then
|
||||
log_info "Creating new database user..."
|
||||
mysql -u "${MYSQL_ADMIN_USER}" -p"${MYSQL_ADMIN_PASSWORD}" -e "CREATE USER '${DB_USER}'@'localhost' IDENTIFIED BY '${DB_PASS}';"
|
||||
mysql -u "${MYSQL_ADMIN_USER}" -p"${MYSQL_ADMIN_PASSWORD}" -e "GRANT ALL PRIVILEGES ON ${DB_NAME}.* TO '${DB_USER}'@'localhost';"
|
||||
mysql -u "${MYSQL_ADMIN_USER}" -p"${MYSQL_ADMIN_PASSWORD}" -e "FLUSH PRIVILEGES;"
|
||||
|
||||
# Update database config file with new values
|
||||
log_info "Updating database configuration..."
|
||||
cp "$CURRENT_DIR/src/config/database-example.js" "$CURRENT_DIR/src/config/database.js"
|
||||
CONFIG_FILE="$CURRENT_DIR/src/config/database.js"
|
||||
sed -i "s/database: \"\"/database: '${DB_NAME}'/" "$CONFIG_FILE"
|
||||
sed -i "s/user: \"\"/user: '${DB_USER}'/" "$CONFIG_FILE"
|
||||
sed -i "s/password: \"\"/password: '${DB_PASS}'/" "$CONFIG_FILE"
|
||||
log_info "Database password has been updated in the configuration file"
|
||||
else
|
||||
log_warn "Database user already exists. Skipping user creation and configuration update."
|
||||
fi
|
||||
|
||||
# Create group and user
|
||||
sudo groupadd smtp
|
||||
sudo useradd -r -g smtp smtp
|
||||
log_info "Creating group and user..."
|
||||
sudo groupadd smtp 2>/dev/null || true
|
||||
sudo useradd -r -g smtp smtp 2>/dev/null || true
|
||||
|
||||
# Create required directories
|
||||
log_info "Creating required directories..."
|
||||
sudo mkdir -p /var/spool/haraka /var/log/haraka
|
||||
sudo chown -R smtp:smtp /var/spool/haraka /var/log/haraka
|
||||
|
||||
# Set permissions
|
||||
log_info "Setting permissions..."
|
||||
sudo chmod 755 /var/spool/haraka
|
||||
sudo chmod 644 /var/log/haraka
|
||||
|
||||
# Install Haraka
|
||||
npm install -g haraka
|
||||
log_info "Installing Haraka..."
|
||||
if ! command -v haraka &> /dev/null; then
|
||||
npm install -g Haraka
|
||||
else
|
||||
log_warn "Haraka is already installed"
|
||||
fi
|
||||
|
||||
# Check if service file exists and handle accordingly
|
||||
log_info "Checking if service file exists..."
|
||||
if [ -f "$SERVICE_PATH" ]; then
|
||||
# Calculate checksums
|
||||
REMOTE_CHECKSUM=$(sha1sum "$SERVICE_PATH" | awk '{print $1}')
|
||||
LOCAL_CHECKSUM=$(sha1sum "$LOCAL_SERVICE_PATH" | awk '{print $1}')
|
||||
|
||||
if [ "$REMOTE_CHECKSUM" != "$LOCAL_CHECKSUM" ]; then
|
||||
log_warn "Service file differs from local version. Updating..."
|
||||
sudo cp "$LOCAL_SERVICE_PATH" "$SERVICE_PATH"
|
||||
sudo systemctl daemon-reload
|
||||
sudo systemctl enable haraka
|
||||
sudo systemctl restart haraka
|
||||
else
|
||||
log_info "Service file is up to date"
|
||||
fi
|
||||
else
|
||||
log_info "Service file not found. Installing..."
|
||||
sudo cp "$LOCAL_SERVICE_PATH" "$SERVICE_PATH"
|
||||
sudo systemctl daemon-reload
|
||||
log_info "Enabling and starting Haraka..."
|
||||
sudo systemctl enable haraka
|
||||
fi
|
||||
|
||||
# Install Haraka plugins
|
||||
mkdir -p $CURRENT_DIR/src/email_server/plugins/queue
|
||||
ln -s $CURRENT_DIR/src/haraka-plugins/queue/store_message.js $CURRENT_DIR/src/email_server/plugins/queue/store_message.js
|
||||
log_info "Installing Haraka plugins..."
|
||||
mkdir -p "$CURRENT_DIR/src/email_server/plugins/queue"
|
||||
rm -f "$CURRENT_DIR/src/email_server/plugins/queue/store_message.js"
|
||||
ln -s "$CURRENT_DIR/src/haraka-plugins/queue/store_message.js" "$CURRENT_DIR/src/email_server/plugins/queue/store_message.js"
|
||||
|
||||
log_info "Installing dependencies..."
|
||||
npm install >> /dev/null 2>&1
|
||||
|
||||
log_info "Running migrations..."
|
||||
npx knex migrate:latest
|
||||
|
||||
CRON_FILE="$CURRENT_DIR/.cron"
|
||||
echo "" > "$CRON_FILE"
|
||||
echo "0 * * * * $CURRENT_DIR/scripts/delete_messages_24h.sh >> /var/log/temp_mail/cleanup.log 2>&1" >> "$CRON_FILE"
|
||||
echo "0 0 * * * $CURRENT_DIR/scripts/delete_emails_14d.sh >> /var/log/temp_mail/cleanup.log 2>&1" >> "$CRON_FILE"
|
||||
|
||||
TEMP_CRON="/tmp/temp_cron"
|
||||
|
||||
mkdir -p /var/log/temp_mail
|
||||
|
||||
# Check if .cron file exists
|
||||
if [ ! -f "$CRON_FILE" ]; then
|
||||
log_error "Cron file not found at $CRON_FILE"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Function to normalize cron entry (remove extra spaces)
|
||||
normalize_cron() {
|
||||
echo "$1" | sed -e 's/^[ \t]*//' -e 's/[ \t]*$//' -e 's/[ \t]\+/ /g'
|
||||
}
|
||||
|
||||
# Function to check if a cron job exists
|
||||
check_cron_job() {
|
||||
local cron_entry="$1"
|
||||
local normalized_entry=$(normalize_cron "$cron_entry")
|
||||
|
||||
# Get current user's crontab
|
||||
crontab -l > "$TEMP_CRON" 2>/dev/null
|
||||
|
||||
# Check if the normalized entry exists in current crontab
|
||||
if grep -Fq "$normalized_entry" "$TEMP_CRON"; then
|
||||
return 0 # Found
|
||||
else
|
||||
return 1 # Not found
|
||||
fi
|
||||
}
|
||||
|
||||
# Function to install cron jobs
|
||||
install_cron_jobs() {
|
||||
log_info "Installing cron jobs..."
|
||||
|
||||
# Get current crontab
|
||||
crontab -l > "$TEMP_CRON" 2>/dev/null
|
||||
|
||||
# Read each line from .cron file
|
||||
while IFS= read -r line || [ -n "$line" ]; do
|
||||
# Skip comments and empty lines
|
||||
[[ $line =~ ^#.*$ ]] || [ -z "$line" ] && continue
|
||||
|
||||
normalized_line=$(normalize_cron "$line")
|
||||
|
||||
if ! grep -Fq "$normalized_line" "$TEMP_CRON"; then
|
||||
log_warn "Cron job not found, adding: $normalized_line"
|
||||
echo "$normalized_line" >> "$TEMP_CRON"
|
||||
else
|
||||
log_info "Cron job already exists: $normalized_line"
|
||||
fi
|
||||
done < "$CRON_FILE"
|
||||
|
||||
# Install new crontab
|
||||
crontab "$TEMP_CRON"
|
||||
|
||||
# Clean up
|
||||
rm -f "$TEMP_CRON"
|
||||
}
|
||||
|
||||
# Main execution
|
||||
log_info "Checking cron jobs..."
|
||||
|
||||
# Read .cron file and check each entry
|
||||
missing_jobs=0
|
||||
while IFS= read -r line || [ -n "$line" ]; do
|
||||
# Skip comments and empty lines
|
||||
[[ $line =~ ^#.*$ ]] || [ -z "$line" ] && continue
|
||||
|
||||
if ! check_cron_job "$line"; then
|
||||
log_warn "Missing cron job: $line"
|
||||
missing_jobs=$((missing_jobs + 1))
|
||||
else
|
||||
log_info "Found cron job: $line"
|
||||
fi
|
||||
done < "$CRON_FILE"
|
||||
|
||||
# If any jobs are missing, offer to install them
|
||||
if [ $missing_jobs -gt 0 ]; then
|
||||
log_warn "Found $missing_jobs missing cron job(s)"
|
||||
install_cron_jobs
|
||||
log_info "Cron jobs have been updated"
|
||||
else
|
||||
log_info "All cron jobs are up to date"
|
||||
fi
|
||||
|
||||
log_info "Installation complete!"
|
||||
log_info "You can now start the email server with: sudo systemctl start haraka"
|
||||
@ -1,15 +1,15 @@
|
||||
module.exports = {
|
||||
development: {
|
||||
client: 'mysql2',
|
||||
client: "mysql2",
|
||||
connection: {
|
||||
database: 'email_api',
|
||||
user: 'email_api',
|
||||
password: '',
|
||||
host: 'localhost',
|
||||
port: 3306
|
||||
database: "",
|
||||
user: "",
|
||||
password: "",
|
||||
host: "localhost",
|
||||
port: 3306,
|
||||
},
|
||||
migrations: {
|
||||
directory: '../db/migrations'
|
||||
}
|
||||
}
|
||||
};
|
||||
directory: "../db/migrations",
|
||||
},
|
||||
},
|
||||
};
|
||||
@ -3,7 +3,6 @@ const router = express.Router();
|
||||
const { authenticateToken } = require('../middleware/auth');
|
||||
const TempEmail = require('../db/models/TempEmail');
|
||||
router.use(authenticateToken);
|
||||
const Domain = require('../db/models/Domain');
|
||||
const DailyStats = require('../db/models/DailyStats');
|
||||
const { generateUniqueName, getRandomDomain, mysqlSafeTimestamp } = require('../utils/functions');
|
||||
|
||||
|
||||
@ -2,7 +2,7 @@ const express = require('express');
|
||||
const router = express.Router();
|
||||
const { authenticateToken } = require('../middleware/auth');
|
||||
const Message = require('../db/models/Message');
|
||||
|
||||
const TempEmail = require("../db/models/TempEmail");
|
||||
router.use(authenticateToken);
|
||||
|
||||
/**
|
||||
|
||||
51
src/utils/logger.js
Normal file
51
src/utils/logger.js
Normal file
@ -0,0 +1,51 @@
|
||||
class Logger {
|
||||
constructor() {
|
||||
this.levels = {
|
||||
INFO: "\x1b[36m", // Cyan
|
||||
WARNING: "\x1b[33m", // Yellow
|
||||
ERROR: "\x1b[31m", // Red
|
||||
CRITICAL: "\x1b[31m\x1b[1m", // Bold Red
|
||||
DEBUG: "\x1b[32m", // Green
|
||||
RESET: "\x1b[0m", // Reset color
|
||||
};
|
||||
}
|
||||
|
||||
_getTimestamp() {
|
||||
const now = new Date();
|
||||
return now.toISOString().replace(/T/, " ").replace(/\..+/, "");
|
||||
}
|
||||
|
||||
_log(level, message) {
|
||||
const timestamp = this._getTimestamp();
|
||||
const color = this.levels[level] || "";
|
||||
console.log(
|
||||
`${color}[${timestamp}] [${level}] ${message}${this.levels.RESET}`
|
||||
);
|
||||
}
|
||||
|
||||
info(message) {
|
||||
this._log("INFO", message);
|
||||
}
|
||||
|
||||
warning(message) {
|
||||
this._log("WARNING", message);
|
||||
}
|
||||
|
||||
error(message) {
|
||||
this._log("ERROR", message);
|
||||
}
|
||||
|
||||
critical(message) {
|
||||
this._log("CRITICAL", message);
|
||||
}
|
||||
|
||||
debug(message) {
|
||||
this._log("DEBUG", message);
|
||||
}
|
||||
}
|
||||
|
||||
// Usage
|
||||
// const log = new Logger();
|
||||
// log.info("This is an info message");
|
||||
|
||||
module.exports = Logger;
|
||||
Loading…
x
Reference in New Issue
Block a user