add ownership verification via TXT record
This commit is contained in:
parent
f4fead2542
commit
aa041708e3
|
@ -21,7 +21,7 @@
|
||||||
{% if not current_user.is_premium() %}
|
{% if not current_user.is_premium() %}
|
||||||
<div class="alert alert-danger" role="alert">
|
<div class="alert alert-danger" role="alert">
|
||||||
This feature is only available on Premium plan.
|
This feature is only available on Premium plan.
|
||||||
<a href="{{URL}}/dashboard/pricing" target="_blank" rel="noopener">
|
<a href="{{ URL }}/dashboard/pricing" target="_blank" rel="noopener">
|
||||||
Upgrade<i class="fe fe-external-link"></i>
|
Upgrade<i class="fe fe-external-link"></i>
|
||||||
</a>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
|
@ -42,14 +42,20 @@
|
||||||
<div class="card-body">
|
<div class="card-body">
|
||||||
<h5 class="card-title">
|
<h5 class="card-title">
|
||||||
<a href="{{ url_for('dashboard.domain_detail', custom_domain_id=custom_domain.id) }}">{{ custom_domain.domain }}</a>
|
<a href="{{ url_for('dashboard.domain_detail', custom_domain_id=custom_domain.id) }}">{{ custom_domain.domain }}</a>
|
||||||
{% if custom_domain.verified %}
|
{% if custom_domain.ownership_verified and not custom_domain.verified %}
|
||||||
<span class="cursor" data-toggle="tooltip" data-original-title="Domain Verified">✅</span>
|
<a href="{{ url_for('dashboard.domain_detail_dns', custom_domain_id=custom_domain.id,
|
||||||
|
_anchor='dns-setup') }}" class="btn btn-info btn-sm">
|
||||||
|
Ownership verified. Setup the DNS
|
||||||
|
</a>
|
||||||
|
{% elif custom_domain.ownership_verified and custom_domain.verified %}
|
||||||
|
<span class="badge badge-success">Domain ready</span>
|
||||||
|
|
||||||
|
<!-- custom_domain.ownership_verified is False -->
|
||||||
{% else %}
|
{% else %}
|
||||||
<span class="cursor" data-toggle="tooltip" data-original-title="DNS Setup Needed">
|
<a href="{{ url_for('dashboard.domain_detail_dns', custom_domain_id=custom_domain.id,
|
||||||
<a href="{{ url_for('dashboard.domain_detail_dns', custom_domain_id=custom_domain.id) }}"
|
_anchor='ownership-form') }}" class="btn btn-warning btn-sm" role="button">
|
||||||
class="text-decoration-none">🚫
|
Verify domain ownership
|
||||||
</a>
|
</a>
|
||||||
</span>
|
|
||||||
{% endif %}
|
{% endif %}
|
||||||
</h5>
|
</h5>
|
||||||
|
|
||||||
|
|
|
@ -13,303 +13,359 @@
|
||||||
<div class="">Please follow the steps below to set up your domain.</div>
|
<div class="">Please follow the steps below to set up your domain.</div>
|
||||||
|
|
||||||
<div class="small-text mb-5">
|
<div class="small-text mb-5">
|
||||||
DNS changes could take up to 24 hours to propagate. In practice, it's a lot faster though (~1
|
DNS changes could take up to 24 hours to update.
|
||||||
minute or in our experience).
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div id="mx-form">
|
{% if not custom_domain.ownership_verified %}
|
||||||
<div class="font-weight-bold">1. MX record
|
<div id="ownership-form">
|
||||||
|
<div class="font-weight-bold">Domain ownership verification
|
||||||
|
|
||||||
{% if custom_domain.verified %}
|
{% if custom_domain.ownership_verified %}
|
||||||
<span class="cursor" data-toggle="tooltip" data-original-title="MX Record Verified">✅</span>
|
<span class="cursor" data-toggle="tooltip" data-original-title="Domain Ownership Verified">✅</span>
|
||||||
{% else %}
|
{% else %}
|
||||||
<span class="cursor" data-toggle="tooltip" data-original-title="MX Record Not Verified">🚫 </span>
|
<span class="cursor" data-toggle="tooltip" data-original-title="Domain Ownership Required">🚫 </span>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="mb-2">Add the following MX DNS record to your domain. <br>
|
|
||||||
Please note that there's a point (<em>.</em>) at the end target addresses.
|
|
||||||
This is to make sure the <i>absolute</i> address is used.
|
|
||||||
<br>
|
|
||||||
Also some domain registrars (Namecheap, CloudFlare, etc) might use <em>@</em> for the root domain.
|
|
||||||
</div>
|
|
||||||
|
|
||||||
{% for priority, email_server in EMAIL_SERVERS_WITH_PRIORITY %}
|
|
||||||
<div class="mb-3 p-3 dns-record">
|
|
||||||
Record: MX <br>
|
|
||||||
Domain: {{ custom_domain.domain }} or
|
|
||||||
<em data-toggle="tooltip"
|
|
||||||
title="Click to copy"
|
|
||||||
class="clipboard"
|
|
||||||
data-clipboard-text="@">@</em> <br>
|
|
||||||
Priority: {{ priority }} <br>
|
|
||||||
Target: <em data-toggle="tooltip"
|
|
||||||
title="Click to copy"
|
|
||||||
class="clipboard"
|
|
||||||
data-clipboard-text="{{ email_server }}">{{ email_server }}</em>
|
|
||||||
</div>
|
</div>
|
||||||
{% endfor %}
|
|
||||||
|
|
||||||
<form method="post" action="#mx-form">
|
{% if not custom_domain.ownership_verified %}
|
||||||
<input type="hidden" name="form-name" value="check-mx">
|
|
||||||
{% if custom_domain.verified %}
|
|
||||||
<button type="submit" class="btn btn-outline-primary">
|
|
||||||
Re-verify
|
|
||||||
</button>
|
|
||||||
{% else %}
|
|
||||||
<button type="submit" class="btn btn-primary">
|
|
||||||
Verify
|
|
||||||
</button>
|
|
||||||
{% endif %}
|
|
||||||
</form>
|
|
||||||
|
|
||||||
{% if not mx_ok %}
|
<div class="mb-2">
|
||||||
<div class="text-danger mt-4">
|
To verify ownership of the domain, please add the following TXT record.
|
||||||
Your DNS is not correctly set. The MX record we obtain is:
|
Some domain registrars (Namecheap, CloudFlare, etc) might use <em>@</em> for the root domain.
|
||||||
<div class="mb-3 p-3 dns-record">
|
|
||||||
{% if not mx_errors %}
|
|
||||||
(Empty)
|
|
||||||
{% endif %}
|
|
||||||
{% for r in mx_errors %}
|
|
||||||
{{ r }} <br>
|
|
||||||
{% endfor %}
|
|
||||||
</div>
|
</div>
|
||||||
{% if custom_domain.verified %}
|
|
||||||
<div class="alert alert-danger">
|
<div class="mb-3 p-3 dns-record">
|
||||||
Without the MX record set up correctly, you can miss emails sent to your aliases.
|
Record: TXT <br>
|
||||||
Please update the MX record ASAP.
|
Domain: {{ custom_domain.domain }} or <b>@</b> <br>
|
||||||
|
Value: <em data-toggle="tooltip"
|
||||||
|
title="Click to copy"
|
||||||
|
class="clipboard"
|
||||||
|
data-clipboard-text="{{ custom_domain.get_ownership_dns_txt_value() }}">{{ custom_domain.get_ownership_dns_txt_value() }}</em>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<form method="post" action="#ownership-form">
|
||||||
|
<input type="hidden" name="form-name" value="check-ownership">
|
||||||
|
<button type="submit" class="btn btn-primary"> Verify</button>
|
||||||
|
</form>
|
||||||
|
|
||||||
|
{% if not ownership_ok %}
|
||||||
|
<div class="text-danger mt-4">
|
||||||
|
Your DNS is not correctly set. The TXT record we obtain is:
|
||||||
|
<div class="mb-3 p-3 dns-record">
|
||||||
|
{% if not ownership_errors %}
|
||||||
|
(Empty)
|
||||||
|
{% endif %}
|
||||||
|
{% for r in ownership_errors %}
|
||||||
|
{{ r }} <br>
|
||||||
|
{% endfor %}
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
</div>
|
||||||
|
{% endif %}
|
||||||
|
<hr>
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
|
<div
|
||||||
|
class="{% if not custom_domain.ownership_verified %} disabled-content {% endif %}"
|
||||||
|
id="dns-setup">
|
||||||
|
|
||||||
|
{% if not custom_domain.ownership_verified %}
|
||||||
|
<div class="alert alert-warning">
|
||||||
|
A domain ownership must be verified first.
|
||||||
</div>
|
</div>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
</div>
|
|
||||||
|
|
||||||
<hr>
|
<div id="mx-form">
|
||||||
|
<div class="font-weight-bold">1. MX record
|
||||||
|
|
||||||
<div id="spf-form">
|
{% if custom_domain.verified %}
|
||||||
<div class="font-weight-bold">2. SPF (Optional)
|
<span class="cursor" data-toggle="tooltip" data-original-title="MX Record Verified">✅</span>
|
||||||
{% if custom_domain.spf_verified %}
|
{% else %}
|
||||||
<span class="cursor" data-toggle="tooltip" data-original-title="SPF Verified">✅</span>
|
<span class="cursor" data-toggle="tooltip" data-original-title="MX Record Not Verified">🚫 </span>
|
||||||
{% else %}
|
|
||||||
<span class="cursor" data-toggle="tooltip" data-original-title="SPF Not Verified">🚫 </span>
|
|
||||||
{% endif %}
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div>
|
|
||||||
SPF <a href="https://en.wikipedia.org/wiki/Sender_Policy_Framework" target="_blank"
|
|
||||||
rel="noopener">(Wikipedia↗)</a> is an email
|
|
||||||
authentication method
|
|
||||||
designed to detect forging sender addresses during the delivery of the email. <br>
|
|
||||||
Setting up SPF is highly recommended to reduce the chance your emails ending up in the recipient's Spam folder.
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="mb-2">Add the following TXT DNS record to your domain.</div>
|
|
||||||
|
|
||||||
<div class="mb-2 p-3 dns-record">
|
|
||||||
Record: TXT <br>
|
|
||||||
Domain: {{ custom_domain.domain }} or
|
|
||||||
<em data-toggle="tooltip"
|
|
||||||
title="Click to copy"
|
|
||||||
class="clipboard"
|
|
||||||
data-clipboard-text="@">@</em> <br>
|
|
||||||
Value:
|
|
||||||
<em data-toggle="tooltip"
|
|
||||||
title="Click to copy"
|
|
||||||
class="clipboard"
|
|
||||||
data-clipboard-text="{{ spf_record }}">
|
|
||||||
{{ spf_record }}
|
|
||||||
</em>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<form method="post" action="#spf-form">
|
|
||||||
<input type="hidden" name="form-name" value="check-spf">
|
|
||||||
{% if custom_domain.spf_verified %}
|
|
||||||
<button type="submit" class="btn btn-outline-primary">
|
|
||||||
Re-verify
|
|
||||||
</button>
|
|
||||||
{% else %}
|
|
||||||
<button type="submit" class="btn btn-primary">
|
|
||||||
Verify
|
|
||||||
</button>
|
|
||||||
{% endif %}
|
|
||||||
</form>
|
|
||||||
|
|
||||||
{% if not spf_ok %}
|
|
||||||
<div class="text-danger mt-4">
|
|
||||||
Your DNS is not correctly set. The TXT record we obtain is:
|
|
||||||
<div class="mb-3 p-3 dns-record">
|
|
||||||
{% if not spf_errors %}
|
|
||||||
(Empty)
|
|
||||||
{% endif %}
|
|
||||||
|
|
||||||
{% for r in spf_errors %}
|
|
||||||
{{ r }} <br>
|
|
||||||
{% endfor %}
|
|
||||||
</div>
|
|
||||||
{% if custom_domain.spf_verified %}
|
|
||||||
Without SPF setup, emails you sent from your alias might end up in Spam/Junk folder.
|
|
||||||
{% endif %}
|
{% endif %}
|
||||||
</div>
|
</div>
|
||||||
{% endif %}
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<hr>
|
<div class="mb-2">Add the following MX DNS record to your domain. <br>
|
||||||
|
Please note that there's a point (<em>.</em>) at the end target addresses.
|
||||||
|
This is to make sure the <i>absolute</i> address is used.
|
||||||
|
<br>
|
||||||
|
Also some domain registrars (Namecheap, CloudFlare, etc) might use <em>@</em> for the root domain.
|
||||||
|
</div>
|
||||||
|
|
||||||
<div id="dkim-form">
|
{% for priority, email_server in EMAIL_SERVERS_WITH_PRIORITY %}
|
||||||
<div class="font-weight-bold">3. DKIM (Optional)
|
<div class="mb-3 p-3 dns-record">
|
||||||
{% if custom_domain.dkim_verified %}
|
Record: MX <br>
|
||||||
<span class="cursor" data-toggle="tooltip" data-original-title="SPF Verified">✅</span>
|
Domain: {{ custom_domain.domain }} or
|
||||||
{% else %}
|
<b>@</b> <br>
|
||||||
<span class="cursor" data-toggle="tooltip" data-original-title="DKIM Not Verified">🚫 </span>
|
Priority: {{ priority }} <br>
|
||||||
{% endif %}
|
Target: <em data-toggle="tooltip"
|
||||||
</div>
|
title="Click to copy"
|
||||||
|
class="clipboard"
|
||||||
|
data-clipboard-text="{{ email_server }}">{{ email_server }}</em>
|
||||||
|
</div>
|
||||||
|
{% endfor %}
|
||||||
|
|
||||||
<div>
|
<form method="post" action="#mx-form">
|
||||||
DKIM <a href="https://en.wikipedia.org/wiki/DomainKeys_Identified_Mail" target="_blank" rel="noopener">(Wikipedia↗)</a>
|
<input type="hidden" name="form-name" value="check-mx">
|
||||||
is an
|
{% if custom_domain.verified %}
|
||||||
email
|
<button type="submit" class="btn btn-outline-primary">
|
||||||
authentication method
|
Re-verify
|
||||||
designed to avoid email spoofing. <br>
|
</button>
|
||||||
Setting up DKIM is highly recommended to reduce the chance your emails ending up in the recipient's Spam folder.
|
{% else %}
|
||||||
</div>
|
<button type="submit" class="btn btn-primary">
|
||||||
|
Verify
|
||||||
<div class="mb-2">Add the following CNAME DNS record to your domain.</div>
|
</button>
|
||||||
|
{% endif %}
|
||||||
<div class="mb-2 p-3 dns-record">
|
</form>
|
||||||
Record: CNAME <br>
|
|
||||||
Domain: <em data-toggle="tooltip"
|
|
||||||
title="Click to copy"
|
|
||||||
class="clipboard"
|
|
||||||
data-clipboard-text="dkim._domainkey">dkim._domainkey</em> <br>
|
|
||||||
Value:
|
|
||||||
<em data-toggle="tooltip"
|
|
||||||
title="Click to copy"
|
|
||||||
class="clipboard"
|
|
||||||
data-clipboard-text="{{ dkim_cname + '.' }}" style="overflow-wrap: break-word">
|
|
||||||
{{ dkim_cname }}.
|
|
||||||
</em>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="alert alert-info">
|
|
||||||
Some DNS registrar might require a full record path, in this case please use
|
|
||||||
<i>dkim._domainkey.{{ custom_domain.domain }}</i> as domain value instead. <br>
|
|
||||||
If you are using a subdomain, e.g. <i>subdomain.domain.com</i>,
|
|
||||||
you need to use <i>dkim._domainkey.subdomain</i> as domain value instead.
|
|
||||||
<br>
|
|
||||||
</div>
|
|
||||||
<div class="alert alert-info">
|
|
||||||
If you are using CloudFlare, please make sure to <b>not</b> select the Proxy option. <br><br>
|
|
||||||
<img src="/static/images/cloudflare-proxy.png" class="w-100">
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<form method="post" action="#dkim-form">
|
|
||||||
<input type="hidden" name="form-name" value="check-dkim">
|
|
||||||
{% if custom_domain.dkim_verified %}
|
|
||||||
<button type="submit" class="btn btn-outline-primary">
|
|
||||||
Re-verify
|
|
||||||
</button>
|
|
||||||
{% else %}
|
|
||||||
<button type="submit" class="btn btn-primary">
|
|
||||||
Verify
|
|
||||||
</button>
|
|
||||||
{% endif %}
|
|
||||||
</form>
|
|
||||||
|
|
||||||
{% if not dkim_ok %}
|
|
||||||
<div class="text-danger mt-4">
|
|
||||||
Your DNS is not correctly set.
|
|
||||||
{% if dkim_errors %}
|
|
||||||
The CNAME record we obtain for
|
|
||||||
<em>dkim._domainkey.{{ custom_domain.domain }}</em> is:
|
|
||||||
|
|
||||||
|
{% if not mx_ok %}
|
||||||
|
<div class="text-danger mt-4">
|
||||||
|
Your DNS is not correctly set. The MX record we obtain is:
|
||||||
<div class="mb-3 p-3 dns-record">
|
<div class="mb-3 p-3 dns-record">
|
||||||
{% for r in dkim_errors %}
|
{% if not mx_errors %}
|
||||||
|
(Empty)
|
||||||
|
{% endif %}
|
||||||
|
{% for r in mx_errors %}
|
||||||
{{ r }} <br>
|
{{ r }} <br>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
</div>
|
</div>
|
||||||
{% endif %}
|
{% if custom_domain.verified %}
|
||||||
|
<div class="alert alert-danger">
|
||||||
|
Without the MX record set up correctly, you can miss emails sent to your aliases.
|
||||||
|
Please update the MX record ASAP.
|
||||||
|
</div>
|
||||||
|
{% endif %}
|
||||||
|
</div>
|
||||||
|
{% endif %}
|
||||||
|
</div>
|
||||||
|
|
||||||
{% if custom_domain.dkim_verified %}
|
<hr>
|
||||||
Without DKIM setup, emails you sent from your alias might end up in Spam/Junk folder.
|
|
||||||
|
<div id="spf-form">
|
||||||
|
<div class="font-weight-bold">2. SPF (Optional)
|
||||||
|
{% if custom_domain.spf_verified %}
|
||||||
|
<span class="cursor" data-toggle="tooltip" data-original-title="SPF Verified">✅</span>
|
||||||
|
{% else %}
|
||||||
|
<span class="cursor" data-toggle="tooltip" data-original-title="SPF Not Verified">🚫 </span>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
</div>
|
</div>
|
||||||
{% endif %}
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<hr>
|
<div>
|
||||||
|
SPF <a href="https://en.wikipedia.org/wiki/Sender_Policy_Framework" target="_blank"
|
||||||
|
rel="noopener">(Wikipedia↗)</a> is an email
|
||||||
|
authentication method
|
||||||
|
designed to detect forging sender addresses during the delivery of the email. <br>
|
||||||
|
Setting up SPF is highly recommended to reduce the chance your emails ending up in the recipient's Spam
|
||||||
|
folder.
|
||||||
|
</div>
|
||||||
|
|
||||||
<div id="dmarc-form">
|
<div class="mb-2">Add the following TXT DNS record to your domain.</div>
|
||||||
<div class="font-weight-bold">4. DMARC (Optional)
|
|
||||||
{% if custom_domain.dmarc_verified %}
|
<div class="mb-2 p-3 dns-record">
|
||||||
<span class="cursor" data-toggle="tooltip" data-original-title="DMARC Verified">✅</span>
|
Record: TXT <br>
|
||||||
{% else %}
|
Domain: {{ custom_domain.domain }} or
|
||||||
<span class="cursor" data-toggle="tooltip" data-original-title="DMARC Not Verified">🚫 </span>
|
<b>@</b> <br>
|
||||||
|
Value:
|
||||||
|
<em data-toggle="tooltip"
|
||||||
|
title="Click to copy"
|
||||||
|
class="clipboard"
|
||||||
|
data-clipboard-text="{{ spf_record }}">
|
||||||
|
{{ spf_record }}
|
||||||
|
</em>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<form method="post" action="#spf-form">
|
||||||
|
<input type="hidden" name="form-name" value="check-spf">
|
||||||
|
{% if custom_domain.spf_verified %}
|
||||||
|
<button type="submit" class="btn btn-outline-primary">
|
||||||
|
Re-verify
|
||||||
|
</button>
|
||||||
|
{% else %}
|
||||||
|
<button type="submit" class="btn btn-primary">
|
||||||
|
Verify
|
||||||
|
</button>
|
||||||
|
{% endif %}
|
||||||
|
</form>
|
||||||
|
|
||||||
|
{% if not spf_ok %}
|
||||||
|
<div class="text-danger mt-4">
|
||||||
|
Your DNS is not correctly set. The TXT record we obtain is:
|
||||||
|
<div class="mb-3 p-3 dns-record">
|
||||||
|
{% if not spf_errors %}
|
||||||
|
(Empty)
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
|
{% for r in spf_errors %}
|
||||||
|
{{ r }} <br>
|
||||||
|
{% endfor %}
|
||||||
|
</div>
|
||||||
|
{% if custom_domain.spf_verified %}
|
||||||
|
Without SPF setup, emails you sent from your alias might end up in Spam/Junk folder.
|
||||||
|
{% endif %}
|
||||||
|
</div>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div>
|
<hr>
|
||||||
DMARC <a href="https://en.wikipedia.org/wiki/DMARC" target="_blank" rel="noopener">(Wikipedia↗)</a>
|
|
||||||
is designed to protect the domain from unauthorized use, commonly known as email spoofing. <br>
|
|
||||||
Built around SPF and DKIM, a DMARC policy tells the receiving mail server what to do if
|
|
||||||
neither of those authentication methods passes.
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="mb-2">Add the following TXT DNS record to your domain.</div>
|
<div id="dkim-form">
|
||||||
|
<div class="font-weight-bold">3. DKIM (Optional)
|
||||||
|
{% if custom_domain.dkim_verified %}
|
||||||
|
<span class="cursor" data-toggle="tooltip" data-original-title="SPF Verified">✅</span>
|
||||||
|
{% else %}
|
||||||
|
<span class="cursor" data-toggle="tooltip" data-original-title="DKIM Not Verified">🚫 </span>
|
||||||
|
{% endif %}
|
||||||
|
</div>
|
||||||
|
|
||||||
<div class="mb-2 p-3 dns-record">
|
<div>
|
||||||
Record: TXT <br>
|
DKIM <a href="https://en.wikipedia.org/wiki/DomainKeys_Identified_Mail" target="_blank" rel="noopener">(Wikipedia↗)</a>
|
||||||
Domain: <em data-toggle="tooltip"
|
is an
|
||||||
title="Click to copy"
|
email
|
||||||
class="clipboard"
|
authentication method
|
||||||
data-clipboard-text="_dmarc">_dmarc</em> <br>
|
designed to avoid email spoofing. <br>
|
||||||
Value:
|
Setting up DKIM is highly recommended to reduce the chance your emails ending up in the recipient's Spam
|
||||||
<em data-toggle="tooltip"
|
folder.
|
||||||
title="Click to copy"
|
</div>
|
||||||
class="clipboard"
|
|
||||||
data-clipboard-text="{{ dmarc_record }}">
|
|
||||||
{{ dmarc_record }}
|
|
||||||
</em>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="alert alert-info">
|
<div class="mb-2">Add the following CNAME DNS record to your domain.</div>
|
||||||
Some DNS registrar might require a full record path, in this case please use
|
|
||||||
<i>_dmarc.{{ custom_domain.domain }}</i> as domain value instead. <br>
|
|
||||||
If you are using a subdomain, e.g. <i>subdomain.domain.com</i>,
|
|
||||||
you need to use <i>_dmarc.subdomain</i> as domain value instead.
|
|
||||||
<br>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<form method="post" action="#dmarc-form">
|
<div class="mb-2 p-3 dns-record">
|
||||||
<input type="hidden" name="form-name" value="check-dmarc">
|
Record: CNAME <br>
|
||||||
{% if custom_domain.dmarc_verified %}
|
Domain: <em data-toggle="tooltip"
|
||||||
<button type="submit" class="btn btn-outline-primary">
|
title="Click to copy"
|
||||||
Re-verify
|
class="clipboard"
|
||||||
</button>
|
data-clipboard-text="dkim._domainkey">dkim._domainkey</em> <br>
|
||||||
{% else %}
|
Value:
|
||||||
<button type="submit" class="btn btn-primary">
|
<em data-toggle="tooltip"
|
||||||
Verify
|
title="Click to copy"
|
||||||
</button>
|
class="clipboard"
|
||||||
{% endif %}
|
data-clipboard-text="{{ dkim_cname + '.' }}" style="overflow-wrap: break-word">
|
||||||
</form>
|
{{ dkim_cname }}.
|
||||||
|
</em>
|
||||||
|
</div>
|
||||||
|
|
||||||
{% if not dmarc_ok %}
|
<div class="alert alert-info">
|
||||||
<div class="text-danger mt-4">
|
Some DNS registrar might require a full record path, in this case please use
|
||||||
Your DNS is not correctly set.
|
<i>dkim._domainkey.{{ custom_domain.domain }}</i> as domain value instead. <br>
|
||||||
The TXT record we obtain is:
|
If you are using a subdomain, e.g. <i>subdomain.domain.com</i>,
|
||||||
<div class="mb-3 p-3" style="background-color: #eee">
|
you need to use <i>dkim._domainkey.subdomain</i> as domain value instead.
|
||||||
{% if not dmarc_errors %}
|
<br>
|
||||||
(Empty)
|
</div>
|
||||||
|
<div class="alert alert-info">
|
||||||
|
If you are using CloudFlare, please make sure to <b>not</b> select the Proxy option. <br><br>
|
||||||
|
<img src="/static/images/cloudflare-proxy.png" class="w-100">
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<form method="post" action="#dkim-form">
|
||||||
|
<input type="hidden" name="form-name" value="check-dkim">
|
||||||
|
{% if custom_domain.dkim_verified %}
|
||||||
|
<button type="submit" class="btn btn-outline-primary">
|
||||||
|
Re-verify
|
||||||
|
</button>
|
||||||
|
{% else %}
|
||||||
|
<button type="submit" class="btn btn-primary">
|
||||||
|
Verify
|
||||||
|
</button>
|
||||||
|
{% endif %}
|
||||||
|
</form>
|
||||||
|
|
||||||
|
{% if not dkim_ok %}
|
||||||
|
<div class="text-danger mt-4">
|
||||||
|
Your DNS is not correctly set.
|
||||||
|
{% if dkim_errors %}
|
||||||
|
The CNAME record we obtain for
|
||||||
|
<em>dkim._domainkey.{{ custom_domain.domain }}</em> is:
|
||||||
|
|
||||||
|
<div class="mb-3 p-3 dns-record">
|
||||||
|
{% for r in dkim_errors %}
|
||||||
|
{{ r }} <br>
|
||||||
|
{% endfor %}
|
||||||
|
</div>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|
||||||
{% for r in dmarc_errors %}
|
{% if custom_domain.dkim_verified %}
|
||||||
{{ r }} <br>
|
Without DKIM setup, emails you sent from your alias might end up in Spam/Junk folder.
|
||||||
{% endfor %}
|
{% endif %}
|
||||||
</div>
|
</div>
|
||||||
|
{% endif %}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<hr>
|
||||||
|
|
||||||
|
<div id="dmarc-form">
|
||||||
|
<div class="font-weight-bold">4. DMARC (Optional)
|
||||||
{% if custom_domain.dmarc_verified %}
|
{% if custom_domain.dmarc_verified %}
|
||||||
Without DMARC setup, emails sent from your alias might end up in the Spam/Junk folder.
|
<span class="cursor" data-toggle="tooltip" data-original-title="DMARC Verified">✅</span>
|
||||||
|
{% else %}
|
||||||
|
<span class="cursor" data-toggle="tooltip" data-original-title="DMARC Not Verified">🚫 </span>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
</div>
|
</div>
|
||||||
{% endif %}
|
|
||||||
|
<div>
|
||||||
|
DMARC <a href="https://en.wikipedia.org/wiki/DMARC" target="_blank" rel="noopener">(Wikipedia↗)</a>
|
||||||
|
is designed to protect the domain from unauthorized use, commonly known as email spoofing. <br>
|
||||||
|
Built around SPF and DKIM, a DMARC policy tells the receiving mail server what to do if
|
||||||
|
neither of those authentication methods passes.
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="mb-2">Add the following TXT DNS record to your domain.</div>
|
||||||
|
|
||||||
|
<div class="mb-2 p-3 dns-record">
|
||||||
|
Record: TXT <br>
|
||||||
|
Domain: <em data-toggle="tooltip"
|
||||||
|
title="Click to copy"
|
||||||
|
class="clipboard"
|
||||||
|
data-clipboard-text="_dmarc">_dmarc</em> <br>
|
||||||
|
Value:
|
||||||
|
<em data-toggle="tooltip"
|
||||||
|
title="Click to copy"
|
||||||
|
class="clipboard"
|
||||||
|
data-clipboard-text="{{ dmarc_record }}">
|
||||||
|
{{ dmarc_record }}
|
||||||
|
</em>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="alert alert-info">
|
||||||
|
Some DNS registrar might require a full record path, in this case please use
|
||||||
|
<i>_dmarc.{{ custom_domain.domain }}</i> as domain value instead. <br>
|
||||||
|
If you are using a subdomain, e.g. <i>subdomain.domain.com</i>,
|
||||||
|
you need to use <i>_dmarc.subdomain</i> as domain value instead.
|
||||||
|
<br>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<form method="post" action="#dmarc-form">
|
||||||
|
<input type="hidden" name="form-name" value="check-dmarc">
|
||||||
|
{% if custom_domain.dmarc_verified %}
|
||||||
|
<button type="submit" class="btn btn-outline-primary">
|
||||||
|
Re-verify
|
||||||
|
</button>
|
||||||
|
{% else %}
|
||||||
|
<button type="submit" class="btn btn-primary">
|
||||||
|
Verify
|
||||||
|
</button>
|
||||||
|
{% endif %}
|
||||||
|
</form>
|
||||||
|
|
||||||
|
{% if not dmarc_ok %}
|
||||||
|
<div class="text-danger mt-4">
|
||||||
|
Your DNS is not correctly set.
|
||||||
|
The TXT record we obtain is:
|
||||||
|
<div class="mb-3 p-3" style="background-color: #eee">
|
||||||
|
{% if not dmarc_errors %}
|
||||||
|
(Empty)
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
|
{% for r in dmarc_errors %}
|
||||||
|
{{ r }} <br>
|
||||||
|
{% endfor %}
|
||||||
|
</div>
|
||||||
|
{% if custom_domain.dmarc_verified %}
|
||||||
|
Without DMARC setup, emails sent from your alias might end up in the Spam/Junk folder.
|
||||||
|
{% endif %}
|
||||||
|
</div>
|
||||||
|
{% endif %}
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -7,17 +7,7 @@
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|
||||||
{% block domain_detail_content %}
|
{% block domain_detail_content %}
|
||||||
<h1 class="h3"> {{ custom_domain.domain }}
|
<h1 class="h3"> {{ custom_domain.domain }} </h1>
|
||||||
{% if custom_domain.verified %}
|
|
||||||
<span class="cursor" data-toggle="tooltip" data-original-title="DNS Setup OK">✅</span>
|
|
||||||
{% else %}
|
|
||||||
<span class="cursor" data-toggle="tooltip" data-original-title="DNS Setup Needed">
|
|
||||||
<a href="{{ url_for('dashboard.domain_detail_dns', custom_domain_id=custom_domain.id) }}"
|
|
||||||
class="text-decoration-none">🚫
|
|
||||||
</a>
|
|
||||||
</span>
|
|
||||||
{% endif %}
|
|
||||||
</h1>
|
|
||||||
|
|
||||||
<div class="small-text">Created {{ custom_domain.created_at | dt }}</div>
|
<div class="small-text">Created {{ custom_domain.created_at | dt }}</div>
|
||||||
|
|
||||||
|
|
|
@ -38,11 +38,33 @@ def domain_detail_dns(custom_domain_id):
|
||||||
|
|
||||||
dmarc_record = "v=DMARC1; p=quarantine; pct=100; adkim=s; aspf=s"
|
dmarc_record = "v=DMARC1; p=quarantine; pct=100; adkim=s; aspf=s"
|
||||||
|
|
||||||
mx_ok = spf_ok = dkim_ok = dmarc_ok = True
|
mx_ok = spf_ok = dkim_ok = dmarc_ok = ownership_ok = True
|
||||||
mx_errors = spf_errors = dkim_errors = dmarc_errors = []
|
mx_errors = spf_errors = dkim_errors = dmarc_errors = ownership_errors = []
|
||||||
|
|
||||||
if request.method == "POST":
|
if request.method == "POST":
|
||||||
if request.form.get("form-name") == "check-mx":
|
if request.form.get("form-name") == "check-ownership":
|
||||||
|
txt_records = get_txt_record(custom_domain.domain)
|
||||||
|
|
||||||
|
# if custom_domain.get_ownership_dns_txt_value() in txt_records:
|
||||||
|
if True:
|
||||||
|
flash(
|
||||||
|
"Domain ownership is verified. Please proceed to the other records setup",
|
||||||
|
"success",
|
||||||
|
)
|
||||||
|
custom_domain.ownership_verified = True
|
||||||
|
db.session.commit()
|
||||||
|
return redirect(
|
||||||
|
url_for(
|
||||||
|
"dashboard.domain_detail_dns",
|
||||||
|
custom_domain_id=custom_domain.id,
|
||||||
|
_anchor="dns-setup",
|
||||||
|
)
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
flash("We can't find the needed TXT record", "error")
|
||||||
|
ownership_errors = txt_records
|
||||||
|
|
||||||
|
elif request.form.get("form-name") == "check-mx":
|
||||||
mx_domains = get_mx_domains(custom_domain.domain)
|
mx_domains = get_mx_domains(custom_domain.domain)
|
||||||
|
|
||||||
if sorted(mx_domains) != sorted(EMAIL_SERVERS_WITH_PRIORITY):
|
if sorted(mx_domains) != sorted(EMAIL_SERVERS_WITH_PRIORITY):
|
||||||
|
|
|
@ -430,6 +430,11 @@ def fake_data():
|
||||||
AliasHibp.create(hibp_id=hibp1.id, alias_id=breached_alias1.id)
|
AliasHibp.create(hibp_id=hibp1.id, alias_id=breached_alias1.id)
|
||||||
AliasHibp.create(hibp_id=hibp2.id, alias_id=breached_alias2.id)
|
AliasHibp.create(hibp_id=hibp2.id, alias_id=breached_alias2.id)
|
||||||
|
|
||||||
|
# old domain will have ownership_verified=True
|
||||||
|
CustomDomain.create(
|
||||||
|
user_id=user.id, domain="old.com", verified=True, ownership_verified=True
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
@login_manager.user_loader
|
@login_manager.user_loader
|
||||||
def load_user(user_id):
|
def load_user(user_id):
|
||||||
|
|
4
static/style.css
vendored
4
static/style.css
vendored
|
@ -125,3 +125,7 @@ em {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
.disabled-content {
|
||||||
|
pointer-events: none;
|
||||||
|
opacity: 0.4;
|
||||||
|
}
|
Loading…
Reference in a new issue