Files

162 lines
6.3 KiB
HTML
Raw Permalink Normal View History

{% extends "base.html" %}
{% block title %}SMTP{% endblock %}
{% block content %}
<h1>[*] SMTP / Mail</h1>
<div class="toolbar">
<button class="btn" onclick="loadSmtpStatus()">Status</button>
<button class="btn" onclick="checkDNS()">Check DNS</button>
<button class="btn" onclick="flushQueue()">Flush Queue</button>
<button class="btn btn-warn" onclick="restartSmtp()">Restart Postfix</button>
<button class="btn" onclick="showTab('status')">Status</button>
<button class="btn" onclick="showTab('send')">Send Email</button>
<button class="btn" onclick="showTab('mass')">Mass Email (BCC)</button>
</div>
<!-- TAB: Status -->
<div id="tab-status">
<div class="grid grid-2">
<div class="card">
<div class="card-title">SMTP Status</div>
<div class="output" id="smtp-output"><span class="info">Loading...</span></div>
</div>
<div class="card">
<div class="card-title">DNS Records (SPF/DKIM/DMARC)</div>
<div class="output" id="dns-output"><span class="info">Click "Check DNS"</span></div>
</div>
</div>
<div class="card">
<div class="card-title">Quick Test</div>
<input type="email" id="test-email" placeholder="recipient@example.com" style="width:300px">
<button class="btn" onclick="sendTest()">Send Test</button>
</div>
</div>
<!-- TAB: Send Email -->
<div id="tab-send" style="display:none">
<div class="card">
<div class="card-title">Compose Email</div>
<label>From</label>
<input type="text" id="send-from" value="noreply@seteclabs.io" style="width:100%">
<label>To</label>
<input type="text" id="send-to" placeholder="recipient@example.com" style="width:100%">
<label>Subject</label>
<input type="text" id="send-subject" placeholder="Email subject" style="width:100%">
<label>Body</label>
<textarea id="send-body" rows="10" style="width:100%" placeholder="Type your message here..."></textarea>
<br><br>
<button class="btn" onclick="sendEmail()">Send Email</button>
</div>
</div>
<!-- TAB: Mass Email (BCC) -->
<div id="tab-mass" style="display:none">
<div class="card">
<div class="card-title">Mass Email (BCC Mode)</div>
<p style="color:#888;font-size:12px;margin-bottom:10px">
Each recipient gets their own individual email. No one can see other recipients' addresses.
</p>
<label>From</label>
<input type="text" id="mass-from" value="noreply@seteclabs.io" style="width:100%">
<label>Recipients (comma or newline separated)</label>
<textarea id="mass-to" rows="5" style="width:100%" placeholder="joe@example.com, sam@example.com, bob@example.com
or one per line:
joe@example.com
sam@example.com
bob@example.com"></textarea>
<label>Subject</label>
<input type="text" id="mass-subject" placeholder="Email subject" style="width:100%">
<label>Body</label>
<textarea id="mass-body" rows="10" style="width:100%" placeholder="Type your message here..."></textarea>
<br><br>
<div class="toolbar">
<button class="btn" onclick="previewMass()">Preview (count recipients)</button>
<button class="btn btn-warn" onclick="sendMass()">Send to All</button>
</div>
<div id="mass-preview" style="margin-top:10px;font-size:12px;color:#888"></div>
</div>
</div>
<div class="card">
<div class="card-title">Output</div>
<div class="output" id="output"><span class="info">Ready.</span></div>
</div>
{% endblock %}
{% block scripts %}
<script>
function showTab(tab) {
document.getElementById('tab-status').style.display = tab === 'status' ? '' : 'none';
document.getElementById('tab-send').style.display = tab === 'send' ? '' : 'none';
document.getElementById('tab-mass').style.display = tab === 'mass' ? '' : 'none';
}
// ── Status ──
async function loadSmtpStatus() {
const res = await apiGet('/api/smtp/status');
showResult(res, 'smtp-output');
}
async function checkDNS() {
const res = await apiGet('/api/smtp/dns-check');
showResult(res, 'dns-output');
}
async function flushQueue() {
const res = await apiPost('/api/smtp/flush');
showResult(res);
}
async function restartSmtp() {
const res = await apiPost('/api/smtp/restart');
showResult(res);
}
async function sendTest() {
const to = document.getElementById('test-email').value;
if (!to) { alert('Enter email address'); return; }
const res = await apiPost('/api/smtp/send-test', {to});
showResult(res);
}
// ── Send Email ──
async function sendEmail() {
const from = document.getElementById('send-from').value.trim();
const to = document.getElementById('send-to').value.trim();
const subject = document.getElementById('send-subject').value.trim();
const body = document.getElementById('send-body').value;
if (!to || !subject) { alert('Fill in To and Subject'); return; }
const res = await apiPost('/api/smtp/send', {from, to, subject, body});
showResult(res);
}
// ── Mass Email ──
function parseRecipients() {
const raw = document.getElementById('mass-to').value;
return raw.split(/[,\n]+/).map(e => e.trim()).filter(e => e && e.includes('@'));
}
function previewMass() {
const recipients = parseRecipients();
const el = document.getElementById('mass-preview');
el.innerHTML = `<span style="color:#00ff41">${recipients.length} recipients found:</span><br>` +
recipients.map(r => ` - ${escHtml(r)}`).join('<br>');
}
async function sendMass() {
const recipients = parseRecipients();
if (!recipients.length) { alert('Enter at least one recipient'); return; }
const from = document.getElementById('mass-from').value.trim();
const subject = document.getElementById('mass-subject').value.trim();
const body = document.getElementById('mass-body').value;
if (!subject) { alert('Enter a subject'); return; }
if (!confirm(`Send email to ${recipients.length} recipients individually (BCC mode)?`)) return;
const out = document.getElementById('output');
out.innerHTML = `<span class="info">Sending to ${recipients.length} recipients...</span>\n`;
const res = await apiPost('/api/smtp/send-mass', {from, recipients, subject, body});
showResult(res);
}
loadSmtpStatus();
</script>
{% endblock %}