Compare commits

15 Commits
v1.0.0 ... main

Author SHA1 Message Date
a0a903009d Feat: Auto-trim whitespace from input fields on blur 2025-12-27 20:40:14 +11:00
158d774731 Update feature screenshot 2025-12-27 20:28:21 +11:00
51c2d4378b Feat: Add Mail Assure to quick presets 2025-12-27 20:20:17 +11:00
592f82d73e Docs: Complete README overhaul with real screenshots 2025-12-27 20:15:26 +11:00
128a5d16b1 Fix: Remove duplicate closing braces causing JS error 2025-12-27 19:35:13 +11:00
fafab6895b Docs: Overhaul README with new screenshots and deployment info 2025-12-27 19:27:47 +11:00
719096be79 Fix: Improve sync script mechanism and pm2 path 2025-12-27 19:01:50 +11:00
d6cf8f6603 Feat: Add git commit info badge 2025-12-27 17:44:39 +11:00
8dcbacf0ed Fix: Add npm install to setup script 2025-12-27 17:40:46 +11:00
3801c87230 Add Cloudflared installation steps 2025-12-27 17:20:15 +11:00
60f922b2a9 Update deployment template with automated instructions 2025-12-27 17:16:17 +11:00
5ee7a469d9 Resolve merge conflict in .gitignore 2025-12-27 17:13:52 +11:00
7f204426ed Add deployment scripts and config 2025-12-27 17:11:42 +11:00
02222026ef Correct description punctuation in README
Fix typo in application description.
2025-12-21 15:06:21 +11:00
Danijel Micic
65bc45f935 docs: Add release notes and update gitignore
- Add RELEASE-NOTES.md
- Ignore zip files to prevent committing large artifacts
2025-12-15 22:01:26 +11:00
17 changed files with 967 additions and 364 deletions

4
.gitignore vendored
View File

@@ -3,3 +3,7 @@ dist
.DS_Store
*.log
.env
deploy-secrets.json
config/secrets.env
scripts/auth.json
*.zip

View File

@@ -0,0 +1,77 @@
# 🚀 Proxmox Deployment Automation (TurnKey Node.js)
**Use this guide to deploy your project to a TurnKey Linux LXC Container.**
This project uses an **automated deployment system** that handles:
- Initial server setup (Dependencies, Nginx, PM2, Cron).
- Automatic updates via Git (Every 5 minutes).
- Seamess updates using PM2.
---
## 📋 Prerequisites
1. **Server**: A Proxmox TurnKey Node.js Container.
2. **Access**: Root SSH password for the container.
3. **Local Files**: Ensure you have `deploy-secrets.json` created (see below).
---
## 🛠️ Step 1: Configure Secrets
Create a file named `deploy-secrets.json` in the project root. **This file is gitignored** and safe to store locally.
```json
{
"host": "172.16.69.217",
"username": "root",
"password": "YOUR_SSH_PASSWORD",
"gitUser": "YOUR_GITHUB_EMAIL",
"gitToken": "YOUR_GITHUB_TOKEN",
"repoUrl": "https://github.com/YOUR_ORG/YOUR_REPO.git"
}
```
---
## 🚀 Step 2: Run Deployment
Open PowerShell in the project root and run:
```powershell
./deploy-to-proxmox.ps1
```
**That's it!** The script will:
1. Connect to your server.
2. Clone the repository using your token.
3. Install all dependencies (Git, Nginx, PM2).
4. Configure Nginx as a reverse proxy (Port 80 -> 4001).
5. Set up a Cron job to auto-sync changes every 5 minutes.
---
## 🔄 How Updates Work
The server runs a cron job (`scripts/sync-and-restart.sh`) every 5 minutes that:
1. Checks GitHub for changes.
2. If changes are found:
- Pulls the new code.
- Installs dependencies (if `package.json` changed).
- Restarts the application via PM2.
To update your live site, simply **Push to GitHub** and wait ~5 minutes.
---
## <20> Troubleshooting
**View Logs:**
```bash
ssh root@<SERVER_IP> "cat /var/log/smtp-tester-sync.log"
```
**Manual Update:**
```bash
ssh root@<SERVER_IP> "/var/www/Advanced-Smtp-Tester/scripts/sync-and-restart.sh"
```

227
README.md
View File

@@ -1,124 +1,175 @@
# Advanced SMTP Tester
# 📧 Advanced SMTP Tester
A powerful desktop application for testing SMTP configurations with support for multiple providers, dark mode, test history, and enhanced error messages.
![Banner](docs/readme_banner.png)
## Features
**A professional, feature-rich SMTP testing utility for developers and system administrators.**
### 🎨 User Interface
- **Dark/Light Mode** - Toggle between themes with persistence
- **Configuration Presets** - Quick-load for Office 365, Gmail, SendGrid, Mailgun, Amazon SES
- **Test History** - Last 50 tests with click-to-load
- **Enhanced Errors** - Helpful troubleshooting tips for common issues
Test SMTP configurations, troubleshoot connection issues, and validate email delivery with an elegant, intuitive interface.
### 🖥️ Desktop Application
- **Native Windows App** - Runs in its own window (no browser needed)
- **System Tray** - Minimize to tray, quick access
- **Menu Bar** - Full application menu
- **Auto-Start Server** - Express server starts automatically
<div align="center">
### 📧 SMTP Testing
- **Multiple Encryption** - STARTTLS, SSL/TLS, Unencrypted
- **Auto-Discovery** - Test multiple port/encryption combinations
- **Beautiful Emails** - Professional HTML test emails
- **Detailed Results** - Full response logs and error messages
[![Live Demo](https://img.shields.io/badge/🌐_Live_Demo-Try_Now-success?style=for-the-badge)](https://advanced-smtp-tester.beyondcloud.technology/)
[![GitHub](https://img.shields.io/badge/GitHub-Repository-blue?style=for-the-badge&logo=github)](https://github.com/DeNNiiInc/Advanced-Smtp-Tester)
[![License](https://img.shields.io/badge/License-ISC-yellow?style=for-the-badge)](LICENSE)
## Installation
</div>
### Desktop App (Windows)
1. Download the latest release from [Releases](https://github.com/DeNNiiInc/Advanced-Smtp-Tester/releases)
2. Extract the ZIP file
3. Run `Advanced-SMTP-Tester.exe`
---
## 🌐 Live Demo
**Try it now:** [https://advanced-smtp-tester.beyondcloud.technology/](https://advanced-smtp-tester.beyondcloud.technology/)
---
## 📸 Screenshots
### Desktop View (1920x1080)
![Desktop Interface](docs/screenshot_desktop.png)
### Mobile View
![Mobile Interface](docs/screenshot_mobile.png)
---
## ✨ Key Features
### 🎨 **Premium User Experience**
- **Dark/Light Mode** - Seamless theme switching with persistence
- **Glassmorphism Design** - Modern, polished interface with smooth animations
- **Fully Responsive** - Perfect experience on desktop, tablet, and mobile devices
- **Git Version Badge** - Always know what version is deployed (bottom-right corner)
### ⚡ **Powerful Testing Capabilities**
- **Quick Presets** - Pre-configured settings for popular providers:
- Microsoft Office 365
- Google Gmail
- SendGrid
- Mailgun
- Amazon SES
- **Auto-Discovery** - Automatically test multiple port/encryption combinations:
- Ports: 25, 465, 587, 2525
- Encryption: SSL/TLS, STARTTLS, Unencrypted
- **Enhanced Error Handling** - Intelligent error analysis with actionable troubleshooting tips
### 📊 **History & Insights**
- **Local Test History** - Automatically saves recent tests in browser storage
- **Detailed Logs** - View complete SMTP transaction logs and server responses
- **Click-to-Reload** - Quickly retest previous configurations
### 🔒 **Security & Privacy**
- **No Server Storage** - Credentials are processed in-memory only
- **Browser-Only History** - Test history stored locally (IndexedDB)
- **Clear Warning** - Password inclusion in test emails is clearly indicated
---
## 🚀 Installation Options
### Option 1: Use the Live Demo ✨ **Recommended**
No installation needed! Just visit:
**[https://advanced-smtp-tester.beyondcloud.technology/](https://advanced-smtp-tester.beyondcloud.technology/)**
### Option 2: Run Locally (Node.js)
### Web Version
```bash
# Clone the repository
git clone https://github.com/DeNNiiInc/Advanced-Smtp-Tester.git
cd Advanced-Smtp-Tester
# Install dependencies
npm install
# Start the server
npm start
```
Open `http://localhost:3000` in your browser.
### Electron Development
# Access at http://localhost:3000
```
### Option 3: Desktop App (Electron)
```bash
npm install
# Development mode
npm run electron
```
## Building from Source
### Web Version
```bash
npm install
npm start
```
### Desktop App
```bash
npm install
# Build Windows installer
npm run build
```
Or use electron-packager:
```bash
npx electron-packager . "Advanced-SMTP-Tester" --platform=win32 --arch=x64 --out=dist --overwrite
```
### Option 4: Automated Proxmox Deployment
## Usage
For automated deployment to **TurnKey Linux Node.js** containers:
1. Create `deploy-secrets.json` (see `PROXMOX_DEPLOY_TEMPLATE.md`)
2. Run: `./deploy-to-proxmox.ps1`
Features automatic:
- Dependency installation (Git, Nginx, PM2, Cloudflared)
- Nginx reverse proxy configuration
- Auto-updates every 5 minutes via cron
📖 **[Full Deployment Guide](PROXMOX_DEPLOY_TEMPLATE.md)**
---
## 💡 Usage
### Quick Start
1. Select a preset (e.g., "Microsoft Office 365")
2. Enter your credentials
3. Enter recipient email
4. Click "Test Configuration & Send Email"
1. Visit [https://advanced-smtp-tester.beyondcloud.technology/](https://advanced-smtp-tester.beyondcloud.technology/)
2. Select a preset (e.g., "Microsoft Office 365")
3. Enter your credentials
4. Enter recipient email address
5. Click **"Test Configuration & Send Email"**
### Auto-Discovery Mode
Click **"Auto Discovery Test"** to automatically test all common port and encryption combinations. Successful configurations will send separate test emails.
### Configuration Presets
- **Office 365**: `smtp.office365.com:587` (STARTTLS)
- **Gmail**: `smtp.gmail.com:587` (STARTTLS)
- **SendGrid**: `smtp.sendgrid.net:587` (STARTTLS)
- **Mailgun**: `smtp.mailgun.org:587` (STARTTLS)
- **Amazon SES**: `email-smtp.us-east-1.amazonaws.com:587` (STARTTLS)
### Auto-Discovery
Click "Auto Discovery Test" to automatically test multiple port/encryption combinations.
| Provider | Host | Port | Encryption |
|----------|------|------|------------|
| **Office 365** | smtp.office365.com | 587 | STARTTLS |
| **Gmail** | smtp.gmail.com | 587 | STARTTLS |
| **SendGrid** | smtp.sendgrid.net | 587 | STARTTLS |
| **Mailgun** | smtp.mailgun.org | 587 | STARTTLS |
| **Amazon SES** | email-smtp.us-east-1.amazonaws.com | 587 | STARTTLS |
| **Mail Assure** | smtpout.mtaroutes.com | 587 | STARTTLS |
## Development
---
### Project Structure
```
Advanced-Smtp-Tester/
├── electron-main.js # Electron entry point
├── server.js # Express server
├── index.html # Main UI
├── public/
│ ├── db.js # IndexedDB wrapper
│ ├── script.js # Frontend logic
│ ├── styles.css # Styling
│ └── Logo.png # App icon
└── .github/
└── workflows/
└── build-desktop.yml # Automated builds
```
### Scripts
- `npm start` - Start web server
- `npm run electron` - Run desktop app
- `npm run build` - Build Windows installer
- `npm run build:dir` - Build unpacked directory
## Technologies
## 🛠️ Technology Stack
- **Backend**: Node.js, Express, Nodemailer
- **Frontend**: Vanilla JavaScript, IndexedDB
- **Desktop**: Electron
- **Build**: electron-builder, electron-packager
- **Deployment**: PM2, Nginx, Git Auto-Sync
- **Design**: Glassmorphism, CSS Variables, Responsive Grid
## License
---
ISC
## 🤝 Contributing
## Author
Contributions are welcome! Please feel free to submit a Pull Request.
Beyond Cloud Technology
1. Fork the repository
2. Create your feature branch (`git checkout -b feature/AmazingFeature`)
3. Commit your changes (`git commit -m 'Add AmazingFeature'`)
4. Push to branch (`git push origin feature/AmazingFeature`)
5. Open a Pull Request
## Links
---
- [GitHub Repository](https://github.com/DeNNiiInc/Advanced-Smtp-Tester)
- [YouTube Channel](https://www.youtube.com/@beyondcloudtechnology)
## 📄 License
This project is licensed under the ISC License.
---
<div align="center">
**Built with ❤️ by Beyond Cloud Technology**
[YouTube](https://www.youtube.com/@beyondcloudtechnology) • [Website](https://beyondcloud.technology) • [GitHub](https://github.com/DeNNiiInc/Advanced-Smtp-Tester)
</div>

44
RELEASE-NOTES.md Normal file
View File

@@ -0,0 +1,44 @@
# Creating GitHub Release
The v1.0.0 tag has been pushed to GitHub. The GitHub Actions workflow will automatically:
1. Build the Windows executable
2. Create a release
3. Upload the built files
## What Happened
**Created ZIP:** `Advanced-SMTP-Tester-v1.0.0-Windows.zip` (137MB)
**Created Tag:** `v1.0.0`
**Pushed Tag:** Tag is now on GitHub
## GitHub Actions Status
The workflow `.github/workflows/build-desktop.yml` will:
- Detect the new tag `v1.0.0`
- Build the Windows app
- Create a GitHub Release
- Upload the installer/portable files
## Check Release Status
Visit: https://github.com/DeNNiiInc/Advanced-Smtp-Tester/releases
The release should appear within a few minutes as GitHub Actions completes the build.
## Manual Upload (If Needed)
If the automated release doesn't work, you can manually create a release:
1. Go to: https://github.com/DeNNiiInc/Advanced-Smtp-Tester/releases/new
2. Select tag: `v1.0.0`
3. Title: `Advanced SMTP Tester v1.0.0`
4. Upload: `Advanced-SMTP-Tester-v1.0.0-Windows.zip`
5. Click "Publish release"
## Local ZIP File
The packaged app is ready at:
`Advanced-SMTP-Tester-v1.0.0-Windows.zip` (137MB)
You can manually upload this to GitHub Releases if needed.

View File

@@ -0,0 +1,25 @@
server {
listen 80;
server_name _;
root /var/www/Advanced-Smtp-Tester;
index index.html;
# Serve static frontend files
location / {
try_files $uri $uri/ =404;
}
# Proxy API requests to Node.js app
location /api {
proxy_pass http://localhost:4001;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection 'upgrade';
proxy_set_header Host $host;
proxy_cache_bypass $http_upgrade;
}
# Increase body size for larger payloads if needed
client_max_body_size 10M;
}

75
deploy-to-proxmox.ps1 Normal file
View File

@@ -0,0 +1,75 @@
# deploy-to-proxmox.ps1
# 1. Read Configuration
if (-not (Test-Path "deploy-secrets.json")) {
Write-Error "Could not find deploy-secrets.json. Please create it first."
exit 1
}
$Config = Get-Content "deploy-secrets.json" | ConvertFrom-Json
$HostName = $Config.host
$User = $Config.username
$Password = $Config.password
$GitUser = $Config.gitUser
$GitToken = $Config.gitToken
$RepoUrl = $Config.repoUrl
# Construct Authenticated Repo URL
# Extract the domain and path from RepoUrl (remove https://)
$RepoPath = $RepoUrl -replace "https://", ""
# Use Token as username (GitHub supports this) to avoid issues with @ in email usernames
$AuthRepoUrl = "https://${GitToken}@${RepoPath}"
$AppName = "Advanced-Smtp-Tester"
$RemoteDir = "/var/www/$AppName"
Write-Host "🚀 Starting Deployment to $HostName..." -ForegroundColor Cyan
# 2. Define Remote Commands
# We use a Here-String for the remote script
$RemoteScript = @"
set -e
echo "🔹 [Remote] Checking prerequisites..."
if ! command -v git &> /dev/null; then
echo "📦 [Remote] Installing Git..."
apt-get update && apt-get install -y git
fi
echo "🔹 [Remote] Preparing directory $RemoteDir..."
mkdir -p "$RemoteDir"
# Check if .git exists, if not clone, else pull
if [ ! -d "$RemoteDir/.git" ]; then
echo " [Remote] Cloning repository..."
# Clone with token for future auth-less pulls
git clone "$AuthRepoUrl" "$RemoteDir"
else
echo " [Remote] Repository exists. Pulling latest..."
cd "$RemoteDir"
# Update remote url to ensure token is correct (in case it changed)
git remote set-url origin "$AuthRepoUrl"
git pull
fi
# Run the setup script from the repo
echo " [Remote] Running setup script..."
cd "$RemoteDir"
chmod +x scripts/setup-server.sh
./scripts/setup-server.sh
echo " [Remote] Deployment Logic Finished."
"@ -replace "`r`n", "`n"
# 3. Execute via Plink (Putty Link) or SSH
# We'll use plink if available because it handles password via argument easier than OpenSSH on Windows
# If plink is not found, we warn the user.
if (Get-Command plink -ErrorAction SilentlyContinue) {
echo y | plink -ssh -l $User -pw $Password $HostName $RemoteScript
}
else {
Write-Warning "Plink not found. Trying standard ssh (you may be prompted for password)."
ssh "$User@$HostName" $RemoteScript
}
Write-Host "✨ Deployment script completed." -ForegroundColor Green

BIN
docs/feature_git_badge.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 144 KiB

BIN
docs/screenshot_desktop.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 464 KiB

BIN
docs/screenshot_mobile.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 99 KiB

14
ecosystem.config.js Normal file
View File

@@ -0,0 +1,14 @@
module.exports = {
apps: [{
name: "Advanced-Smtp-Tester",
script: "server.js",
instances: 1,
autorestart: true,
watch: false,
max_memory_restart: '1G',
env: {
NODE_ENV: "production",
PORT: 4001
}
}]
};

View File

@@ -1,10 +1,12 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta name="description" content="Advanced SMTP Tester - Test your SMTP configurations securely and easily." />
<meta
name="description"
content="Advanced SMTP Tester - Test your SMTP configurations securely and easily."
/>
<title>Advanced SMTP Tester</title>
<link rel="icon" type="image/png" href="public/Logo.png" />
<link rel="stylesheet" href="public/styles.css" />
@@ -14,7 +16,8 @@
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
<link
href="https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700;800&family=JetBrains+Mono:wght@400;500&display=swap"
rel="stylesheet" />
rel="stylesheet"
/>
</head>
<body>
@@ -36,11 +39,16 @@
<p class="subtitle">
Advanced SMTP Configuration & Delivery Testing Utility
</p>
<a href="https://www.youtube.com/@beyondcloudtechnology" target="_blank" rel="noopener noreferrer"
class="youtube-link">
<a
href="https://www.youtube.com/@beyondcloudtechnology"
target="_blank"
rel="noopener noreferrer"
class="youtube-link"
>
<svg class="youtube-icon" viewBox="0 0 24 24" fill="currentColor">
<path
d="M23.498 6.186a3.016 3.016 0 0 0-2.122-2.136C19.505 3.545 12 3.545 12 3.545s-7.505 0-9.377.505A3.017 3.017 0 0 0 .502 6.186C0 8.07 0 12 0 12s0 3.93.502 5.814a3.016 3.016 0 0 0 2.122 2.136c1.871.505 9.376.505 9.376.505s7.505 0 9.377-.505a3.015 3.015 0 0 0 2.122-2.136C24 15.93 24 12 24 12s0-3.93-.502-5.814zM9.545 15.568V8.432L15.818 12l-6.273 3.568z" />
d="M23.498 6.186a3.016 3.016 0 0 0-2.122-2.136C19.505 3.545 12 3.545 12 3.545s-7.505 0-9.377.505A3.017 3.017 0 0 0 .502 6.186C0 8.07 0 12 0 12s0 3.93.502 5.814a3.016 3.016 0 0 0 2.122 2.136c1.871.505 9.376.505 9.376.505s7.505 0 9.377-.505a3.015 3.015 0 0 0 2.122-2.136C24 15.93 24 12 24 12s0-3.93-.502-5.814zM9.545 15.568V8.432L15.818 12l-6.273 3.568z"
/>
</svg>
Watch on YouTube @beyondcloudtechnology
</a>
@@ -66,6 +74,7 @@
<option value="sendgrid">SendGrid</option>
<option value="mailgun">Mailgun</option>
<option value="amazonses">Amazon SES</option>
<option value="mailassure">Mail Assure</option>
<option value="custom">💾 Last Used Configuration</option>
</select>
</div>
@@ -74,11 +83,23 @@
<!-- Server Details -->
<div class="form-group">
<label for="host">SMTP Host</label>
<input type="text" id="host" name="host" placeholder="smtp.example.com" required />
<input
type="text"
id="host"
name="host"
placeholder="smtp.example.com"
required
/>
</div>
<div class="form-group">
<label for="port">Port</label>
<input type="number" id="port" name="port" placeholder="587" required />
<input
type="number"
id="port"
name="port"
placeholder="587"
required
/>
</div>
<div class="form-group">
<label for="secure">Encryption</label>
@@ -92,13 +113,29 @@
<!-- Auth Details -->
<div class="form-group">
<label for="user">Username / Email</label>
<input type="text" id="user" name="user" placeholder="user@example.com" required />
<input
type="text"
id="user"
name="user"
placeholder="user@example.com"
required
/>
</div>
<div class="form-group">
<label for="pass">Password</label>
<div class="password-input-wrapper">
<input type="password" id="pass" name="pass" placeholder="••••••••" required />
<button type="button" class="toggle-password" onclick="togglePassword()">
<input
type="password"
id="pass"
name="pass"
placeholder="••••••••"
required
/>
<button
type="button"
class="toggle-password"
onclick="togglePassword()"
>
👁️
</button>
</div>
@@ -107,11 +144,22 @@
<!-- Email Details -->
<div class="form-group">
<label for="from">From Address (Optional)</label>
<input type="email" id="from" name="from" placeholder="Defaults to Username" />
<input
type="email"
id="from"
name="from"
placeholder="Defaults to Username"
/>
</div>
<div class="form-group">
<label for="to">To Address</label>
<input type="email" id="to" name="to" placeholder="recipient@example.com" required />
<input
type="email"
id="to"
name="to"
placeholder="recipient@example.com"
required
/>
</div>
</div>
@@ -147,10 +195,14 @@
<div class="history-panel" id="historyPanel">
<div class="history-header">
<h3>📋 Test History</h3>
<button class="clear-history-btn" id="clearHistoryBtn">Clear All</button>
<button class="clear-history-btn" id="clearHistoryBtn">
Clear All
</button>
</div>
<div id="historyList">
<div class="history-empty">No test history yet. Run a test to see it here!</div>
<div class="history-empty">
No test history yet. Run a test to see it here!
</div>
</div>
</div>
</div>
@@ -159,19 +211,30 @@
<!-- Footer -->
<footer class="footer">
<p>&copy; 2025 Beyond Cloud Technology. All rights reserved.</p>
<a href="https://github.com/DeNNiiInc/Advanced-Smtp-Tester" target="_blank" rel="noopener noreferrer"
class="github-link">
<a
href="https://github.com/DeNNiiInc/Advanced-Smtp-Tester"
target="_blank"
rel="noopener noreferrer"
class="github-link"
>
<svg class="github-icon" viewBox="0 0 24 24" fill="currentColor">
<path
d="M12 0c-6.626 0-12 5.373-12 12 0 5.302 3.438 9.8 8.207 11.387.599.111.793-.261.793-.577v-2.234c-3.338.726-4.033-1.416-4.033-1.416-.546-1.387-1.333-1.756-1.333-1.756-1.089-.745.083-.729.083-.729 1.205.084 1.839 1.237 1.839 1.237 1.07 1.834 2.807 1.304 3.492.997.107-.775.418-1.305.762-1.604-2.665-.305-5.467-1.334-5.467-5.931 0-1.311.469-2.381 1.236-3.221-.124-.303-.535-1.524.117-3.176 0 0 1.008-.322 3.301 1.23.957-.266 1.983-.399 3.003-.404 1.02.005 2.047.138 3.006.404 2.291-1.552 3.297-1.23 3.297-1.23.653 1.653.242 2.874.118 3.176.77.84 1.235 1.911 1.235 3.221 0 4.609-2.807 5.624-5.479 5.921.43.372.823 1.102.823 2.222v3.293c0 .319.192.694.801.576 4.765-1.589 8.199-6.086 8.199-11.386 0-6.627-5.373-12-12-12z" />
d="M12 0c-6.626 0-12 5.373-12 12 0 5.302 3.438 9.8 8.207 11.387.599.111.793-.261.793-.577v-2.234c-3.338.726-4.033-1.416-4.033-1.416-.546-1.387-1.333-1.756-1.333-1.756-1.089-.745.083-.729.083-.729 1.205.084 1.839 1.237 1.839 1.237 1.07 1.834 2.807 1.304 3.492.997.107-.775.418-1.305.762-1.604-2.665-.305-5.467-1.334-5.467-5.931 0-1.311.469-2.381 1.236-3.221-.124-.303-.535-1.524.117-3.176 0 0 1.008-.322 3.301 1.23.957-.266 1.983-.399 3.003-.404 1.02.005 2.047.138 3.006.404 2.291-1.552 3.297-1.23 3.297-1.23.653 1.653.242 2.874.118 3.176.77.84 1.235 1.911 1.235 3.221 0 4.609-2.807 5.624-5.479 5.921.43.372.823 1.102.823 2.222v3.293c0 .319.192.694.801.576 4.765-1.589 8.199-6.086 8.199-11.386 0-6.627-5.373-12-12-12z"
/>
</svg>
View on GitHub
</a>
</footer>
</div>
<!-- Version Badge -->
<div id="versionBadge" class="version-badge hidden">
<span class="commit-hash"></span>
<span class="commit-sep"></span>
<span class="commit-date"></span>
</div>
<script src="public/db.js"></script>
<script src="public/script.js"></script>
</body>
</html>

View File

@@ -34,6 +34,12 @@ const PRESETS = {
port: '587',
secure: 'false',
name: 'Amazon SES'
},
mailassure: {
host: 'smtpout.mtaroutes.com',
port: '587',
secure: 'false',
name: 'Mail Assure'
}
};
@@ -233,6 +239,19 @@ function displayErrorWithTips(errorMessage, container) {
container.innerHTML = errorMessage + tipsHTML;
}
// ===================================
// AUTO-TRIM INPUT FIELDS
// ===================================
// Automatically trim whitespace from all text inputs on blur
document.addEventListener('DOMContentLoaded', () => {
const textInputs = document.querySelectorAll('input[type="text"], input[type="email"], input[type="password"]');
textInputs.forEach(input => {
input.addEventListener('blur', function() {
this.value = this.value.trim();
});
});
});
// ===================================
// PASSWORD TOGGLE
// ===================================
@@ -469,6 +488,50 @@ document.getElementById('autoTestBtn').addEventListener('click', async function
}
});
// ===================================
// VERSION INFO
// ===================================
async function loadVersionInfo() {
try {
const response = await fetch('/api/version');
const data = await response.json();
if (data.hash && data.hash !== 'Unknown') {
const badge = document.getElementById('versionBadge');
const hashSpan = badge.querySelector('.commit-hash');
const dateSpan = badge.querySelector('.commit-date');
hashSpan.textContent = data.hash; // e.g., 9f3a914
dateSpan.textContent = timeAgo(new Date(data.date)); // e.g., 3d ago
badge.classList.remove('hidden');
}
} catch (e) {
console.warn('Failed to load version info:', e);
}
}
function timeAgo(date) {
const seconds = Math.floor((new Date() - date) / 1000);
let interval = seconds / 31536000;
if (interval > 1) return Math.floor(interval) + "y ago";
interval = seconds / 2592000;
if (interval > 1) return Math.floor(interval) + "mo ago";
interval = seconds / 86400;
if (interval > 1) return Math.floor(interval) + "d ago";
interval = seconds / 3600;
if (interval > 1) return Math.floor(interval) + "h ago";
interval = seconds / 60;
if (interval > 1) return Math.floor(interval) + "m ago";
return Math.floor(seconds) + "s ago";
}
// ===================================
// INITIALIZATION
// ===================================
@@ -482,6 +545,9 @@ window.addEventListener('DOMContentLoaded', async () => {
// Load history
await loadHistory();
// Load Version Info
await loadVersionInfo();
// Load last used configuration
const settings = await window.smtpDB.getSettings();
if (settings) {

View File

@@ -77,12 +77,12 @@ body {
left: 0;
width: 100%;
height: 100%;
background: radial-gradient(circle at 15% 50%,
background: radial-gradient(
circle at 15% 50%,
var(--gradient-bg-1) 0%,
transparent 25%),
radial-gradient(circle at 85% 30%,
var(--gradient-bg-2) 0%,
transparent 25%);
transparent 25%
),
radial-gradient(circle at 85% 30%, var(--gradient-bg-2) 0%, transparent 25%);
z-index: -1;
pointer-events: none;
transition: background 0.3s ease;
@@ -276,9 +276,11 @@ select:focus {
}
.btn-primary {
background: linear-gradient(135deg,
background: linear-gradient(
135deg,
var(--accent-primary),
var(--accent-hover));
var(--accent-hover)
);
color: white;
box-shadow: 0 4px 12px var(--accent-glow);
}
@@ -663,3 +665,51 @@ select:focus {
.log-output::-webkit-scrollbar-thumb:hover {
background: var(--text-secondary);
}
/* Version Badge */
.version-badge {
position: fixed;
bottom: 1.5rem;
right: 1.5rem;
background: rgba(15, 23, 42, 0.8);
backdrop-filter: blur(8px);
border: 1px solid var(--border-color);
border-radius: 20px;
padding: 0.4rem 0.8rem;
display: flex;
align-items: center;
gap: 0.5rem;
font-size: 0.85rem;
z-index: 1000;
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.2);
transition: all 0.3s ease;
}
[data-theme="light"] .version-badge {
background: rgba(255, 255, 255, 0.8);
border-color: rgba(0, 0, 0, 0.1);
}
.version-badge:hover {
transform: translateY(-2px);
box-shadow: 0 6px 16px rgba(0, 0, 0, 0.3);
}
.commit-hash {
font-family: "JetBrains Mono", monospace;
color: #a78bfa; /* Slightly purple to match example */
font-weight: 600;
}
[data-theme="light"] .commit-hash {
color: #7c3aed;
}
.commit-sep {
color: var(--text-secondary);
font-size: 0.6rem;
}
.commit-date {
color: var(--text-secondary);
}

62
scripts/setup-server.sh Normal file
View File

@@ -0,0 +1,62 @@
#!/bin/bash
# Exit on error
set -e
APP_NAME="Advanced-Smtp-Tester"
APP_DIR="/var/www/$APP_NAME"
echo "🚀 Starting Server Setup for $APP_NAME..."
# 1. Install Dependencies
echo "📦 Installing system dependencies..."
apt-get update
# Note: nodejs and npm should be present in the TurnKey Node.js template
apt-get install -y git nginx curl build-essential
# Install PM2 globally if not exists
if ! command -v pm2 &> /dev/null; then
echo "📦 Installing PM2..."
npm install -g pm2
fi
# 1.1 Install Cloudflared (Optional but recommended)
echo "☁️ Installing Cloudflared..."
mkdir -p --mode=0755 /usr/share/keyrings
curl -fsSL https://pkg.cloudflare.com/cloudflare-public-v2.gpg | tee /usr/share/keyrings/cloudflare-public-v2.gpg >/dev/null
echo 'deb [signed-by=/usr/share/keyrings/cloudflare-public-v2.gpg] https://pkg.cloudflare.com/cloudflared any main' | tee /etc/apt/sources.list.d/cloudflared.list
apt-get update && apt-get install -y cloudflared
# 1.2 Install App Dependencies
echo "📦 Installing Application Dependencies..."
cd "$APP_DIR"
npm install
# 2. Setup Nginx
echo "⚙️ Configuring Nginx..."
cp "$APP_DIR/config/nginx.conf.template" "/etc/nginx/sites-available/$APP_NAME"
# Remove default site if exists
rm -f /etc/nginx/sites-enabled/default
rm -f /etc/nginx/sites-enabled/nodejs # Common in TurnKey
# Enable site
ln -sf "/etc/nginx/sites-available/$APP_NAME" "/etc/nginx/sites-enabled/"
# Test and Reload
nginx -t && systemctl reload nginx
# 3. Setup PM2
echo "⚙️ Configuring PM2..."
cd "$APP_DIR"
pm2 start ecosystem.config.js
pm2 save
pm2 startup systemd -u root --hp /root
# 4. Setup Cron Job for Auto-Sync (Every 5 minutes)
echo "⏰ Setting up Auto-Sync Cron Job..."
SCRIPT_PATH="$APP_DIR/scripts/sync-and-restart.sh"
chmod +x "$SCRIPT_PATH"
# Add to crontab if not already there
(crontab -l 2>/dev/null; echo "*/5 * * * * $SCRIPT_PATH") | awk '!x[$0]++' | crontab -
echo "✅ Setup Complete! Application is running and auto-sync is enabled."
echo "🌐 Access your app at http://<YOUR_SERVER_IP>"

View File

@@ -0,0 +1,52 @@
#!/bin/bash
# Configuration
APP_DIR="/var/www/Advanced-Smtp-Tester"
LOG_FILE="/var/log/smtp-tester-sync.log"
# Add /usr/local/bin to PATH to ensure PM2 is found
export PATH=$PATH:/usr/local/bin
# Navigate to app directory
cd "$APP_DIR" || exit 1
# Log function
log() {
echo "[$(date '+%Y-%m-%d %H:%M:%S')] $1" >> "$LOG_FILE"
}
log "Checking for updates..."
# Fetch latest changes
git fetch origin
# Check if we are behind
LOCAL=$(git rev-parse HEAD)
REMOTE=$(git rev-parse @{u}) # This gets the upstream commit for the current branch
if [ "$LOCAL" != "$REMOTE" ]; then
log "Changes detected. Updating..."
# Force reset to match origin (avoids merge conflicts)
git reset --hard origin/main >> "$LOG_FILE" 2>&1
# Check if package.json changed (compare old local HEAD with new remote HEAD)
# Note: git diff --name-only $LOCAL $REMOTE would compare the old local HEAD with the new remote HEAD
# After git reset --hard, HEAD is already at REMOTE.
# To check if package.json changed *between the old state and the new state*,
# we need to compare the old LOCAL with the new REMOTE.
if git diff --name-only "$LOCAL" "$REMOTE" | grep "package.json"; then
log "package.json changed. Installing dependencies..."
npm install >> "$LOG_FILE" 2>&1
fi
log "Restarting application..."
pm2 restart Advanced-Smtp-Tester >> "$LOG_FILE" 2>&1
log "Update complete."
else
# Uncomment next line for verbose logging of no-changes
# log "No changes detected."
# echo "No changes."
log "No changes found."
fi

View File

@@ -3,10 +3,25 @@ const nodemailer = require("nodemailer");
const bodyParser = require("body-parser");
const cors = require("cors");
const path = require("path");
const { execSync } = require("child_process");
const app = express();
const port = process.env.PORT || 3000;
// Get Git Commit Info
let gitInfo = {
hash: 'Unknown',
date: 'Unknown'
};
try {
const hash = execSync('git log -1 --format="%h"').toString().trim();
const date = execSync('git log -1 --format="%cd"').toString().trim();
gitInfo = { hash, date };
} catch (e) {
console.warn("Could not retrieve git info:", e.message);
}
app.use(cors());
app.use(bodyParser.json());
@@ -18,6 +33,11 @@ app.get('/', (req, res) => {
res.sendFile(path.join(__dirname, 'index.html'));
});
// API Endpoint for Version Info
app.get('/api/version', (req, res) => {
res.json(gitInfo);
});
app.post('/api/test-smtp', async (req, res) => {
const { host, port, secure, user, pass, from, to } = req.body;