148 lines
7.6 KiB
HTML
148 lines
7.6 KiB
HTML
{{define "title"}}Relay Account — {{.Account.Username}}{{end}}
|
|
{{define "content"}}
|
|
<div class="flex items-center gap-3 mb-6">
|
|
<a href="/admin/domains" class="text-gray-400 text-sm hover:text-white">Domains</a>
|
|
<span class="text-gray-600">/</span>
|
|
<a href="/admin/domains/{{.Domain.ID}}" class="text-gray-400 text-sm hover:text-white">{{.Domain.Name}}</a>
|
|
<span class="text-gray-600">/</span>
|
|
<h1 class="text-xl font-bold text-white" style="font-family:monospace">{{.Account.Username}}</h1>
|
|
{{if .Account.Enabled}}<span class="badge badge-green">active</span>{{else}}<span class="badge badge-red">disabled</span>{{end}}
|
|
</div>
|
|
|
|
<div style="display:grid;grid-template-columns:1fr 1fr;gap:1.5rem">
|
|
|
|
<!-- Left column -->
|
|
<div>
|
|
<!-- Enable/disable -->
|
|
<div class="card">
|
|
<div class="text-sm font-semibold text-gray-300 mb-3">Status</div>
|
|
<form method="POST" action="/admin/domains/{{.Domain.ID}}/relayaccount/{{.Account.ID}}/toggle">
|
|
<input type="hidden" name="_csrf" value="{{.CSRF}}">
|
|
{{if .Account.Enabled}}
|
|
<input type="hidden" name="enabled" value="0">
|
|
<button type="submit" class="btn btn-danger btn-sm">Disable account</button>
|
|
{{else}}
|
|
<input type="hidden" name="enabled" value="1">
|
|
<button type="submit" class="btn btn-primary btn-sm">Enable account</button>
|
|
{{end}}
|
|
</form>
|
|
</div>
|
|
|
|
<!-- Change password -->
|
|
<div class="card">
|
|
<div class="text-sm font-semibold text-gray-300 mb-3">Change password</div>
|
|
<form method="POST" action="/admin/domains/{{.Domain.ID}}/relayaccount/{{.Account.ID}}/password">
|
|
<input type="hidden" name="_csrf" value="{{.CSRF}}">
|
|
<div class="field">
|
|
<label>New password (min 8 characters)</label>
|
|
<input type="password" name="password" required minlength="8" maxlength="1024">
|
|
</div>
|
|
<button type="submit" class="btn btn-primary btn-sm">Set password</button>
|
|
</form>
|
|
</div>
|
|
|
|
<!-- Delete -->
|
|
<div class="card" style="border:1px solid #7f1d1d">
|
|
<div class="text-sm font-semibold text-red-400 mb-2">Delete relay account</div>
|
|
<div class="text-xs text-gray-400 mb-3">Permanently removes this relay account and all its send-as patterns. Cannot be undone.</div>
|
|
<form method="POST" action="/admin/domains/{{.Domain.ID}}/relayaccount/{{.Account.ID}}/delete"
|
|
onsubmit="return confirm('Delete relay account {{.Account.Username}}?')">
|
|
<input type="hidden" name="_csrf" value="{{.CSRF}}">
|
|
<button type="submit" class="btn btn-danger btn-sm">Delete account</button>
|
|
</form>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Right column -->
|
|
<div>
|
|
<!-- Account info -->
|
|
<div class="card">
|
|
<div class="text-sm font-semibold text-gray-300 mb-3">Account info</div>
|
|
<div class="text-xs space-y-1.5 text-gray-400">
|
|
<div>Username: <span class="text-white" style="font-family:monospace">{{.Account.Username}}</span></div>
|
|
<div>Domain: <span class="text-white">{{.Domain.Name}}</span></div>
|
|
{{if .Account.DisplayName}}<div>Display name: <span class="text-white">{{.Account.DisplayName}}</span></div>{{end}}
|
|
{{if .Account.Description}}<div>Description: <span class="text-white">{{.Account.Description}}</span></div>{{end}}
|
|
<div>Created: <span class="text-white">{{shortTime .Account.CreatedAt}}</span></div>
|
|
<div class="text-gray-500 mt-2">This is a relay-only account. It has no mailbox or IMAP access.
|
|
Authenticate via SMTP using the username and password above.</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Send-as patterns -->
|
|
<div class="card">
|
|
<div class="text-sm font-semibold text-gray-300 mb-2">Permitted sender addresses</div>
|
|
<div class="text-xs text-gray-400 mb-3">
|
|
Define which From addresses this relay account may use. Use
|
|
<span style="font-family:monospace;color:#93c5fd">*@{{.Domain.Name}}</span>
|
|
to allow any address at the domain, or specify exact addresses.
|
|
</div>
|
|
{{if .SendAs}}
|
|
<div style="margin-bottom:.75rem">
|
|
{{range .SendAs}}
|
|
<div style="display:flex;align-items:center;justify-content:space-between;padding:.375rem .5rem;background:#111827;border-radius:.25rem;margin-bottom:.375rem">
|
|
<span style="font-family:monospace;font-size:.75rem;color:#93c5fd">{{.Pattern}}</span>
|
|
<form method="POST" action="/admin/domains/{{$.Domain.ID}}/relayaccount/{{$.Account.ID}}/sendas/{{.ID}}/delete" style="margin:0">
|
|
<input type="hidden" name="_csrf" value="{{$.CSRF}}">
|
|
<button type="submit" class="btn btn-danger btn-sm" style="padding:.125rem .5rem;font-size:.7rem">Remove</button>
|
|
</form>
|
|
</div>
|
|
{{end}}
|
|
</div>
|
|
{{else}}
|
|
<div class="text-xs text-gray-500 mb-3">No sender patterns configured. This account cannot send yet.</div>
|
|
{{end}}
|
|
<form method="POST" action="/admin/domains/{{.Domain.ID}}/relayaccount/{{.Account.ID}}/sendas" style="display:flex;gap:.5rem;align-items:flex-end">
|
|
<input type="hidden" name="_csrf" value="{{.CSRF}}">
|
|
<div class="field" style="margin:0;flex:1">
|
|
<label style="font-size:.7rem">Pattern (exact email or *@domain.com)</label>
|
|
<input type="text" name="pattern" required placeholder="sender@{{.Domain.Name}} or *@{{.Domain.Name}}" maxlength="255">
|
|
</div>
|
|
<button type="submit" class="btn btn-primary btn-sm">Add</button>
|
|
</form>
|
|
</div>
|
|
|
|
<!-- IP whitelist -->
|
|
<div class="card">
|
|
<div class="text-sm font-semibold text-gray-300 mb-2">Allowed source IPs</div>
|
|
<div class="text-xs text-gray-400 mb-3">
|
|
Connections from these IPs may send as any permitted sender address above
|
|
<span style="color:#d1d5db">without SMTP authentication</span>.
|
|
Accepts plain IPs or CIDR ranges.
|
|
</div>
|
|
{{if .IPs}}
|
|
<div style="margin-bottom:.75rem">
|
|
{{range .IPs}}
|
|
<div style="display:flex;align-items:center;justify-content:space-between;padding:.375rem .5rem;background:#111827;border-radius:.25rem;margin-bottom:.375rem">
|
|
<div>
|
|
<span style="font-family:monospace;font-size:.75rem;color:#6ee7b7">{{.CIDR}}</span>
|
|
{{if .Description}}<span style="font-size:.7rem;color:#6b7280;margin-left:.5rem">{{.Description}}</span>{{end}}
|
|
</div>
|
|
<form method="POST" action="/admin/domains/{{$.Domain.ID}}/relayaccount/{{$.Account.ID}}/ip/{{.ID}}/delete" style="margin:0">
|
|
<input type="hidden" name="_csrf" value="{{$.CSRF}}">
|
|
<button type="submit" class="btn btn-danger btn-sm" style="padding:.125rem .5rem;font-size:.7rem">Remove</button>
|
|
</form>
|
|
</div>
|
|
{{end}}
|
|
</div>
|
|
{{else}}
|
|
<div class="text-xs text-gray-500 mb-3">No IP rules. Authentication always required.</div>
|
|
{{end}}
|
|
<form method="POST" action="/admin/domains/{{.Domain.ID}}/relayaccount/{{.Account.ID}}/ip" style="display:flex;gap:.5rem;align-items:flex-end">
|
|
<input type="hidden" name="_csrf" value="{{.CSRF}}">
|
|
<div class="field" style="margin:0;flex:1">
|
|
<label style="font-size:.7rem">IP or CIDR</label>
|
|
<input type="text" name="cidr" required placeholder="10.0.0.1 or 10.0.0.0/24" maxlength="50">
|
|
</div>
|
|
<div class="field" style="margin:0;flex:1">
|
|
<label style="font-size:.7rem">Description (optional)</label>
|
|
<input type="text" name="description" placeholder="App server" maxlength="255">
|
|
</div>
|
|
<button type="submit" class="btn btn-primary btn-sm">Add</button>
|
|
</form>
|
|
</div>
|
|
</div>
|
|
|
|
</div>
|
|
{{end}}
|