mirror of
https://github.com/DeNNiiInc/Advanced-Smtp-Tester.git
synced 2026-04-17 17:35:59 +00:00
Add auto-discovery SMTP testing, unencrypted support, and BCT branding
This commit is contained in:
BIN
BCT-Base/Logo.png
Normal file
BIN
BCT-Base/Logo.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 749 KiB |
55
BCT-Base/index.html
Normal file
55
BCT-Base/index.html
Normal 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>© 2025 Beyond Cloud Technology. All rights reserved.</p>
|
||||
</footer>
|
||||
</div>
|
||||
</body>
|
||||
|
||||
</html>
|
||||
297
BCT-Base/styles.css
Normal file
297
BCT-Base/styles.css
Normal 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;
|
||||
}
|
||||
}
|
||||
18
index.html
18
index.html
@@ -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 -->
|
||||
|
||||
@@ -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';
|
||||
}
|
||||
});
|
||||
|
||||
@@ -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
365
server.js
@@ -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}`);
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user