Add SMTP notification support with WHM settings UI
Send email via curl SMTP when SMTP_HOST is configured, falling back to system mail/sendmail when empty. NOTIFY_EMAIL now accepts comma-separated addresses. WHM Settings page gets an SMTP card with Send Test Email button. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -17,9 +17,17 @@ LOG_LEVEL="info" # debug, info, warn, error
|
||||
LOG_RETAIN=90 # Days to keep log files
|
||||
|
||||
# ── Notifications ──────────────────────────────────────────────
|
||||
NOTIFY_EMAIL="" # Email address for notifications (empty = disabled)
|
||||
NOTIFY_EMAIL="" # Comma-separated email addresses (empty = disabled)
|
||||
NOTIFY_ON="failure" # always, failure, never
|
||||
|
||||
# ── SMTP Settings (optional) ─────────────────────────────────
|
||||
SMTP_HOST="" # SMTP server hostname (empty = use system mail)
|
||||
SMTP_PORT=587 # SMTP port (587=TLS/STARTTLS, 465=SSL, 25=none)
|
||||
SMTP_USER="" # SMTP username
|
||||
SMTP_PASSWORD="" # SMTP password
|
||||
SMTP_FROM="" # From address (falls back to SMTP_USER)
|
||||
SMTP_SECURITY="tls" # tls (STARTTLS), ssl (implicit), none
|
||||
|
||||
# ── Advanced ───────────────────────────────────────────────────
|
||||
LOCK_FILE="/var/run/gniza.lock"
|
||||
SSH_TIMEOUT=30 # SSH connection timeout in seconds
|
||||
|
||||
@@ -21,6 +21,12 @@ load_config() {
|
||||
LOG_RETAIN="${LOG_RETAIN:-$DEFAULT_LOG_RETAIN}"
|
||||
NOTIFY_EMAIL="${NOTIFY_EMAIL:-}"
|
||||
NOTIFY_ON="${NOTIFY_ON:-$DEFAULT_NOTIFY_ON}"
|
||||
SMTP_HOST="${SMTP_HOST:-}"
|
||||
SMTP_PORT="${SMTP_PORT:-$DEFAULT_SMTP_PORT}"
|
||||
SMTP_USER="${SMTP_USER:-}"
|
||||
SMTP_PASSWORD="${SMTP_PASSWORD:-}"
|
||||
SMTP_FROM="${SMTP_FROM:-}"
|
||||
SMTP_SECURITY="${SMTP_SECURITY:-$DEFAULT_SMTP_SECURITY}"
|
||||
LOCK_FILE="${LOCK_FILE:-$DEFAULT_LOCK_FILE}"
|
||||
SSH_TIMEOUT="${SSH_TIMEOUT:-$DEFAULT_SSH_TIMEOUT}"
|
||||
SSH_RETRIES="${SSH_RETRIES:-$DEFAULT_SSH_RETRIES}"
|
||||
@@ -31,6 +37,7 @@ load_config() {
|
||||
|
||||
export TEMP_DIR INCLUDE_ACCOUNTS EXCLUDE_ACCOUNTS BWLIMIT RETENTION_COUNT
|
||||
export LOG_DIR LOG_LEVEL LOG_RETAIN NOTIFY_EMAIL NOTIFY_ON
|
||||
export SMTP_HOST SMTP_PORT SMTP_USER SMTP_PASSWORD SMTP_FROM SMTP_SECURITY
|
||||
export LOCK_FILE SSH_TIMEOUT SSH_RETRIES RSYNC_EXTRA_OPTS
|
||||
}
|
||||
|
||||
@@ -50,6 +57,19 @@ validate_config() {
|
||||
*) log_error "LOG_LEVEL must be debug|info|warn|error, got: $LOG_LEVEL"; ((errors++)) || true ;;
|
||||
esac
|
||||
|
||||
# SMTP validation (only when SMTP_HOST is set)
|
||||
if [[ -n "${SMTP_HOST:-}" ]]; then
|
||||
case "$SMTP_SECURITY" in
|
||||
tls|ssl|none) ;;
|
||||
*) log_error "SMTP_SECURITY must be tls|ssl|none, got: $SMTP_SECURITY"; ((errors++)) || true ;;
|
||||
esac
|
||||
|
||||
if [[ -n "${SMTP_PORT:-}" ]] && { [[ ! "$SMTP_PORT" =~ ^[0-9]+$ ]] || (( SMTP_PORT < 1 || SMTP_PORT > 65535 )); }; then
|
||||
log_error "SMTP_PORT must be 1-65535, got: $SMTP_PORT"
|
||||
((errors++)) || true
|
||||
fi
|
||||
fi
|
||||
|
||||
if (( errors > 0 )); then
|
||||
log_error "Configuration has $errors error(s)"
|
||||
return 1
|
||||
|
||||
@@ -48,4 +48,6 @@ readonly DEFAULT_SSH_TIMEOUT=30
|
||||
readonly DEFAULT_SSH_RETRIES=3
|
||||
readonly DEFAULT_REMOTE_TYPE="ssh"
|
||||
readonly DEFAULT_S3_REGION="us-east-1"
|
||||
readonly DEFAULT_SMTP_PORT=587
|
||||
readonly DEFAULT_SMTP_SECURITY="tls"
|
||||
readonly DEFAULT_CONFIG_FILE="/etc/gniza/gniza.conf"
|
||||
|
||||
122
lib/notify.sh
122
lib/notify.sh
@@ -1,5 +1,105 @@
|
||||
#!/usr/bin/env bash
|
||||
# gniza/lib/notify.sh — Email notifications
|
||||
# gniza/lib/notify.sh — Email notifications (SMTP via curl or legacy mail/sendmail)
|
||||
|
||||
_send_via_smtp() {
|
||||
local subject="$1"
|
||||
local body="$2"
|
||||
|
||||
local from="${SMTP_FROM:-$SMTP_USER}"
|
||||
if [[ -z "$from" ]]; then
|
||||
log_error "SMTP_FROM or SMTP_USER must be set for SMTP delivery"
|
||||
return 1
|
||||
fi
|
||||
|
||||
# Build the RFC 2822 message
|
||||
local message=""
|
||||
message+="From: $from"$'\r\n'
|
||||
message+="To: $NOTIFY_EMAIL"$'\r\n'
|
||||
message+="Subject: $subject"$'\r\n'
|
||||
message+="Content-Type: text/plain; charset=UTF-8"$'\r\n'
|
||||
message+="Date: $(date -R)"$'\r\n'
|
||||
message+=$'\r\n'
|
||||
message+="$body"
|
||||
|
||||
# Build curl command
|
||||
local -a curl_args=(
|
||||
'curl' '--silent' '--show-error'
|
||||
'--connect-timeout' '30'
|
||||
'--max-time' '60'
|
||||
)
|
||||
|
||||
# Protocol URL based on security setting
|
||||
case "${SMTP_SECURITY:-tls}" in
|
||||
ssl)
|
||||
curl_args+=("--url" "smtps://${SMTP_HOST}:${SMTP_PORT}")
|
||||
;;
|
||||
tls)
|
||||
curl_args+=("--url" "smtp://${SMTP_HOST}:${SMTP_PORT}" "--ssl-reqd")
|
||||
;;
|
||||
none)
|
||||
curl_args+=("--url" "smtp://${SMTP_HOST}:${SMTP_PORT}")
|
||||
;;
|
||||
esac
|
||||
|
||||
# Auth credentials
|
||||
if [[ -n "${SMTP_USER:-}" ]]; then
|
||||
curl_args+=("--user" "${SMTP_USER}:${SMTP_PASSWORD}")
|
||||
fi
|
||||
|
||||
# Sender
|
||||
curl_args+=("--mail-from" "$from")
|
||||
|
||||
# Recipients (split NOTIFY_EMAIL on commas)
|
||||
local IFS=','
|
||||
local -a recipients=($NOTIFY_EMAIL)
|
||||
unset IFS
|
||||
local rcpt
|
||||
for rcpt in "${recipients[@]}"; do
|
||||
rcpt="${rcpt## }" # trim leading space
|
||||
rcpt="${rcpt%% }" # trim trailing space
|
||||
[[ -n "$rcpt" ]] && curl_args+=("--mail-rcpt" "$rcpt")
|
||||
done
|
||||
|
||||
# Upload the message from stdin
|
||||
curl_args+=("-T" "-")
|
||||
|
||||
log_debug "Sending via SMTP to ${SMTP_HOST}:${SMTP_PORT} (${SMTP_SECURITY})"
|
||||
|
||||
local curl_output
|
||||
curl_output=$(echo "$message" | "${curl_args[@]}" 2>&1)
|
||||
local rc=$?
|
||||
|
||||
if (( rc == 0 )); then
|
||||
return 0
|
||||
else
|
||||
log_error "SMTP delivery failed (curl exit code: $rc): $curl_output"
|
||||
return 1
|
||||
fi
|
||||
}
|
||||
|
||||
_send_via_legacy() {
|
||||
local subject="$1"
|
||||
local body="$2"
|
||||
|
||||
# Convert comma-separated to space-separated for mail command
|
||||
local recipients="${NOTIFY_EMAIL//,/ }"
|
||||
|
||||
if command -v mail &>/dev/null; then
|
||||
echo "$body" | mail -s "$subject" $recipients
|
||||
elif command -v sendmail &>/dev/null; then
|
||||
{
|
||||
echo "To: $NOTIFY_EMAIL"
|
||||
echo "Subject: $subject"
|
||||
echo "Content-Type: text/plain; charset=UTF-8"
|
||||
echo ""
|
||||
echo "$body"
|
||||
} | sendmail -t
|
||||
else
|
||||
log_warn "No mail command available, cannot send notification"
|
||||
return 1
|
||||
fi
|
||||
return 0
|
||||
}
|
||||
|
||||
send_notification() {
|
||||
local subject="$1"
|
||||
@@ -20,23 +120,17 @@ send_notification() {
|
||||
|
||||
log_debug "Sending notification to $NOTIFY_EMAIL: $full_subject"
|
||||
|
||||
if command -v mail &>/dev/null; then
|
||||
echo "$body" | mail -s "$full_subject" "$NOTIFY_EMAIL"
|
||||
elif command -v sendmail &>/dev/null; then
|
||||
{
|
||||
echo "To: $NOTIFY_EMAIL"
|
||||
echo "Subject: $full_subject"
|
||||
echo "Content-Type: text/plain; charset=UTF-8"
|
||||
echo ""
|
||||
echo "$body"
|
||||
} | sendmail -t
|
||||
if [[ -n "${SMTP_HOST:-}" ]]; then
|
||||
_send_via_smtp "$full_subject" "$body"
|
||||
else
|
||||
log_warn "No mail command available, cannot send notification"
|
||||
return 1
|
||||
_send_via_legacy "$full_subject" "$body"
|
||||
fi
|
||||
|
||||
local rc=$?
|
||||
if (( rc == 0 )); then
|
||||
log_debug "Notification sent"
|
||||
return 0
|
||||
fi
|
||||
return $rc
|
||||
}
|
||||
|
||||
send_backup_report() {
|
||||
|
||||
@@ -9,6 +9,7 @@ use Fcntl qw(:flock);
|
||||
our @MAIN_KEYS = qw(
|
||||
TEMP_DIR INCLUDE_ACCOUNTS EXCLUDE_ACCOUNTS
|
||||
RSYNC_EXTRA_OPTS LOG_DIR LOG_LEVEL LOG_RETAIN NOTIFY_EMAIL NOTIFY_ON
|
||||
SMTP_HOST SMTP_PORT SMTP_USER SMTP_PASSWORD SMTP_FROM SMTP_SECURITY
|
||||
LOCK_FILE SSH_TIMEOUT SSH_RETRIES
|
||||
);
|
||||
|
||||
@@ -67,7 +68,7 @@ sub escape_value {
|
||||
}
|
||||
|
||||
# Keys whose values are written with single quotes (preserves special chars).
|
||||
my %SINGLE_QUOTE_KEYS = (REMOTE_PASSWORD => 1, S3_SECRET_ACCESS_KEY => 1);
|
||||
my %SINGLE_QUOTE_KEYS = (REMOTE_PASSWORD => 1, S3_SECRET_ACCESS_KEY => 1, SMTP_PASSWORD => 1);
|
||||
|
||||
# escape_password($string)
|
||||
# For single-quoted bash values: only strip single quotes (can't appear in single-quoted strings).
|
||||
|
||||
@@ -525,6 +525,93 @@ sub init_remote_dir {
|
||||
return (0, "Unknown remote type: $type");
|
||||
}
|
||||
|
||||
# ── SMTP Connection Test ──────────────────────────────────────
|
||||
|
||||
sub test_smtp_connection {
|
||||
my (%args) = @_;
|
||||
|
||||
my $host = $args{host} // '';
|
||||
my $port = $args{port} || '587';
|
||||
my $user = $args{user} // '';
|
||||
my $password = $args{password} // '';
|
||||
my $from = $args{from} // $user;
|
||||
my $security = $args{security} || 'tls';
|
||||
my $to = $args{to} // '';
|
||||
|
||||
return (0, 'SMTP host is required') if $host eq '';
|
||||
return (0, 'Recipient email is required') if $to eq '';
|
||||
return (0, 'From address or SMTP user is required') if $from eq '';
|
||||
|
||||
# Build the test email
|
||||
chomp(my $hostname = `hostname -f 2>/dev/null` || `hostname`);
|
||||
my $date = `date -R`; chomp $date;
|
||||
my $message = "From: $from\r\nTo: $to\r\nSubject: [gniza] SMTP Test from $hostname\r\n"
|
||||
. "Content-Type: text/plain; charset=UTF-8\r\nDate: $date\r\n\r\n"
|
||||
. "This is a test email from gniza on $hostname.\r\n"
|
||||
. "If you received this, SMTP is configured correctly.\r\n";
|
||||
|
||||
# Write message to temp file
|
||||
my $tmpfile = "/tmp/gniza-smtp-test-$$.eml";
|
||||
if (open my $fh, '>', $tmpfile) {
|
||||
print $fh $message;
|
||||
close $fh;
|
||||
} else {
|
||||
return (0, "Failed to write temp file: $!");
|
||||
}
|
||||
|
||||
# Build curl command
|
||||
my @cmd = ('curl', '--silent', '--show-error', '--connect-timeout', '30', '--max-time', '60');
|
||||
|
||||
if ($security eq 'ssl') {
|
||||
push @cmd, '--url', "smtps://$host:$port";
|
||||
} elsif ($security eq 'tls') {
|
||||
push @cmd, '--url', "smtp://$host:$port", '--ssl-reqd';
|
||||
} else {
|
||||
push @cmd, '--url', "smtp://$host:$port";
|
||||
}
|
||||
|
||||
if ($user ne '') {
|
||||
push @cmd, '--user', "$user:$password";
|
||||
}
|
||||
|
||||
push @cmd, '--mail-from', $from;
|
||||
|
||||
# Support multiple recipients
|
||||
my @recipients = split /\s*,\s*/, $to;
|
||||
for my $rcpt (@recipients) {
|
||||
next if $rcpt eq '';
|
||||
push @cmd, '--mail-rcpt', $rcpt;
|
||||
}
|
||||
|
||||
push @cmd, '-T', $tmpfile;
|
||||
|
||||
my ($in, $out, $err_fh) = (undef, undef, gensym);
|
||||
my $pid = eval { open3($in, $out, $err_fh, @cmd) };
|
||||
unless ($pid) {
|
||||
unlink $tmpfile;
|
||||
return (0, "Failed to run curl: $@");
|
||||
}
|
||||
close $in if $in;
|
||||
|
||||
my $stdout = do { local $/; <$out> } // '';
|
||||
my $stderr = do { local $/; <$err_fh> } // '';
|
||||
close $out;
|
||||
close $err_fh;
|
||||
|
||||
waitpid($pid, 0);
|
||||
my $exit_code = $? >> 8;
|
||||
unlink $tmpfile;
|
||||
|
||||
chomp $stderr;
|
||||
|
||||
if ($exit_code == 0) {
|
||||
return (1, undef);
|
||||
}
|
||||
|
||||
my $msg = $stderr || "curl exited with code $exit_code";
|
||||
return (0, $msg);
|
||||
}
|
||||
|
||||
# ── Page Wrappers ────────────────────────────────────────────
|
||||
|
||||
sub page_header {
|
||||
|
||||
@@ -71,6 +71,42 @@ sub validate_main_config {
|
||||
}
|
||||
}
|
||||
|
||||
# SMTP validation (only when SMTP_HOST is set)
|
||||
if (defined $data->{SMTP_HOST} && $data->{SMTP_HOST} ne '') {
|
||||
if ($data->{SMTP_HOST} !~ /^[a-zA-Z0-9._-]+$/) {
|
||||
push @errors, 'SMTP_HOST contains invalid characters';
|
||||
}
|
||||
|
||||
if (defined $data->{SMTP_PORT} && $data->{SMTP_PORT} ne '') {
|
||||
if ($data->{SMTP_PORT} !~ /^\d+$/ || $data->{SMTP_PORT} < 1 || $data->{SMTP_PORT} > 65535) {
|
||||
push @errors, 'SMTP_PORT must be 1-65535';
|
||||
}
|
||||
}
|
||||
|
||||
if (defined $data->{SMTP_SECURITY} && $data->{SMTP_SECURITY} ne '') {
|
||||
unless ($data->{SMTP_SECURITY} =~ /^(tls|ssl|none)$/) {
|
||||
push @errors, 'SMTP_SECURITY must be tls, ssl, or none';
|
||||
}
|
||||
}
|
||||
|
||||
if (defined $data->{SMTP_FROM} && $data->{SMTP_FROM} ne '') {
|
||||
unless ($data->{SMTP_FROM} =~ /^[^\s@]+\@[^\s@]+\.[^\s@]+$/) {
|
||||
push @errors, 'SMTP_FROM must be a valid email address';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
# Validate NOTIFY_EMAIL addresses (comma-separated)
|
||||
if (defined $data->{NOTIFY_EMAIL} && $data->{NOTIFY_EMAIL} ne '') {
|
||||
my @addrs = split /\s*,\s*/, $data->{NOTIFY_EMAIL};
|
||||
for my $addr (@addrs) {
|
||||
next if $addr eq '';
|
||||
unless ($addr =~ /^[^\s@]+\@[^\s@]+\.[^\s@]+$/) {
|
||||
push @errors, "Invalid email address: $addr";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
# Filter out empty strings from helper returns
|
||||
return [grep { $_ ne '' } @errors];
|
||||
}
|
||||
|
||||
@@ -14,6 +14,53 @@ use GnizaWHM::UI;
|
||||
my $CONFIG_FILE = '/etc/gniza/gniza.conf';
|
||||
my $form = Cpanel::Form::parseform();
|
||||
my $method = $ENV{'REQUEST_METHOD'} // 'GET';
|
||||
my $action = $form->{'action'} // '';
|
||||
|
||||
# ── Handle SMTP Test (JSON) ──────────────────────────────────
|
||||
|
||||
if ($action eq 'test_smtp') {
|
||||
print "Content-Type: application/json\r\n\r\n";
|
||||
|
||||
my $host = $form->{'SMTP_HOST'} // '';
|
||||
my $port = $form->{'SMTP_PORT'} || '587';
|
||||
my $user = $form->{'SMTP_USER'} // '';
|
||||
my $password = $form->{'SMTP_PASSWORD'} // '';
|
||||
my $from = $form->{'SMTP_FROM'} // '';
|
||||
my $security = $form->{'SMTP_SECURITY'} || 'tls';
|
||||
my $to = $form->{'NOTIFY_EMAIL'} // '';
|
||||
|
||||
if ($host eq '') {
|
||||
print qq({"success":false,"message":"SMTP Host is required."});
|
||||
exit;
|
||||
}
|
||||
if ($to eq '') {
|
||||
print qq({"success":false,"message":"Notification email is required for test."});
|
||||
exit;
|
||||
}
|
||||
|
||||
my ($ok, $err) = GnizaWHM::UI::test_smtp_connection(
|
||||
host => $host,
|
||||
port => $port,
|
||||
user => $user,
|
||||
password => $password,
|
||||
from => $from,
|
||||
security => $security,
|
||||
to => $to,
|
||||
);
|
||||
if ($ok) {
|
||||
print qq({"success":true,"message":"Test email sent successfully. Check your inbox."});
|
||||
} else {
|
||||
$err //= 'Unknown error';
|
||||
$err =~ s/\\/\\\\/g;
|
||||
$err =~ s/"/\\"/g;
|
||||
$err =~ s/\n/\\n/g;
|
||||
$err =~ s/\r/\\r/g;
|
||||
$err =~ s/\t/\\t/g;
|
||||
$err =~ s/[\x00-\x1f]//g;
|
||||
print qq({"success":false,"message":"SMTP test failed: $err"});
|
||||
}
|
||||
exit;
|
||||
}
|
||||
|
||||
# ── Handle POST ──────────────────────────────────────────────
|
||||
|
||||
@@ -147,10 +194,34 @@ print qq{</div>\n</div>\n};
|
||||
# Section: Notifications
|
||||
print qq{<div class="card bg-base-100 shadow-sm border border-base-300 mb-6">\n<div class="card-body">\n};
|
||||
print qq{<h2 class="card-title text-sm">Notifications</h2>\n};
|
||||
field_text('NOTIFY_EMAIL', 'Email Address', 'Empty = disabled');
|
||||
field_text('NOTIFY_EMAIL', 'Email Address(es)', 'Comma-separated, empty = disabled');
|
||||
field_select('NOTIFY_ON', 'Notify On', ['always', 'failure', 'never']);
|
||||
print qq{</div>\n</div>\n};
|
||||
|
||||
# Section: SMTP Settings
|
||||
print qq{<div class="card bg-base-100 shadow-sm border border-base-300 mb-6">\n<div class="card-body">\n};
|
||||
print qq{<h2 class="card-title text-sm">SMTP Settings</h2>\n};
|
||||
print qq{<p class="text-xs text-base-content/60 mb-3">Optional. When SMTP Host is empty, system mail/sendmail is used.</p>\n};
|
||||
field_text('SMTP_HOST', 'SMTP Host', 'e.g. smtp.gmail.com');
|
||||
field_text('SMTP_PORT', 'SMTP Port', 'Default: 587');
|
||||
field_text('SMTP_USER', 'SMTP Username', 'e.g. user@gmail.com');
|
||||
|
||||
# SMTP Password (type=password)
|
||||
my $smtp_pw_val = GnizaWHM::UI::esc($conf->{SMTP_PASSWORD} // '');
|
||||
print qq{<div class="flex items-center gap-3 mb-2.5">\n};
|
||||
print qq{ <label class="w-44 font-medium text-sm" for="SMTP_PASSWORD">SMTP Password</label>\n};
|
||||
print qq{ <input type="password" class="input input-bordered input-sm w-full max-w-xs" id="SMTP_PASSWORD" name="SMTP_PASSWORD" value="$smtp_pw_val">\n};
|
||||
print qq{</div>\n};
|
||||
|
||||
field_text('SMTP_FROM', 'From Address', 'Falls back to SMTP Username');
|
||||
field_select('SMTP_SECURITY', 'Security', ['tls', 'ssl', 'none']);
|
||||
|
||||
print qq{<div class="flex gap-2 mt-3">\n};
|
||||
print qq{ <button type="button" class="btn btn-secondary btn-sm" id="test-smtp-btn" onclick="gnizaTestSmtp()">Send Test Email</button>\n};
|
||||
print qq{</div>\n};
|
||||
print qq{<div id="gniza-smtp-alert" class="mt-3"></div>\n};
|
||||
print qq{</div>\n</div>\n};
|
||||
|
||||
# Section: Advanced
|
||||
print qq{<div class="card bg-base-100 shadow-sm border border-base-300 mb-6">\n<div class="card-body">\n};
|
||||
print qq{<h2 class="card-title text-sm">Advanced</h2>\n};
|
||||
@@ -167,5 +238,56 @@ print qq{</div>\n};
|
||||
|
||||
print qq{</form>\n};
|
||||
|
||||
print <<'JS';
|
||||
<script>
|
||||
function gnizaTestSmtp() {
|
||||
var btn = document.getElementById('test-smtp-btn');
|
||||
var fd = new FormData();
|
||||
fd.append('action', 'test_smtp');
|
||||
fd.append('SMTP_HOST', document.getElementById('SMTP_HOST').value);
|
||||
fd.append('SMTP_PORT', document.getElementById('SMTP_PORT').value);
|
||||
fd.append('SMTP_USER', document.getElementById('SMTP_USER').value);
|
||||
fd.append('SMTP_PASSWORD', document.getElementById('SMTP_PASSWORD').value);
|
||||
fd.append('SMTP_FROM', document.getElementById('SMTP_FROM').value);
|
||||
fd.append('SMTP_SECURITY', document.getElementById('SMTP_SECURITY').value);
|
||||
fd.append('NOTIFY_EMAIL', document.getElementById('NOTIFY_EMAIL').value);
|
||||
|
||||
var email = document.getElementById('NOTIFY_EMAIL').value;
|
||||
var host = document.getElementById('SMTP_HOST').value;
|
||||
if (!host) { gnizaSmtpToast('error', 'SMTP Host is required.'); return; }
|
||||
if (!email) { gnizaSmtpToast('error', 'Notification email is required for test.'); return; }
|
||||
|
||||
btn.disabled = true;
|
||||
btn.innerHTML = '<span class="loading loading-spinner loading-xs"></span> Sending\u2026';
|
||||
|
||||
fetch('settings.cgi', { method: 'POST', body: fd })
|
||||
.then(function(r) { return r.json(); })
|
||||
.then(function(data) {
|
||||
gnizaSmtpToast(data.success ? 'success' : 'error', data.message);
|
||||
})
|
||||
.catch(function(err) {
|
||||
gnizaSmtpToast('error', 'Request failed: ' + err.toString());
|
||||
})
|
||||
.finally(function() {
|
||||
btn.disabled = false;
|
||||
btn.innerHTML = 'Send Test Email';
|
||||
});
|
||||
}
|
||||
|
||||
function gnizaSmtpToast(type, msg) {
|
||||
var area = document.getElementById('gniza-smtp-alert');
|
||||
if (!area) return;
|
||||
area.innerHTML = '';
|
||||
var el = document.createElement('div');
|
||||
el.className = 'alert alert-' + type;
|
||||
el.style.cssText = 'padding:12px 20px;border-radius:8px;font-size:14px';
|
||||
el.textContent = msg;
|
||||
area.appendChild(el);
|
||||
setTimeout(function() { el.style.opacity = '0'; }, type === 'error' ? 6000 : 3000);
|
||||
setTimeout(function() { area.innerHTML = ''; }, type === 'error' ? 6500 : 3500);
|
||||
}
|
||||
</script>
|
||||
JS
|
||||
|
||||
print GnizaWHM::UI::page_footer();
|
||||
Whostmgr::HTMLInterface::footer();
|
||||
|
||||
Reference in New Issue
Block a user