Add auto-discovery SMTP testing, unencrypted support, and BCT branding

This commit is contained in:
2025-12-13 12:06:36 +11:00
parent bf66d6915e
commit fcc79e76f0
7 changed files with 862 additions and 20 deletions

BIN
BCT-Base/Logo.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 749 KiB

55
BCT-Base/index.html Normal file
View File

@@ -0,0 +1,55 @@
<!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="Beyond Cloud Technology Project Base">
<title>Beyond Cloud Technology - Project Base</title>
<link rel="icon" type="image/png" href="Logo.png">
<link rel="stylesheet" href="styles.css">
</head>
<body>
<div class="container">
<!-- Header -->
<header class="header">
<div class="header-content">
<h1 class="title">
<img src="Logo.png" alt="BCT Logo" class="title-icon">
Beyond Cloud Technology - Project Title
</h1>
<p class="subtitle">Project Description Goes Here</p>
<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" />
</svg>
Watch on YouTube @beyondcloudtechnology
</a>
</div>
<div class="header-controls">
<!-- Theme toggle or other controls can go here -->
</div>
</header>
<!-- Main Content Area -->
<main class="main-content">
<div class="panel">
<div class="panel-header">
<div class="panel-icon">🚀</div>
<h2 class="panel-title">Project Content</h2>
</div>
<p>This is the base template. Add your project content here.</p>
</div>
</main>
<!-- Footer -->
<footer class="footer">
<p>&copy; 2025 Beyond Cloud Technology. All rights reserved.</p>
</footer>
</div>
</body>
</html>

297
BCT-Base/styles.css Normal file
View File

@@ -0,0 +1,297 @@
/* ===================================
BEYOND CLOUD TECHNOLOGY - BASE DESIGN SYSTEM
=================================== */
/* Import Modern Typography */
@import url('https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700;800&family=JetBrains+Mono:wght@400;500;600&display=swap');
/* ===================================
CSS VARIABLES - DESIGN TOKENS
=================================== */
:root {
/* Dark Theme Colors */
--color-bg-primary: #0a0e1a;
--color-bg-secondary: #131829;
--color-bg-tertiary: #1a2035;
--color-bg-glass: rgba(26, 32, 53, 0.7);
--color-bg-glass-hover: rgba(26, 32, 53, 0.85);
/* Accent Colors */
--color-accent-primary: #6366f1;
--color-accent-secondary: #8b5cf6;
--color-accent-success: #10b981;
--color-accent-warning: #f59e0b;
--color-accent-danger: #ef4444;
--color-accent-info: #3b82f6;
/* Gradients */
--gradient-primary: linear-gradient(135deg, #6366f1 0%, #8b5cf6 100%);
--gradient-success: linear-gradient(135deg, #10b981 0%, #059669 100%);
--gradient-danger: linear-gradient(135deg, #ef4444 0%, #dc2626 100%);
--gradient-warning: linear-gradient(135deg, #f59e0b 0%, #d97706 100%);
/* Text Colors */
--color-text-primary: #f8fafc;
--color-text-secondary: #cbd5e1;
--color-text-tertiary: #94a3b8;
--color-text-muted: #64748b;
/* Border & Shadow */
--color-border: rgba(148, 163, 184, 0.1);
--color-border-hover: rgba(148, 163, 184, 0.2);
--shadow-sm: 0 2px 8px rgba(0, 0, 0, 0.3);
--shadow-md: 0 4px 16px rgba(0, 0, 0, 0.4);
--shadow-lg: 0 8px 32px rgba(0, 0, 0, 0.5);
--shadow-glow: 0 0 20px rgba(99, 102, 241, 0.3);
/* Spacing */
--spacing-xs: 0.5rem;
--spacing-sm: 0.75rem;
--spacing-md: 1rem;
--spacing-lg: 1.5rem;
--spacing-xl: 2rem;
--spacing-2xl: 3rem;
/* Border Radius */
--radius-sm: 0.375rem;
--radius-md: 0.5rem;
--radius-lg: 0.75rem;
--radius-xl: 1rem;
/* Typography */
--font-primary: 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;
--font-mono: 'JetBrains Mono', 'Courier New', monospace;
/* Transitions */
--transition-fast: 150ms cubic-bezier(0.4, 0, 0.2, 1);
--transition-base: 250ms cubic-bezier(0.4, 0, 0.2, 1);
--transition-slow: 350ms cubic-bezier(0.4, 0, 0.2, 1);
}
/* ===================================
GLOBAL RESET & BASE STYLES
=================================== */
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
html {
font-size: 16px;
scroll-behavior: smooth;
}
body {
font-family: var(--font-primary);
background: var(--color-bg-primary);
color: var(--color-text-primary);
line-height: 1.6;
min-height: 100vh;
overflow-x: hidden;
position: relative;
transition: background var(--transition-base), color var(--transition-base);
}
/* Animated Background */
body::before {
content: '';
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
background:
radial-gradient(circle at 20% 30%, rgba(99, 102, 241, 0.1) 0%, transparent 50%),
radial-gradient(circle at 80% 70%, rgba(139, 92, 246, 0.1) 0%, transparent 50%);
pointer-events: none;
z-index: 0;
}
/* ===================================
LAYOUT STRUCTURE
=================================== */
.container {
max-width: 1400px;
margin: 0 auto;
padding: var(--spacing-xl);
position: relative;
z-index: 1;
min-height: 100vh;
display: flex;
flex-direction: column;
}
.main-content {
flex: 1;
}
/* Header */
.header {
text-align: center;
margin-bottom: var(--spacing-lg);
animation: fadeInDown 0.6s ease-out;
position: relative;
display: block;
}
.header-content {
position: relative;
display: flex;
flex-direction: column;
align-items: center;
}
.title {
font-size: 3rem;
font-weight: 700;
background: var(--gradient-primary);
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
background-clip: text;
margin-bottom: var(--spacing-xs);
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
gap: 0;
line-height: 1.2;
}
.title-icon {
width: 2.5rem;
height: 2.5rem;
stroke: url(#gradient);
color: var(--color-accent-primary);
filter: drop-shadow(0 0 10px rgba(99, 102, 241, 0.5));
margin-bottom: var(--spacing-xs);
}
.subtitle {
font-size: 1.125rem;
color: var(--color-text-secondary);
font-weight: 300;
margin-bottom: var(--spacing-sm);
}
/* YouTube Link */
.youtube-link {
display: inline-flex;
align-items: center;
gap: var(--spacing-sm);
padding: var(--spacing-sm) var(--spacing-md);
background: linear-gradient(135deg, #FF0000 0%, #CC0000 100%);
color: white;
text-decoration: none;
border-radius: var(--radius-md);
font-weight: 600;
font-size: 0.875rem;
box-shadow: 0 2px 8px rgba(255, 0, 0, 0.3);
transition: all var(--transition-base);
animation: pulse-glow 2s ease-in-out infinite;
margin-top: var(--spacing-md);
}
.youtube-link:hover {
transform: translateY(-2px) scale(1.03);
box-shadow: 0 4px 15px rgba(255, 0, 0, 0.5);
animation: none;
color: white;
}
.youtube-icon {
width: 1.25rem;
height: 1.25rem;
flex-shrink: 0;
}
@keyframes pulse-glow {
0%,
100% {
box-shadow: 0 2px 8px rgba(255, 0, 0, 0.3);
}
50% {
box-shadow: 0 2px 15px rgba(255, 0, 0, 0.5);
}
}
/* Footer */
.footer {
text-align: center;
margin-top: var(--spacing-2xl);
padding: var(--spacing-xl) 0;
border-top: 1px solid var(--color-border);
color: var(--color-text-muted);
font-size: 0.875rem;
}
/* ===================================
GLASS PANEL COMPONENT
=================================== */
.panel {
background: var(--color-bg-glass);
backdrop-filter: blur(20px);
border: 1px solid var(--color-border);
border-radius: var(--radius-xl);
padding: var(--spacing-xl);
box-shadow: var(--shadow-md);
transition: all var(--transition-base);
}
.panel:hover {
background: var(--color-bg-glass-hover);
border-color: var(--color-border-hover);
box-shadow: var(--shadow-lg);
}
.panel-header {
display: flex;
align-items: center;
gap: var(--spacing-md);
margin-bottom: var(--spacing-lg);
padding-bottom: var(--spacing-md);
border-bottom: 1px solid var(--color-border);
}
.panel-icon {
width: 2.5rem;
height: 2.5rem;
display: flex;
align-items: center;
justify-content: center;
background: var(--gradient-primary);
border-radius: var(--radius-md);
font-size: 1.25rem;
}
.panel-title {
font-size: 1.5rem;
font-weight: 700;
color: var(--color-text-primary);
}
/* Animations */
@keyframes fadeInDown {
from {
opacity: 0;
transform: translateY(-20px);
}
to {
opacity: 1;
transform: translateY(0);
}
}
/* Responsive */
@media (max-width: 640px) {
.container {
padding: var(--spacing-md);
}
.title {
font-size: 2rem;
}
}

View File

@@ -34,6 +34,19 @@
<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"
>
<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"
/>
</svg>
Watch on YouTube @beyondcloudtechnology
</a>
</div>
</header>
@@ -73,6 +86,7 @@
<select id="secure" name="secure">
<option value="false">STARTTLS (587/25)</option>
<option value="true">SSL/TLS (465)</option>
<option value="none">Unencrypted (No TLS)</option>
</select>
</div>
@@ -134,6 +148,10 @@
<span class="btn-text">Test Configuration & Send Email</span>
<div class="loading-spinner hidden"></div>
</button>
<button type="button" class="btn btn-secondary" id="autoTestBtn">
<span class="btn-text">🔍 Auto Discovery Test</span>
<div class="loading-spinner hidden"></div>
</button>
</div>
<!-- Warning for Password Transmission -->

View File

@@ -65,3 +65,96 @@ document.getElementById('smtpForm').addEventListener('submit', async function(e)
btnText.textContent = 'Test Configuration & Send Email';
}
});
// Auto Discovery Test Handler
document.getElementById('autoTestBtn').addEventListener('click', async function() {
const btn = document.getElementById('autoTestBtn');
const spinner = btn.querySelector('.loading-spinner');
const btnText = btn.querySelector('.btn-text');
const resultsDiv = document.getElementById('results');
const statusDiv = document.getElementById('statusMessage');
const logOutput = document.getElementById('logOutput');
// Get form data
const form = document.getElementById('smtpForm');
const formData = new FormData(form);
const data = Object.fromEntries(formData.entries());
// Only need host, user, pass, from, to for auto test
const autoTestData = {
host: data.host,
user: data.user,
pass: data.pass,
from: data.from,
to: data.to
};
// Reset UI
resultsDiv.classList.add('hidden');
statusDiv.className = 'status-message';
statusDiv.textContent = '';
logOutput.textContent = '';
// Set Loading State
btn.disabled = true;
spinner.classList.remove('hidden');
btnText.textContent = 'Testing All Configurations...';
try {
const response = await fetch('/api/auto-test-smtp', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify(autoTestData),
});
const result = await response.json();
// Show Results
resultsDiv.classList.remove('hidden');
if (result.success) {
statusDiv.classList.add('status-success');
statusDiv.textContent = `${result.message}`;
// Format detailed results
let detailedOutput = `Total Tests: ${result.totalTests}\n`;
detailedOutput += `Successful: ${result.successfulConfigs}\n`;
detailedOutput += `Failed: ${result.totalTests - result.successfulConfigs}\n\n`;
detailedOutput += '─'.repeat(50) + '\n\n';
result.results.forEach((test, index) => {
detailedOutput += `Test ${index + 1}: ${test.config}\n`;
detailedOutput += ` Port: ${test.port}\n`;
detailedOutput += ` Encryption: ${test.secure ? 'SSL/TLS' : 'STARTTLS'}\n`;
detailedOutput += ` Status: ${test.status === 'success' ? '✅ SUCCESS' : '❌ FAILED'}\n`;
if (test.status === 'success') {
detailedOutput += ` Email Sent: ${test.messageId}\n`;
} else {
detailedOutput += ` Error: ${test.error}\n`;
}
detailedOutput += '\n';
});
logOutput.textContent = detailedOutput;
} else {
statusDiv.classList.add('status-error');
statusDiv.textContent = '❌ Error: ' + result.message;
logOutput.textContent = result.error || 'Unknown error occurred.';
}
} catch (error) {
resultsDiv.classList.remove('hidden');
statusDiv.classList.add('status-error');
statusDiv.textContent = '❌ Network Error';
logOutput.textContent = error.toString();
} finally {
// Reset Button
btn.disabled = false;
spinner.classList.add('hidden');
btnText.textContent = '🔍 Auto Discovery Test';
}
});

View File

@@ -88,6 +88,7 @@ body {
gap: 1rem;
background: linear-gradient(135deg, #fff 0%, #cbd5e1 100%);
-webkit-background-clip: text;
background-clip: text;
-webkit-text-fill-color: transparent;
}
@@ -104,9 +105,38 @@ body {
font-weight: 400;
}
.youtube-link {
display: inline-flex;
align-items: center;
gap: 0.5rem;
margin-top: 1rem;
padding: 0.6rem 1.2rem;
background: rgba(255, 0, 0, 0.1);
border: 1px solid rgba(255, 0, 0, 0.3);
border-radius: var(--radius-md);
color: #ff6b6b;
text-decoration: none;
font-size: 0.9rem;
font-weight: 500;
transition: all 0.3s ease;
}
.youtube-link:hover {
background: rgba(255, 0, 0, 0.2);
border-color: rgba(255, 0, 0, 0.5);
transform: translateY(-2px);
box-shadow: 0 4px 12px rgba(255, 0, 0, 0.3);
}
.youtube-icon {
width: 20px;
height: 20px;
}
/* Panel */
.panel {
background: var(--bg-glass);
-webkit-backdrop-filter: blur(12px);
backdrop-filter: blur(12px);
border: 1px solid rgba(255, 255, 255, 0.1);
border-radius: var(--radius-lg);
@@ -238,6 +268,28 @@ select:focus {
transform: translateY(0);
}
.btn-secondary {
background: linear-gradient(135deg, #10b981, #059669);
color: white;
box-shadow: 0 4px 12px rgba(16, 185, 129, 0.4);
}
.btn-secondary:hover {
transform: translateY(-2px);
box-shadow: 0 6px 16px rgba(16, 185, 129, 0.5);
}
.btn-secondary:active {
transform: translateY(0);
}
.form-actions {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));
gap: 1rem;
margin-bottom: var(--spacing-md);
}
.btn:disabled {
opacity: 0.7;
cursor: not-allowed;

365
server.js
View File

@@ -29,7 +29,7 @@ app.post('/api/test-smtp', async (req, res) => {
);
// Create Transporter
const transporter = nodemailer.createTransport({
const transporterConfig = {
host: host,
port: parseInt(port),
secure: secure === true || secure === "true", // true for 465, false for other ports
@@ -37,10 +37,16 @@ app.post('/api/test-smtp', async (req, res) => {
user: user,
pass: pass,
},
tls: {
};
// Only add TLS settings if secure is not explicitly "none"
if (secure !== "none") {
transporterConfig.tls = {
rejectUnauthorized: false, // Allow self-signed certs for testing flexibility
},
});
};
}
const transporter = nodemailer.createTransport(transporterConfig);
try {
// 1. Verify Connection
@@ -53,22 +59,128 @@ app.post('/api/test-smtp', async (req, res) => {
to: to,
subject: "SMTP Test - Advanced SMTP Tester",
html: `
<div style="font-family: Arial, sans-serif; padding: 20px; background-color: #f4f4f4; border-radius: 10px;">
<h2 style="color: #333;">SMTP Test Successful</h2>
<p>This email confirms that your SMTP settings are correct.</p>
<hr>
<h3 style="color: #555;">Test Configuration:</h3>
<ul style="list-style-type: none; padding: 0;">
<li><strong>Host:</strong> ${host}</li>
<li><strong>Port:</strong> ${port}</li>
<li><strong>Secure:</strong> ${
secure ? "Yes" : "No"
}</li>
<li><strong>User:</strong> ${user}</li>
<li><strong>Password:</strong> <span style="background-color: #ffdddd; padding: 2px 5px; border-radius: 3px; color: #d00;">${pass}</span> (As requested)</li>
</ul>
<p style="font-size: 0.8em; color: #888;">Generated by Advanced SMTP Tester</p>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
</head>
<body style="margin: 0; padding: 0; font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Inter', 'Helvetica Neue', Arial, sans-serif; background-color: #f5f7fa;">
<table width="100%" cellpadding="0" cellspacing="0" style="background-color: #f5f7fa; padding: 40px 20px;">
<tr>
<td align="center">
<table width="600" cellpadding="0" cellspacing="0" style="background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); border-radius: 16px; box-shadow: 0 10px 30px rgba(0,0,0,0.15); overflow: hidden;">
<!-- Header -->
<tr>
<td style="padding: 40px 40px 30px; text-align: center;">
<h1 style="margin: 0; color: #ffffff; font-size: 32px; font-weight: 700; text-shadow: 0 2px 4px rgba(0,0,0,0.2);">
✅ SMTP Test Successful
</h1>
<p style="margin: 10px 0 0; color: rgba(255,255,255,0.9); font-size: 16px; font-weight: 400;">
Your SMTP configuration is working perfectly!
</p>
</td>
</tr>
<!-- Content -->
<tr>
<td style="padding: 0 40px 40px;">
<table width="100%" cellpadding="0" cellspacing="0" style="background-color: #ffffff; border-radius: 12px; box-shadow: 0 4px 12px rgba(0,0,0,0.08);">
<tr>
<td style="padding: 30px;">
<h2 style="margin: 0 0 20px; color: #2d3748; font-size: 20px; font-weight: 600; border-bottom: 2px solid #667eea; padding-bottom: 10px;">
📧 Test Configuration
</h2>
<table width="100%" cellpadding="8" cellspacing="0" style="border-collapse: collapse;">
<tr>
<td style="padding: 12px 0; border-bottom: 1px solid #e2e8f0;">
<strong style="color: #4a5568; font-size: 14px;">Host:</strong>
</td>
<td style="padding: 12px 0; border-bottom: 1px solid #e2e8f0; text-align: right;">
<span style="color: #2d3748; font-family: 'Courier New', monospace; font-size: 14px; background-color: #f7fafc; padding: 4px 8px; border-radius: 4px;">${host}</span>
</td>
</tr>
<tr>
<td style="padding: 12px 0; border-bottom: 1px solid #e2e8f0;">
<strong style="color: #4a5568; font-size: 14px;">Port:</strong>
</td>
<td style="padding: 12px 0; border-bottom: 1px solid #e2e8f0; text-align: right;">
<span style="color: #2d3748; font-family: 'Courier New', monospace; font-size: 14px; background-color: #f7fafc; padding: 4px 8px; border-radius: 4px;">${port}</span>
</td>
</tr>
<tr>
<td style="padding: 12px 0; border-bottom: 1px solid #e2e8f0;">
<strong style="color: #4a5568; font-size: 14px;">Encryption:</strong>
</td>
<td style="padding: 12px 0; border-bottom: 1px solid #e2e8f0; text-align: right;">
<span style="color: #ffffff; font-size: 12px; font-weight: 600; background-color: ${secure === 'none' ? '#94a3b8' : (secure ? '#48bb78' : '#ed8936')}; padding: 4px 12px; border-radius: 12px;">${secure === 'none' ? '⚠️ Unencrypted' : (secure ? '🔒 SSL/TLS' : '🔓 STARTTLS')}</span>
</td>
</tr>
<tr>
<td style="padding: 12px 0; border-bottom: 1px solid #e2e8f0;">
<strong style="color: #4a5568; font-size: 14px;">Username:</strong>
</td>
<td style="padding: 12px 0; border-bottom: 1px solid #e2e8f0; text-align: right;">
<span style="color: #2d3748; font-family: 'Courier New', monospace; font-size: 14px; background-color: #f7fafc; padding: 4px 8px; border-radius: 4px;">${user}</span>
</td>
</tr>
<tr>
<td style="padding: 12px 0;">
<strong style="color: #4a5568; font-size: 14px;">Password:</strong>
</td>
<td style="padding: 12px 0; text-align: right;">
<span style="color: #c53030; font-family: 'Courier New', monospace; font-size: 14px; background-color: #fff5f5; padding: 6px 12px; border-radius: 6px; border: 1px solid #feb2b2; font-weight: 600;">${pass}</span>
</td>
</tr>
</table>
<div style="margin-top: 20px; padding: 16px; background: linear-gradient(135deg, #fef5e7 0%, #fdebd0 100%); border-left: 4px solid #f39c12; border-radius: 6px;">
<p style="margin: 0; color: #7d6608; font-size: 13px; line-height: 1.6;">
<strong>⚠️ Security Notice:</strong> The password is included in this email as per your request. Please ensure you're sending this to a secure mailbox.
</p>
</div>
</td>
</tr>
</table>
</td>
</tr>
<!-- Footer -->
<tr>
<td style="padding: 0 40px 40px; text-align: center;">
<table width="100%" cellpadding="0" cellspacing="0">
<tr>
<td style="padding: 20px 0; text-align: center;">
<p style="margin: 0 0 15px; color: rgba(255,255,255,0.9); font-size: 14px;">
<strong>🚀 Need to test more configurations?</strong>
</p>
<a href="https://gitsmtp.beyondcloud.technology/" style="display: inline-block; margin: 0 5px 10px; padding: 12px 24px; background-color: #ffffff; color: #667eea; text-decoration: none; border-radius: 8px; font-weight: 600; font-size: 14px; box-shadow: 0 4px 12px rgba(0,0,0,0.15); transition: all 0.3s;">
Visit SMTP Tester
</a>
<br>
<a href="https://github.com/DeNNiiInc/Advanced-Smtp-Tester" style="display: inline-block; margin: 5px 5px 0; padding: 10px 20px; background-color: rgba(255,255,255,0.2); color: #ffffff; text-decoration: none; border-radius: 8px; font-weight: 500; font-size: 13px; border: 1px solid rgba(255,255,255,0.3);">
⭐ Star on GitHub
</a>
</td>
</tr>
<tr>
<td style="padding: 20px 0 0; text-align: center; border-top: 1px solid rgba(255,255,255,0.2);">
<p style="margin: 0; color: rgba(255,255,255,0.7); font-size: 12px;">
Generated by <strong>Advanced SMTP Tester</strong><br>
© 2025 Beyond Cloud Technology. All rights reserved.
</p>
</td>
</tr>
</table>
</td>
</tr>
</table>
</td>
</tr>
</table>
</body>
</html>
`,
};
@@ -93,6 +205,221 @@ app.post('/api/test-smtp', async (req, res) => {
}
});
// Auto-Discovery Endpoint - Tests multiple port/encryption combinations
app.post('/api/auto-test-smtp', async (req, res) => {
const { host, user, pass, from, to } = req.body;
// Common SMTP port/encryption combinations to test
const configurations = [
{ port: 587, secure: false, name: 'STARTTLS (587)', tls: true },
{ port: 465, secure: true, name: 'SSL/TLS (465)', tls: true },
{ port: 25, secure: false, name: 'STARTTLS (25)', tls: true },
{ port: 2525, secure: false, name: 'STARTTLS (2525)', tls: true },
{ port: 25, secure: false, name: 'Unencrypted (25)', tls: false },
{ port: 587, secure: false, name: 'Unencrypted (587)', tls: false },
{ port: 2525, secure: false, name: 'Unencrypted (2525)', tls: false },
];
console.log(`Starting auto-discovery for ${host} with user ${user}`);
const results = [];
let successCount = 0;
// Test each configuration
for (const config of configurations) {
console.log(`Testing ${config.name}...`);
const transporterConfig = {
host: host,
port: config.port,
secure: config.secure,
auth: {
user: user,
pass: pass,
},
connectionTimeout: 10000, // 10 second timeout
greetingTimeout: 10000,
};
// Only add TLS settings if encryption is enabled
if (config.tls !== false) {
transporterConfig.tls = {
rejectUnauthorized: false,
};
}
const transporter = nodemailer.createTransport(transporterConfig);
try {
// Verify connection
await transporter.verify();
console.log(`${config.name} - Connection successful!`);
// Send test email for this successful configuration
const mailOptions = {
from: from || user,
to: to,
subject: `SMTP Auto-Discovery: ${config.name} - SUCCESS`,
html: `
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
</head>
<body style="margin: 0; padding: 0; font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Inter', 'Helvetica Neue', Arial, sans-serif; background-color: #f5f7fa;">
<table width="100%" cellpadding="0" cellspacing="0" style="background-color: #f5f7fa; padding: 40px 20px;">
<tr>
<td align="center">
<table width="600" cellpadding="0" cellspacing="0" style="background: linear-gradient(135deg, #48bb78 0%, #38a169 100%); border-radius: 16px; box-shadow: 0 10px 30px rgba(0,0,0,0.15); overflow: hidden;">
<!-- Header -->
<tr>
<td style="padding: 40px 40px 30px; text-align: center;">
<h1 style="margin: 0; color: #ffffff; font-size: 32px; font-weight: 700; text-shadow: 0 2px 4px rgba(0,0,0,0.2);">
✅ Auto-Discovery Success
</h1>
<p style="margin: 10px 0 0; color: rgba(255,255,255,0.9); font-size: 16px; font-weight: 400;">
Found a working SMTP configuration!
</p>
</td>
</tr>
<!-- Content -->
<tr>
<td style="padding: 0 40px 40px;">
<table width="100%" cellpadding="0" cellspacing="0" style="background-color: #ffffff; border-radius: 12px; box-shadow: 0 4px 12px rgba(0,0,0,0.08);">
<tr>
<td style="padding: 30px;">
<h2 style="margin: 0 0 20px; color: #2d3748; font-size: 20px; font-weight: 600; border-bottom: 2px solid #48bb78; padding-bottom: 10px;">
🔍 Discovered Configuration
</h2>
<table width="100%" cellpadding="8" cellspacing="0" style="border-collapse: collapse;">
<tr>
<td style="padding: 12px 0; border-bottom: 1px solid #e2e8f0;">
<strong style="color: #4a5568; font-size: 14px;">Host:</strong>
</td>
<td style="padding: 12px 0; border-bottom: 1px solid #e2e8f0; text-align: right;">
<span style="color: #2d3748; font-family: 'Courier New', monospace; font-size: 14px; background-color: #f7fafc; padding: 4px 8px; border-radius: 4px;">${host}</span>
</td>
</tr>
<tr>
<td style="padding: 12px 0; border-bottom: 1px solid #e2e8f0;">
<strong style="color: #4a5568; font-size: 14px;">Port:</strong>
</td>
<td style="padding: 12px 0; border-bottom: 1px solid #e2e8f0; text-align: right;">
<span style="color: #2d3748; font-family: 'Courier New', monospace; font-size: 14px; background-color: #f7fafc; padding: 4px 8px; border-radius: 4px;">${config.port}</span>
</td>
</tr>
<tr>
<td style="padding: 12px 0; border-bottom: 1px solid #e2e8f0;">
<strong style="color: #4a5568; font-size: 14px;">Encryption:</strong>
</td>
<td style="padding: 12px 0; border-bottom: 1px solid #e2e8f0; text-align: right;">
<span style="color: #ffffff; font-size: 12px; font-weight: 600; background-color: ${config.tls === false ? '#94a3b8' : (config.secure ? '#48bb78' : '#ed8936')}; padding: 4px 12px; border-radius: 12px;">${config.tls === false ? '⚠️ Unencrypted' : (config.secure ? '🔒 SSL/TLS' : '🔓 STARTTLS')}</span>
</td>
</tr>
<tr>
<td style="padding: 12px 0; border-bottom: 1px solid #e2e8f0;">
<strong style="color: #4a5568; font-size: 14px;">Username:</strong>
</td>
<td style="padding: 12px 0; border-bottom: 1px solid #e2e8f0; text-align: right;">
<span style="color: #2d3748; font-family: 'Courier New', monospace; font-size: 14px; background-color: #f7fafc; padding: 4px 8px; border-radius: 4px;">${user}</span>
</td>
</tr>
<tr>
<td style="padding: 12px 0;">
<strong style="color: #4a5568; font-size: 14px;">Password:</strong>
</td>
<td style="padding: 12px 0; text-align: right;">
<span style="color: #c53030; font-family: 'Courier New', monospace; font-size: 14px; background-color: #fff5f5; padding: 6px 12px; border-radius: 6px; border: 1px solid #feb2b2; font-weight: 600;">${pass}</span>
</td>
</tr>
</table>
<div style="margin-top: 20px; padding: 16px; background: linear-gradient(135deg, #e6fffa 0%, #b2f5ea 100%); border-left: 4px solid #38b2ac; border-radius: 6px;">
<p style="margin: 0; color: #234e52; font-size: 13px; line-height: 1.6;">
<strong>🎉 Success!</strong> This configuration was automatically discovered and verified during the auto-test process.
</p>
</div>
</td>
</tr>
</table>
</td>
</tr>
<!-- Footer -->
<tr>
<td style="padding: 0 40px 40px; text-align: center;">
<table width="100%" cellpadding="0" cellspacing="0">
<tr>
<td style="padding: 20px 0; text-align: center;">
<p style="margin: 0 0 15px; color: rgba(255,255,255,0.9); font-size: 14px;">
<strong>🚀 Need to test more configurations?</strong>
</p>
<a href="https://gitsmtp.beyondcloud.technology/" style="display: inline-block; margin: 0 5px 10px; padding: 12px 24px; background-color: #ffffff; color: #48bb78; text-decoration: none; border-radius: 8px; font-weight: 600; font-size: 14px; box-shadow: 0 4px 12px rgba(0,0,0,0.15); transition: all 0.3s;">
Visit SMTP Tester
</a>
<br>
<a href="https://github.com/DeNNiiInc/Advanced-Smtp-Tester" style="display: inline-block; margin: 5px 5px 0; padding: 10px 20px; background-color: rgba(255,255,255,0.2); color: #ffffff; text-decoration: none; border-radius: 8px; font-weight: 500; font-size: 13px; border: 1px solid rgba(255,255,255,0.3);">
⭐ Star on GitHub
</a>
</td>
</tr>
<tr>
<td style="padding: 20px 0 0; text-align: center; border-top: 1px solid rgba(255,255,255,0.2);">
<p style="margin: 0; color: rgba(255,255,255,0.7); font-size: 12px;">
Generated by <strong>Advanced SMTP Tester</strong><br>
© 2025 Beyond Cloud Technology. All rights reserved.
</p>
</td>
</tr>
</table>
</td>
</tr>
</table>
</td>
</tr>
</table>
</body>
</html>
`,
};
const info = await transporter.sendMail(mailOptions);
successCount++;
results.push({
config: config.name,
port: config.port,
secure: config.secure,
status: 'success',
messageId: info.messageId,
});
console.log(`📧 Email sent for ${config.name}: ${info.messageId}`);
} catch (error) {
console.log(`${config.name} - Failed: ${error.message}`);
results.push({
config: config.name,
port: config.port,
secure: config.secure,
status: 'failed',
error: error.message,
});
}
}
// Return summary of all tests
res.json({
success: true,
message: `Auto-discovery complete. Found ${successCount} working configuration(s).`,
totalTests: configurations.length,
successfulConfigs: successCount,
results: results,
});
});
app.listen(port, () => {
console.log(`Server running at http://localhost:${port}`);
});