email: Show DNS entries for all domains instead of just primary

- Promote reverse DNS information to primary heading.

- Add information that only one domain have reverse DNS configured.

- Clarify that ISP are also responsible for reverse DNS.

- Show reverse DNS records only for primary domain.

Tests:

- View email app. List of domains is shown in the domain section. Primary domain
is marked with a special icon.

- Clicking on the domain works. DNS and reverse DNS information is shown. DKIM
key information is present.

Signed-off-by: Sunil Mohan Adapa <sunil@medhas.org>
Reviewed-by: Benedek Nagy <contact@nbenedek.me>
This commit is contained in:
Sunil Mohan Adapa 2025-01-03 17:57:38 -08:00 committed by Benedek Nagy
parent 900a7e6fdb
commit 055e7603b2
No known key found for this signature in database
GPG Key ID: E167EC84BC1CDBBF
5 changed files with 132 additions and 77 deletions

View File

@ -46,9 +46,8 @@ class Entry: # pylint: disable=too-many-instance-attributes
return ' '.join(pieces)
def get_entries():
"""Return the list of DNS entries to make."""
domain = privileged.domain.get_domains()['primary_domain']
def get_entries(domain: str) -> list[Entry]:
"""Return the list of DNS entries to be set in DNS server for domain."""
mx_spam_entries = [
Entry(type_='MX', value=f'{domain}.'),
Entry(type_='TXT', value='v=spf1 mx a ~all'),
@ -77,10 +76,9 @@ def get_entries():
return mx_spam_entries + dkim_entries + autoconfig_entries
def get_reverse_entries() -> list[Entry]:
def get_reverse_entries(domain: str) -> list[Entry]:
"""Return the list of reverse DNS entries to make."""
entries = []
domain = privileged.domain.get_domains()['primary_domain']
for ip_type in typing.get_args(typing.Literal['ipv4', 'ipv6']):
try:
ip_address = lookup_public_address(ip_type)

View File

@ -0,0 +1,95 @@
{% extends "base.html" %}
{% comment %}
# SPDX-License-Identifier: AGPL-3.0-or-later
{% endcomment %}
{% load i18n %}
{% block content %}
<h3>{% trans "DNS Records for domain:" %} {{ domain }}</h3>
<p>
{% blocktrans trimmed %}
The following DNS records must be added manually on this domain for the
mail server to work properly for this domain.
{% endblocktrans %}
</p>
<div class="table-responsive">
<table class="table table-sm">
<thead>
<tr>
<th>{% trans "Domain" %}</th>
<th>{% trans "TTL" %}</th>
<th>{% trans "Class" %}</th>
<th>{% trans "Type" %}</th>
<th>{% trans "Priority" %}</th>
<th>{% trans "Weight" %}</th>
<th>{% trans "Port" %}</th>
<th>{% trans "Host/Target/Value" %}</th>
</tr>
</thead>
<tbody>
{% for dns_entry in dns_entries %}
<tr>
<td>{{ dns_entry.domain|default_if_none:"" }}</td>
<td>{{ dns_entry.ttl }}</td>
<td>{{ dns_entry.class_ }}</td>
<td>{{ dns_entry.type_ }}</td>
<td>{{ dns_entry.priority }}</td>
<td>{{ dns_entry.weight|default_if_none:"" }}</td>
<td>{{ dns_entry.port|default_if_none:"" }}</td>
<td class="text-break">{{ dns_entry.get_split_value }}</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
{% if domain == primary_domain %}
<h3>{% trans "Reverse DNS Records for IP Addresses" %}</h3>
<p>
{% blocktrans trimmed %}
If your {{ box_name }} runs on a cloud service infrastructure, you
should configure <a href="https://en.wikipedia.org/wiki/Reverse_DNS_lookup">
Reverse DNS lookup</a>. This isn't mandatory, however, it greatly improves
email deliverability. Reverse DNS isn't configured where your regular DNS
is. You should look for it in the settings of your VPS/ISP. Some providers
preconfigure the IP address part for you and you only have to set the
domain part. Only one of your domains can have Revese DNS lookup
configured unless you have multiple public IP addresses.
{% endblocktrans %}
</p>
<p>
{% blocktrans trimmed %}
An external service is used to lookup public IP address to show in the
following section. This can be configured in the privacy app.
{% endblocktrans %}
</p>
<div class="table-responsive">
<table class="table table-sm">
<thead>
<tr>
<th>{% trans "Host" %}</th>
<th>{% trans "TTL" %}</th>
<th>{% trans "Type" %}</th>
<th>{% trans "Host/Target/Value" %}</th>
</tr>
</thead>
<tbody>
{% for dns_entry in reverse_dns_entries %}
<tr>
<td>{{ dns_entry.domain|default_if_none:"" }}</td>
<td>{{ dns_entry.ttl }}</td>
<td>{{ dns_entry.type_ }}</td>
<td class="text-break">{{ dns_entry.get_split_value }}</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
{% endif %}
{% endblock %}

View File

@ -17,82 +17,28 @@
{% endblock %}
{% block extra_content %}
{{ block.super }}
<h3>{% trans "DNS Records" %}</h3>
<h3>{% trans "Domains" %}</h3>
<p>
{% blocktrans trimmed %}
The following DNS records must be added manually on your primary domain
for the mail server to work properly.
The following domains are configured. View details to see the list of DNS
entries to be made for the domain.
{% endblocktrans %}
</p>
<div class="table-responsive">
<table class="table table-sm">
<thead>
<tr>
<th>{% trans "Domain" %}</th>
<th>{% trans "TTL" %}</th>
<th>{% trans "Class" %}</th>
<th>{% trans "Type" %}</th>
<th>{% trans "Priority" %}</th>
<th>{% trans "Weight" %}</th>
<th>{% trans "Port" %}</th>
<th>{% trans "Host/Target/Value" %}</th>
</tr>
</thead>
<tbody>
{% for dns_entry in dns_entries %}
<tr>
<td>{{ dns_entry.domain|default_if_none:"" }}</td>
<td>{{ dns_entry.ttl }}</td>
<td>{{ dns_entry.class_ }}</td>
<td>{{ dns_entry.type_ }}</td>
<td>{{ dns_entry.priority }}</td>
<td>{{ dns_entry.weight|default_if_none:"" }}</td>
<td>{{ dns_entry.port|default_if_none:"" }}</td>
<td class="text-break">{{ dns_entry.get_split_value }}</td>
</tr>
<div class="row">
<div class="col-md-6">
<div class="list-group">
{% for domain in all_domains %}
<div class="list-group-item">
<a href="{% url 'email:dns' domain %}"
title="{% blocktrans %}View domain: {{ domain }}{% endblocktrans %}">
{{ domain }}</a>
{% if domain == primary_domain %}<div class="app-icon fa fa-tag"></div>{% endif %}
</div>
{% endfor %}
</tbody>
</table>
</div>
<h4>{% trans "Reverse DNS" %}</h4>
<p>
{% blocktrans trimmed %}
If your {{ box_name }} runs on a cloud service infrastructure, you
should configure <a href="https://en.wikipedia.org/wiki/Reverse_DNS_lookup">
Reverse DNS lookup</a>. This isn't mandatory, however, it greatly improves
email deliverability. Reverse DNS isn't configured where your regular DNS
is. You should look for it in the settings of your VPS. Some providers
preconfigure the IP address part for you and you only have to set the domain part.
{% endblocktrans %}
</p>
<div class="table-responsive">
<table class="table table-sm">
<thead>
<tr>
<th>{% trans "Host" %}</th>
<th>{% trans "TTL" %}</th>
<th>{% trans "Type" %}</th>
<th>{% trans "Host/Target/Value" %}</th>
</tr>
</thead>
<tbody>
{% for dns_entry in reverse_dns_entries %}
<tr>
<td>{{ dns_entry.domain|default_if_none:"" }}</td>
<td>{{ dns_entry.ttl }}</td>
<td>{{ dns_entry.type_ }}</td>
<td class="text-break">{{ dns_entry.get_split_value }}</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
</div>
</div>
{% endblock %}

View File

@ -3,7 +3,7 @@
URLs for the email module.
"""
from django.urls import path
from django.urls import path, re_path
from stronghold.decorators import public
from plinth.utils import non_admin_view
@ -12,6 +12,8 @@ from . import views
urlpatterns = [
path('apps/email/', views.EmailAppView.as_view(), name='index'),
re_path('apps/email/dns/(?P<domain>[^/]+)/$', views.DnsView.as_view(),
name='dns'),
path('apps/email/aliases/', non_admin_view(views.AliasView.as_view()),
name='aliases'),
path('apps/email/config.xml', public(views.XmlView.as_view())),

View File

@ -25,8 +25,7 @@ class EmailAppView(AppView):
def get_context_data(self, **kwargs):
"""Add additional context data for rendering the template."""
context = super().get_context_data(**kwargs)
context['dns_entries'] = dns.get_entries()
context['reverse_dns_entries'] = dns.get_reverse_entries()
context.update(privileged.domain.get_domains())
return context
def get_initial(self):
@ -51,6 +50,21 @@ class EmailAppView(AppView):
return super().form_valid(form)
class DnsView(TemplateView):
"""Show the DNS records to configure on a given domain."""
template_name = 'email-dns.html'
def get_context_data(self, **kwargs):
"""Add additional context data for rendering the template."""
domain = self.kwargs['domain']
context = super().get_context_data(**kwargs)
primary_domain = privileged.domain.get_domains()['primary_domain']
context['primary_domain'] = primary_domain
context['dns_entries'] = dns.get_entries(domain)
context['reverse_dns_entries'] = dns.get_reverse_entries(domain)
return context
class AliasView(FormView):
"""View to create, list, enable, disable and delete aliases.