add SPF check
This commit is contained in:
parent
1598fd8f36
commit
6723487a23
|
@ -28,16 +28,17 @@
|
||||||
|
|
||||||
{% if not custom_domain.verified %}
|
{% if not custom_domain.verified %}
|
||||||
<hr>
|
<hr>
|
||||||
Please follow the following steps to set up your domain: <br>
|
<div class="mb-3">Please follow the following steps to set up your domain: </div>
|
||||||
|
|
||||||
<div>
|
<div class="row">
|
||||||
<span class="badge badge-primary badge-pill mr-2">1</span>
|
<div class="col-1">
|
||||||
Add the following MX DNS record to your domain
|
<span class="badge badge-primary badge-pill">1</span>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="ml-6 mt-3">
|
<div class="col-11">
|
||||||
|
Add the following MX DNS record to your domain
|
||||||
{% for priority, email_server in EMAIL_SERVERS_WITH_PRIORITY %}
|
{% for priority, email_server in EMAIL_SERVERS_WITH_PRIORITY %}
|
||||||
<div class="ml-3 text-info">
|
<div class="ml-2 mb-3 p-3" style="background-color: #eee">
|
||||||
Domain: <em>{{ custom_domain.domain }}</em> <br>
|
Domain: <em>{{ custom_domain.domain }}</em> <br>
|
||||||
Priority: 10 <br>
|
Priority: 10 <br>
|
||||||
Target: <em>{{ email_server }}</em> <br>
|
Target: <em>{{ email_server }}</em> <br>
|
||||||
|
@ -46,19 +47,48 @@
|
||||||
|
|
||||||
Or if you edit your DNS record in text format, use the following code: <br>
|
Or if you edit your DNS record in text format, use the following code: <br>
|
||||||
|
|
||||||
<pre class="ml-3">
|
<pre class="ml-3">{% for priority, email_server in EMAIL_SERVERS_WITH_PRIORITY %}{{ custom_domain.domain }} IN MX {{ priority }} {{ email_server }}<br>{% endfor %}</pre>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-1"><span class="badge badge-primary badge-pill">2</span></div>
|
||||||
|
<div class="col-11">
|
||||||
|
<span class="font-weight-bold">[Optional]</span>
|
||||||
|
Setup <a href="https://en.wikipedia.org/wiki/Sender_Policy_Framework" target="_blank">
|
||||||
|
SPF <i class="fe fe-external-link"></i></a> record.
|
||||||
|
This can avoid emails forwarded to your personal inbox classified as spam. <br>
|
||||||
|
Please note that some email providers can still classify these forwards as spam, in this case
|
||||||
|
do not hesitate to create rules to avoid these emails mistakenly gone into spam.
|
||||||
|
You can find how to whitelist a domain on
|
||||||
|
<a href="https://www.simplelogin.io/help" target="_blank">Whitelist domain<i class="fe fe-external-link"></i></a><br>
|
||||||
|
|
||||||
|
Please add the following TXT DNS record to your domain:
|
||||||
|
|
||||||
|
<div class="ml-3 mb-2 p-3" style="background-color: #eee">
|
||||||
|
Domain: <em>{{ custom_domain.domain }}</em> <br>
|
||||||
|
Value:
|
||||||
|
<em>
|
||||||
|
v=spf1
|
||||||
{% for priority, email_server in EMAIL_SERVERS_WITH_PRIORITY %}
|
{% for priority, email_server in EMAIL_SERVERS_WITH_PRIORITY %}
|
||||||
{{ custom_domain.domain }} IN MX {{ priority }} {{ email_server }}
|
include:{{ email_server[:-1] }}
|
||||||
{% endfor %}
|
{% endfor %} -all
|
||||||
</pre>
|
</em>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div>
|
Or if you edit your DNS record in text format, use the following code: <br>
|
||||||
<span class="badge badge-primary badge-pill mr-2">2</span>
|
|
||||||
|
<pre class="ml-3">{{ custom_domain.domain }} IN TXT "v=spf1 {% for priority, email_server in EMAIL_SERVERS_WITH_PRIORITY %}include:{{ email_server[:-1] }} {% endfor %}-all"</pre>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-1">
|
||||||
|
<span class="badge badge-primary badge-pill mr-2">3</span>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="col-11">
|
||||||
Verify 👇🏽
|
Verify 👇🏽
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="ml-6 mt-3">
|
|
||||||
<form method="post">
|
<form method="post">
|
||||||
<input type="hidden" name="form-name" value="check-domain">
|
<input type="hidden" name="form-name" value="check-domain">
|
||||||
<input type="hidden" name="custom-domain-id" value="{{ custom_domain.id }}">
|
<input type="hidden" name="custom-domain-id" value="{{ custom_domain.id }}">
|
||||||
|
@ -73,6 +103,7 @@
|
||||||
|
|
||||||
As the change could take up to 24 hours, do not hesitate to come back to this page and verify again.
|
As the change could take up to 24 hours, do not hesitate to come back to this page and verify again.
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
|
@ -5,7 +5,7 @@ from wtforms import StringField, validators
|
||||||
|
|
||||||
from app.config import EMAIL_SERVERS_WITH_PRIORITY, EMAIL_SERVERS
|
from app.config import EMAIL_SERVERS_WITH_PRIORITY, EMAIL_SERVERS
|
||||||
from app.dashboard.base import dashboard_bp
|
from app.dashboard.base import dashboard_bp
|
||||||
from app.dns_utils import get_mx_domains
|
from app.dns_utils import get_mx_domains, get_spf_domain
|
||||||
from app.email_utils import notify_admin
|
from app.email_utils import notify_admin
|
||||||
from app.extensions import db
|
from app.extensions import db
|
||||||
from app.models import CustomDomain
|
from app.models import CustomDomain
|
||||||
|
@ -75,11 +75,17 @@ def custom_domain():
|
||||||
flash("You cannot delete this domain", "warning")
|
flash("You cannot delete this domain", "warning")
|
||||||
return redirect(url_for("dashboard.custom_domain"))
|
return redirect(url_for("dashboard.custom_domain"))
|
||||||
else:
|
else:
|
||||||
|
spf_domains = get_spf_domain(custom_domain.domain)
|
||||||
|
for email_server in EMAIL_SERVERS:
|
||||||
|
email_server = email_server[:-1] # remove the trailing .
|
||||||
|
if email_server not in spf_domains:
|
||||||
|
flash(f"{email_server} is not included in your SPF record.", "warning")
|
||||||
|
|
||||||
mx_domains = get_mx_domains(custom_domain.domain)
|
mx_domains = get_mx_domains(custom_domain.domain)
|
||||||
if mx_domains != EMAIL_SERVERS:
|
if mx_domains != EMAIL_SERVERS:
|
||||||
errors[
|
errors[
|
||||||
custom_domain.id
|
custom_domain.id
|
||||||
] = f"Your DNS is not correctly set. The MX record we obtain is {mx_domains}"
|
] = f"""Your DNS is not correctly set. The MX record we obtain is: {",".join(mx_domains)}"""
|
||||||
else:
|
else:
|
||||||
flash(
|
flash(
|
||||||
"Your domain is verified. Now it can be used to create custom alias",
|
"Your domain is verified. Now it can be used to create custom alias",
|
||||||
|
|
|
@ -11,3 +11,28 @@ def get_mx_domains(hostname) -> [str]:
|
||||||
ret.append(r)
|
ret.append(r)
|
||||||
|
|
||||||
return ret
|
return ret
|
||||||
|
|
||||||
|
|
||||||
|
_include_spf = "include:"
|
||||||
|
|
||||||
|
|
||||||
|
def get_spf_domain(hostname) -> [str]:
|
||||||
|
"""return all domains listed in *include:*"""
|
||||||
|
try:
|
||||||
|
answers = dns.resolver.query(hostname, "TXT")
|
||||||
|
except dns.resolver.NoAnswer:
|
||||||
|
return []
|
||||||
|
|
||||||
|
ret = []
|
||||||
|
|
||||||
|
for a in answers: # type: dns.rdtypes.ANY.TXT.TXT
|
||||||
|
for record in a.strings:
|
||||||
|
record = record.decode() # record is bytes
|
||||||
|
|
||||||
|
if record.startswith("v=spf1"):
|
||||||
|
parts = record.split(" ")
|
||||||
|
for part in parts:
|
||||||
|
if part.startswith(_include_spf):
|
||||||
|
ret.append(part[part.find(_include_spf) + len(_include_spf) :])
|
||||||
|
|
||||||
|
return ret
|
||||||
|
|
Loading…
Reference in a new issue