A free, open, self-hosted app platform (GNU AGPLv3): one-click app deploys, Traefik reverse proxy with automatic SSL, rootless Docker support, gluetun VPN routing, and a web dashboard to manage it all. Free & open forever to self-host; optional paid hosted services fund it. See PROMISE.md. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com> Signed-off-by: librelad <librelad@digitalangels.vip>
143 lines
7.1 KiB
JavaScript
Executable File
143 lines
7.1 KiB
JavaScript
Executable File
const net = require('net');
|
|
|
|
/* =========================
|
|
Mail Connection Test
|
|
========================= */
|
|
async function testConnection(req, res) {
|
|
try {
|
|
const { host, port, secure, username, password, from } = req.body;
|
|
|
|
// Validate required fields
|
|
if (!host || !port || !username || !password) {
|
|
return res.status(400).json({
|
|
success: false,
|
|
message: 'Missing required fields: host, port, username, password'
|
|
});
|
|
}
|
|
|
|
const result = await new Promise((resolve, reject) => {
|
|
const socket = new net.Socket();
|
|
let response = '';
|
|
let connected = false;
|
|
|
|
socket.connect(parseInt(port), host, () => {
|
|
connected = true;
|
|
//console.log(`Connected to ${host}:${port}`);
|
|
|
|
// Wait for SMTP greeting
|
|
socket.once('data', (data) => {
|
|
response = data.toString();
|
|
//console.log('SMTP greeting:', response.trim());
|
|
|
|
if (response.startsWith('220')) {
|
|
// Send EHLO
|
|
socket.write('EHLO test.example.com\r\n');
|
|
|
|
// Wait for EHLO response
|
|
socket.once('data', (ehloData) => {
|
|
const ehloResponse = ehloData.toString();
|
|
//console.log('EHLO response:', ehloResponse.trim());
|
|
|
|
if (ehloResponse.startsWith('250')) {
|
|
// Try to authenticate if username/password provided
|
|
if (username && password) {
|
|
socket.write(`AUTH LOGIN\r\n`);
|
|
|
|
socket.once('data', (authChallenge) => {
|
|
const authResponse = authChallenge.toString();
|
|
//console.log('AUTH response:', authResponse.trim());
|
|
|
|
if (authResponse.startsWith('334')) {
|
|
// Send username (base64 encoded)
|
|
const usernameB64 = Buffer.from(username).toString('base64');
|
|
socket.write(usernameB64 + '\r\n');
|
|
|
|
socket.once('data', (userChallenge) => {
|
|
const userResponse = userChallenge.toString();
|
|
//console.log('Username response:', userResponse.trim());
|
|
|
|
if (userResponse.startsWith('334')) {
|
|
// Send password (base64 encoded)
|
|
const passwordB64 = Buffer.from(password).toString('base64');
|
|
socket.write(passwordB64 + '\r\n');
|
|
|
|
socket.once('data', (passResponse) => {
|
|
const passResult = passResponse.toString();
|
|
//console.log('Password response:', passResult.trim());
|
|
|
|
if (passResult.startsWith('235')) {
|
|
resolve({
|
|
success: true,
|
|
message: `Successfully connected and authenticated to ${host}:${port} with ${secure || 'none'} security`
|
|
});
|
|
} else {
|
|
reject(new Error('Authentication failed: Invalid username or password'));
|
|
}
|
|
socket.end();
|
|
});
|
|
} else {
|
|
reject(new Error('Authentication failed: Invalid username'));
|
|
socket.end();
|
|
}
|
|
});
|
|
} else {
|
|
reject(new Error('Server does not support authentication'));
|
|
socket.end();
|
|
}
|
|
});
|
|
} else {
|
|
resolve({
|
|
success: true,
|
|
message: `Successfully connected to ${host}:${port} with ${secure || 'none'} security (no authentication tested)`
|
|
});
|
|
socket.end();
|
|
}
|
|
} else {
|
|
reject(new Error('EHLO command failed'));
|
|
socket.end();
|
|
}
|
|
});
|
|
} else {
|
|
reject(new Error('Server did not send proper SMTP greeting'));
|
|
socket.end();
|
|
}
|
|
});
|
|
});
|
|
|
|
socket.on('error', (err) => {
|
|
if (!connected) {
|
|
reject(new Error(`Connection failed: ${err.message}`));
|
|
} else {
|
|
reject(new Error(`SMTP error: ${err.message}`));
|
|
}
|
|
});
|
|
|
|
socket.setTimeout(10000, () => {
|
|
socket.destroy();
|
|
reject(new Error('Connection timeout'));
|
|
});
|
|
});
|
|
|
|
res.json(result);
|
|
|
|
} catch (error) {
|
|
console.error('Mail connection test error:', error);
|
|
res.status(500).json({
|
|
success: false,
|
|
message: error.message || 'Mail connection test failed',
|
|
details: error.stack || 'No stack trace available',
|
|
error: error.toString(),
|
|
config: {
|
|
host: host,
|
|
port: port,
|
|
secure: secure,
|
|
username: username ? '[REDACTED]' : 'not provided',
|
|
password: password ? '[REDACTED]' : 'not provided',
|
|
from: from
|
|
}
|
|
});
|
|
}
|
|
}
|
|
|
|
module.exports = { testConnection };
|