2025-06-07 10:48:03 +01:00
{% extends "base.html" %}
{% block title %}Domains - Email Server Management{% endblock %}
{% block page_title %}Domain Management{% endblock %}
{% block content %}
< div class = "d-flex justify-content-between align-items-center mb-4" >
< h2 >
< i class = "bi bi-globe me-2" > < / i >
Domains
< / h2 >
< a href = "{{ url_for('email.add_domain') }}" class = "btn btn-primary" >
< i class = "bi bi-plus-circle me-2" > < / i >
Add Domain
< / a >
< / div >
< div class = "card" >
< div class = "card-header" >
< h5 class = "mb-0" >
< i class = "bi bi-list-ul me-2" > < / i >
All Domains
< / h5 >
< / div >
< div class = "card-body p-0" >
{% if domains %}
< div class = "table-responsive" >
< table class = "table table-dark table-hover mb-0" >
< thead >
< tr >
< th > Domain Name< / th >
< th > Status< / th >
< th > Created< / th >
2025-06-08 22:51:07 +01:00
< th > Senders< / th >
2025-06-07 10:48:03 +01:00
< th > DKIM< / th >
< th > Actions< / th >
< / tr >
< / thead >
< tbody >
{% for domain in domains %}
< tr >
< td >
< div class = "fw-bold" > {{ domain.domain_name }}< / div >
< / td >
< td >
{% if domain.is_active %}
< span class = "badge bg-success" >
< i class = "bi bi-check-circle me-1" > < / i >
Active
< / span >
{% else %}
< span class = "badge bg-danger" >
< i class = "bi bi-x-circle me-1" > < / i >
Inactive
< / span >
{% endif %}
< / td >
< td >
< small class = "text-muted" >
{{ domain.created_at.strftime('%Y-%m-%d %H:%M') }}
< / small >
< / td >
< td >
< span class = "badge bg-info" >
2025-06-08 22:51:07 +01:00
{{ domain.users|length }} senders
2025-06-07 10:48:03 +01:00
< / span >
< / td >
< td >
2025-06-08 22:51:07 +01:00
{% set active_dkim_keys = domain.dkim_keys|selectattr('is_active')|list %}
{% if active_dkim_keys %}
< span class = "dns-status" id = "dkim-status-{{ domain.domain_name.replace('.', '-') }}" >
< span class = "status-indicator status-warning" > < / span >
< i class = "bi bi-shield-check" title = "DKIM Active (DNS not checked)" > < / i >
2025-06-07 10:48:03 +01:00
< / span >
{% else %}
2025-06-08 22:51:07 +01:00
{% if domain.dkim_keys|length > 0 %}
< span class = "text-secondary" >
< i class = "bi bi-shield" title = "DKIM Disabled" > < / i >
< / span >
{% else %}
< span class = "text-danger" >
< i class = "bi bi-shield-exclamation" title = "No DKIM Key" > < / i >
< / span >
{% endif %}
2025-06-07 10:48:03 +01:00
{% endif %}
< / td >
< td >
< div class = "btn-group btn-group-sm" role = "group" >
2025-06-07 11:57:21 +01:00
<!-- Edit Button -->
< a href = "{{ url_for('email.edit_domain', domain_id=domain.id) }}"
class = "btn btn-outline-primary"
title = "Edit Domain" >
< i class = "bi bi-pencil" > < / i >
2025-06-07 10:48:03 +01:00
< / a >
2025-06-07 11:57:21 +01:00
<!-- Toggle Enable/Disable Button -->
< form method = "post" action = "{{ url_for('email.toggle_domain', domain_id=domain.id) }}" class = "d-inline" >
{% if domain.is_active %}
2025-06-07 10:48:03 +01:00
< button type = "submit"
2025-06-07 11:57:21 +01:00
class = "btn btn-outline-warning"
onclick = "return confirm('Are you sure you want to disable domain \'{{ domain.domain_name }}\'?')"
title = "Disable Domain" >
< i class = "bi bi-pause-circle" > < / i >
2025-06-07 10:48:03 +01:00
< / button >
2025-06-07 11:57:21 +01:00
{% else %}
< button type = "submit"
class = "btn btn-outline-success"
onclick = "return confirm('Are you sure you want to enable domain \'{{ domain.domain_name }}\'?')"
title = "Enable Domain" >
< i class = "bi bi-play-circle" > < / i >
< / button >
{% endif %}
< / form >
<!-- Remove Button -->
< form method = "post" action = "{{ url_for('email.remove_domain', domain_id=domain.id) }}" class = "d-inline" >
< button type = "submit"
class = "btn btn-outline-danger"
onclick = "return confirm('WARNING: This will permanently delete domain \'{{ domain.domain_name }}\' and ALL associated data (users, IPs, DKIM keys). This action cannot be undone. Are you sure you want to continue?')"
title = "Permanently Remove Domain" >
< i class = "bi bi-trash" > < / i >
< / button >
< / form >
2025-06-07 10:48:03 +01:00
< / div >
< / td >
< / tr >
{% endfor %}
< / tbody >
< / table >
< / div >
{% else %}
< div class = "text-center py-5" >
< i class = "bi bi-globe text-muted" style = "font-size: 4rem;" > < / i >
< h4 class = "text-muted mt-3" > No domains configured< / h4 >
< p class = "text-muted" > Get started by adding your first domain< / p >
< a href = "{{ url_for('email.add_domain') }}" class = "btn btn-primary" >
< i class = "bi bi-plus-circle me-2" > < / i >
Add Your First Domain
< / a >
< / div >
{% endif %}
< / div >
< / div >
{% if domains %}
< div class = "row mt-4" >
< div class = "col-md-6" >
< div class = "card" >
< div class = "card-header" >
< h6 class = "mb-0" >
< i class = "bi bi-info-circle me-2" > < / i >
Domain Information
< / h6 >
< / div >
< div class = "card-body" >
< ul class = "list-unstyled mb-0" >
< li class = "mb-2" >
< i class = "bi bi-check-circle text-success me-2" > < / i >
< strong > Active domains:< / strong > {{ domains|selectattr('is_active')|list|length }}
< / li >
< li class = "mb-2" >
< i class = "bi bi-shield-check text-warning me-2" > < / i >
2025-06-08 22:51:07 +01:00
< strong > DKIM configured:< / strong >
{% set dkim_count = namespace(active=0) %}
{% for domain in domains %}
{% set active_dkim_keys = domain.dkim_keys|selectattr('is_active')|list %}
{% if active_dkim_keys %}
{% set dkim_count.active = dkim_count.active + 1 %}
{% endif %}
{% endfor %}
{{ dkim_count.active }}
2025-06-07 10:48:03 +01:00
< / li >
< / ul >
< / div >
< / div >
< / div >
< div class = "col-md-6" >
< div class = "card" >
< div class = "card-header" >
< h6 class = "mb-0" >
< i class = "bi bi-lightbulb me-2" > < / i >
Quick Tips
< / h6 >
< / div >
< div class = "card-body" >
< ul class = "list-unstyled mb-0" >
< li class = "mb-2" >
< i class = "bi bi-arrow-right text-primary me-2" > < / i >
DKIM keys are automatically generated for new domains
< / li >
< li class = "mb-2" >
< i class = "bi bi-arrow-right text-primary me-2" > < / i >
Configure DNS records after adding domains
< / li >
< li >
< i class = "bi bi-arrow-right text-primary me-2" > < / i >
2025-06-08 22:51:07 +01:00
Add senders or whitelist IPs for authentication
2025-06-07 10:48:03 +01:00
< / li >
< / ul >
< / div >
< / div >
< / div >
< / div >
{% endif %}
{% endblock %}
2025-06-08 22:51:07 +01:00
{% block extra_js %}
< script >
async function checkDomainDKIM ( domain , selector ) {
const dkimStatus = document . getElementById ( ` dkim-status- ${ domain . replace ( '.' , '-' ) } ` ) ;
if ( ! dkimStatus ) return ;
try {
// Check DKIM DNS
const response = await fetch ( "{{ url_for('email.check_dkim_dns') }}" , {
method : 'POST' ,
headers : {
'Content-Type' : 'application/x-www-form-urlencoded'
} ,
body : new URLSearchParams ( {
domain : domain ,
selector : selector
} )
} ) ;
const result = await response . json ( ) ;
if ( result . success ) {
dkimStatus . innerHTML = `
<span class="status-indicator status-success"></span>
<i class="bi bi-shield-check" title="DKIM Active & DNS Configured"></i>
` ;
} else {
dkimStatus . innerHTML = `
<span class="status-indicator" style="background-color: #fd7e14;"></span>
<i class="bi bi-shield-exclamation" title="DKIM Active but DNS not found"></i>
` ;
}
} catch ( error ) {
console . error ( 'DKIM DNS check error:' , error ) ;
dkimStatus . innerHTML = `
<span class="status-indicator status-danger"></span>
<i class="bi bi-shield-x" title="Error checking DKIM DNS"></i>
` ;
}
}
// Check DKIM DNS for all domains when page loads
document . addEventListener ( 'DOMContentLoaded' , async function ( ) {
{ % for domain in domains % }
{ % set active _dkim _keys = domain . dkim _keys | selectattr ( 'is_active' ) | list % }
{ % if active _dkim _keys % }
{ % set active _key = active _dkim _keys | first % }
await checkDomainDKIM ( '{{ domain.domain_name }}' , '{{ active_key.selector }}' ) ;
{ % endif % }
{ % endfor % }
} ) ;
< / script >
< style >
. status-indicator {
width : 8 px ;
height : 8 px ;
border-radius : 50 % ;
display : inline-block ;
margin-right : 0.5 rem ;
}
. status-success { background-color : #28a745 ; }
. status-warning { background-color : #ffc107 ; }
. status-danger { background-color : #dc3545 ; }
. dns-status {
display : inline-flex ;
align-items : center ;
}
< / style >
{% endblock %}