4.21.3
This commit is contained in:
138
app/templates/dashboard/domain_detail/auto-create.html
Normal file
138
app/templates/dashboard/domain_detail/auto-create.html
Normal file
@ -0,0 +1,138 @@
|
||||
{% extends "dashboard/domain_detail/base.html" %}
|
||||
|
||||
{% set domain_detail_page = "auto_create" %}
|
||||
{% block title %}{{ custom_domain.domain }} Auto Create Rules{% endblock %}
|
||||
{% block domain_detail_content %}
|
||||
|
||||
<h1 class="h2 mb-1">{{ custom_domain.domain }} auto create alias rules</h1>
|
||||
<div>
|
||||
<span class="badge badge-info">Advanced</span>
|
||||
<span class="badge badge-warning">Beta</span>
|
||||
</div>
|
||||
{% if custom_domain.catch_all %}
|
||||
|
||||
<div class="alert alert-warning mt-3">Rules are ineffective when catch-all is enabled.</div>
|
||||
{% endif %}
|
||||
<div class="{% if custom_domain.catch_all %} disabled-content{% endif %}">
|
||||
<div class="mt-3 mb-2">
|
||||
For a greater control than a simple catch-all, you can define a set of <b>rules</b> to auto create aliases.
|
||||
<br />
|
||||
A rule is based on a regular expression (<b>regex</b>): if an alias <b>fully</b> matches the expression,
|
||||
it'll be automatically created.
|
||||
</div>
|
||||
<div class="alert alert-info">
|
||||
Only the <b>local</b> part of the alias (i.e. <b>@{{ custom_domain.domain }}</b> is ignored) during the
|
||||
regex test.
|
||||
</div>
|
||||
<div class="alert alert-info">When there are several rules, rules will be evaluated by their order.</div>
|
||||
{% if custom_domain.auto_create_rules | length > 0 %}
|
||||
|
||||
<div class="mt-2" id="rule-list">
|
||||
{% for auto_create_rule in custom_domain.auto_create_rules %}
|
||||
|
||||
<div class="card">
|
||||
<div class="card-body">
|
||||
Order: <b>{{ auto_create_rule.order }}</b>
|
||||
<br />
|
||||
<input readonly value="{{ auto_create_rule.regex }}" class="form-control">
|
||||
New alias will belong to
|
||||
{% for mailbox in auto_create_rule.mailboxes %}
|
||||
|
||||
<b>{{ mailbox.email }}</b>
|
||||
{% if not loop.last %},{% endif %}
|
||||
{% endfor %}
|
||||
<form method="post" class="mt-2">
|
||||
<input type="hidden" name="form-name" value="delete-auto-create-rule">
|
||||
<input type="hidden" name="rule-id" value="{{ auto_create_rule.id }}">
|
||||
<button class="btn btn-outline-danger btn-sm float-right">Delete</button>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
{% endfor %}
|
||||
</div>
|
||||
{% endif %}
|
||||
<div class="mt-2" id="new-rule">
|
||||
<hr />
|
||||
<h3>New rule</h3>
|
||||
<form method="post" action="#rule-list" data-parsley-validate>
|
||||
<input type="hidden" name="form-name" value="create-auto-create-rule">
|
||||
{{ new_auto_create_rule_form.csrf_token }}
|
||||
<div class="form-group">
|
||||
<label>Regex</label>
|
||||
{{ new_auto_create_rule_form.regex(class="form-control",
|
||||
placeholder="prefix.*"
|
||||
) }}
|
||||
{{ render_field_errors(new_auto_create_rule_form.regex) }}
|
||||
<div class="small-text">
|
||||
For example, if you want aliases that starts with <b>prefix</b> to be automatically created, you can set
|
||||
the
|
||||
regex to <em data-toggle="tooltip"
|
||||
title="Click to copy"
|
||||
class="clipboard"
|
||||
data-clipboard-text="prefix.*">prefix.*</em>
|
||||
<br />
|
||||
If you want aliases that ends with <b>suffix</b> to be automatically created, you can use the regex
|
||||
<em data-toggle="tooltip"
|
||||
title="Click to copy"
|
||||
class="clipboard"
|
||||
data-clipboard-text=".*suffix">.*suffix</em>
|
||||
<br />
|
||||
To test out regex, we recommend using regex tester tool like
|
||||
<a href="https://regex101.com" target="_blank">https://regex101.com↗</a>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label>Order</label>
|
||||
{{ new_auto_create_rule_form.order(class="form-control", placeholder="10", min=1, value=1, type="number") }}
|
||||
{{ render_field_errors(new_auto_create_rule_form.order) }}
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<div class="flex-grow-1 mr-2">
|
||||
<select data-width="100%"
|
||||
required
|
||||
class="mailbox-select"
|
||||
multiple
|
||||
name="mailbox_ids">
|
||||
{% for mailbox in mailboxes %}
|
||||
|
||||
<option value="{{ mailbox.id }}"
|
||||
{% if mailbox.id == current_user.default_mailbox_id %} selected{% endif %}>
|
||||
{{ mailbox.email }}
|
||||
</option>
|
||||
{% endfor %}
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
<button class="btn btn-primary mt-2">Create</button>
|
||||
</form>
|
||||
</div>
|
||||
<div id="debug-zone">
|
||||
<hr />
|
||||
<h3>Debug Zone</h3>
|
||||
<p>You can test whether an alias will be automatically created given the rules above</p>
|
||||
<div class="alert alert-info">No worries, no alias will be created during the test :)</div>
|
||||
<form method="post" action="#debug-zone">
|
||||
<input type="hidden" name="form-name" value="test-auto-create-rule">
|
||||
{{ auto_create_test_form.csrf_token }}
|
||||
<div class="d-flex">
|
||||
<div class="form-group d-flex">
|
||||
{{ auto_create_test_form.local(class="form-control", type="text", placeholder="local", value=auto_create_test_local) }}
|
||||
{{ render_field_errors(auto_create_test_form.local) }}
|
||||
<b class="pt-2 ml-1">@{{ custom_domain.domain }}</b>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<button class="btn btn-outline-primary">Test</button>
|
||||
</div>
|
||||
</form>
|
||||
{% if auto_create_test_result %}
|
||||
|
||||
<div class="alert {% if auto_create_test_passed %}
|
||||
alert-success {% else %} alert-warning {% endif %}">
|
||||
{{ auto_create_test_result }}
|
||||
</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
{% endblock %}
|
||||
{% block script %}<script>$('.mailbox-select').multipleSelect();</script>{% endblock %}
|
45
app/templates/dashboard/domain_detail/base.html
Normal file
45
app/templates/dashboard/domain_detail/base.html
Normal file
@ -0,0 +1,45 @@
|
||||
{% extends "default.html" %}
|
||||
|
||||
{% if custom_domain.is_sl_subdomain %}
|
||||
|
||||
{% set active_page = "subdomain" %}
|
||||
{% else %}
|
||||
{% set active_page = "custom_domain" %}
|
||||
{% endif %}
|
||||
{% block default_content %}
|
||||
|
||||
<div class="row">
|
||||
<div class="col-lg-3 order-lg-1 mb-4">
|
||||
<div class="list-group list-group-transparent mb-0">
|
||||
<a href="{{ url_for('dashboard.domain_detail', custom_domain_id=custom_domain.id) }}"
|
||||
class="list-group-item list-group-item-action {{ 'active' if domain_detail_page == 'info' }}">
|
||||
<span class="icon mr-3"><i class="fe fe-flag"></i></span>Info
|
||||
</a>
|
||||
{% if not custom_domain.is_sl_subdomain %}
|
||||
|
||||
<a href="{{ url_for('dashboard.domain_detail_dns', custom_domain_id=custom_domain.id) }}"
|
||||
class="list-group-item list-group-item-action {{ 'active' if domain_detail_page == 'dns' }}">
|
||||
<span class="icon mr-3"><i class="fe fe-cloud"></i></span>DNS
|
||||
</a>
|
||||
{% endif %}
|
||||
<a href="{{ url_for('dashboard.domain_detail_trash', custom_domain_id=custom_domain.id) }}"
|
||||
class="list-group-item list-group-item-action {{ 'active' if domain_detail_page == 'trash' }}">
|
||||
<span class="icon mr-3"><i class="fe fe-trash"></i></span>Deleted Alias
|
||||
</a>
|
||||
<a href="{{ url_for('dashboard.domain_detail_auto_create', custom_domain_id=custom_domain.id) }}"
|
||||
class="list-group-item list-group-item-action {{ 'active' if domain_detail_page == 'auto_create' }}">
|
||||
<span class="icon mr-3"><i class="fe fe-layers"></i></span>Auto Create
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-lg-9">
|
||||
<div class="card">
|
||||
<div class="card-body">
|
||||
<div class="text-wrap p-lg-6 domain_detail_content">
|
||||
{% block domain_detail_content %}{% endblock %}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% endblock %}
|
409
app/templates/dashboard/domain_detail/dns.html
Normal file
409
app/templates/dashboard/domain_detail/dns.html
Normal file
@ -0,0 +1,409 @@
|
||||
{% extends "dashboard/domain_detail/base.html" %}
|
||||
|
||||
{% set domain_detail_page = "dns" %}
|
||||
{% block title %}{{ custom_domain.domain }} DNS{% endblock %}
|
||||
{% block domain_detail_content %}
|
||||
|
||||
<div class="p-4 mr-auto" style="max-width: 60rem;">
|
||||
<h1 class="h2">{{ custom_domain.domain }}</h1>
|
||||
<div>Please follow the steps below to set up your domain.</div>
|
||||
<div class="small-text mb-5">DNS changes could take up to 24 hours to update.</div>
|
||||
{% if not custom_domain.ownership_verified %}
|
||||
|
||||
<div id="ownership-form">
|
||||
<div class="font-weight-bold">
|
||||
Domain ownership verification
|
||||
{% if custom_domain.ownership_verified %}
|
||||
|
||||
<span class="cursor"
|
||||
data-toggle="tooltip"
|
||||
data-original-title="Domain Ownership Verified">✅</span>
|
||||
{% else %}
|
||||
<span class="cursor"
|
||||
data-toggle="tooltip"
|
||||
data-original-title="Domain Ownership Required">🚫</span>
|
||||
{% endif %}
|
||||
</div>
|
||||
{% if not custom_domain.ownership_verified %}
|
||||
|
||||
<div class="mb-2">
|
||||
To verify ownership of the domain, please add the following TXT record.
|
||||
Some domain registrars (Namecheap, CloudFlare, etc) might use <em>@</em> for the root domain.
|
||||
</div>
|
||||
<div class="mb-3 p-3 dns-record">
|
||||
Record: TXT
|
||||
<br />
|
||||
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">
|
||||
{{ csrf_form.csrf_token }}
|
||||
<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>
|
||||
{% 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>
|
||||
{% endif %}
|
||||
<div id="mx-form">
|
||||
<div class="font-weight-bold">
|
||||
1. MX record
|
||||
{% if custom_domain.verified %}
|
||||
|
||||
<span class="cursor"
|
||||
data-toggle="tooltip"
|
||||
data-original-title="MX Record Verified">✅</span>
|
||||
{% else %}
|
||||
<span class="cursor"
|
||||
data-toggle="tooltip"
|
||||
data-original-title="MX Record Not Verified">🚫</span>
|
||||
{% endif %}
|
||||
</div>
|
||||
<div class="mb-2">
|
||||
Add the following MX DNS record to your domain.
|
||||
<br />
|
||||
Please note that there's a dot (<em>.</em>) at the end target addresses.
|
||||
If your domain registrar doesn't allow this trailing dot, please remove it when adding the DNS record.
|
||||
<br />
|
||||
Some domain registrars (Namecheap, CloudFlare, etc) might also 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
|
||||
<b>@</b>
|
||||
<br />
|
||||
Priority: {{ priority }}
|
||||
<br />
|
||||
Target: <em data-toggle="tooltip"
|
||||
title="Click to copy"
|
||||
class="clipboard"
|
||||
data-clipboard-text="{{ email_server }}">{{ email_server }}</em>
|
||||
</div>
|
||||
{% endfor %}
|
||||
<form method="post" action="#mx-form">
|
||||
{{ csrf_form.csrf_token }}
|
||||
<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="text-danger mt-4">
|
||||
Your DNS is not correctly set. The MX record we obtain is:
|
||||
<div class="mb-3 p-3 dns-record">
|
||||
{% if not mx_errors %}(Empty){% endif %}
|
||||
{% for r in mx_errors %}
|
||||
|
||||
{{ r }}
|
||||
<br />
|
||||
{% endfor %}
|
||||
</div>
|
||||
{% 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>
|
||||
<hr />
|
||||
<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 %}
|
||||
</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
|
||||
<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">
|
||||
{{ csrf_form.csrf_token }}
|
||||
<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 %}
|
||||
</div>
|
||||
<hr />
|
||||
<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>
|
||||
DKIM
|
||||
<a href="https://en.wikipedia.org/wiki/DomainKeys_Identified_Mail"
|
||||
target="_blank"
|
||||
rel="noopener">(Wikipedia↗)</a>
|
||||
is an
|
||||
email
|
||||
authentication method
|
||||
designed to avoid email spoofing.
|
||||
<br />
|
||||
Setting up DKIM 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 CNAME DNS records to your domain.
|
||||
</div>
|
||||
{% for dkim_prefix, dkim_cname_value in dkim_records %}
|
||||
|
||||
<div class="mb-2 p-3 dns-record">
|
||||
Record: CNAME
|
||||
<br />
|
||||
Domain: <em data-toggle="tooltip"
|
||||
title="Click to copy"
|
||||
class="clipboard"
|
||||
data-clipboard-text="{{ dkim_prefix }}">{{ dkim_prefix }}</em>
|
||||
<br />
|
||||
Value:
|
||||
<em data-toggle="tooltip"
|
||||
title="Click to copy"
|
||||
class="clipboard"
|
||||
data-clipboard-text="{{ dkim_cname_value }}."
|
||||
style="overflow-wrap: break-word">
|
||||
{{ dkim_cname_value }}.
|
||||
</em>
|
||||
</div>
|
||||
{% endfor %}
|
||||
<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">
|
||||
{{ csrf_form.csrf_token }}
|
||||
<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">
|
||||
<p>
|
||||
Your DNS is not correctly set.
|
||||
</p>
|
||||
<ul>
|
||||
{% for custom_record, retrieved_cname in dkim_errors.items() %}
|
||||
|
||||
<li>
|
||||
The CNAME record we obtain for <em>{{ custom_record }}</em> is {{ retrieved_cname }}
|
||||
</li>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
{% if custom_domain.dkim_verified %}
|
||||
|
||||
Without DKIM setup, emails you sent from your alias might end up in Spam/Junk folder.
|
||||
{% endif %}
|
||||
</div>
|
||||
{% if custom_domain.dkim_verified %}
|
||||
|
||||
<div class="text-danger mt-4">
|
||||
DKIM is still enabled. Please update your DKIM settings with all CNAME records
|
||||
</div>
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
</div>
|
||||
<hr />
|
||||
<div id="dmarc-form">
|
||||
<div class="font-weight-bold">
|
||||
4. DMARC (Optional)
|
||||
{% if custom_domain.dmarc_verified %}
|
||||
|
||||
<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 %}
|
||||
</div>
|
||||
<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">
|
||||
{{ csrf_form.csrf_token }}
|
||||
<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>
|
||||
{% endblock %}
|
179
app/templates/dashboard/domain_detail/info.html
Normal file
179
app/templates/dashboard/domain_detail/info.html
Normal file
@ -0,0 +1,179 @@
|
||||
{% extends "dashboard/domain_detail/base.html" %}
|
||||
|
||||
{% set domain_detail_page = "info" %}
|
||||
{% block title %}{{ custom_domain.domain }} Info{% endblock %}
|
||||
{% block domain_detail_content %}
|
||||
|
||||
<h1 class="h2 mb-1">{{ custom_domain.domain }}</h1>
|
||||
<div class="small-text">Created {{ custom_domain.created_at | dt }}. {{ nb_alias }} aliases</div>
|
||||
<hr />
|
||||
<h3 class="mb-1">Auto create/on the fly alias</h3>
|
||||
<div>
|
||||
<form method="post">
|
||||
{{ csrf_form.csrf_token }}
|
||||
<input type="hidden" name="form-name" value="switch-catch-all">
|
||||
<label class="custom-switch cursor mt-2 pl-0" data-toggle="tooltip" {% if custom_domain.catch_all %}
|
||||
title="Disable catch-all" {% else %} title="Enable catch-all" {% endif %}>
|
||||
<input type="checkbox" class="custom-switch-input" {{ "checked" if custom_domain.catch_all else "" }}>
|
||||
<span class="custom-switch-indicator"></span>
|
||||
<spam class="ml-2">
|
||||
Catch All
|
||||
</spam>
|
||||
</label>
|
||||
</form>
|
||||
<div>
|
||||
Simply use <b>anything@{{ custom_domain.domain }}</b>
|
||||
next time you need an alias: it'll be <b>automatically</b>
|
||||
created the first time it receives an email.
|
||||
To have more fine-grained control, you can also define
|
||||
<a href="{{ url_for('dashboard.domain_detail_auto_create', custom_domain_id=custom_domain.id) }}">
|
||||
auto create
|
||||
rules
|
||||
<i class="fe fe-chevrons-right"></i>
|
||||
</a>
|
||||
.
|
||||
</div>
|
||||
</div>
|
||||
<div class="{% if not custom_domain.catch_all %} disabled-content{% endif %}">
|
||||
<div>
|
||||
Auto-created aliases are automatically owned by the following mailboxes
|
||||
<i class="fe fe-corner-right-down"></i>
|
||||
.
|
||||
</div>
|
||||
{% set domain_mailboxes=custom_domain.mailboxes %}
|
||||
<form method="post" class="mt-2">
|
||||
{{ csrf_form.csrf_token }}
|
||||
<input type="hidden" name="form-name" value="update">
|
||||
<input type="hidden" name="domain-id" value="{{ custom_domain.id }}">
|
||||
<div class="d-flex">
|
||||
<div class="flex-grow-1 mr-2">
|
||||
<select data-width="100%"
|
||||
required
|
||||
class="mailbox-select"
|
||||
multiple
|
||||
name="mailbox_ids">
|
||||
{% for mailbox in mailboxes %}
|
||||
|
||||
<option value="{{ mailbox.id }}"
|
||||
{% if mailbox in domain_mailboxes %} selected{% endif %}>
|
||||
{{ mailbox.email }}
|
||||
</option>
|
||||
{% endfor %}
|
||||
</select>
|
||||
</div>
|
||||
<div>
|
||||
<button class="btn btn-outline-primary btn-sm">Update</button>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
<hr />
|
||||
<h3 class="mb-1">Default Display Name</h3>
|
||||
<div>
|
||||
Default display name for aliases created with <b>{{ custom_domain.domain }}</b>
|
||||
unless overwritten by the alias display name.
|
||||
</div>
|
||||
<div>
|
||||
<form method="post" class="form-inline">
|
||||
{{ csrf_form.csrf_token }}
|
||||
<input type="hidden" name="form-name" value="set-name">
|
||||
<div class="form-group">
|
||||
<input class="form-control mr-2"
|
||||
value="{{ custom_domain.name or "" }}"
|
||||
name="alias-name"
|
||||
placeholder="Alias Display Name">
|
||||
</div>
|
||||
<button class="btn btn-outline-primary" name="action" value="save">Save</button>
|
||||
{% if custom_domain.name %}
|
||||
|
||||
<button class="btn btn-outline-danger float-right ml-2"
|
||||
name="action"
|
||||
value="remove">Remove</button>
|
||||
{% endif %}
|
||||
</form>
|
||||
</div>
|
||||
<hr />
|
||||
<h3 class="mb-1">Random Prefix Generation</h3>
|
||||
<div>Add a random prefix for this domain when creating a new alias.</div>
|
||||
<div>
|
||||
<form method="post">
|
||||
{{ csrf_form.csrf_token }}
|
||||
<input type="hidden"
|
||||
name="form-name"
|
||||
value="switch-random-prefix-generation">
|
||||
<label class="custom-switch cursor mt-2 pl-0" data-toggle="tooltip" {% if custom_domain.random_prefix_generation %}
|
||||
title="Disable random prefix generation" {% else %} title="Enable random prefix generation" {% endif %}>
|
||||
<input type="checkbox" class="custom-switch-input" {{ "checked" if custom_domain.random_prefix_generation else "" }}>
|
||||
<span class="custom-switch-indicator"></span>
|
||||
</label>
|
||||
</form>
|
||||
</div>
|
||||
<hr />
|
||||
<h3 class="mb-1">
|
||||
{% if custom_domain.is_sl_subdomain %}
|
||||
|
||||
Delete Subdomain
|
||||
{% else %}
|
||||
Delete Domain
|
||||
{% endif %}
|
||||
</h3>
|
||||
<div class="mb-3">
|
||||
{% if custom_domain.is_sl_subdomain %}
|
||||
|
||||
<div class="alert alert-danger">
|
||||
This operation is <b>irreversible</b>.
|
||||
All aliases associated with this subdomain will be deleted.
|
||||
</div>
|
||||
<div class="alert alert-warning">
|
||||
Because a deleted subdomain can't be recycled, i.e. reused by someone else,
|
||||
deleting a subdomain won't restore the subdomain quota.
|
||||
After deletion, your subdomain quota will still be {{ current_user.subdomain_quota }}.
|
||||
We recommend to disable the <b>catch-all</b> option instead of deleting this subdomain.
|
||||
</div>
|
||||
{% else %}
|
||||
<div class="alert alert-danger">
|
||||
This operation is <b>irreversible</b>.
|
||||
All aliases associated with this domain will be deleted.
|
||||
</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
<form method="post">
|
||||
{{ csrf_form.csrf_token }}
|
||||
<input type="hidden" name="form-name" value="delete">
|
||||
<span class="delete-custom-domain btn btn-danger">Delete {{ custom_domain.domain }}</span>
|
||||
</form>
|
||||
{% endblock %}
|
||||
{% block script %}
|
||||
|
||||
<script>
|
||||
$('.mailbox-select').multipleSelect();
|
||||
|
||||
$(".custom-switch-input").change(function (e) {
|
||||
$(this).closest("form").submit();
|
||||
});
|
||||
|
||||
$(".delete-custom-domain").on("click", function (e) {
|
||||
let that = $(this);
|
||||
|
||||
bootbox.confirm({
|
||||
message: "All aliases associated with <b>{{ custom_domain.domain }}</b> will be also deleted. <br />" +
|
||||
"This operation is not reversible, please confirm.",
|
||||
buttons: {
|
||||
confirm: {
|
||||
label: 'Yes, delete it',
|
||||
className: 'btn-danger'
|
||||
},
|
||||
cancel: {
|
||||
label: 'Cancel',
|
||||
className: 'btn-outline-primary'
|
||||
}
|
||||
},
|
||||
callback: function (result) {
|
||||
if (result) {
|
||||
that.closest("form").submit();
|
||||
}
|
||||
}
|
||||
})
|
||||
});
|
||||
</script>
|
||||
{% endblock %}
|
52
app/templates/dashboard/domain_detail/trash.html
Normal file
52
app/templates/dashboard/domain_detail/trash.html
Normal file
@ -0,0 +1,52 @@
|
||||
{% extends "dashboard/domain_detail/base.html" %}
|
||||
|
||||
{% set domain_detail_page = "trash" %}
|
||||
{% block title %}{{ custom_domain.domain }} deleted aliases{% endblock %}
|
||||
{% block domain_detail_content %}
|
||||
|
||||
<h1 class="h3">
|
||||
{{ custom_domain.domain }} deleted alias (aka Trash)
|
||||
<a class="ml-3 text-info"
|
||||
style="font-size: 12px"
|
||||
data-toggle="collapse"
|
||||
href="#howtouse"
|
||||
role="button"
|
||||
aria-expanded="false"
|
||||
aria-controls="collapseExample">
|
||||
How to use <i class="fe fe-chevrons-down"></i>
|
||||
</a>
|
||||
</h1>
|
||||
<div class="alert alert-primary collapse" id="howtouse" role="alert">
|
||||
On this page you can view all aliases that have been deleted and belong to the domain
|
||||
<b>{{ custom_domain.domain }}</b>.
|
||||
<br />
|
||||
When an alias is in the trash, it cannot be re-created, either via the alias creation page or on-the-fly with the
|
||||
domain catch-all option.
|
||||
</div>
|
||||
{% if domain_deleted_aliases | length > 0 %}
|
||||
|
||||
<form method="post">
|
||||
{{ csrf_form.csrf_token }}
|
||||
<input type="hidden" name="form-name" value="empty-all">
|
||||
<button class="btn btn-outline-danger">Empty Trash</button>
|
||||
<div class="small-text">
|
||||
Remove all deleted aliases from the trash, allowing them to be re-created.
|
||||
That operation is irreversible.
|
||||
</div>
|
||||
</form>
|
||||
{% else %}
|
||||
There's no deleted alias recorded for this domain.
|
||||
{% endif %}
|
||||
{% for deleted_alias in domain_deleted_aliases %}
|
||||
|
||||
<hr />
|
||||
<b>{{ deleted_alias.email }}</b> -
|
||||
deleted {{ deleted_alias.created_at | dt }}
|
||||
<form method="post">
|
||||
{{ csrf_form.csrf_token }}
|
||||
<input type="hidden" name="form-name" value="remove-single">
|
||||
<input type="hidden" name="deleted-alias-id" value="{{ deleted_alias.id }}">
|
||||
<button class="btn btn-sm btn-outline-warning">Remove from trash</button>
|
||||
</form>
|
||||
{% endfor %}
|
||||
{% endblock %}
|
Reference in New Issue
Block a user