Add files via upload

This commit is contained in:
Harold Finch
2023-04-10 07:23:44 +02:00
committed by GitHub
parent 047f85e92d
commit ae35dc5986
56 changed files with 11982 additions and 0 deletions

View File

@@ -0,0 +1,280 @@
{% if session.get('account_is_mail_user') %}
{% extends "layout_user.html" %}
{% else %}
{% extends "layout.html" %}
{% endif %}
{% from "macros/form_inputs.html" import
input_csrf_token
with context
%}
{% from "macros/general.html" import
set_account_activity_img,
show_pages
with context
%}
{% from "macros/amavisd.html" import
display_search_modal,
display_idtabs_of_maillog,
display_icon_of_account_profile
with context
%}
{% from "macros/msg_handlers.html" import amavisd_msg_handler with context %}
{% block title %}
{% if log_type == 'sent' %}
{{ _('Sent Mails') }}
{% elif log_type == 'received' %}
{{ _('Received Mails') }}
{% endif %}
{% endblock %}
{% if session.get('account_is_mail_user') %}
{% block navlinks_rcvd_mails %}class="active"{% endblock %}
{% else %}
{% block navlinks_activities %}class="active"{% endblock %}
{% endif %}
{% block main %}
{# Show system message #}
{{ amavisd_msg_handler(msg) }}
{# Hide sender, recipient, score #}
{% set show_sender = True %}
{% set show_recipient = True %}
{% set show_score = False %}
{% if log_type == 'sent' and account_type == 'user' %}
{% set show_sender = False %}
{% endif %}
{% if log_type == 'received' and account_type == 'user' %}
{% set show_recipient = False %}
{% endif %}
{% if session.get('account_is_mail_user') %}
{% set show_recipient = False %}
{% endif %}
{% if log_type == 'received' %}
{% set show_score = True %}
{% endif %}
{% if log_type == 'sent' %}
{% if account_type == 'domain' %}
{% set tab_title = _('Mails Sent by Domain: %s') |format(account) %}
{% set pages_baseurl = ctx.homepath + '/activities/sent/domain/' + account %}
{% elif account_type == 'user' %}
{% set tab_title = _('Mails Sent by User: %s') |format(account) %}
{% set pages_baseurl = ctx.homepath + '/activities/sent/user/' + account %}
{% else %}
{% set tab_title = _('Sent Mails') %}
{% set pages_baseurl = ctx.homepath + '/activities/sent' %}
{% endif %}
{% elif log_type == 'received' %}
{% if account_type == 'domain' %}
{% set tab_title = _('Received Mails of Domain: %s') |format(account) %}
{% set pages_baseurl = ctx.homepath + '/activities/received/domain/' + account %}
{% elif account_type == 'user' %}
{% set tab_title = _('Received Mails of User: %s') |format(account) %}
{% set pages_baseurl = ctx.homepath + '/activities/received/user/' + account %}
{% else %}
{% set tab_title = _('Received Mails') %}
{% set pages_baseurl = ctx.homepath + '/activities/received' %}
{% endif %}
{% endif %}
<div class="content-box">
<div class="box-body">
{% if session.get('account_is_mail_user') %}
{% set pages_baseurl = ctx.homepath + '/activities/received/user/' + account %}
{% else %}
<div class="box-header clear">
<ul class="tabs clear">
{{ display_idtabs_of_maillog(log_type=log_type, account_type=account_type, account=account) }}
</ul>
<h2>
{{ tab_title }}
{% if total is defined and records |length > 0 %}
({{ (cur_page-1) * page_size_limit + 1 }}-{{ (cur_page-1) * page_size_limit + records |length}}/{{ total }})
{% endif %}
{% if removeLogsInDays > 0 %}
<a href="#about-inout-maillogs" class="label modal-link"><i class="fa fa-info-circle fa-lg" title="{{ _('About mail logs') }}"></i></a>
{% endif %}
{% if not session.get('account_is_mail_user') %}
<a href="#search-inout-maillogs" class="label modal-link"><i class="fa fa-search-plus fa-lg" title="{{ _('Search') }}"></i></a>
{{ display_icon_of_account_profile(account_type=account_type, account=account) }}
{% endif %}
</h2>
{% if removeLogsInDays > 0 %}
<div id="about-inout-maillogs" class="modal-window modal-600">
<h2>{{ _('About mail logs') }}</h2>
<ul class="standard clean-padding bt-space10">
<li class="bt-space5">{{ _('Mail logs of incoming and outgoing mails which older than %d days will be deleted from database permanently.') |format(removeLogsInDays) }}</li>
</ul>
{% if session.get('is_global_admin') %}
<p>{{ _("You can change the kept days here:") }} <a href="{{ ctx.homepath }}/system/settings#data_cleanup">{{ _("Data Clean Up") }}</a></p>
{% endif %}
</div>
{% endif %}
{{ display_search_modal() }}
</div>{# box-header #}
{% endif %} {# account_is_mail_user #}
{% if account_type %}
<form name="{{log_type}}" method="post" action="{{ctx.homepath}}/activities/{{ log_type }}/{{account_type}}/{{ account }}/page/{{ cur_page }}">
{% else %}
<form name="{{log_type}}" method="post" action="{{ctx.homepath}}/activities/{{ log_type }}/page/{{ cur_page }}">
{% endif %}
{{ input_csrf_token() }}
<table class="style1">
<thead>
<tr>
<th class="checkbox"><input type="checkbox" class="checkbox select-all" /></th>
<th data-sort="string-ins">{{ _('Subject') }}</th>
{% if show_sender %}
<th data-sort="string-ins">{{ _('Sender') }}</th>
{% endif %}
{% if show_recipient %}
<th data-sort="string-ins">{{ _('Recipient') }}</th>
{% endif %}
<th data-sort="int">{{ _('Size') }}</th>
{% if log_type == 'received' -%}
<th data-sort="float">{{ _('Score') }}</th>
{% endif %}
<th data-sort="int">{{ _('Date') }}</th>
</tr>
</thead>
<tbody>
{% if records %}
{% for r in records %}
{% set sender_email = r.sender_email |e %}
{% set recipient = r.recipient |e %}
<tr>
{% if log_type == 'sent' %}
{# Process recipients #}
<td class="checkbox"><input type="checkbox" name="record" value="{{ r.mail_id |e }}\r\n{{ recipient }}" class="clickable"/></td>
{% else %}
{# Process senders #}
<td class="checkbox"><input type="checkbox" name="record" value="{{ r.mail_id |e }}\r\n{{ sender_email }}" class="clickable"/></td>
{% endif %}
<td class="wrapword">{{ r.subject |e }}</td>
{% if show_sender %}
<td class="wrapword">{{ sender_email }}
{%- if account_type is sameas none -%}
<a href="{{ctx.homepath}}/profile/{% if r.policy == 'MLMMJ' %}ml{% else %}user{% endif %}/general/{{ sender_email }}"><i class="fa fa-cog fa-lg fr-space" title="{{ _('Edit account profile') }}"></i></a>
{{ set_account_activity_img('sent', 'user', sender_email, float='right') }}
{% endif %}
</td>
{% endif %}
{% if show_recipient %}
<td class="wrapword">{{ recipient }}
{%- if account_type is sameas none -%}
<a href="{{ctx.homepath}}/profile/user/general/{{ recipient }}"><i class="fa fa-cog fa-lg fr-space" title="{{ _('Edit account profile') }}"></i></a>
{{ set_account_activity_img('received', 'user', recipient, float='right') }}
{% endif %}
</td>
{% endif %}
<td data-sort-value="{{ r.size }}" style="white-space: nowrap;">{{ r.size |file_size_format |e }}</td>
{% if show_score %}
<td data-sort-value="{{ r.spam_level }}" style="white-space: nowrap;">{{ r.spam_level |e }}</td>
{% endif %}
<td data-sort-value="{{ r.time_num }}" style="white-space: nowrap;">{{ r.time_num |epoch_seconds_to_gmt | utc_to_timezone(timezone=session['timezone']) }}</td>
</tr>
{% endfor %}
{% else %}
<tr>
<td></td>
{% set colspan = 6 %}
{% if log_type == 'sent' %}
{# no 'Score' column #}
{% set colspan = colspan - 1 %}
{% endif %}
{% if session.get('account_is_mail_user') %}
{# no 'Recipient' column #}
{% set colspan = colspan - 1 %}
{% endif %}
{% if log_type == 'sent' %}
<td colspan="{{ colspan }}">{{ _('No outgoing mails.') }}</td>
{% elif log_type == 'received' %}
<td colspan="{{ colspan }}">{{ _('No incoming mails.') }}</td>
{% endif %}
</tr>
{% endif %}
</tbody>
</table>
<div class="tab-footer clear f1">
<div class="fl">
<select name="action" class="fl-space">
<option>{{ _('Choose Action') }}</option>
<option disabled>----</option>
<option value="delete">{{ _('Delete selected') }}</option>
{# not available for normal domain, because not sure adding blacklists for which domain #}
{% if session.get('amavisd_enable_policy_lookup') %}
{% if session.get('is_global_admin') or session.get('account_is_mail_user') %}
<option disabled>----</option>
{% if log_type == 'sent' %}
<option value="delete_whitelist_rcpt">{{ _('Delete selected, and whitelist recipient(s)') }}</option>
<option value="delete_whitelist_rcpt_domain">{{ _('Delete selected, and whitelist entire recipient domain(s)') }}</option>
<option value="delete_whitelist_rcpt_subdomain">{{ _('Delete selected, and whitelist recipient domain(s) and all sub-domains') }}</option>
<option disabled>----</option>
<option value="delete_blacklist_rcpt">{{ _('Delete selected, and blacklist recipient(s)') }}</option>
<option value="delete_blacklist_rcpt_domain">{{ _('Delete selected, and blacklist entire recipient domain(s)') }}</option>
<option value="delete_blacklist_rcpt_subdomain">{{ _('Delete selected, and blacklist recipient domain(s) and all sub-domains') }}</option>
{% elif log_type == 'received' %}
<option value="delete_whitelist_sender">{{ _('Delete selected, and whitelist sender(s)') }}</option>
<option value="delete_whitelist_sender_domain">{{ _('Delete selected, and whitelist entire sender domain(s)') }}</option>
<option value="delete_whitelist_sender_subdomain">{{ _('Delete selected, and whitelist sender domain(s) and all sub-domains') }}</option>
<option disabled>----</option>
<option value="delete_blacklist_sender">{{ _('Delete selected, and blacklist sender(s)') }}</option>
<option value="delete_blacklist_sender_domain">{{ _('Delete selected, and blacklist entire sender domain(s)') }}</option>
<option value="delete_blacklist_sender_subdomain">{{ _('Delete selected, and blacklist sender domain(s) and all sub-domains') }}</option>
{% endif %}
{% endif %}
{% endif %}
<option disabled>----</option>
<option value="deleteAll">{{ _('Delete all in database') }}</option>
</select>
<input type="submit" value="{{ _('Apply') }}" class="button fl-space" />
</div>{# .fl #}
{{ show_pages(baseurl=pages_baseurl, total=total, cur_page=cur_page) }}
</div>{# .tab-footer #}
</form>
</div>{# box-body #}
</div>{# content-box #}
{% endblock main %}

View File

@@ -0,0 +1,131 @@
{% extends "layout.html" %}
{% from "macros/form_inputs.html" import input_csrf_token with context %}
{% from "macros/general.html" import show_pages with context %}
{% from "macros/amavisd.html" import
display_search_modal,
display_idtabs_of_maillog,
display_icon_of_account_profile,
display_amavisd_quarantined_mails
with context
%}
{% from "macros/msg_handlers.html" import amavisd_msg_handler with context %}
{% block title %}{{ _('Quarantined Mails') }}{% endblock %}
{% block navlinks_activities %}class="active"{% endblock %}
{% block main %}
{# Show system message #}
{{ amavisd_msg_handler(msg) }}
<div class="content-box">
<div class="box-body">
<div class="box-header clear">
<ul class="tabs clear">
{% if account_type is sameas none %}
<li><a href="{{ctx.homepath}}/activities/admins">{{ _('Admin Log') }}</a></li>
{% endif %}
{{ display_idtabs_of_maillog(log_type='quarantined', account_type=account_type, account=account) }}
</ul>
<h2>
{% if account_type == 'domain' %}
{{ _('Quarantined Mails of Domain: %s') |format(account) }}
{% set pages_baseurl = ctx.homepath + '/activities/quarantined/domain/' + account %}
{% elif account_type == 'user' %}
{{ _('Quarantined Mails of User: %s') |format(account) }}
{% set pages_baseurl = ctx.homepath + '/activities/quarantined/user/' + account %}
{% else %}
{{ _('Quarantined Mails') }}
{% set pages_baseurl = ctx.homepath + '/activities/quarantined' %}
{% endif %}
{% if quarantined_type %}
{% set pages_baseurl = pages_baseurl + '/' + quarantined_type %}
{% endif %}
{% if total is defined and records|length > 0 %}
({{ (cur_page-1) * page_size_limit + 1 }}-{{ (cur_page-1) * page_size_limit + records |length}}/{{ total }})
{% endif %}
<a href="#about-quarantining" class="label modal-link"><i class="fa fa-info-circle fa-lg"></i></a>
<a href="#search-inout-maillogs" class="label modal-link"><i class="fa fa-search-plus fa-lg" title="{{ _('Search') }}"></i></a>
{{ display_icon_of_account_profile(account_type=account_type, account=account) }}
</h2>
<div id="about-quarantining" class="modal-window modal-600">
<h2>{{ _('About quarantined mails') }}</h2>
<div class="rule3"></div>
<ul class="standard clean-padding bt-space10">
<li class="bt-space5">{{ _("Quarantined mails are not delivered to users' mailboxes yet, you can either delete them or release them. Mails will be delivered to user mailboxes after released.") }}</li>
{% if removeQuarantinedInDays > 0 %}
<li class="bt-space5">{{ _('Quarantined mails older than %d days will be deleted from database permanently.') |format(removeQuarantinedInDays) }}</li>
{% endif %}
</ul>
<div class="bt-space0">&nbsp;</div>
</div>
{{ display_search_modal() }}
</div>{# .box-header #}
<form name="quarantined" method="post" action="{{ pages_baseurl }}/page/{{ cur_page }}">
{{ input_csrf_token() }}
{{ display_amavisd_quarantined_mails(records,
account=account,
account_type=account_type,
sort_by_score=sort_by_score) }}
<div class="tab-footer clear f1">
<div class="fl">
<select name="action" class="fl-space">
<option>{{ _('Choose Action') }}</option>
<option disabled>----</option>
<option value="release">{{ _('Release selected') }}</option>
{% if session.get('amavisd_enable_policy_lookup') %}
<option value="release_whitelist_sender">{{ _('Release selected, and whitelist sender(s)') }}</option>
<option value="release_whitelist_sender_domain">{{ _('Release selected, and whitelist entire sender domain(s)') }}</option>
<option value="release_whitelist_sender_subdomain">{{ _('Release selected, and whitelist sender domain(s) and all sub-domains') }}</option>
{% endif %}
<option disabled>----</option>
<option value="delete">{{ _('Delete selected') }}</option>
{% if session.get('amavisd_enable_policy_lookup') %}
<option value="delete_blacklist_sender">{{ _('Delete selected, and blacklist sender(s)') }}</option>
<option value="delete_blacklist_sender_domain">{{ _('Delete selected, and blacklist entire sender domain(s)') }}</option>
<option value="delete_blacklist_sender_subdomain">{{ _('Delete selected, and blacklist sender domain(s) and all sub-domains') }}</option>
{% endif %}
{% if session.get('is_global_admin') %}
{% if account_type is sameas none %}
<option disabled>----</option>
<option value="deleteAll">{{ _('Delete all in database') }}</option>
{% endif %}
{% endif %}
</select>
<input type="submit" value="{{ _('Apply') }}" class="button fl-space" />
</div>
{% if sort_by_score %}
{{ show_pages(baseurl=pages_baseurl,
total=total,
cur_page=cur_page,
url_suffix='?sort_by_score') }}
{% else %}
{{ show_pages(baseurl=pages_baseurl, total=total, cur_page=cur_page) }}
{% endif %}
</div>
</form>
</div>{# -- End .box-body -- #}
</div> {# -- End .content-box -- #}
{% endblock main %}

View File

@@ -0,0 +1,30 @@
{# Please do apply template filter 'e' to show mail content #}
<tr class="box-slide-tr" id="box-tr-{{ mail_id.replace('+', '') |e }}">
<td>&nbsp;</td>
<td colspan="7" class="box-slide-body ln-normal">
<table>
<tr><th colspan="2">{{ _('Mail Body') }}</th></tr>
<tr><td colspan="2">{% for body_part in bodies %}<p class="wrapword">{{ body_part |e }}</p>{% endfor %}</td></tr>
{% if attachments |length > 0 %}
<tr><th colspan="2">{{ _('Attachments') }}</th></tr>
{% for fn in attachments %}
<tr>
<th class="right">{{ loop.index }}</th>
<td><span class="wrapword">{{ fn |e }}</span></td>
</tr>
{% endfor %}
{% endif %}
<tr><th colspan="2">{{ _('Mail Headers') }}</th></tr>
{% for hdr in headers %}
<tr>
<th>{{ hdr[0] |e }}</th>
<td><span class="wrapword">{{ hdr[1] |e }}</span></td>
</tr>
{% endfor %}
</table>
</td>
<td>&nbsp;</td>
</tr>

View File

@@ -0,0 +1,98 @@
{% extends "layout_user.html" %}
{% from "macros/form_inputs.html" import
input_csrf_token
with context
%}
{% from "macros/general.html" import
display_subnav,
show_pages
with context
%}
{% from "macros/amavisd.html" import
display_search_modal,
display_amavisd_quarantined_mails
with context %}
{% from "macros/msg_handlers.html" import amavisd_msg_handler with context %}
{% block title %}{{ _('Quarantined Mails') }}{% endblock %}
{% block navlinks_quarantined %}class="active"{% endblock %}
{% block main %}
{# Show system message #}
{{ amavisd_msg_handler(msg) }}
<div class="content-box">
<div class="box-body">
{% if account_type is sameas none %}
<form name="quarantined" method="post" action="{{ctx.homepath}}/activities/quarantined/page/{{ cur_page }}">
{% else %}
<form name="quarantined" method="post" action="{{ctx.homepath}}/activities/quarantined/{{account_type}}/{{ account }}/page/{{ cur_page }}">
{% endif %}
{{ input_csrf_token() }}
{{ display_amavisd_quarantined_mails(records,
account=account,
account_type=account_type,
show_link_for_email=false,
show_recipient=false,
sort_by_score=sort_by_score) }}
{% set disabled_user_preferences = session.get('disabled_user_preferences', []) %}
<div class="tab-footer clear f1">
<div class="fl">
<select name="action" class="fl-space">
<option>{{ _('Choose Action') }}</option>
<option disabled>----</option>
<option value="release">{{ _('Release selected') }}</option>
{% if 'wblist' not in disabled_user_preferences %}
{% if session.get('amavisd_enable_policy_lookup') %}
<option value="release_whitelist_sender">{{ _('Release selected, and whitelist sender(s)') }}</option>
<option value="release_whitelist_sender_domain">{{ _('Release selected, and whitelist entire sender domain(s)') }}</option>
<option value="release_whitelist_sender_subdomain">{{ _('Release selected, and whitelist sender domain(s) and all sub-domains') }}</option>
{% endif %}
{% endif %}
<option disabled>----</option>
<option value="delete">{{ _('Delete selected') }}</option>
{% if 'wblist' not in disabled_user_preferences %}
{% if session.get('amavisd_enable_policy_lookup') %}
<option value="delete_blacklist_sender">{{ _('Delete selected, and blacklist sender(s)') }}</option>
<option value="delete_blacklist_sender_domain">{{ _('Delete selected, and blacklist entire sender domain(s)') }}</option>
<option value="delete_blacklist_sender_subdomain">{{ _('Delete selected, and blacklist sender domain(s) and all its sub-domains') }}</option>
{% endif %}
{% endif %}
{% if session.get('is_global_admin') %}
{% if account_type is sameas none %}
<option value="deleteAll">{{ _('Delete all in database') }}</option>
{% endif %}
{% endif %}
</select>
<input type="submit" value="{{ _('Apply') }}" class="button fl-space" />
</div>
{% if sort_by_score %}
{{ show_pages(baseurl=ctx.homepath + '/activities/quarantined/user/' + account,
total=total,
cur_page=cur_page,
url_suffix='?sort_by_score') }}
{% else %}
{{ show_pages(baseurl=ctx.homepath + '/activities/quarantined/user/' + account,
total=total,
cur_page=cur_page)}}
{% endif %}
</div>
</form>
</div>{# -- End .box-body -- #}
</div> {# -- End .content-box -- #}
{% endblock main %}

View File

@@ -0,0 +1,65 @@
{% if session.get('account_is_mail_user') %}
{% extends "layout_user.html" %}
{% block navlinks_spampolicy %}class="active"{% endblock %}
{% else %}
{% extends "layout.html" %}
{% block navlinks_system %}class="active"{% endblock %}
{% endif %}
{% from "macros/form_inputs.html" import
input_submit,
input_csrf_token
with context
%}
{% from "macros/general.html" import
display_subnav
with context %}
{% from "macros/amavisd.html" import display_spam_policy with context %}
{% from "macros/msg_handlers.html" import user_msg_handler with context %}
{% block title %}{{ _('Spam Policy') }}{% endblock %}
{% if session.get('is_global_admin') %}
{% block breadcrumb %}
{% set crumbs = [] %}
{% if session.get('is_global_admin') and session.get('amavisd_enable_policy_lookup') %}
{% set crumbs = crumbs + [('active', ctx.homepath + '/system/spampolicy', _('Global Spam Policy')),
(ctx.homepath + '/system/wblist', _('Whitelists & Blacklists'))] %}
{% endif %}
{% if session.get('is_global_admin') %}
{% if session.get('iredapd_enabled') %}
{% set crumbs = crumbs + [(ctx.homepath + '/system/greylisting', _('Greylisting')),
(ctx.homepath + '/system/throttle', _('Throttling')),
] %}
{% endif %}
{% endif %}
{{ display_subnav(crumbs) }}
{% endblock %}
{% endif %}
{% block main %}
{#-- Show system message --#}
{{ user_msg_handler(msg) }}
<div class="content-box">
<div class="box-body">
<div class="box-wrap clear">
<form name="spampolicy" method="post" action="{{ctx.homepath}}{{current_url}}">
{{ input_csrf_token() }}
{{ display_spam_policy(account_type=account_type,
spampolicy=spampolicy,
custom_ban_rules=custom_ban_rules,
global_spam_score=global_spam_score) }}
{{ input_submit() }}
</form>
</div>{# box-wrap #}
</div>{# box-body #}
</div>{# content-box #}
{% endblock main %}

View File

@@ -0,0 +1,60 @@
{% extends "layout.html" %}
{% from "macros/form_inputs.html" import
input_submit,
input_csrf_token
with context
%}
{% from "macros/general.html" import
display_subnav,
display_per_account_wblist_all
with context
%}
{% from "macros/msg_handlers.html" import amavisd_msg_handler with context %}
{% block title %}{{ _('Add whitelist and blacklist') }}{% endblock %}
{% block navlinks_create %}class="active"{% endblock %}
{% block breadcrumb %}
{% set crumbs = [] %}
{% if session.get('is_global_admin') %}
{% if session.get('amavisd_enable_policy_lookup') %}
{% set crumbs = crumbs + [(ctx.homepath + '/system/spampolicy', _('Global Spam Policy')),
(ctx.homepath + '/system/wblist', _('Whitelists & Blacklists'))] %}
{% endif %}
{% if session.get('iredapd_enabled') %}
{% set crumbs = crumbs + [(ctx.homepath + '/system/greylisting', _('Greylisting')),
(ctx.homepath + '/system/throttle', _('Throttling')),
] %}
{% endif %}
{% endif %}
{{ display_subnav(crumbs) }}
{% endblock %}
{% block main %}
{# Show system message #}
{{ amavisd_msg_handler(msg) }}
<div class="content-box">
<div class="box-body">
<div class="box-header clear">
<h2>{{ _('Add whitelist and blacklist') }}</h2>
</div>
<div class="box-wrap clear">
<form name="create" method="post" action="{{ctx.homepath}}/create/wblist">
{{ input_csrf_token() }}
{{ display_per_account_wblist_all([], [], [], []) }}
{{ input_submit(label=_('Add')) }}
</form>
</div>{# .box-wrap #}
</div>{# .box-body #}
</div>{# .content-box #}
{% endblock main %}

View File

@@ -0,0 +1,68 @@
{% extends "layout.html" %}
{% from "macros/form_inputs.html" import
input_submit,
input_csrf_token
with context
%}
{% from "macros/general.html" import
display_subnav,
display_per_account_wblist_all,
show_pages
with context
%}
{% from "macros/msg_handlers.html" import amavisd_msg_handler with context %}
{% block title %}{{ _('Whitelists & Blacklists') }}{% endblock %}
{% block navlinks_system %}class="active"{% endblock %}
{% block breadcrumb %}
{% set crumbs = [] %}
{% if session.get('is_global_admin') %}
{% if session.get('amavisd_enable_policy_lookup') %}
{% set crumbs = crumbs + [(ctx.homepath + '/system/spampolicy', _('Global Spam Policy')),
('active', ctx.homepath + '/system/wblist', _('Whitelists & Blacklists'))] %}
{% endif %}
{% if session.get('iredapd_enabled') %}
{% set crumbs = crumbs + [(ctx.homepath + '/system/greylisting', _('Greylisting')),
(ctx.homepath + '/system/throttle', _('Throttling')),
] %}
{% endif %}
{% endif %}
{{ display_subnav(crumbs) }}
{% endblock %}
{% block main %}
{#-- Show system message --#}
{{ amavisd_msg_handler(msg) }}
<div class="content-box">
<div class="box-body">
<div class="box-header clear">
<ul class="tabs clear">
<li class="active"><a href="{{ ctx.homepath }}/system/wblist">{{ _('Sender Addresses') }}</a></li>
<li><a href="{{ ctx.homepath }}/system/wblist/rdns">{{ _('Reverse DNS Name') }}</a></li>
</ul>
<h2>{{ _('Whitelists and Blacklists based on sender addresses') }}</h2>
</div>
<div class="box-wrap clear">
<form name="wblist" method="post" action="{{ctx.homepath}}/system/wblist">
{{ input_csrf_token() }}
{{ display_per_account_wblist_all(inbound_whitelists=whitelists,
inbound_blacklists=blacklists,
outbound_whitelists=outbound_whitelists,
outbound_blacklists=outbound_blacklists) }}
{{ input_submit() }}
</form>
</div>{# box-wrap #}
</div>{# box-body #}
</div>{# content-box #}
{% endblock main %}

View File

@@ -0,0 +1,41 @@
{% extends "layout_user.html" %}
{% from "macros/form_inputs.html" import
input_submit,
input_csrf_token
with context
%}
{% from "macros/general.html" import
set_account_activity_img,
display_subnav,
display_per_account_wblist_all
with context
%}
{% from "macros/msg_handlers.html" import user_msg_handler with context %}
{% block title %}{{ _('White/Blacklist') }}{% endblock %}
{% block navlinks_wblist %}class="active"{% endblock %}
{% block main %}
{#-- Show system message --#}
{{ user_msg_handler(msg) }}
<div class="content-box">
<div class="box-body">
<div class="box-wrap clear">
<form name="wblist" method="post" action="{{ctx.homepath}}/preferences/wblist">
{{ input_csrf_token() }}
{{ display_per_account_wblist_all(inbound_whitelists=whitelists,
inbound_blacklists=blacklists,
show_outbound_wblist=False) }}
{{ input_submit() }}
</form>
</div>{# box-wrap #}
</div>{# box-body #}
</div>{# content-box #}
{% endblock main %}

View File

@@ -0,0 +1,230 @@
{# version, hostname, uptime, loadavg, #}
{% extends "layout.html" %}
{% from "macros/msg_handlers.html" import success_info, error_info with context %}
{% block title %} {{ _('Dashboard') }} {% endblock %}
{% block navlinks_dashboard %}class="active"{% endblock %}
{% block main %}
{# Checked and get response data #}
{% if session.get('new_version_available') %}
{{ success_info( _("New version of iRedAdmin-Pro, %s, is now available for upgrading. <a href='%s/system/license' class='button green'>Details</a>") |format(session.get('new_version') |e, ctx.homepath), removable=false, trusted=true ) }}
{% elif session.get('new_version_available') is sameas false %}
{# Error while checking new version #}
{{ error_info( _('Error while checking new version of iRedAdmin-Pro:') + ' ' + session.get('new_version_check_error') |e ) }}
{% endif %}
<div class="columns clear">
<div class="col1-3">
{% if session.get('amavisd_enable_logging') or session.get('fail2ban_enabled') or session.get('iredapd_enabled') %}
<h2>{{ _('Statistics of latest 24 hours') |title }}</h2>
<table class="basic">
<tbody>
{% if session.get('amavisd_enable_logging') %}
<tr>
<td><i class="fa fa-inbox fa-lg color-green"></i></td>
<th>{{ _('Received') }}</th>
{% if session.get('disable_viewing_mail_log') %}
<td class="full">{{ num_incoming_mails }}</td>
{% else %}
<td class="full"><a href="{{ctx.homepath}}/activities/received">{{ num_incoming_mails }}</a></td>
{% endif %}
</tr>
<tr>
<td><i class="fa fa-paper-plane fa-lg color-blue"></i></td>
<th>{{ _('Sent') }}</th>
{% if session.get('disable_viewing_mail_log') %}
<td>{{ num_outgoing_mails }}</td>
{% else %}
<td><a href="{{ctx.homepath}}/activities/sent">{{ num_outgoing_mails }}</a></td>
{% endif %}
</tr>
{% if session.get('amavisd_enable_quarantine') %}
<tr>
<td><i class="fa fa-biohazard fa-lg color-red"></i></td>
<th>{{ _('Virus') }}</th>
{% if session.get('disable_viewing_mail_log') %}
<td class="full">{{ num_virus }}</td>
{% else %}
<td class="full"><a href="{{ctx.homepath}}/activities/quarantined/virus">{{ num_virus }}</a></td>
{% endif %}
</tr>
<tr>
<td><i class="fa fa-question fa-lg color-purple"></i></td>
<th>{{ _('Quarantined') }}</th>
{% if session.get('disable_managing_quarantined_mails') %}
<td class="full">{{ num_quarantined }}</td>
{% else %}
<td class="full"><a href="{{ctx.homepath}}/activities/quarantined">{{ num_quarantined }}</a></td>
{% endif %}
</tr>
{% endif %}
{% endif %}
{% if session.get('iredapd_enabled') %}
<tr>
<td><i class="fa fa-ban fa-lg color-red"></i></td>
<th>{{ _('Rejected Messages') }}</th>
<td class="full"><a href="{{ ctx.homepath }}/activities/smtp/sessions/rejected">{{ num_rejected }}</a></td>
</tr>
<tr>
<td><i class="fa fa-shoe-prints fa-lg color-green"></i></td>
<th>{{ _('Outbound SMTP Sessions') }}</th>
<td class="full"><a href="{{ ctx.homepath }}/activities/smtp/sessions/outbound">{{ num_smtp_outbound_sessions }}</a></td>
</tr>
{% endif %}
{% if session.get('is_global_admin') and session.get('fail2ban_enabled') %}
<tr>
<td><i class="fa fa-ban fa-lg color-red"></i></td>
<th>{{ _('Banned IP Addresses') }}</th>
<td class="full"><a id="count_banned_ip" href="{{ ctx.homepath }}/activities/fail2ban/banned">{{ num_banned }}</a></td>
</tr>
{% endif %}
</table>
{% endif %}
<h2>{{ _('System Information') }}</h2>
<div class="box-wrap clear">
<table class="basic">
<tbody>
{# Show number of total domains, users, aliases #}
<tr>
<th>{{ _('Number of domains') }}</th>
<td class="full"><a href="{{ctx.homepath}}/domains">{{ num_existing_domains |e }}</a>{% if backend in ['mysql', 'pgsql'] %}{% if num_max_domains >= 0 %} ({{ _('Max:') }} {{ num_max_domains }}){% endif %}{% endif %}</td>
</tr>
{% if backend in ['mysql', 'pgsql'] %}
<tr>
<th>{{ _('Number of users') }}</th>
<td class="full">{{ num_existing_users |e }}{% if num_max_users >= 0 %} ({{ _('Max:') }} {{ num_max_users }}){% endif %}</td>
</tr>
<tr>
<th>{{ _('Number of mailing lists') }}</th>
<td class="full">{{ num_existing_lists |e }}{% if num_max_lists >= 0 %} ({{ _('Max:') }} {{ num_max_lists }}){% endif %}</td>
</tr>
<tr>
<th>{{ _('Number of aliases') }}</th>
<td class="full">{{ num_existing_aliases |e }}{% if num_max_aliases >= 0 %} ({{ _('Max:') }} {{ num_max_aliases }}){% endif %}</td>
</tr>
{% endif %}
{% if session.get('is_global_admin') %}
{% if session.get('show_used_quota') %}
<tr>
<th>{{ _('Stored emails') }}</th>
<td class="full">{% if total_messages %}{{ total_messages |e }} {{ _('Emails') }}.{% endif %} {% if total_bytes %}{{ total_bytes |file_size_format }}.{% endif %}</td>
</tr>
{% endif %}
<tr>
<th>iRedMail</th>
<td>{{ iredmail_version }}</td>
</tr>
<tr>
<th>iRedAdmin-Pro</th>
<td>{{ version |e }}
{% if backend == 'mysql' %}
(MySQL)
{% elif backend == 'pgsql' %}
(PostgreSQL)
{% elif backend == 'ldap' %}
(LDAP)
{% endif %}
</td>
</tr>
{# ---- System Information ---- #}
<tr>
<th>{{ _('Hostname') }}</th>
<td>{{ hostname |e }}</td>
</tr>
{% if uptime is not sameas none and uptime|length == 3 %}
<tr>
<th>{{ _('Uptime') }}</th>
<td>{{ _('%s days, %s hours, %s minutes.') |format(uptime[0] |e, uptime[1] |e, uptime[2] |e ) }}</td>
</tr>
{% endif %}
<tr>
<th>{{ _('Server Load') }}</th>
<td>{{ loadavg[0] }}, {{ loadavg[1] }}, {{ loadavg[2] }}</td>
</tr>
{# ---- Network interfaces and IP info ---- #}
{% for netif in netif_data %}
<tr>
<th>{{ _('Network') }} ({{ netif[0] |e }})</th>
<td>{{ netif[1] }}</td>
</tr>
{% endfor %}
{% endif %}{# global admin #}
</tbody>
</table>
</div> {# .box-wrap #}
</div>{# col1-3 #}
{% if session.get('amavisd_enable_logging') %}
<div class="col1-3">
<h2>{{ _('Top Senders') |title }}</h2>
<table class="basic">
<tbody>
{% for s in top_senders %}
<tr>
<td class="right">{{ s.total |e }}</td>
{% if s.mail %}
{% set _mail = s.mail |e %}
{% if session.get('disable_viewing_mail_log') is sameas true %}
<td class="full">{{ _mail }}</td>
{% elif s.policy == 'MLMMJ' %}
<td class="full"><a href="{{ctx.homepath}}/profile/ml/general/{{_mail}}">{{ _mail }}</a> ({{ _('Mailing List') }})</td>
{% else %}
<td class="full"><a href="{{ctx.homepath}}/activities/sent/user/{{ _mail }}">{{ _mail }}</a></td>
{% endif %}
{% else %}
<td class="full">&lt;&gt;</td>
{% endif %}
</tr>
{% endfor %}
</tbody>
</table>
</div>
<div class="col1-3 lastcol">
<h2>{{ _('Top Recipients') |title }}</h2>
<table class="basic">
<tbody>
{% for s in top_recipients %}
<tr>
<td class="right">{{ s.total |e }}</td>
{% if s.mail %}
{% set _mail = s.mail |e %}
{% if session.get('disable_viewing_mail_log') is sameas true %}
<td class="full">{{ _mail }}</td>
{% else %}
<td class="full"><a href="{{ctx.homepath}}/activities/received/user/{{ _mail }}">{{ _mail }}</a></td>
{% endif %}
{% else %}
<td class="full">&lt;&gt;</td>
{% endif %}
</tr>
{% endfor %}
</tbody>
</table>
</div>
</div>
{% endif %}
{% endblock main %}

View File

@@ -0,0 +1,8 @@
{% extends "layout.html" %}
{% from "macros/msg_handlers.html" import error_info %}
{% block main %}
<div>
{{ error_info(_('Security token did not match. Please refresh current page and re-perform form action.')) }}
</div>
{% endblock %}

View File

@@ -0,0 +1,19 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
<meta http-equiv="imagetoolbar" content="no"/>
<title>{{ _('Error') }}</title>
<link rel="stylesheet" type="text/css" href="{{ctx.homepath}}/static/{{skin}}/css/reset.css" />
<link rel="stylesheet" type="text/css" href="{{ctx.homepath}}/static/{{skin}}/css/screen.css" />
<link rel="icon" type="image/x-icon" href="{{ctx.homepath}}/static/{% if brand_favicon %}{{ brand_favicon }}{% else %}favicon.ico{% endif %}" />
</head>
{% from "macros/msg_handlers.html" import login_msg_handler with context %}
<body class="error">
{{ login_msg_handler(error) }}
</body>
</html>

View File

@@ -0,0 +1,114 @@
{% extends "layout.html" %}
{% block title %}{{ _('Banned IP Addresses') }}{% endblock %}
{% block navlinks_activities %}class="active"{% endblock %}
{% block main %}
<div class="content-box">
<div class="box-body">
<div class="box-header clear">
<h2>{{ _('Banned IP Addresses') }}
(<span id="banned_total" style="font-size: 16px;">{{ rows | length }}</span>)
<i class="fa fa-info-circle fa-1x color-link" title="{{ _('Unbanning IP address may take up to one minute, please be patient.') }}"></i>
</h2>
</div>
<div class="clear"></div>
<table class="style1">
<thead>
<tr>
<th data-sort="string-ins">{{ _('IP Address') }}</th>
<th data-sort="string-ins">{{ _('Client Hostname') }}</th>
<th data-sort="string-ins">{{ _('Country') }}</th>
<th data-sort="string-ins">{{ _('Ports') }}</th>
<th data-sort="string-ins">{{ _('Jail') }}</th>
<th data-sort="string-ins" data-sort-onload=yes data-sort-default="desc">{{ _('Time') }}</th>
</tr>
</thead>
<tbody>
{% if rows |length == 0 %}
<tr>
<td colspan="6">{{ _('No banned IP address.') }}</td>
</tr>
{% endif %}
{% for row in rows %}
{% set row_id = loop.index %}
{% set record_id = row.id | int %}
{% set ip = row.ip |e %}
{% set remove = row.remove | int %}
{# `failures=0` means banned manually, no matched log lines stored in sql db. #}
{% set failures = row.failures | int %}
<tr id="row_{{ row_id }}" {% if remove != 0 %}class="pending_removal"{% endif %}>
<td>
{{ ip }}
{% if remove == 0 %}
<span
id="span_{{ row_id }}"
class="button green fr-space vcenter"
style="width: 45px;"
onclick="unbanip('{{ row_id }}', '{{ ip }}')"
>{{ _('Unban') }}</span>
{% else %}
<span
class="button grey fr-space vcenter"
style="width: 45px;"
>{{ _('Pending') }}</span>
{% endif %}
{% if failures > 0 %}
<a
href="{{ ctx.homepath }}/activities/fail2ban/banned/loglines/{{ record_id |e }}"
class="button blue fr-space vcenter modal-link"
style="width: 20px;">{{ _('Log') }}</a>
{% endif %}
</td>
<td>{% if row.rdns %}{{ row.rdns |e }}{% endif %}</td>
<td>{{ row.country |e }}</td>
<td>{{ row.ports.replace(',', ', ') |e }}</td>
<td>{{ row.jail |e }}</td>
<td style="white-space: nowrap;">{{ row.timestamp | utc_to_timezone(timezone=session['timezone'])}}</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
</div>
{% endblock main %}
{% block extra_js %}
<script type="text/javascript">
function unbanip(row_id, ip) {
var url = '{{ ctx.homepath }}/activities/fail2ban/unbanip/' + ip;
var banned_total = $('#banned_total').text();
$.ajax({
type: "DELETE",
url: url,
success: function (ret) {
if (ret._success) {
$('#span_' + row_id).text('{{ _("Pending") }}').removeClass('green').addClass('grey');
setTimeout(function() {
$('#row_' + row_id).remove();
$('#banned_total').text(banned_total-1);
}, 60000);
} else {
alert(ret._msg);
}
}
});
}
{# While loading page, existing pending removal items should be removed. #}
setTimeout(function() {
$('.pending_removal').remove();
}, 60000);
</script>
{% endblock extra_js %}

View File

@@ -0,0 +1,21 @@
<div class="modal-window modal-800">
{# Use first 6 chars as Month and Day #}
{% if loglines %}
{% set mmdd = loglines[:6] %}
{% set lines = loglines.split(mmdd) %}
<table class="style1">
<tbody>
{% for line in lines %}
{% if line %}
<tr>
<td>{{ mmdd |e }} {{ line | e }}</td>
</tr>
{% endif %}
{% endfor %}
</tbody>
</table>
{% else %}
<p>{{ _('No matched log lines.') }}</p>
{% endif %}
</div>

View File

@@ -0,0 +1,96 @@
{% extends "layout.html" %}
{% from "macros/general.html" import
set_account_activity_img,
display_subnav,
show_pages
with context %}
{% from "macros/iredapd.html" import
display_smtp_outbound_sessions,
display_idtabs_of_smtp_sessions
with context %}
{% block title %}{{ _('Outbound SMTP Sessions') }}{% endblock %}
{% block navlinks_activities %}class="active"{% endblock %}
{% block main %}
<div class="content-box">
<div class="box-body">
<div class="box-header clear">
<ul class="tabs clear">
{{ display_idtabs_of_smtp_sessions(activity='outbound_smtp') }}
</ul>
{% set kw_map = {'domain': _('Domain'),
'sasl_username': _('Authenticated User'),
'sender': _('Envelope Sender'),
'recipient': _('Recipient'),
'ip': _('IP Address'),
'encryption_protocol': _('Encryption Protocol'),
} %}
<h2>
{{ _('Outbound SMTP Sessions') }}
{% if account_type in ['domain', 'sasl_username', 'sender', 'recipient', 'client_address', 'encryption_protocol'] %}
{{ kw_map[account_type] }} {{ account }}
{% endif %}
{% if total %}
({{ (current_page-1) * page_size_limit + 1 }}-{{ (current_page-1) * page_size_limit + (rows |length) }}/{{ total }})
{% endif %}
</h2>
</div>
<div class="clear">
{% if num_insecure_outbound is defined and num_insecure_outbound > 0 %}
<div id="insecure_outbound_usernames" class="modal-window modal-600">
<table class="style1">
{#
<thead>
<tr>
<th>{{ _('Email') }}</th>
<th></th>
</tr>
</thead>
#}
<tbody>
{% for i in insecure_outbound_usernames %}
{% set mail = i | e %}
<tr>
<td>{{ mail }}</td>
<td>
<a href="{{ctx.homepath}}/profile/user/general/{{ mail }}"><i class="fa fa-cog fa-lg" title="{{ _('Edit account profile') }}"></i></a>
{{ set_account_activity_img('sent', 'user', mail, float=false) }}
<a href="{{ctx.homepath}}/activities/smtp/sessions/outbound/sasl_username/{{ mail }}" title="{{ _('Outbound SMTP Sessions') }}"><i class="fa fa-shoe-prints fa-lg color-green"></i></a>
</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
<p style="padding: 10px 10px 10px 10px;">
<i class="fas fa-exclamation-circle color-warning"></i>
<a class="modal-link" href="#insecure_outbound_usernames">{{ _('%d users sent emails without secure connection in last %d hours.') |format(num_insecure_outbound, query_insecure_outbound_hours) }}</a>
</p>
{% endif %}
{{ display_smtp_outbound_sessions(rows=rows) }}
{% set baseurl = ctx.homepath + '/activities/smtp/sessions/outbound' %}
{% if account_type and account %}
{% set baseurl = baseurl + '/' + account_type + '/' + account %}
{% endif %}
{{ show_pages(baseurl=baseurl,
total=total,
cur_page=current_page) }}
</div>
</div>{# box-body #}
</div>{# content-box #}
{% endblock main %}

View File

@@ -0,0 +1,108 @@
{% extends "layout.html" %}
{% from "macros/general.html" import
display_subnav,
show_pages
with context %}
{% from "macros/iredapd.html" import
display_smtp_sessions,
display_idtabs_of_smtp_sessions
with context %}
{% block title %}
{% if rejected_only %}
{{ _('Rejected SMTP Sessions') }}
{% else %}
{{ _('SMTP Sessions') }}
{% endif %}
{% endblock %}
{% block navlinks_activities %}class="active"{% endblock %}
{% block main %}
<div class="content-box">
<div class="box-body">
<div class="box-header clear">
<ul class="tabs clear">
{% if rejected_only %}
{{ display_idtabs_of_smtp_sessions(activity='rejected_smtp') }}
{% else %}
{{ display_idtabs_of_smtp_sessions(activity='smtp') }}
{% endif %}
</ul>
{% set kw_map = {'domain': _('Domain'),
'sasl_username': _('User'),
'sender': _('Envelope Sender'),
'recipient': _('Recipient'),
'ip': _('IP Address'),
'encryption_protocol': _('Encryption Protocol'),
} %}
<h2>{{ _('SMTP Sessions') }}
{% if account_type in ['domain', 'sasl_username', 'sender', 'recipient', 'client_address', 'encryption_protocol'] %}
{{ kw_map[account_type] }} {{ account }}
{% endif %}
{% if total %}
({{ (current_page-1) * page_size_limit + 1 }}-{{ (current_page-1) * page_size_limit + (rows |length) }}/{{ total }})
{% endif %}
</h2>
</div>
<div class="clear">
{{ display_smtp_sessions(
rows=rows,
whitelisted_senderscore_ips=whitelisted_senderscore_ips,
whitelisted_greylisting_ips=whitelisted_greylisting_ips) }}
{% if rejected_only %}
{% set base_url = ctx.homepath + '/activities/smtp/sessions/rejected' %}
{% else %}
{% set base_url = ctx.homepath + '/activities/smtp/sessions' %}
{% endif %}
{{ show_pages(baseurl=base_url,
total=total,
cur_page=current_page) }}
</div>
</div>{# box-body #}
</div>{# content-box #}
{% endblock main %}
{% if session.get('is_global_admin') %}
{% block extra_js %}
<script type="text/javascript">
function whitelist_ip_for_senderscore(row_id, ip) {
$.ajax({
type: "PUT",
url: '{{ ctx.homepath }}/api/wblist/senderscore/whitelist/' + ip,
success: function (ret) {
if (ret._success) {
$('#span_' + row_id).html('<i class="fas fa-check"></i> {{ _("Whitelisted") }}').removeClass('button green');
} else {
alert(ret._msg);
}
}
});
}
function whitelist_ip_for_greylisting(row_id, ip) {
$.ajax({
type: "PUT",
url: '{{ ctx.homepath }}/api/greylisting/global/whitelist/' + ip,
success: function (ret) {
if (ret._success) {
$('#span_' + row_id).html('<i class="fas fa-check"></i> {{ _("Whitelisted") }}').removeClass('button green');
} else {
alert(ret._msg);
}
}
});
}
</script>
{% endblock extra_js %}
{% endif %}

View File

@@ -0,0 +1,109 @@
{% extends "layout.html" %}
{% from "macros/form_inputs.html" import
input_submit,
input_csrf_token
with context
%}
{% from "macros/general.html" import
display_subnav,
show_pages
with context
%}
{% from "macros/iredapd.html" import
display_greylisting_setting,
display_greylisting_whitelist_domains,
display_greylisting_whitelists
with context
%}
{% from "macros/msg_handlers.html" import greylist_msg_handler with context %}
{% block title %}{{ _('Greylisting') }}{% endblock %}
{% block navlinks_system %}class="active"{% endblock %}
{% block breadcrumb %}
{% set crumbs = [] %}
{% if session.get('is_global_admin') %}
{% if session.get('amavisd_enable_policy_lookup') %}
{% set crumbs = crumbs + [(ctx.homepath + '/system/spampolicy', _('Global Spam Policy')),
(ctx.homepath + '/system/wblist', _('Whitelists & Blacklists')),
] %}
{% endif %}
{% if session.get('iredapd_enabled') %}
{% set crumbs = crumbs + [('active', ctx.homepath + '/system/greylisting', _('Greylisting')),
(ctx.homepath + '/system/throttle', _('Throttling')),
] %}
{% endif %}
{% endif %}
{{ display_subnav(crumbs) }}
{% endblock %}
{% block main %}
{# Show system message #}
{{ greylist_msg_handler(msg) }}
<div class="content-box">
<div class="box-body">
<div class="box-header clear">
<ul class="tabs clear">
<li><a href="#settings">{{ _('Settings') }}</a></li>
<li><a href="#tracking_data">{{ _('Tracking Data') }}</a></li>
</ul>
<h2>{{ _('Greylisting') }}</h2>
</div>
<div class="box-wrap clear">
<div id="settings">
<form name="default_greylisting" method="post" action="{{ctx.homepath}}/system/greylisting">
{{ input_csrf_token() }}
{{ display_greylisting_setting(account='@.', gl_setting=gl_setting) }}
<div class="bt-space0">&nbsp;</div>
{{ display_greylisting_whitelist_domains(domains=gl_whitelist_domains) }}
<div class="bt-space0">&nbsp;</div>
{{ display_greylisting_whitelists(account='@.', gl_whitelists=gl_whitelists) }}
{{ input_submit() }}
</form>
</div>
{# Tracking data #}
<div id="tracking_data">
<p>{{ _('Sender domains listed below have not passed greylisting service yet.') }}</p>
<table class="style1">
<thead>
<tr>
<th class="checkbox"><input type="checkbox" class="checkbox select-all" /></th>
<th style="width: 10px;">{{ _('Delivery Attempts') }}</th>
<th>{{ _('Sender Domain') }}</th>
</tr>
</thead>
<tbody>
{% if tracking_records %}
{% for r in tracking_records %}
{% set sender_domain = r.sender_domain | e %}
<tr>
<td><input type="checkbox" name="sender_domain" class="checkbox" value="{{ sender_domain }}" />
<td>{{ r.total }}</td>
<td><a href="{{ ctx.homepath }}/system/greylisting/tracking/domain/{{ sender_domain }}" class="label modal-link">{{ sender_domain }}</a></td>
</tr>
{% endfor %}
{% else %}
<tr><td></td><td colspan="2">{{ _('No data available.') }}</td></tr>
{% endif %}
</tbody>
</table>
</div>{# #tracking_data #}
</div>{# .box-wrap #}
</div>{# .box-body #}
</div>{# .content-box #}
{% endblock main %}

View File

@@ -0,0 +1,26 @@
<div class="modal-window modal-800">
<p>{{ _('Old records will be cleaned up regularly.') }}</p>
<table class="style1">
<thead>
<tr>
<th style="text-align: left;">{{ _('Sender') }}</th>
<th style="text-align: left;">{{ _('Recipient') }}</th>
<th style="text-align: left;">{{ _('Address') }}</th>
<th style="text-align: left;">{{ _('First Attempt') }}</th>
<th style="text-align: left;">{{ _('Expire') }}</th>
</tr>
</thead>
<tbody>
{% for r in tracking_records %}
<tr>
<td style="text-align: left;">{{ r.sender }}</td>
<td style="text-align: left;">{{ r.recipient }}</td>
<td style="text-align: left;">{{ r.client_address }}</td>
<td style="text-align: left;">{{ r.init_time | epoch_seconds_to_gmt | utc_to_timezone(timezone=session['timezone']) }}</td>
<td style="text-align: left;">{{ r.block_expired | epoch_seconds_to_gmt | utc_to_timezone(timezone=session['timezone']) }}</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>

View File

@@ -0,0 +1,78 @@
{% extends "layout.html" %}
{% from "macros/form_inputs.html" import
input_submit,
input_csrf_token
with context
%}
{% from "macros/general.html" import
display_subnav,
show_pages
with context %}
{% from "macros/iredapd.html" import
display_throttle_setting
with context
%}
{% from "macros/msg_handlers.html" import throttle_msg_handler with context %}
{% block title %}{{ _('Throttle') }}{% endblock %}
{% block navlinks_system %}class="active"{% endblock %}
{% block breadcrumb %}
{% set crumbs = [] %}
{% if session.get('is_global_admin') and session.get('amavisd_enable_policy_lookup') %}
{% set crumbs = crumbs + [(ctx.homepath + '/system/spampolicy', _('Global Spam Policy')),
(ctx.homepath + '/system/wblist', _('Whitelists & Blacklists')),
(ctx.homepath + '/system/greylisting', _('Greylisting')),
('active', ctx.homepath + '/system/throttle', _('Throttle')),
] %}
{% endif %}
{{ display_subnav(crumbs) }}
{% endblock %}
{% block main %}
{# Show system message #}
{{ throttle_msg_handler(msg) }}
<div class="content-box">
<div class="box-body">
<div class="box-wrap clear">
<form name="default_throttle" method="post" action="{{ctx.homepath}}/system/throttle">
<div class="columns clear">
{{ input_csrf_token() }}
{{ display_throttle_setting(
account='@.',
setting=outbound_setting,
inout_type='outbound',
) }}
{{ display_throttle_setting(
account='@.',
setting=inbound_setting,
inout_type='inbound',
with_left_border=true,
) }}
<div class="col1-3 lastcol">
<div class="mark_blue bt-space10">
<ul class="standard clean-padding bt-space10">
<li class="bt-space5">{{ _('This is default throttling applied to all individual accounts.') }}</li>
<li class="bt-space5">{{ _('You can set per-domain and per-user throttling in account profile page.') }}</li>
<li class="bt-space5">{{ _('Per-domain throttling has higher priority than default throttling set in this page, per-user throttling has the highest priority.') }}</li>
</ul>
</div>
</div>{#-- .col1-3 --#}
</div>
{{ input_submit() }}
</form>
</div> {# .box-wrap #}
</div>{# .box-body #}
</div>{# .content-box #}
{% endblock main %}

View File

@@ -0,0 +1,78 @@
{% extends "layout.html" %}
{% from "macros/form_inputs.html" import
input_submit,
input_csrf_token
with context
%}
{% from "macros/general.html" import
display_subnav
with context %}
{% from "macros/iredapd.html" import
display_wblist_rdns,
display_wblist_rdns_formats
with context %}
{% from "macros/msg_handlers.html" import wblist_msg_handler with context %}
{% block title %}{{ _('Whitelists & Blacklists') }}{% endblock %}
{% block navlinks_system %}class="active"{% endblock %}
{% block breadcrumb %}
{% set crumbs = [] %}
{% if session.get('is_global_admin') %}
{% if session.get('amavisd_enable_policy_lookup') %}
{% set crumbs = crumbs + [(ctx.homepath + '/system/spampolicy', _('Global Spam Policy')),
('active', ctx.homepath + '/system/wblist', _('Whitelists & Blacklists'))] %}
{% endif %}
{% if session.get('iredapd_enabled') %}
{% set crumbs = crumbs + [(ctx.homepath + '/system/greylisting', _('Greylisting')),
(ctx.homepath + '/system/throttle', _('Throttling')),
] %}
{% endif %}
{% endif %}
{{ display_subnav(crumbs) }}
{% endblock %}
{% block main %}
{#-- Show system message --#}
{{ wblist_msg_handler(msg) }}
<div class="content-box">
<div class="box-body">
<div class="box-header clear">
<ul class="tabs clear">
<li><a href="{{ ctx.homepath }}/system/wblist">{{ _('Sender Addresses') }}</a></li>
<li class="active"><a href="{{ ctx.homepath }}/system/wblist/rdns">{{ _('Reverse DNS Name') }}</a></li>
</ul>
<h2>{{ _('Whitelists and Blacklists based on reverse DNS name of sender server IP address') }}</h2>
</div>
<div class="box-wrap clear">
<form name="wblist_rdns" method="post" action="{{ctx.homepath}}/system/wblist/rdns">
<div class="columns clear">
{{ input_csrf_token() }}
<div class="col2-3">
{{ display_wblist_rdns(values=whitelists,
html_input_name='whitelists',
label=_('Whitelists')) }}
{{ display_wblist_rdns(values=blacklists,
html_input_name='blacklists',
label=_('Blacklists')) }}
</div>
{{ display_wblist_rdns_formats() }}
</div>
{{ input_submit() }}
</form>
</div>{# box-wrap #}
</div>{# box-body #}
</div>{# content-box #}
{% endblock main %}

View File

@@ -0,0 +1,231 @@
{% from "macros/form_inputs.html" import
input_csrf_token
with context
%}
{% from "macros/general.html" import load_jquery %}
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-type" content="text/html; charset=utf-8" />
<title>{% block title %}{%endblock%}</title>
{# CSS #}
<link rel="stylesheet" type="text/css" href="{{ctx.homepath}}/static/{{skin}}/css/reset.css" />
<link rel="stylesheet" type="text/css" href="{{ctx.homepath}}/static/{{skin}}/css/fancybox.css" />
<link rel="stylesheet" type="text/css" href="{{ctx.homepath}}/static/fontawesome/css/fontawesome-all.min.css" />
<link rel="stylesheet" type="text/css" href="{{ctx.homepath}}/static/{{skin}}/css/screen.css" />
<link rel="icon" type="image/x-icon" href="{{ctx.homepath}}/static/{% if brand_favicon %}{{ brand_favicon }}{% else %}favicon.ico{% endif %}" />
</head>
<body>
<div class="pagetop">
<div class="head pagesize">{# -- head layout -- #}
<div class="head_top">
<div class="topbuts">
<ul class="clear">
{% if session.get('is_global_admin') %}
{% if session.get('new_version_available') %}
<li><a href="{{ctx.homepath}}/system/license" class="red">{{ _('New version is available.') }}</a></li>
{% endif %}
{% endif %}
{% if backend in ['ldap', 'mysql', 'pgsql'] %}
<li>
<form method="post" action="{{ctx.homepath}}/search" class="search_form">
{{ input_csrf_token() }}
<input type="text"
name="searchString"
size="30"
placeholder="{{ _('Search mail accounts') }}"
class="search_field"
/>
</form>
</li>
{% endif %}
<li><a href="{{ctx.homepath}}/profile/{%if session.get('admin_is_mail_user') %}user{%else%}admin{%endif%}/general/{{session.get('username')}}">{{ _('Preferences') }}</a></li>
{% if session.get('is_global_admin') %}
{% if backend in ['ldap', 'mysql', 'pgsql'] %}
<li><a href="{{ctx.homepath}}/system/license">{{ _('License') }}</a></li>
{% endif %}
{% endif %}
<li><a href="{{ctx.homepath}}/logout" class="red">{{ _('Logout') }}</a></li>
</ul>
<div class="user clear">
<span class="user-detail">
<span class="text">{{ _('Logged in as %s') |format(session.get('username')) }}</span>
<i class="fas fa-download" style="color: #00A5C4;"></i>
<a href="{{ ctx.homepath }}/export/managed_accounts/{{ session.get('username') }}"
target="_blank" rel="noopener"
style="color: #00A5C4;">{{ _('Export all managed accounts') }}</a><br />
{% if session.get('is_global_admin') %}
<i class="fas fa-download" style="color: #00A5C4;"></i>
<a href="{{ ctx.homepath }}/export/statistics/admins"
target="_blank" rel="noopener"
style="color: #00A5C4;">{{ _('Export statistics of admins') }}</a>
{% endif %}
</span>
</div>
</div>
<div class="logo clear">
<a href="{{ctx.homepath}}/">
{# Logo image and brand name, description #}
{% if brand_logo %}
<img style="height: 80px;"
src="{{ctx.homepath}}/static/{{ brand_logo }}"
alt="logo"
class="picture"
/>
{% endif %}
<span class="textlogo">
<span class="title">{{ brand_name }}</span>
<span class="text">{{ brand_desc }}</span>
</span>
</a>
</div>
</div> <!-- *** End head_top *** -->
<div class="menu"><!-- menu -->
<ul class="clear">
<li {% block navlinks_dashboard %}{% endblock %}><a href="{{ctx.homepath}}/dashboard">{{ _('Dashboard') }}</a></li>
<li {% block navlinks_domains %}{% endblock %}><a href="{{ctx.homepath}}/domains">{{ _('Domains and Accounts') }}</a></li>
{# Display extra menus for global admin. #}
{% if session.get('is_global_admin') %}
<li {% block navlinks_admins %}{% endblock %}><a href="{{ctx.homepath}}/admins">{{ _('Admins') }}</a></li>
{% endif %}
<li {% block navlinks_activities %}{% endblock %}><a href="#">{{ _('Activities') }}</a>
<ul>
<li><a href="{{ctx.homepath}}/activities/admins">{{ _('Admin Log') }}</a></li>
{% if session.get("is_global_admin") and session.get('fail2ban_enabled') %}
<li><a href="{{ctx.homepath}}/activities/fail2ban/banned">{{ _('Banned IP Addresses') }}</a></li>
{% endif %}
{% if session.get('iredapd_enabled') %}
<li><a href="{{ctx.homepath}}/activities/smtp/sessions">{{ _('SMTP Sessions') }}</a>
<ul>
<li><a href="{{ctx.homepath}}/activities/smtp/sessions">{{ _('All') }}</a></li>
<li><a href="{{ctx.homepath}}/activities/smtp/sessions/rejected">{{ _('Rejected') }}</a></li>
<li><a href="{{ctx.homepath}}/activities/smtp/sessions/outbound">{{ _('Outbound') }}</a></li>
</ul>
</li>
{% endif %}
{% if session.get('amavisd_enable_logging') and (session.get('disable_viewing_mail_log') is not sameas true) %}
<li><a href="{{ctx.homepath}}/activities/sent">{{ _('Sent Mails') }}</a></li>
<li><a href="{{ctx.homepath}}/activities/received">{{ _('Received Mails') }}</a></li>
{% endif %}
{% if session.get('amavisd_enable_quarantine') and (session.get('disable_managing_quarantined_mails') is not sameas true) %}
<li><a href="{{ctx.homepath}}/activities/quarantined">{{ _('Quarantined Mails') }}</a>
<ul>
<li><a href="{{ctx.homepath}}/activities/quarantined/spam">{{ _('Spam') }}</a>
<li><a href="{{ctx.homepath}}/activities/quarantined/virus">{{ _('Virus') }}</a>
<li><a href="{{ctx.homepath}}/activities/quarantined/banned">{{ _('Banned') }}</a>
<li><a href="{{ctx.homepath}}/activities/quarantined/badheader">{{ _('Bad Header') }}</a>
<li><a href="{{ctx.homepath}}/activities/quarantined/clean">{{ _('Clean') }}</a>
</ul>
</li>
{% endif %}
</ul>
</li>
{% if session.get('is_global_admin') or session.get('create_new_domains') %}
<li {% block navlinks_system %}{% endblock %}><a href="{{ctx.homepath}}/activities/admins">{{ _('System') }}</a>
<ul>
{% if session.get('is_global_admin') %}
<li><a href="{{ctx.homepath}}/system/settings">{{ _('Settings') }}</a></li>
{% endif %}
{% if session.get('is_global_admin') or session.get('create_new_domains') %}
<li><a href="{{ctx.homepath}}/verify/domain_ownership">{{ _('Domain ownership verification') }}</a></li>
{% endif %}
{% if session.get('is_global_admin') %}
{% if session.get('amavisd_enable_policy_lookup') or session.get('iredapd_enabled') %}
{% if session.get('amavisd_enable_policy_lookup') %}
<li><a href="{{ctx.homepath}}/system/spampolicy">{{ _('Global Spam Policy') }}</a></li>
<li><a href="{{ctx.homepath}}/system/wblist">{{ _('Whitelists & Blacklists') }}</a></li>
{% endif %}
{% if session.get('iredapd_enabled') %}
<li><a href="{{ctx.homepath}}/system/greylisting">{{ _('Greylisting') }}</a></li>
<li><a href="{{ctx.homepath}}/system/throttle">{{ _('Throttle') }}</a></li>
{% endif %}
{% endif %}
{% endif %}
</ul>
</li>
{% endif %}
<li {% block navlinks_create %}{% endblock %}>
<a href="#"><i class="fa fa-plus fa-lg"></i> {{ _('Add') }}...</a>
<ul>
{% if session.get('is_global_admin') or session.get('create_new_domains') %}
<li><a href="{{ctx.homepath}}/create/domain">{{ _('Domain') }}</a></li>
{% endif %}
{% if session.get('is_global_admin') %}
<li><a href="{{ctx.homepath}}/create/admin">{{ _('Admin') }}</a></li>
{% endif %}
<li><a href="{{ctx.homepath}}/create/user">{{ _('User') }}</a></li>
{% if backend == 'ldap' %}
<li><a href="{{ctx.homepath}}/create/maillist">{{ _('Mailing List') }}</a></li>
<li><a href="{{ctx.homepath}}/create/ml">{{ _('Mailing List (Subscribable)') }}</a></li>
{% elif backend in ['mysql', 'pgsql'] %}
<li><a href="{{ctx.homepath}}/create/ml">{{ _('Mailing List (Subscribable)') }}</a></li>
{% endif %}
<li><a href="{{ctx.homepath}}/create/alias">{{ _('Alias') }}</a></li>
{% if session.get('is_global_admin') %}
{% if session.get('amavisd_enable_policy_lookup') %}
<li><a href="{{ctx.homepath}}/create/wblist">{{ _('Whitelists & Blacklists') }}</a></li>
{% endif %}
{% endif %}
</ul>
</li>
</ul>
</div> <!-- End menu -->
</div> <!-- End head layout -->
</div><!-- End page top -->
{% block breadcrumb %}{% endblock %}
<div class="main pagesize"> <!-- *** mainpage layout *** -->
<div class="main-wrap">
<div class="page clear">
{# Main page content #}
{% block main %}{% endblock %}
</div>{# -- End .page .clear -- #}
</div>{# -- End .main-wrap -- #}
</div>{# -- End .main .pagesize -- #}
{# Basic javascript functions. #}
<script type="text/javascript">
// redirect to url
function change_url(domain, baseurl) {
if ( domain.options[domain.selectedIndex].value != 'none' ) {
location.href = baseurl + domain.options[domain.selectedIndex].value;
}
};
</script>
{#-- Load jQuery --#}
{% block js %}
{{ load_jquery() }}
{% endblock js %}
{% block extra_js %}{% endblock extra_js %}
</body>
</html>

View File

@@ -0,0 +1,135 @@
{% from "macros/general.html" import load_jquery %}
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-type" content="text/html; charset=utf-8">
<title>{% block title %}{%endblock%}</title>
{# CSS #}
<link rel="stylesheet" type="text/css" href="{{ctx.homepath}}/static/{{skin}}/css/reset.css">
<link rel="stylesheet" type="text/css" href="{{ctx.homepath}}/static/{{skin}}/css/fancybox.css">
<link rel="stylesheet" type="text/css" href="{{ctx.homepath}}/static/fontawesome/css/fontawesome-all.min.css" />
<link rel="stylesheet" type="text/css" href="{{ctx.homepath}}/static/{{skin}}/css/screen.css">
<link rel="icon" type="image/x-icon" href="{{ctx.homepath}}/static/{% if brand_favicon %}{{ brand_favicon }}{% else %}favicon.ico{% endif %}" />
</head>
<body>
<div class="pagetop">
<div class="head pagesize">{# -- head layout -- #}
<div class="head_top">
<div class="topbuts">
<ul class="clear">
<li><a href="{{ctx.homepath}}/logout" class="red">{{ _('Logout') }}</a></li>
</ul>
<div class="user clear">
<span class="user-detail">
<span class="text">{{ _('Logged in as %s') |format(session.get('username')) }}</span>
</span>
</div>
</div>
<div class="logo clear">
<a href="{{ctx.homepath}}/">
{# Logo image and brand name, description #}
{% if brand_logo %}
<img style="height: 80px;"
src="{{ctx.homepath}}/static/{{ brand_logo }}"
alt="logo"
class="picture"
/>
{% endif %}
<span class="textlogo">
<span class="title">{{ brand_name }}</span>
<span class="text">{{ brand_desc }}</span>
</span>
</a>
</div>
</div> <!-- *** End head_top *** -->
<div class="menu"><!-- menu -->
<ul class="clear">
<li {% block navlinks_preferences %}{% endblock %}>
<a href="{{ctx.homepath}}/preferences">{{ _('Preferences') }}</a>
</li>
{% if 'manageml' not in session['disabled_user_preferences'] %}
<li {% block navlinks_manageml %}{% endblock %}>
<a href="{{ctx.homepath}}/self-service/mls">{{ _('Mailing Lists') }}</a>
</li>
{% endif %}
{% if 'quarantine' not in session['disabled_user_preferences'] %}
{% if session.get('amavisd_enable_quarantine') %}
<li {% block navlinks_quarantined %}{% endblock %}><a href="{{ctx.homepath}}/activities/quarantined/user/{{ session['username'] }}">{{ _('Quarantined Mails') }}</a></li>
{% endif %}
{% endif %}
{% if 'rcvd_mails' not in session['disabled_user_preferences'] %}
{% if session.get('amavisd_enable_logging') %}
<li {% block navlinks_rcvd_mails %}{% endblock %}><a href="{{ctx.homepath}}/activities/received/user/{{ session['username'] }}">{{ _('Received Mails') }}</a></li>
{% endif %}
{% endif %}
{% if session.get('amavisd_enable_policy_lookup') %}
{% if 'wblist' not in session['disabled_user_preferences'] %}
<li {% block navlinks_wblist %}{% endblock %}><a href="{{ctx.homepath}}/preferences/wblist">{{ _('White/Blacklists') }}</a></li>
{% endif %}
{% if 'spampolicy' not in session['disabled_user_preferences'] %}
<li {% block navlinks_spampolicy %}{% endblock %}><a href="{{ctx.homepath}}/preferences/spampolicy">{{ _('Spam Policy') }}</a></li>
{% endif %}
{% endif %}
</ul>
</div> <!-- End menu -->
</div> <!-- End head layout -->
</div><!-- End page top -->
{% block breadcrumb %}{% endblock %}
<div class="main pagesize"> <!-- *** mainpage layout *** -->
<div class="main-wrap">
<div class="page clear">
{# Main page content #}
{% block main %}{% endblock %}
</div>{# -- End .page .clear -- #}
</div>{# -- End .main-wrap -- #}
</div>{# -- End .main .pagesize -- #}
{# Page footer #}
{% block footer %}
<div class="footer">
<div class="pagesize clear">
<p class="bt-space0">
&copy <a href="https://www.iredmail.org/" target="_blank" rel="noopener">iRedMail</a>
{% if session.get('is_global_admin') %}
| <a href="https://forum.iredmail.org/" target="_blank" rel="noopener">{{ _('News & Announcements') }}</a>
| <a href="{{ url_support }}" target="_blank" rel="noopener">{{ _('Support') }}</a>
{% else %}
| <a href="mailto:{{session.get('webmaster')}}">{{ _('Contact webmaster') }}</a>
{% endif %}
</p>
</div>
</div>
{% endblock footer %}
{#-- Basic javascript functions. --#}
<script type="text/javascript">
function change_url(domain, baseurl) {
if ( domain.options[domain.selectedIndex].value != 'none' ) {
location.href = baseurl + domain.options[domain.selectedIndex].value;
}
}
</script>
{#-- Load jQuery --#}
{% block js %}
{{ load_jquery() }}
{% endblock js %}
{% block extra_js %}{% endblock extra_js %}
</body>
</html>

View File

@@ -0,0 +1,85 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
<meta http-equiv="imagetoolbar" content="no"/>
<title>{{ _('Login to manage your mail domains & accounts') |title }}</title>
<link rel="stylesheet" type="text/css" href="{{ctx.homepath}}/static/{{skin}}/css/reset.css" />
<link rel="stylesheet" type="text/css" href="{{ctx.homepath}}/static/{{skin}}/css/screen.css" />
<link rel="icon" type="image/x-icon" href="{{ctx.homepath}}/static/{% if brand_favicon %}{{ brand_favicon }}{% else %}favicon.ico{% endif %}" />
<style type="text/css">
html { background: #333333; }
</style>
<script type="text/javascript">
function change_url(domain, baseurl) {
if ( domain.options[domain.selectedIndex].value != 'none' ) {
location.href = baseurl + domain.options[domain.selectedIndex].value;
}
}
</script>
</head>
{#
@languagemaps language maps
#}
{% from "macros/msg_handlers.html" import login_msg_handler with context %}
<body class="login">
<div class="login-box">
<div class="login-border">
<div class="login-style">
<div class="login-header">
<div class="logo clear">
{% if brand_logo %}
<img src="{{ctx.homepath}}/static/{{ brand_logo }}" alt="logo" class="picture" height="40px" />
{% endif %}
<span class="textlogo">
<span class="title">{{ _('Login to manage your mail domains & accounts') |title }}</span>
</span>
</div>
</div>
{# Show system message if available #}
<p class="clear">
{{ login_msg_handler(msg) }}
</p>
<form name="login" method="post" action="{{ctx.homepath}}/login">
<div class="login-inside">
<div class="login-data">
<div class="row clear">
<label class="size-80 fl-space">{{ _('Username')}}</label>
<input type="text" name="username" size="25" class="text" id="user" />
</div>
<div class="row clear">
<label class="size-80 fl-space">{{ _('Password') }}</label>
<input type="password" name="password" size="25" class="text" id="password" />
</div>
<input type="submit" name="form_login" class="button green" value="{{ _('Login') }}" />
</div>
</div>
<div class="login-footer clear">
<span class="text fr">
<select name="lang" onchange="change_url(this, baseurl='{{ctx.homepath}}/login?lang=');">
{% for lang in languagemaps %}
<option value="{{ lang |e }}" {% if ctx.lang == lang %}selected{%endif%}>{{ languagemaps[lang] |e }}</option>
{% endfor %}
</select>
</span>
</div>
</form>
</div>
</div>
</div>
</body>
</html>

View File

@@ -0,0 +1,453 @@
{% from "macros/form_inputs.html" import input_csrf_token with context %}
{% from "macros/msg_handlers.html" import general_info with context %}
{% macro display_amavisd_quarantined_mails(records,
account=None,
account_type=None,
show_link_for_email=true,
show_sender=true,
show_recipient=true,
sort_by_score=false) -%}
{% set current_url = ctx.home + ctx.path %}
{% if '/page/' in current_url %}
{% set current_url = current_url.split('/page/', 0)[0] %}
{% endif %}
<table class="style1">
<thead>
<tr>
<th class="checkbox"><input type="checkbox" class="checkbox select-all" /></th>
<th data-sort="string-ins">{{ _('Subject') }}</th>
{% if show_sender %}
<th data-sort="string-ins">{{ _('Sender') }}</th>
{% endif %}
{% if show_recipient %}
<th data-sort="string-ins">{{ _('Recipient') }}</th>
{% endif %}
<th data-sort="string-ins">{{ _('Kind') }}</th>
<th data-sort="int">{{ _('Size') }}</th>
{% if sort_by_score %}
<th data-sort="float"><a href="{{current_url}}">{{ _('Score') }}</a></th>
{% else %}
<th data-sort="float"><a href="{{current_url}}?sort_by_score">{{ _('Score') }}</a></th>
{% endif %}
<th data-sort="int">{{ _('Date') }}</th>
<th></th>
</tr>
</thead>
<tbody>
{% if records %}
{% for r in records %}
{% set sender = r.sender_email |e %}
{% set recipient = r.recipient |e %}
{% set mailid_orig = r.mail_id |string |e %}
{% set mailid_for_js = mailid_orig.replace('+', '') %}
<tr class="box-slide-head clickable" id="{{ mailid_for_js }}" mailid="{{ mailid_orig }}">
<td class="checkbox"><input type="checkbox" name="record" value="{{ mailid_orig }}\r\n{{ r.secret_id |e }}\r\n{{sender}}" class="clickable"/></td>
<td>{{ r.subject |e |cut_string(length=50) }}</td>
{% if show_sender %}
<td>
{% if show_link_for_email %}
<a href="{{ctx.homepath}}/activities/quarantined/user/{{ sender }}">{{ sender }}</a>
{% else %}
{{ sender }}
{% endif %}
</td>
{% endif %}
{% if show_recipient %}
<td>
{% if show_link_for_email %}
<a href="{{ctx.homepath}}/activities/quarantined/user/{{ recipient }}">{{ recipient }}</a>
{% else %}
{{ recipient }}
{% endif %}
</td>
{% endif %}
{% if r.content in ['S', 's', 'Y'] %}
{% if account_type in ['user', 'domain'] %}
<td><a href="{{ctx.homepath}}/activities/quarantined/{{ account_type }}/{{ account }}/spam">{{ _('Spam') }}</a></td>
{% else %}
<td><a href="{{ctx.homepath}}/activities/quarantined/spam">{{ _('Spam') }}</a></td>
{% endif %}
{% elif r.content in ['V'] %}
{% if account_type in ['user', 'domain'] %}
<td style="background-color: red;"><a href="{{ctx.homepath}}/activities/quarantined/{{ account_type }}/{{ account }}/virus" style="color: white; font-weight: bold;">{{ _('Virus') }}</a></td>
{% else %}
<td style="background-color: red;"><a href="{{ctx.homepath}}/activities/quarantined/virus" style="color: white; font-weight: bold;">{{ _('Virus') }}</a></td>
{% endif %}
{% elif r.content in ['B'] %}
{% if account_type in ['user', 'domain'] %}
<td><a href="{{ctx.homepath}}/activities/quarantined/{{ account_type }}/{{ account }}/banned">{{ _('Spam') }}</a></td>
{% else %}
<td><a href="{{ctx.homepath}}/activities/quarantined/banned">{{ _('Banned') }}</a></td>
{% endif %}
{% elif r.content in ['H'] %}
{% if account_type in ['user', 'domain'] %}
<td><a href="{{ctx.homepath}}/activities/quarantined/{{ account_type }}/{{ account }}/badheader">{{ _('Bad Header') }}</a></td>
{% else %}
<td><a href="{{ctx.homepath}}/activities/quarantined/badheader">{{ _('Bad Header') }}</a></td>
{% endif %}
{% elif r.content in ['M'] %}
{% if account_type in ['user', 'domain'] %}
<td><a href="{{ctx.homepath}}/activities/quarantined/{{ account_type }}/{{ account }}/badmime">{{ _('Bad Mime') }}</a></td>
{% else %}
<td><a href="{{ctx.homepath}}/activities/quarantined/badmime">{{ _('Bad Mime') }}</a></td>
{% endif %}
{% elif r.content in ['C'] %}
{% if account_type in ['user', 'domain'] %}
<td><a href="{{ctx.homepath}}/activities/quarantined/{{ account_type }}/{{ account }}/clean">{{ _('Clean') }}</a></td>
{% else %}
<td><a href="{{ctx.homepath}}/activities/quarantined/clean">{{ _('Clean') }}</a></td>
{% endif %}
{% else %}
<td>{{ r.content }}</td>
{% endif %}
<td data-sort-value="{{ r.size }}">{{ r.size |file_size_format |e }}</td>
<td data-sort-value="{{ r.spam_level }}">{{ r.spam_level |e }}</td>
<td data-sort-value="{{ r.time_num }}">{{ r.time_num | epoch_seconds_to_gmt | utc_to_timezone(timezone=session['timezone']) }}</td>
<td class="vcenter slide-but checkbox"><span title="{{ _('View or hide mail body and headers') }}">more</span></td>
</tr>
{% endfor %}
{% else %}
{% set colspan = 8 %}
{% if not show_sender %}
{% set colspan = colspan - 1 %}
{% endif %}
{% if not show_recipient %}
{% set colspan = colspan - 1 %}
{% endif %}
<tr>
<td></td>
<td colspan="{{ colspan }}">{{ _('No quarantined mails.') }}</td>
</tr>
{% endif %}
</tbody>
</table>
{%- endmacro %}
{% macro display_search_modal() -%}
<div id="search-inout-maillogs" class="modal-window modal-600">
<h2>{{ _('Search activities') }}</h2>
<div class="rule3"></div>
<form name="search" method="post" action="{{ctx.homepath}}/activities/search">
{{ input_csrf_token() }}
<div class="form-field clear">
<h4 class="size-250 fl-space">{{ _('Domain name or mail address') }} <span class="required">*</span></h4>
<input type="text" name="account" value="" size="35" class="text" />
</div>
<div class="form-field clear">
<h4 class="size-250 fl-space">{{ _('Choose activity type') }}</h4>
<input type="submit" name="quarantined" class="button red" value="{{ _('Quarantined')}}" />
<input type="submit" name="received" class="button green" value="{{ _('Received')}}" />
<input type="submit" name="sent" class="button green" value="{{ _('Sent')}}" />
</div>
</form>
<div class="bt-space0">&nbsp;</div>
</div>
{%- endmacro %}
{% macro display_idtabs_of_maillog(log_type, account_type, account) -%}
{% if session.get('amavisd_enable_logging') and (session.get('disable_viewing_mail_log') is not sameas true) %}
{% if account_type is sameas none %}
<li {% if log_type == 'sent' %}class="active"{% endif %}><a href="{{ctx.homepath}}/activities/sent">{{ _('Sent Mails') }}</a></li>
<li {% if log_type == 'received' %}class="active"{% endif %}><a href="{{ctx.homepath}}/activities/received">{{ _('Received Mails') }}</a></li>
{% else %}
<li {% if log_type == 'sent' %}class="active"{% endif %}><a href="{{ctx.homepath}}/activities/sent/{{account_type}}/{{account}}">{{ _('Sent Mails') }}</a></li>
<li {% if log_type == 'received' %}class="active"{% endif %}><a href="{{ctx.homepath}}/activities/received/{{account_type}}/{{account}}">{{ _('Received Mails') }}</a></li>
{% endif %}
{% endif %}
{% if session.get('amavisd_enable_quarantine') and (session.get('disable_managing_quarantined_mails') is not sameas true) %}
{% if account_type is sameas none %}
<li {% if log_type == 'quarantined' %}class="active"{% endif %}><a href="{{ctx.homepath}}/activities/quarantined">{{ _('Quarantined Mails') }}</a></li>
{% else %}
<li {% if log_type == 'quarantined' %}class="active"{% endif %}><a href="{{ctx.homepath}}/activities/quarantined/{{account_type}}/{{account}}">{{ _('Quarantined Mails') }}</a></li>
{% endif %}
{% endif %}
{%- endmacro %}
{% macro display_icon_of_account_profile(account_type, account) -%}
{% if account_type is not sameas none %}
<a href="{{ctx.homepath}}/profile/{{ account_type }}/general/{{ account }}">
<i class="fa fa-cog fa-lg"
{% if account_type == 'domain' %}
title="{{ _('Edit domain profile') }}"
{% elif account_type == 'user' %}
title="{{ _('Edit account profile') }}"
{% endif %}
></i>
</a>
{% endif %}
{%- endmacro %}
{% macro display_spam_policy(account_type, spampolicy, custom_ban_rules=None, global_spam_score=6) -%}
{% if spampolicy %}
{% set policy_is_empty = False %}
{% else %}
{% set policy_is_empty = True %}
{% endif %}
{% set _bypass_spam_checks = spampolicy.get('bypass_spam_checks') %}
{% set _bypass_virus_checks = spampolicy.get('bypass_virus_checks') %}
{% set _bypass_header_checks = spampolicy.get('bypass_header_checks') %}
{% set _bypass_banned_checks = spampolicy.get('bypass_banned_checks') %}
{% set _spam_lover = spampolicy.get('spam_lover') %}
{% set _virus_lover = spampolicy.get('_virus_lover') %}
{% set _banned_files_lover = spampolicy.get('banned_files_lover') %}
{% set _bad_header_lover = spampolicy.get('bad_header_lover') %}
{% set _spam_quarantine_to = spampolicy.get('spam_quarantine_to') %}
{% set _virus_quarantine_to = spampolicy.get('virus_quarantine_to') %}
{% set _banned_quarantine_to = spampolicy.get('banned_quarantine_to') %}
{% set _bad_header_quarantine_to = spampolicy.get('bad_header_quarantine_to') %}
{% set _banned_rulenames = [] %}
{# banned_rulenames could be whitespace-separated or comma-separated, we use comma-separated syntax but try to support comma-separated too. #}
{# replace whiltespace by comma first, then split by comma #}
{% set _sql_banned_rulenames = spampolicy.get("banned_rulenames", "") %}
{% if _sql_banned_rulenames %}
{% set _banned_rulenames = _sql_banned_rulenames.replace(" ", ",").split(",") %}
{% endif %}
{% if not spampolicy %}
{{ general_info(msg=_('Account does not have specific spam policy yet, server-wide policy will be applied.'), removable=false, trusted=true) }}
{% endif %}
{% if not custom_ban_rules %}
{% set custom_ban_rules = {} %}
{% endif %}
{# @spampolicy: sql record of `amavisd.policy` #}
<div class="columns clear">
<div class="col2-3">
<div class="form-field clear">
<h4 class="size-300 fl-space">{{ _('Spam checking') }}</h4>
<div class="form-checkbox-item clear">
<input type="checkbox"
name="enable_spam_checks"
{% if _bypass_spam_checks in ('N', None) %}checked="checked"{% endif %}
/>
<label>{{ _('Enable spam checking') }}</label>
</div>
</div>
<div class="form-field clear">
<h4 class="size-300 fl-space">&nbsp;</h4>
<div class="form-checkbox-item clear">
<input type="checkbox"
name="spam_quarantine_to"
{% if _spam_lover in ('N', None) and _spam_quarantine_to == 'spam-quarantine' %}checked="checked"{% endif %}
/>
<label>{{ _('Quarantine spam') }}</label>
</div>
</div>
<div class="form-field clear">
<h4 class="size-300 fl-space">{{ _('Virus checking') }}</h4>
<div class="form-checkbox-item clear">
<input type="checkbox"
name="enable_virus_checks"
{% if _bypass_virus_checks in ('N', None) %}checked="checked"{% endif %}
/>
<label>{{ _('Enable virus checking') }}</label>
</div>
</div>
<div class="form-field clear">
<h4 class="size-300 fl-space">&nbsp;</h4>
<div class="form-checkbox-item clear">
<input type="checkbox"
name="virus_quarantine_to"
{% if _virus_lover in ('N', None) and _virus_quarantine_to == 'virus-quarantine' %}checked="checked"{% endif %}
/>
<label>{{ _('Quarantine virus') }}</label>
</div>
</div>
<div class="form-field clear">
<h4 class="size-300 fl-space">{{ _('Bad-header checking') }}</h4>
<div class="form-checkbox-item clear">
<input type="checkbox"
name="enable_header_checks"
{% if _bypass_header_checks in ('N', None) %}checked="checked"{% endif %}
/>
<label>{{ _('Enable bad-header checking') }}</label>
</div>
</div>
<div class="form-field clear">
<h4 class="size-300 fl-space">&nbsp;</h4>
<div class="form-checkbox-item clear">
<input type="checkbox"
name="bad_header_quarantine_to"
{% if _bad_header_lover in ('N', None) and _bad_header_quarantine_to == 'bad-header-quarantine' %}checked="checked"{% endif %}
/>
<label>{{ _('Quarantine bad-header email') }}</label>
</div>
</div>
<div class="form-field clear">
<h4 class="size-300 fl-space">{{ _('Banned file type checking') }}</h4>
<div class="form-checkbox-item clear">
<input type="checkbox"
name="enable_banned_checks"
{% if _bypass_banned_checks in ('N', None) %}checked="checked"{% endif %}
/>
<label>{{ _('Enable banned file type checking') }}</label>
</div>
</div>
<div class="form-field clear">
<h4 class="size-300 fl-space">&nbsp;</h4>
<div class="form-checkbox-item clear">
<input type="checkbox"
name="banned_quarantine_to"
{% if _banned_files_lover in ('N', None) and _banned_quarantine_to == 'banned-quarantine' %}checked="checked"{% endif %}
/>
<label>{{ _('Quarantine email which contains banned file types') }}</label>
</div>
</div>
</div>
{% if not policy_is_empty %}
<div class="col1-3 lastcol">
<input type="submit"
name="delete_policy"
value="{{ _('Delete policy and use default settings') }}"
class="button red"
/>
</div>{# col1-3 #}
{% endif %}
</div>
<div class="rule"></div>
<div class="columns clear">
<div class="col2-3">
<div class="form-field clear">
<h4 class="size-300 fl-space">{{ _('Ban rules') }}</h4>
<div class="form-checkbox-item clear">
<input type="checkbox"
name="banned_rulenames"
value="ALLOW_MS_OFFICE"
{% if "ALLOW_MS_OFFICE" in _banned_rulenames %}checked="checked"{% endif %}
/>
<label>{{ _('Allow all Microsoft Office documents') }}</label>
</div>
</div>
{% for (_name, _comment) in [("ALLOW_MS_WORD", _("Allow Microsoft Office Word documents")),
("ALLOW_MS_EXCEL", _("Allow Microsoft Office Excel documents")),
("ALLOW_MS_PPT", _("Allow Microsoft Office PowerPoint documents"))] %}
<div class="form-field clear">
<h4 class="size-300 fl-space">&nbsp;</h4>
<div class="form-checkbox-item clear">
<input type="checkbox"
name="banned_rulenames"
value="{{ _name }}"
{% if _name in _banned_rulenames %}checked="checked"{% endif %}
/>
<label>{{ _comment }}</label>
</div>
</div>
{% endfor %}
{% for _name in custom_ban_rules %}
<div class="form-field clear">
<h4 class="size-300 fl-space">&nbsp;</h4>
<div class="form-checkbox-item clear">
<input type="checkbox"
name="banned_rulenames"
value="{{ _name }}"
{% if _name in _banned_rulenames %}checked="checked"{% endif %}
/>
<label>{{ custom_ban_rules[_name] | e }}</label>
</div>
</div>
{% endfor %}
</div>{# .col2-3 #}
<div class="col1-3 lastcol">
<div class="mark_blue bt-space10">
<ul class="standard clean-padding bt-space10">
<li class="bt-space5"><a href="https://docs.iredmail.org/iredadmin-pro.custom.ban.rules.html" target="_blank" rel="noopener">{{ _('Custom ban rules') }}</a></li>
</ul>
</div>
</div>{# col1-3 #}
</div>{# .columns #}
<div class="rule"></div>
<div class="columns clear">
<div class="col2-3">
{% if backend != 'pgsql' %}
<div class="form-field clear">
<h4 class="size-300 fl-space">{{ _('Prefix text [SPAM] to the subject of spam') }}</h4>
<div class="form-checkbox-item clear">
<input type="checkbox"
name="modify_spam_subject"
{% if spampolicy.get('spam_subject_tag2') %}checked="checked"{% endif %}
/>
</div>
</div>
{% endif %}
<div class="form-field clear">
<h4 class="size-300 fl-space">{{ _('Mark mail as spam when score is >=') }}</h4>
<div class="form-checkbox-item clear">
<input type="text" name="spam_tag2_level" value="{% if spampolicy.get('spam_tag2_level') is not sameas none %}{{ spampolicy.spam_tag2_level }}{% endif %}" />
{% if not global_spam_score %}
{% set global_spam_score = 6 %}
{% endif %}
<label class="color-grey">{{ _('Default is %s.') |format(global_spam_score) }}</label>
</div>
</div>
<div class="form-field clear">
<h4 class="size-300 fl-space">{{ _('Block or quarantine marked spam when score is >=') }}</h4>
<div class="form-checkbox-item clear">
<input type="text" name="spam_kill_level" value="{% if spampolicy.get('spam_kill_level') is not sameas none %}{{ spampolicy.spam_kill_level }}{% endif %}" />
{% if not global_spam_kill_score %}
{% set global_spam_kill_score = 6.9 %}
{% endif %}
<label class="color-grey">{{ _('Default is %s.') |format(global_spam_kill_score) }}</label>
</div>
</div>
{% if session.get('is_global_admin') %}
{% if account_type == 'global' %}
<div class="form-field clear">
<h4 class="size-300 fl-space">{{ _('Always insert X-Spam-* headers') }}</h4>
<div class="form-checkbox-item clear">
<input type="checkbox" name="always_insert_x_spam_headers" {% if spampolicy.get('spam_tag_level') == -100 %}checked="checked"{% endif %} />
</div>
</div>
{% endif %}
{% endif %}
</div>{# col2-3 #}
<div class="col1-3 lastcol">
<div class="mark_blue bt-space10">
<ul class="standard clean-padding bt-space10">
<li class="bt-space5">{{ _('If many clean mails were marked as spam, please slightly increase the score.') }}</li>
<li class="bt-space5">{{ _('If many spam message were not classified, please slightly decrease the score.') }}</li>
</ul>
</div>
</div>{# col1-3 #}
</div>
{%- endmacro %}

View File

@@ -0,0 +1,205 @@
{% macro input_csrf_token(token=none) -%}
{% if token is sameas none %}
{% set token = csrf_token() %}
{% else %}
{% set token = token |e %}
{% endif %}
<!--suppress ALL -->
<input type="hidden" name="csrf_token" value="{{ token }}"/>
{%- endmacro %}
{% macro input_text(label,
input_name,
value=None,
required=False,
multivalue=False,
multivalue_parent_css_id=None,
enable_input=true,
comment=none,
comment_as_tooltip=false,
comment_as_text=false,
size=35,
maxlength=0) -%}
{% if not value %}
{% set value = '' %}
{% endif %}
<div class="form-field clear">
<h4 class="size-250 fl-space">{{ label }}{% if required %}<span class="required">*</span>{% endif %}</h4>
<input type="text"
size="{{ size }}"
name="{{ input_name |e }}"
value="{{ value |e }}"
class="text {% if not enable_input %}disabled{% endif %}"
{% if not enable_input %}disabled="disabled"{% endif %}
{% if maxlength %}maxlength="{{ maxlength |e }}"{% endif %}
/>{% if enable_input %}{% if multivalue %}<input type="button" value="+" onclick="add_input_inside_id('{{ multivalue_parent_css_id }}', '{{ input_name }}')" />{% endif %}{% endif %}
{% if comment %}
{% if comment_as_tooltip %}
<i class="fa fa-info-circle fa-lg"
title="{{ comment | e}}"
style="cursor: help;"></i>
{% elif comment_as_text %}
{{ comment |e }}
{% else %}
<small>{{ comment |e }}</small>
{% endif %}
{% endif %}
</div>
{%- endmacro %}
{% macro input_radios(label,
input_name,
options,
value=None,
required=False,
comment=none,
comment_as_tooltip=false,
enable_input=true) -%}
{#
`options` must be a list with 2-element tuples:
[('<input_value>', '<description>', '<extra-comment>'), ...]
#}
{% if not value %}
{% set value = '' %}
{% endif %}
{% for (_opt_value, _opt_desc) in options %}
<div class="form-field clear">
<h4 class="size-250 fl-space">
{%- if loop.first -%}
{{ label }}
{%- if required -%}<span class="required">*</span>{%- endif -%}
{%- if comment -%}
{%- if comment_as_tooltip -%}
&nbsp;
<i class="fa fa-info-circle fa-lg .color-green"
title="{{ comment | e}}"
style="cursor: help;"></i>
{%- else -%}
{{ comment |e }}
{%- endif -%}
{%- endif -%}
{% else %}
&nbsp;
{%- endif -%}
</h4>
<div>
<input type="radio"
class="radio {% if not enable_input %}disabled{% endif %}"
name="{{ input_name |e }}"
value="{{ _opt_value |e }}"
{% if not enable_input %}disabled="disabled"{% endif %}
{% if value == _opt_value %}checked="checked"{% endif %}
/>{% if _opt_desc %} {{ _opt_desc |e }}{% endif %}
</div>
</div>
{% endfor %}
{% endmacro %}
{% macro input_checkbox(label,
input_name,
checked=false,
required=false,
enable_input=true,
comment=none,
comment_as_tooltip=false,
add_hidden_input=false) -%}
<div class="form-field clear">
<h4 class="size-250 fl-space">{% if label %}{{ label }}{% else %}&nbsp;{% endif %}{% if required %}<span class="required">*</span>{% endif %}</h4>
<input type="checkbox"
class="checkbox {% if not enable_input %}disabled{% endif %}"
name="{{ input_name |e }}"
{% if checked in [true, 'yes'] %}checked="checked"{% endif %}
{% if not enable_input %}disabled="disabled"{% endif %}
/>
{% if comment %}
{% if comment_as_tooltip %}
<i class="fa fa-info-circle fa-lg"
title="{{ comment | e}}"
style="cursor: help;"></i>
{% else %}
{{ comment |e }}
{% endif %}
{% endif %}
{% if add_hidden_input %}
<input type="hidden" name="hidden_{{ input_name |e }}" />
{% endif %}
</div>
{% endmacro %}
{% macro input_textarea(label,
input_name,
value=None,
comment=None,
is_list_of_emails=False,
is_list_of_ip_or_network=False,
required=False,
enable_input=true,
rows=4,
cols='50%') -%}
{% if not value %}
{% set value = '' %}
{% endif %}
<div class="form-field clear">
<h4 class="size-250 fl-space">{{ label }}{% if required %}<span class="required">*</span>{% endif %}</h4>
{% if is_list_of_emails %}
<small>{{ _('One mail address per line. Invalid address will be discarded.') }}</small>
{% elif is_list_of_ip_or_network %}
<small>{{ _('One IP address or network per line. Invalid address or network will be discarded.') }}</small>
{% endif %}
<textarea name="{{ input_name }}"
rows="{{ rows }}"
cols="{{ cols }}"
class="textarea {% if not enable_input %}disabled{% endif %}"
{% if not enable_input %}disabled="disabled"{% endif %}
>{% if is_list_of_emails or is_list_of_ip_or_network %}{% for addr in value |sort %}{{ addr |e }}
{% endfor %}{% else %}{{ value | e }}{% endif %}</textarea>
</div>
{%- endmacro %}
{% macro input_select(label, input_name, options, value=none, offer_none=false) -%}
<div class="form-field clear">
<h4 class="size-250 fl-space">{% if label %}{{ label |e }}{% else %}&nbsp;{% endif %}</h4>
<select name="{{ input_name }}">
{% if offer_none %}
<option value="none" {% if not value %}selected{% endif %}></option>
{% endif %}
{% for opt in options %}
<option value="{{ opt }}" {% if opt == value %}selected{% endif %}>{{ opt }}</option>
{% endfor %}
</select>
</div>
{% endmacro %}
{% macro input_submit(label=none,
name=none,
color='green',
float=none) -%}
<div class="rule2"></div>
<div class="form-field clear">
<h4 class="size-250 fl-space">&nbsp;</h4>
<span>
<input type="submit"
class="button {{ color |e }}
{% if float == 'left' %}fl-space{% elif float == 'right' %}fr-space{% endif %}"
{% if name %}name="{{ name }}"{% endif %}
value="{% if label %}{{ label |e }}{% else %}{{ _('Save changes') }}{% endif %}"
/>
</span>
</div>
{%- endmacro %}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,566 @@
{% macro display_greylisting_setting(account, gl_setting) -%}
{#
@gl_setting is sql query result of per-account greylisting setting.
#}
{# Defaults to global setting: account == '@.' #}
{% set account_type = 'global' %}
{% set label = _('Greylisting service') %}
{# Detect account type #}
{% if account == '@.' %}
{% set account_type = 'global' %}
{% elif account.startswith('@') %}
{% set account_type = 'domain' %}
{% set label = _('Greylisting service for this domain') %}
{% elif '@' in account %}
{% set account_type = 'user' %}
{% set label = _('Greylisting service for this user') %}
{% endif %}
{# is_greylisted:
@None - Inherit global setting (no greylisting setting found)
@True - Explicitly enabled
@False - Explicitly disabled
#}
{% set is_greylisted = None %}
{% if gl_setting.active == 1 %}
{% set is_greylisted = True %}
{% elif gl_setting.active == 0 %}
{% set is_greylisted = False %}
{% endif %}
<div class="columns clear">
<div class="col2-3">
<h4 class="size-250 fl-space">{{ label }}</h4>
{% if account_type in ['domain', 'user'] %}
<div class="form-checkbox-item clear">
<input type="radio"
name="greylisting"
value="inherit"
class="checkbox fl-space"
rel="checkboxhorizont"
{% if is_greylisted is sameas none %}checked="checked"{%endif%}
/> {{ _('Inherit global setting') }}
</div>
<h4 class="size-250 fl-space">&nbsp;</h4>
{% endif %}
<div class="form-checkbox-item clear">
<input type="radio"
name="greylisting"
value="enable"
class="checkbox fl-space"
rel="checkboxhorizont"
{% if is_greylisted is sameas true %}checked="checked"{%endif%}
/> {{ _('Enable greylisting service') }}
</div>
<h4 class="size-250 fl-space">&nbsp;</h4>
<div class="form-checkbox-item clear">
<input type="radio"
name="greylisting"
value="disable"
class="checkbox fl-space"
rel="checkboxhorizont"
{% if is_greylisted is sameas false %}checked="checked"{%endif%}
/> {{ _('Disable greylisting service') }}
</div>
</div>
<div class="col1-3 lastcol">
<div class="mark_blue">
<p style="padding-bottom: 10px;"><a href="#about_greylisting" class="label modal-link">{{ _('About greylisting') }}</a></p>
</div>
</div>
{# About greylisting #}
<div id="about_greylisting" class="modal-window modal-600">
<h2>{{ _('About greylisting') }}</h2>
<div class="rule3"></div>
<ul class="standard clean-padding bt-space10">
<li class="bt-space10">{{ _('Greylisting is a method of defending your email users against spam. A mail transfer agent (MTA, e.g. Postfix) using greylisting will temporarily reject any email from a sender it does not recognize. If the mail is legitimate the originating server will, after a delay, try again and, if sufficient time has elapsed (usually 7 to 30 minutes), the email will be accepted.') }}</li>
<li class="bt-space10">{{ _('Greylisting helps block out huge amounts of spam, not recommended to turn it off.') }}</li>
<li class="bt-space10">{{ _('Refer to <a href="http://www.greylisting.org/" target="_blank" rel="noopener">greylisting.org</a> for technical details about greylisting.') }}</li>
</ul>
<div class="bt-space0">&nbsp;</div>
</div>
</div>
{% endmacro %}
{% macro display_greylisting_whitelist_domains(domains) -%}
<div class="columns clear">
<div class="col2-3">
<h4 class="size-250 fl-space">{{ _('Do not apply greylisting on emails sent from domains listed below') }}</h4>
<small>{{ _('One domain per line.') }} ({{ _('%d in total.') |format(domains |length) }})</small>
<textarea name="whitelist_domains" class="textarea" rows="10" style="width: 50%;">{% for d in domains %}{{ d }}
{% endfor %}</textarea>
</div>
<div class="col1-3 lastcol">
<div class="mark_blue bt-space10">
<ul class="standard clean-padding bt-space10">
<li>{{ _('Server will NOT apply greylisting on IP addresses or networks specified in the SPF and MX DNS records of listed mail domains.') }}</li>
</ul>
</div>
</div>
</div>
{% endmacro %}
{% macro display_greylisting_whitelists(account, gl_whitelists) -%}
<div class="columns clear">
<div class="col2-3">
<h4 class="size-250 fl-space">{{ _('Do not apply greylisting on listed senders') }}</h4>
<small>{{ _('One sender per line.') }}{% if gl_whitelists %} ({{ _('%d in total.') |format(gl_whitelists |length) }}){% endif %}</small>
<textarea name="whitelists" class="textarea" rows="15" style="width: 50%;">{% for record in gl_whitelists %}{{ record.sender }}{% if record.comment %} # {{ record.comment |e }}{% endif %}
{% endfor %}</textarea>
</div>
<div class="col1-3 lastcol">
<div class="mark_blue bt-space10">
<h4>{{ _('Sender address format') }}</h4>
<ul class="standard clean-padding bt-space10">
<li><strong>{{ _('IP Address') }}</strong>
<ul>
<li>{{ _('Single IP Address') }}: <em><u>192.168.2.10</u></em></li>
<li>{{ _('CIDR formatted range of IP addresses') }}: <em><u>192.168.2.0/24</u></em></li>
</ul>
</li>
<li><strong>{{ _('Email address or domain names') }}</strong>
<ul>
<li>{{ _('Single user') }}: <em><u>user@example.com</u></em></li>
<li>{{ _('Entire domain') }}: <em><u>@example.com</u></em></li>
<li>{{ _('All sub-domains') }}: <em><u>@.example.com</u></em></li>
</ul>
</li>
<li>{{ _('Record comment can be added after a #') }}: <em><u>192.168.2.20 # {{ _('Comment') }}</u></em></li>
</ul>
</div>
</div>
</div>
{% endmacro %}
{% macro display_throttle_setting(account,
setting,
inout_type='inbound',
with_left_border=false) -%}
{# @inout_type: inbound, outbound #}
{% if not setting %}
{% set has_setting = false %}
{% if account == '@.' %}
{# Global setting #}
{% set setting = {'period': 86400,
'priority': 0,
'max_msgs': 0,
'max_quota': 0,
'msg_size': 0,
'max_rcpts': 0} %}
{% else %}
{% set setting = {'period': 86400,
'priority': 0,
'max_msgs': -1,
'max_quota': -1,
'msg_size': -1,
'max_rcpts': -1} %}
{% endif %}
{% else %}
{% set has_setting = true %}
{% endif %}
{% if with_left_border %}
<div class="col1-3-compat-left-border">
{% else %}
<div class="col1-3-compat">
{% endif %}
<div class="form-field clear bt-space10">
<div class="form-checkbox-item clear">
<input type="checkbox"
class="checkbox"
name="enable_{{inout_type}}_throttling"
{% if has_setting %}checked="checked"{% endif %}
/>
{% if inout_type == 'inbound' -%}
<strong>{{ _('Throttle inbound mails') }}</strong>
{% else %}
<strong>{{ _('Throttle outbound mails') }}</strong>
{% endif %}
<span class="required">*</span>
</div>
</div>
{% if setting.period in [86400, 3600, 60] %}
{% set is_custom_period = false %}
{% else %}
{% set is_custom_period = true %}
{% endif %}
<div class="form-field clear bt-space10">
<h4>{{ _('Period of time') }}<span class="required">*</span></h4>
<div class="form-radio-item clear">
<input type="radio" class="radio fl-space" name="{{inout_type}}_period" value="86400" {% if setting.period == 86400 %}checked="checked"{% endif %}/> {{ _('1 Day') }}
</div>
<div class="form-radio-item clear">
<input type="radio" class="radio fl-space" name="{{inout_type}}_period" value="3600" {% if setting.period == 3600 %}checked="checked"{% endif %}/> {{ _('1 Hour') }}
</div>
<div class="form-radio-item clear">
<input type="radio" class="radio fl-space" name="{{inout_type}}_period" value="60" {% if setting.period == 60 %}checked="checked"{% endif %}/> {{ _('1 Minute') }}
</div>
<div class="form-radio-item clear">
<input type="radio" class="radio fl-space" name="{{inout_type}}_period" {% if is_custom_period %}checked="checked"{% endif %}/> {{ _('Custom:') }}
<input type="text" name="custom_{{inout_type}}_period" size="10" value="{% if is_custom_period %}{{ setting.period |e }}{% endif %}" /> {{ _('Seconds') }}
</div>
</div>
{# max_msgs #}
{% set is_custom_max_msgs = true %}
<div class="form-field clear bt-space10">
{% if inout_type == 'inbound' %}
<h4>{{ _('Number of max inbound emails') }}</h4>
{% else %}
<h4>{{ _('Number of max outbound emails') }}</h4>
{% endif %}
{# 1: Unlimited
2: inherit from throttle setting which has lower priority
3: define explicit setting
#}
{% if account != '@.' %}
<div class="form-radio-item clear">
<input type="radio"
name="{{inout_type}}_max_msgs"
value="-1"
{% if setting.max_msgs == -1 %}
checked="checked"
{% set is_custom_max_msgs = false %}
{% endif %}
/>
{% if account.startswith('@') %}
{{ _('Inherit global throttle setting') }}
{% else %}
{{ _('Inherit per-domain throttle setting') }}
{% endif %}
</div>
{% endif %}
<div class="form-radio-item clear">
<input type="radio"
name="{{inout_type}}_max_msgs"
value="0"
{% if setting.max_msgs == 0 %}
checked="checked"
{% set is_custom_max_msgs = false %}
{% endif %}
/> {{ _('Unlimited') }}
</div>
<div class="form-radio-item clear">
<input type="radio" name="{{inout_type}}_max_msgs"
{% if is_custom_max_msgs %}checked="checked"{% endif %}
/> {{ _('Custom:') }}
<input type="text" name="custom_{{inout_type}}_max_msgs" size="15"
value="{% if setting.max_msgs > 0 %}{{ setting.max_msgs |e }}{% endif %}"
/>
</div>
</div>
{# max_quota #}
{% set is_custom_max_quota = true %}
<div class="form-field clear bt-space10">
{% if inout_type == 'inbound' %}
<h4>{{ _('Cumulative size of all inbound emails') }}</h4>
{% else %}
<h4>{{ _('Cumulative size of all outbound emails') }}</h4>
{% endif %}
{% if account != '@.' %}
<div class="form-radio-item clear">
<input type="radio"
name="{{inout_type}}_max_quota"
value="-1"
{% if setting.max_quota == -1 %}
checked="checked"
{% set is_custom_max_quota = false %}
{% endif %}
/> {{ _('Inherit from account which has lower priority') }}
</div>
{% endif %}
<div class="form-radio-item clear">
<input type="radio"
name="{{inout_type}}_max_quota"
value="0"
{% if setting.max_quota == 0 %}
checked="checked"
{% set is_custom_max_quota = false %}
{% endif %}
/> {{ _('Unlimited') }}
</div>
<div class="form-radio-item clear">
<input type="radio" name="{{inout_type}}_max_quota"
{% if is_custom_max_quota %}checked="checked"{% endif %}
/> {{ _('Custom:') }}
<input type="text" name="custom_{{inout_type}}_max_quota" size="15"
value="{% if setting.max_quota > 0 %}{{ setting.max_quota |e }}{% endif %}"
/> Bytes
</div>
</div>
{# msg_size #}
{% set is_custom_msg_size = true %}
<div class="form-field clear">
<h4>{{ _('Max size of single email') }}</h4>
{% if account != '@.' %}
<div class="form-radio-item clear">
<input type="radio"
name="{{inout_type}}_msg_size"
value="-1"
{% if setting.msg_size == -1 %}
checked="checked"
{% set is_custom_msg_size = false %}
{% endif %}
/> {{ _('Inherit from account which has lower priority') }}
</div>
{% endif %}
<div class="form-radio-item clear">
<input type="radio" name="{{inout_type}}_msg_size"
{% if setting.msg_size == 0 %}
checked="checked"
value="0"
{% set is_custom_msg_size = false %}
{% endif %}
/> {{ _('Unlimited') }}
</div>
<div class="form-radio-item clear">
<input type="radio" name="{{inout_type}}_msg_size"
{% if is_custom_msg_size %}checked="checked"{% endif %}
/> {{ _('Custom:') }}
<input type="text" name="custom_{{inout_type}}_msg_size" size="15"
value="{% if setting.msg_size > 0 %}{{ setting.msg_size |e }}{% endif %}"
/> Bytes
</div>
</div>
{# max_rcpts #}
{% if inout_type == "outbound" %}
{% set is_custom_max_rcpts = true %}
<div class="form-field clear">
<h4>{{ _('Max recipients of single email') }}</h4>
{% if account != '@.' %}
<div class="form-radio-item clear">
<input type="radio"
name="{{inout_type}}_max_rcpts"
value="-1"
{% if setting.max_rcpts == -1 %}
checked="checked"
{% set is_custom_max_rcpts = false %}
{% endif %}
/> {{ _('Inherit from account which has lower priority') }}
</div>
{% endif %}
<div class="form-radio-item clear">
<input type="radio" name="{{inout_type}}_max_rcpts"
{% if setting.max_rcpts == 0 %}
checked="checked"
value="0"
{% set is_custom_max_rcpts = false %}
{% endif %}
/> {{ _('Unlimited') }}
</div>
<div class="form-radio-item clear">
<input type="radio" name="{{inout_type}}_max_rcpts"
{% if is_custom_max_rcpts %}checked="checked"{% endif %}
/> {{ _('Custom:') }}
<input type="text" name="custom_{{inout_type}}_max_rcpts" size="15"
value="{% if setting.max_rcpts > 0 %}{{ setting.max_rcpts |e }}{% endif %}"
/>
</div>
</div>
{% endif %}
</div>{# col1-3 #}
{% endmacro %}
{# iRedAPD: wblist_rdns #}
{% macro display_wblist_rdns(values, html_input_name, label, rows=10) -%}
<div class="columns clear">
<div class="form-field clear">
<h4>{{ label |e }} ({{ _('One record per line.') }} {% if values %}{{ _('%d in total.') |format(values |length) }}{% endif %})
</h4>
{% if values |length == 0 %}
<textarea name="{{ html_input_name |e }}" rows="{{ rows }}" class="textarea" style="width: 95%;"></textarea>
{% else %}
<textarea name="{{ html_input_name |e }}" rows="{{ rows }}" class="textarea" style="width: 95%;">{% for v in values |sort %}{{ v |e }}
{% endfor %}</textarea>
{% endif %}
</div>
</div>
{%- endmacro %}
{% macro display_wblist_rdns_formats() -%}
<div class="col1-3 lastcol">
<div class="mark_blue bt-space10">
<ul class="standard clean-padding bt-space10">
<li class="bt-space5">{{ _('Whitelist has higher priority than blacklist.') }}</li>
</ul>
<h4>{{ _('Valid record formats') }}</h4>
<ul class="standard clean-padding bt-space10">
<li class="bt-space5"><strong>{{ _('Entire domain') }}</strong>: <u>domain.tld</u></li>
<li class="bt-space5"><strong>{{ _('Domain and its sub-domains') }}</strong>: <u>.domain.tld</u></li>
</ul>
</div>
<div class="notification note-attention">
<p>{{ _("This feature requires iRedAPD plugin 'wblist_rdns', please make sure it's enabled in file /opt/iredapd/settings.py.") }}</p>
</div>
</div>{# col1-3 #}
{%- endmacro %}
{% macro display_smtp_outbound_sessions(rows) -%}
<table id="smtp_outbound_sessions" class="style1">
<thead>
<tr>
<th data-sort="int"><a href="{{ ctx.homepath }}{{ ctx.path }}">{{ _('Time') }}</a></th>
<th data-sort="string">{{ _('Client Address') }}</th>
<th data-sort="string">{{ _('Auth Username') }}</th>
<th data-sort="string">{{ _('Envelope Sender') }}</th>
<th data-sort="string">{{ _('Recipient') }}</th>
<th data-sort="string">{{ _('Encryption Protocol') }}</th>
</tr>
</thead>
<tbody>
{% if rows %}
{% for row in rows %}
{% set sasl_username = row.get('sasl_username', '') |e %}
{% set sender = row.get('sender', '') |e %}
{% set recipient = row.get('recipient', '') |e %}
{% set client_address = row.get('client_address', '') |e %}
{% set encryption_protocol = row.get('encryption_protocol', '') |e %}
<tr>
<td data-sort-value="{{ row['time_num'] |e }}">{{ row['time'] | utc_to_timezone(timezone=session.get('timezone')) }}</td>
<td><a href="{{ ctx.homepath }}/activities/smtp/sessions/outbound/client_address/{{ client_address }}">{{ client_address }}</a></td>
<td><a href="{{ ctx.homepath }}/activities/smtp/sessions/outbound/sasl_username/{{ sasl_username }}">{{ sasl_username }}</a></td>
<td><a href="{{ ctx.homepath }}/activities/smtp/sessions/outbound/sender/{{ sender }}">{{ sender }}</a></td>
<td><a href="{{ ctx.homepath }}/activities/smtp/sessions/outbound/recipient/{{ recipient }}">{{ recipient }}</a></td>
<td><a href="{{ ctx.homepath }}/activities/smtp/sessions/outbound/encryption_protocol/{{ encryption_protocol }}">{{ encryption_protocol }}</a></td>
</tr>
{% endfor %}
{% else %}
<tr><td colspan="6">{{ _('No SMTP authentication activity.') }}</td></tr>
{% endif %}
</tbody>
</table>
{%- endmacro %}
{% macro display_smtp_sessions(rows,
whitelisted_senderscore_ips=none,
whitelisted_greylisting_ips=none) -%}
{% if whitelisted_senderscore_ips is sameas none %}
{% set whitelisted_senderscore_ips = [] %}
{% endif %}
{% if whitelisted_greylisting_ips is sameas none %}
{% set whitelisted_greylisting_ips = [] %}
{% endif %}
<table id="log_smtp_rejections" class="style1">
<thead>
<tr>
<th data-sort="int">{{ _('Time') }}</th>
<th data-sort="string">{{ _('Client Address') }}</th>
<th data-sort="string">{{ _('Auth Username') }}</th>
<th data-sort="string">{{ _('Envelope Sender') }}</th>
<th data-sort="string">{{ _('Recipient') }}</th>
<th data-sort="string">{{ _('SMTP Action') }}</th>
<th data-sort="string">{{ _('Rejection Reason') }}</th>
</tr>
</thead>
<tbody>
{% if rows %}
{% for row in rows %}
{% set sasl_username = row.get('sasl_username', '') |e %}
{% set sender = row.get('sender', '') |e %}
{% set recipient = row.get('recipient', '') |e %}
{% set client_address = row.get('client_address', '') |e %}
{% set action = row.get('action', '') |e %}
{% set reason = row.get('reason', '') | e %}
{% set _is_senderscore = false %}
{% set _is_greylisting = false %}
{% set _is_whitelisted = false %}
{% set _onclick_func = none %}
{% if action == 'REJECT' and reason.startswith('Server IP address has bad reputation') %}
{% set _is_senderscore = true %}
{% set _onclick_func = 'whitelist_ip_for_senderscore' %}
{% if client_address in whitelisted_senderscore_ips %}
{% set _is_whitelisted = true %}
{% endif %}
{%- elif action == '451' and reason == '4.7.1 Intentional policy rejection, please try again later' -%}
{% set _is_greylisting = true %}
{% set _onclick_func = 'whitelist_ip_for_greylisting' %}
{% if client_address in whitelisted_greylisting_ips %}
{% set _is_whitelisted = true %}
{% endif %}
{% endif %}
<tr>
<td data-sort-value="{{ row['time_num'] |e }}">{{ row['time'] | utc_to_timezone(timezone=session.get('timezone')) }}</td>
<td>
<a href="{{ ctx.homepath }}/activities/smtp/sessions/client_address/{{ client_address }}">{{ client_address }}</a>
{% if session.get('is_global_admin') %}
{% if _is_whitelisted %}
<span class="fr-space vcenter"><i class="fas fa-check"></i> {{ _('Whitelisted') }}</span>
{% elif _is_senderscore or _is_greylisting %}
{# Display a button to whitelist this IP address. #}
<span
id="span_{{ loop.index }}"
class="button green fr-space vcenter"
onclick="{{ _onclick_func }}('{{ loop.index }}', '{{ client_address}}')"
>{{ _('Whitelist') }}</span>
{% endif %}
{% endif %}
</td>
<td><a href="{{ ctx.homepath }}/activities/smtp/sessions/sasl_username/{{ sasl_username }}">{{ sasl_username }}</a></td>
<td><a href="{{ ctx.homepath }}/activities/smtp/sessions/sender/{{ sender }}">{{ sender }}</a></td>
<td><a href="{{ ctx.homepath }}/activities/smtp/sessions/recipient/{{ recipient }}">{{ recipient }}</a></td>
<td>
{%- if action == 'DUNNO' -%}
{{ _('Dunno') }}
{%- elif action == 'OK' -%}
{{ _('Whitelisted') }}
{%- else %}
{% if _is_greylisting %}
{{ _('Greylisted') }}
{%- else -%}
{{ action }}
{%- endif -%}
{%- endif -%}
</td>
<td>{% if action not in ['DUNNO', 'OK', '451'] %}{{ reason }}{% endif %}</td>
</tr>
{% endfor %}
{% else %}
<tr><td colspan="7">{{ _('No matched SMTP sessions.') }}</td></tr>
{% endif %}
</tbody>
</table>
{%- endmacro %}
{% macro display_idtabs_of_smtp_sessions(activity) -%}
<li {% if activity == 'smtp' %}class="active"{% endif %}><a href="{{ctx.homepath}}/activities/smtp/sessions">{{ _('All') }}</a></li>
<li {% if activity == 'rejected_smtp' %}class="active"{% endif %}><a href="{{ctx.homepath}}/activities/smtp/sessions/rejected">{{ _('Rejected') }}</a></li>
<li {% if activity == 'outbound_smtp' %}class="active"{% endif %}><a href="{{ctx.homepath}}/activities/smtp/sessions/outbound">{{ _('Outbound') }}</a></li>
{%- endmacro %}

View File

@@ -0,0 +1,410 @@
{% from "macros/form_inputs.html" import
input_text,
input_checkbox,
input_textarea,
input_csrf_token
with context
%}
{% from "macros/general.html" import
display_filter_by_first_char,
display_list_access_policies
with context
%}
{% macro display_maillist_basic_profile(profile=None, access_policy=None, mail=None) -%}
{% if not profile %}
{% set profile = {} %}
{% endif %}
{{ input_text(label=_('Prefix text to mail subject'),
input_name='subject_prefix',
value=profile.get('subject_prefix', '')) }}
{% set max_mail_size_in_bytes = profile.get('max_message_size', '0') | int %}
{% if max_mail_size_in_bytes == 0 %}
{% set max_mail_size_in_form = 0 %}
{% set max_mail_size_unit = 'MB' %}
{% elif (max_mail_size_in_bytes % 1024) == 0 and max_mail_size_in_bytes >= (1024*1024) %}
{# MB #}
{% set max_mail_size_in_form = (max_mail_size_in_bytes / (1024*1024)) | int %}
{% set max_mail_size_unit = 'MB' %}
{% else %}
{# KB #}
{% set max_mail_size_in_form = (max_mail_size_in_bytes / 1024) |int %}
{% set max_mail_size_unit = 'KB' %}
{% endif %}
<div class="form-field clear">
<h4 class="size-250 fl-space">{{ _('Max message size') }}</h4>
<input type="text"
size="10"
class="text"
name="max_mail_size"
value="{% if max_mail_size_in_form > 0 %}{{ max_mail_size_in_form }}{% endif %}"
/>
<input type="radio" name="max_mail_size_unit" value="MB" {% if max_mail_size_unit == 'MB' %}checked="checked"{% endif %} /> MB
<input type="radio" name="max_mail_size_unit" value="KB" {% if max_mail_size_unit == 'KB' %}checked="checked"{% endif %} /> KB
</div>
{{ input_textarea(label=_('Footer text (plain text format)'),
input_name='footer_text',
value=profile.get('footer_text', ''),
rows=3,
cols='60%') }}
{{ input_textarea(label=_('Footer text (HTML format)'),
input_name='footer_html',
value=profile.get('footer_html', ''),
rows=3,
cols='60%') }}
<div class="rule"></div>
{{ display_list_access_policies(policy=access_policy, enable_members_and_moderators_only=false) }}
<div class="rule"></div>
{{ input_checkbox(label=_('Archive'),
input_name='disable_archive',
checked=profile.get('disable_archive'),
comment=_('Do not archive received emails'),
comment_as_tooltip=false,
add_hidden_input=true) }}
<div class="rule"></div>
{{ input_checkbox(label=_('Mail posting'),
input_name='disable_send_copy_to_sender',
checked=profile.get('disable_send_copy_to_sender'),
comment=_('Do not send a copy to sender'),
comment_as_tooltip=false,
add_hidden_input=true) }}
<div class="rule"></div>
{{ input_checkbox(label=_('Subscription control'),
input_name='close_list',
checked=profile.get('close_list'),
comment=_('Disable subscription and unsubscription via email (existing subscribers are still able to send to list)'),
comment_as_tooltip=false,
add_hidden_input=true) }}
{{ input_checkbox(label='',
input_name='disable_subscription',
checked=profile.get('disable_subscription'),
comment=_('Disable subscription but allow unsubscription via email'),
comment_as_tooltip=false,
add_hidden_input=true) }}
{{ input_checkbox(label='',
input_name='disable_subscription_confirm',
checked=profile.get('disable_subscription_confirm'),
comment=_('Disable subscription confirm'),
comment_as_tooltip=false,
add_hidden_input=true) }}
<div class="rule"></div>
{{ input_checkbox(label=_('Access control'),
input_name='moderated',
checked=profile.get('moderated'),
comment=_('Moderate all posts (Moderators are required)'),
comment_as_tooltip=false,
add_hidden_input=true) }}
<div class="rule"></div>
{{ input_checkbox(label=_('Notifications'),
input_name='disable_notify_when_subscriber_only',
checked=profile.get('disable_notify_when_subscriber_only'),
comment=_('Do not notify sender when posting to a subscriber-only mailing list was denied'),
comment_as_tooltip=false,
add_hidden_input=true) }}
{{ input_checkbox(label='',
input_name='disable_notify_when_moderator_only',
checked=profile.get('disable_notify_when_moderator_only'),
comment=_('Do not notify sender when posting to a moderator-only mailing list was denied'),
comment_as_tooltip=false,
add_hidden_input=true) }}
{{ input_checkbox(label='',
input_name='disable_notify_subscription_moderated',
checked=profile.get('disable_notify_subscription_moderated'),
comment=_('Do not notify subscription requestor when subscription is under moderated'),
comment_as_tooltip=false,
add_hidden_input=true) }}
{{ input_checkbox(label='',
input_name='disable_notify_when_exceeding_max_mail_size',
checked=profile.get('disable_notify_when_exceeding_max_mail_size'),
comment=_('Do not notify sender when posting was denied due to exceed max message size'),
comment_as_tooltip=false,
add_hidden_input=true) }}
{{ input_checkbox(label='',
input_name='notify_sender_when_moderated',
checked=profile.get('notify_sender_when_moderated'),
comment=_('Notify sender if email is under moderated'),
comment_as_tooltip=false,
add_hidden_input=true) }}
{{ input_checkbox(label='',
input_name='notify_owner_when_sub_unsub',
checked=profile.get('notify_owner_when_sub_unsub'),
comment=_('Notify owner(s) when someone subscribe to or unsubscribe from the mailing list'),
comment_as_tooltip=false,
add_hidden_input=true) }}
{%- endmacro %}
{% macro display_maillist_owners(mail, addresses=None) %}
{% if not addresses %}
{% set addresses = [] %}
{% endif %}
{% set (listname, domain) = mail.split('@', 1) %}
<div class="columns clear">
<div class="col2-3 clear">
<div class="form-field clear">
<h4 class="size-250 fl-space">{{ _('Owners') }}</h4>
<small>{{ _('One mail address per line. Invalid address will be discarded.') }}</small>
<textarea name="owners"
rows="6"
style="width: 50%"
class="textarea"
>{%- for addr in addresses |sort %}{% if addr != mail %}{{ addr |e }}
{% endif %}{%- endfor -%}
</textarea>
</div>
</div>{# .col2-3 #}
<div class="col1-3 lastcol">
<div class="mark_blue bt-space10">
<ul class="standard clean-padding bt-space10">
<li class="bt-space5">{{ _('Email addresses of the mailing list owners which need to be contacted via email %s, either by the system or by end users.') | format(listname + '+owner@' + domain) }}</li>
</ul>
</div>
</div>
</div>{# .columns #}
{% endmacro %}
{% macro display_maillist_moderators(mail, addresses=None) %}
{% if not addresses %}
{% set addresses = [] %}
{% endif %}
<div class="columns clear">
<div class="col2-3 clear">
<div class="form-field clear">
<h4 class="size-250 fl-space">{{ _('Moderators') }}</h4>
<small>{{ _('One mail address per line. Invalid address will be discarded.') }}</small>
<textarea name="moderators"
rows="6"
style="width: 50%"
class="textarea"
>{%- for addr in addresses |sort %}{% if addr != mail %}{{ addr |e }}
{% endif %}{%- endfor -%}
</textarea>
</div>
</div>{# .col2-3 #}
<div class="col1-3 lastcol">
<div class="mark_blue bt-space10">
<ul class="standard clean-padding bt-space10">
<li class="bt-space5">{{ _('Email addresses of the mailing list moderators which need to be contacted when there is some email under moderated. If empty, mailing list owners will be used instead.') }}</li>
</ul>
</div>
</div>
</div>{# .columns #}
{% endmacro %}
{% macro display_maillist_subscription_moderators(mail, profile, addresses=None) %}
{% if not addresses %}
{% set addresses = [] %}
{% endif %}
<div class="columns clear">
<div class="col2-3 clear">
{{ input_checkbox(label=_('Moderate subscriptions'),
input_name='moderate_subscription',
checked=profile.get('moderate_subscription'),
add_hidden_input=true) }}
<div class="form-field clear">
<h4 class="size-250 fl-space">{{ _('Subscription Moderators') }}</h4>
<small>{{ _('One mail address per line. Invalid address will be discarded.') }}</small>
<textarea name="subscription_moderators"
rows="6"
style="width: 50%"
class="textarea"
>{%- for addr in addresses |sort %}{% if addr != mail %}{{ addr |e }}
{% endif %}{%- endfor -%}
</textarea>
</div>
</div>{# .col2-3 #}
<div class="col1-3 lastcol">
<div class="mark_blue bt-space10">
<ul class="standard clean-padding bt-space10">
<li class="bt-space5">{{ _('Email addresses of the mailing list moderators which need to be contacted when there is someone subscribing to the list and under moderated. If empty, mailing list moderators will be used instead.') }}</li>
</ul>
</div>
</div>
</div>{# .columns #}
{% endmacro %}
{% macro display_modal_add_subscribers(form_post_url) %}
<div id="add_subscribers" class="modal-window modal-400" >
<form method="post" action="{{ form_post_url }}">
{{ input_csrf_token() }}
<h2>{{ _('Add new members') }}</h2>
<div class="columns clear">
{#
<div class="form-field clear">
<span class="clean-padding">
<input type="checkbox" name="require_confirm" /> {{ _('Send email to new members for subscription confirm') }}
</span>
</div>
#}
<div class="form-field clear">
<small>{{ _('One mail address per line. Invalid address will be discarded.') }}</small>
<textarea name="new_subscribers" rows="10" style="width: 90%" class="textarea"></textarea>
</div>
<div class="rule"></div>
</div>
<input type="submit" value="{{ _('Add') }}" class="button green" />
</form>
</div>
{% endmacro %}
{% macro display_maillist_subscribers(mail, subscribers=None, account_is_enabled=true) -%}
<div class="clear left-space5" style="margin-top: -10px; margin-bottom: 10px;">
<i class="fa fa-filter fa-lg"></i>
{{ _('Filter:') }} <input type="text" id="subscriber_search" />
{% if account_is_enabled %}
<i class="fa fa-plus fa-lg"></i>
<a href="#add_subscribers" class="modal-link">{{ _('Add new members') }}</a>
{% else %}
<i class="fa fa-exclamation-triangle fa-lg"></i>{{ _('To add new members, please enable mailing list account first.') }}
{% endif %}
</div>
<table id="subscribers" class="style1 clear" style="margin-bottom: 10px;">
<thead>
<tr>
<th class="checkbox"><input type="checkbox" class="checkbox select-all" /></th>
<th data-sort="string-ins">{{ _('Email') }}</th>
<th data-sort="string-ins">{{ _('Domain') }}</th>
<th data-sort="string-ins">{{ _('Mail Delivery') }}</th>
</tr>
</thead>
<tbody id="subscribers_tbody">
{% if subscribers %}
{% for i in subscribers |sort(attribute='mail') %}
{% set _mail = i.mail |e %}
{% set _subscription = i.subscription | e %}
{% set _domain = _mail.split('@', 1)[-1] %}
<tr>
<td class="checkbox"><input type="checkbox" class="checkbox" name="subscriber" value="{{ _mail }}" /></td>
<td>{{ _mail }}</td>
<td>{{ _domain }}</td>
<td>
{%- if _subscription == 'normal' -%}
{{ _('All emails') }}
{%- elif _subscription == 'digest' -%}
{{ _('Digest') }}
{%- elif _subscription == 'nomail' -%}
{{ _('No email') }}
{%- else %}
{{ _subscription }}
{%- endif -%}
</td>
</tr>
{% endfor %}
{% else %}
<tr>
<td></td>
<td colspan="3">{{ _('No members.') }}</td>
</tr>
{% endif %}
</tbody>
</table>
{% if subscribers %}
<div class="tab-footer clear f1">
<div class="fl">
<select name="action" class="fl-space" id="account_list_actions" >
<option>{{ _('Choose Action') }}</option>
<option disabled>----</option>
<option value="remove">{{ _('Remove selected members') }}</option>
<option disabled>----</option>
<option value="remove_all" class="color-red">{{ _('Remove ALL members') }}</option>
</select>
<input type="submit" name="submit_subscribers" value="{{ _('Apply') }}" class="button fl-space" />
</div>
</div>
{% endif %}
{% endmacro %}
{% macro display_modal_newsletter_html_code(mlid) %}
<div id="newsletter_html_code" class="modal-window modal-800" >
<h2>{{ _('Get a newsletter signup form') }}</h2>
{% set _url = ctx.homedomain + newsletter_base_url + '/subscribe/' + mlid |e %}
{% set _form = '<h3>Subscribe to our newsletter</h3>
<form method="post" action="%s">
<input name="subscriber" value="" placeholder="Enter your email address" />
<input type="submit" value="Subscribe" />
</form>' | format(_url) %}
<p>{{ _('You can embed a mailing list signup form (HTML code below) on any page of your website. Feel free to customize the form to add your brand name, logo image, or combine it with special offers to attract new subscribers and boost engagement.') }}</p>
<div class="rule"></div>
<pre style="font-style: italic;">{{ _form |e }}</pre>
<div class="rule"></div>
<h2>{{ _('Redirect user to subscription page') }}</h2>
<p>{{ _('If you prefer redirecting user to a subscription page, this is the url of subscription page.') }}</p>
<div class="rule"></div>
<pre style="font-style: italic;">{{ _url }}</pre>
</div>
{% endmacro %}
{% macro display_maillist_newsletter_profile(is_newsletter=False, description=None) -%}
{% if not description %}
{% set description = '' %}
{% endif %}
<div class="columns clear">
<div class="col2-3 clear">
{{ input_checkbox(label=_('Enable newsletter-style mailing list'),
input_name='is_newsletter',
comment=_('Enable subscription and unsubscription from website'),
checked=is_newsletter) }}
{{ input_textarea(label=_('Text to introduce this newsletter on subscription page'),
input_name='description',
value=description) }}
</div>
<div class="col1-3 clear lastcol">
<div class="mark_blue bt-space5">
<p><i class="fa fa-code fa-lg"></i> <a href="#newsletter_html_code" class="modal-link"><span class="text">{{ _('Get a newsletter signup form') }}</span></a></p>
</div>
</div>
</div>
{%- endmacro %}

View File

@@ -0,0 +1,475 @@
{% macro success_info(msg, removable=true, trusted=false) -%}
<div class="notification note-success">
{% if removable is not sameas false %}
<a href="#" class="close">Close</a>
{% endif %}
<p><i class="far fa-check-circle fa-lg fa-fw"></i>
{% if trusted %}
{{ msg }}
{% else %}
{{ msg |e }}
{% endif %}
</p>
</div>
{%- endmacro %}
{% macro error_info(msg, removable=false, trusted=false) -%}
<div class="notification note-error">
{% if removable is not sameas false %}
<a href="#" class="close">Close</a>
{% endif %}
<p><i class="fa fa-times-circle fa-lg fa-fw"></i> <strong>{{ _('Error:') }}</strong>
{% if trusted %}
{{ msg }}
{% else %}
{{ msg |e }}
{% endif %}
</p>
</div>
{%- endmacro %}
{% macro warning_info(msg, removable=false, trusted=false) -%}
<div class="notification note-attention" class="padding-left: 0px;">
{% if removable is not sameas false %}
<a href="#" class="close">Close</a>
{% endif %}
<p><i class="fa fa-exclamation-triangle fa-lg fa-fw"></i>
{% if trusted %}
{{ msg }}
{% else %}
{{ msg |e }}
{% endif %}
</p>
</div>
{%- endmacro %}
{% macro general_info(msg, removable=true, trusted=false) -%}
<div class="notification note-info">
{% if removable is not sameas false %}
<a href="#" class="close">Close</a>
{% endif %}
<p><i class="fa fa-info fa-lg fa-fw"></i>
{% if trusted %}
{{ msg }}
{% else %}
{{ msg |e }}
{% endif %}
</p>
</div>
{%- endmacro %}
{% macro login_msg_handler(msg) -%}
{% if msg is defined and msg is not sameas none and msg|string != '' %}
{% set handlers = {
'LOGIN_REQUIRED': error_info(_('Login required')),
'INVALID_CREDENTIALS': error_info(_('Username or password is incorrect.')),
'INVALID_USERNAME': error_info(_('Username must be an valid email address.')),
'EMPTY_PASSWORD': error_info(_('Empty password is not allowed.')),
'SESSION_EXPIRED': error_info(_('Session expired, please re-login.')),
'NOT_ALLOWED_IP': error_info(_('Login from your IP address is not allowed.')),
'INVALID_PRODUCT_ID': error_info(_('Your license is invalid. Please contact support@iredmail.org to fix it.')),
}
%}
{% if msg == 'SERVER_DOWN' %}
{{ error_info(_('Server is down. Please contact <a href="mailto:%s">webmaster</a> to solve it.' % webmaster ), trusted=true) }}
{% elif msg is sameas false %}
{{ error_info( ('Authentication failed.') ) }}
{% else %}
{% if msg in handlers %}
{{ handlers[msg] }}
{% else %}
{{ error_info( msg ) }}
{% endif %}
{% endif %}
{% endif %}
{%- endmacro %}
{% macro creation_limit_msg_handler(msg=none) -%}
{% if msg is defined and msg is not sameas none and msg|string != '' %}
{% set handlers = {
'EXCEED_LIMIT_DOMAIN': error_info(_('Already reaches account limit (mail domains).')),
'EXCEED_LIMIT_QUOTA': error_info(_('Already reaches account limit (mailbox quota).')),
'EXCEED_LIMIT_USERS': error_info(_('Already reaches account limit (mail users).')),
'EXCEED_LIMIT_ALIASES': error_info(_('Already reaches account limit (mail aliases).')),
'EXCEED_LIMIT_LISTS': error_info(_('Already reaches account limit (mailing lists).')),
}
%}
{% if msg in handlers %}
{{ handlers[msg] }}
{% else %}
{{ error_info(msg) }}
{% endif %}
{% endif %}
{%- endmacro %}
{% macro domain_msg_handler(msg=none) -%}
{% if msg is defined and msg is not sameas none and msg|string != '' %}
{% set handlers = {
'UPDATED': success_info(_('Profile has been updated.')),
'INVALID_ACTION': error_info(_('Invalid action.')),
'DELETED': success_info(_('Selected domains have been deleted.')),
'DISABLED': success_info(_('Selected domains were disabled.')),
'ENABLED': success_info(_('Selected domains were enabled.')),
'INVALID_DOMAIN_NAME': error_info(_('Invalid domain name.')),
'INVALID_MAIL': error_info(_('Invalid mail address.')),
'EMPTY_DOMAIN': error_info(_('Domain name is empty.')),
'EXCEEDED_LDAP_SERVER_SIZELIMIT': error_info(_('Server-side size limit exceeded. Please increase "sizelimit" in your LDAP server.')),
'ALREADY_EXISTS': error_info(_('Domain already exists. Please check both primary or alias domains.')),
'PERMISSION_DENIED': error_info(_('Permission denied.')),
'DOMAIN_NAME_MISMATCH': error_info(_('Submited domain name is incorrect.')),
'NO_SUCH_ACCOUNT': error_info(_('Account does not exist.')),
'NO_DOMAIN_SELECTED': error_info(_('Please select at least one domain.')),
'NO_DOMAIN_AVAILABLE': error_info(_('No domain under control.')),
'EXCEED_LIMIT_DOMAIN': error_info(_('Already reaches account limit (mail domains).')),
'EXCEED_LIMIT_QUOTA': error_info(_('Already reaches account limit (mailbox quota).')),
'EXCEED_LIMIT_USERS': error_info(_('Already reaches account limit (mail users).')),
'EXCEED_LIMIT_ALIASES': error_info(_('Already reaches account limit (mail aliases).')),
'EXCEED_LIMIT_LISTS': error_info(_('Already reaches account limit (mailing lists).')),
}
%}
{% if msg == 'CREATED' %}
<div class='notification note-success'><a href='#' class='close'></a>
<p><i class="far fa-check-circle fa-lg fa-fw"></i>
{{ _('Domain created.') }} <a href='{{ctx.homepath}}/create/domain'>{{ _('Add one more?') }}</a> {{ _('Or create other mail accounts:') }} <a href='{{ctx.homepath}}/create/user/{{cur_domain}}'>{{ _('User') }}</a>, <a href='{{ctx.homepath}}/create/ml/{{cur_domain}}'>{{ _('Mailing List') }}</a>.
</p>
</div>
{% else %}
{% if msg in handlers %}
{{ handlers[msg] }}
{% else %}
{{ error_info(msg) }}
{% endif %}
{% endif %}
{% endif %}
{%- endmacro %}
{% macro user_msg_handler(msg) -%}
{% if msg %}
{% set handlers = {
'UPDATED': success_info(_('Profile has been updated.')),
'UPDATED_FAILED': error_info( _('Profile updated failed.')),
'INVALID_ACTION': error_info(_('Invalid action.')),
'NO_DOMAIN_AVAILABLE': general_info( _('No domain under control.') ),
'MISSING_DOMAIN_OR_USERNAME': error_info( _('Domain name or username is missed.') ),
'INVALID_MAIL': error_info(_('Invalid mail address.')),
'INVALID_ACCOUNT': error_info(_('Invalid account.')),
'EXCEEDED_DOMAIN_QUOTA_SIZE': error_info(_('Domain quota size exceeded. Please contact your administrator or service provider to increase it.')),
'EXCEEDED_DOMAIN_ACCOUNT_LIMIT': error_info(_('Exceeded domain account limit. Please contact your administrator or service provider to increase it.')),
'DELETED': success_info( _('Selected accounts were deleted.') ),
'DISABLED': success_info( _('Selected accounts were disabled.') ),
'ENABLED': success_info( _('Selected accounts were enabled.') ),
'MARKASADMIN': success_info( _('Selected accounts were marked as domain admin.') ),
'UNMARKASADMIN': success_info( _('Selected accounts were unmarked as domain admin.') ),
'MARKASGLOBALADMIN': success_info( _('Selected accounts were marked as global admin.') ),
'UNMARKASGLOBALADMIN': success_info( _('Selected accounts were unmarked as global admin.') ),
'INCORRECT_OLDPW': error_info( _('Current password is incorrect.') ),
'PW_MISMATCH': error_info( _('New passwords are not match.') ),
'PW_NON_ASCII': error_info( _('Please do not use non-ascii character in password.') ),
'PW_EMPTY': error_info( _('Password is empty.') ),
'PW_SHORTER_THAN_MIN_LENGTH': error_info( _('Password is too short.') ),
'PW_GREATER_THAN_MAX_LENGTH': error_info( _('Password is too long.') ),
'PW_NO_LETTER': error_info( _('No letter in password.') ),
'PW_NO_UPPERCASE': error_info( _('No uppercase letter in password.') ),
'PW_NO_DIGIT_NUMBER': error_info( _('No digit number in password.') ),
'PW_NO_SPECIAL_CHAR': error_info( _('No special character in password.') ),
'ALREADY_EXISTS': error_info(_('Account already exists, please choose another one.')),
'NO_DOMAIN': error_info(_('No mail domain available.')),
'NO_ACCOUNT_SELECTED': error_info(_('Please select at least one account.')),
'NOT_ALLOWED': error_info(_('Not allowed to create mail user under this domain.')),
'PERMISSION_DENIED': error_info(_("Permission denied.")),
'PERMISSION_DENIED_UPDATE_GLOBAL_ADMIN_PROFILE': error_info(_("You are not allowed to update global domain admin's profile.")),
'WBLIST_UPDATED': success_info( _('Records were successfully updated.')),
'EMAIL_CHANGED': success_info( _('Email address was changed.')),
'NO_SUCH_ACCOUNT': error_info(_('Account does not exist.')),
}
%}
{% if msg == 'CREATED' %}
<div class='notification note-success'><a href='#' class='close'></a>
<p><i class="far fa-check-circle fa-lg fa-fw"></i>
{{ _('User created.') }} <a href="{{ctx.homepath}}/create/user/{{mail.split('@',1)[-1]}}">{{ _('Add one more?') }}</a>
</p>
</div>
{% else %}
{% if msg in handlers %}
{{ handlers[msg] }}
{% else %}
{{ error_info(msg) }}
{% endif %}
{% endif %}
{% endif %}
{%- endmacro %}
{% macro admin_msg_handler(msg) -%}
{% if msg is defined and msg is not sameas none and msg|string != '' %}
{% set handlers = {
'UPDATED': success_info(_('Profile has been updated.')),
'INVALID_ACTION': error_info(_('Invalid action.')),
'PERMISSION_DENIED': error_info(_("Permission denied.")),
'DELETED': success_info(_('Selected accounts were deleted.')),
'DISABLED': success_info(_('Selected accounts were disabled.')),
'ENABLED': success_info(_('Selected accounts were enabled.')),
'NO_ACCOUNT_SELECTED': error_info(_('No account selected.')),
'INCORRECT_OLDPW': error_info(_('Current password is incorrect.')),
'INVALID_CREDENTIALS': error_info(_('Current password is incorrect.')),
'PW_MISMATCH': error_info(_('New passwords are not match.')),
'PW_NON_ASCII': error_info( _('Please do not use non-ascii character in password.') ),
'PW_EMPTY': error_info(_('Password is empty.')),
'PW_NO_LETTER': error_info( _('No letter in password.') ),
'PW_NO_UPPERCASE': error_info( _('No uppercase letter in password.') ),
'PW_NO_DIGIT_NUMBER': error_info( _('No digit number in password.') ),
'PW_NO_SPECIAL_CHAR': error_info( _('No special character in password.') ),
'INVALID_MAIL': error_info(_('Invalid mail address.')),
'ALREADY_EXISTS': error_info(_('Account already exists, please choose another one.')),
'NO_SUCH_ACCOUNT': error_info(_('Account does not exist.')),
'CAN_NOT_BE_LOCAL_DOMAIN': error_info(_('Standalone admin account cannot be an user of local domain.')),
}
%}
{% if msg == 'CREATED' %}
<div class='notification note-success'><a href='#' class='close'></a>
<p><i class="far fa-check-circle fa-lg fa-fw"></i>
{{ _('Admin created.') }} <a href="{{ctx.homepath}}/create/admin">{{ _('Add one more?') }}</a>
</p>
</div>
{% elif msg == 'PW_SHORTER_THAN_MIN_LENGTH' %}
{{ error_info( _('New password must contain at least %s characters.') |format(min_passwd_length) ) }}
{% elif msg == 'PW_GREATER_THAN_MAX_LENGTH' %}
{{ error_info( _('New password must NOT contain more than %s characters.') |format(max_passwd_length) ) }}
{% else %}
{% if msg in handlers %}
{{ handlers[msg] }}
{% else %}
{{ error_info(msg) }}
{% endif %}
{% endif %}
{% endif %}
{%- endmacro %}
{% macro maillist_msg_handler(msg) -%}
{% if msg %}
{% set handlers = {
'ALREADY_EXISTS': error_info(_('Account already exists, please choose another one.')),
'INVALID_MAIL': error_info(_('Invalid mail address.')),
'NO_ACCOUNT_SELECTED': error_info(_('No account selected.')),
'UPDATED': success_info(_('Profile has been updated.')),
'INVALID_ACTION': error_info(_('Invalid action.')),
'UPDATED_FAILED': error_info(_('Profile updated failed.')),
'MEMBER_ASSIGNED': success_info(_('Member assigned success.')),
'MEMBER_REMOVED': success_info(_('Member removed success.')),
'MODERATOR_ASSIGNED_SUCCESS': success_info(_('Moderators assigned success.')),
'MODERATOR_REMOVED_SUCCESS': success_info(_('Moderators removed success.')),
'DELETED': success_info(_('Selected accounts were deleted.')),
'DISABLED': success_info(_('Selected accounts were disabled.')),
'ENABLED': success_info(_('Selected accounts were enabled.')),
'NO_DOMAIN_AVAILABLE': general_info(_('No domain under control.')),
'NO_MODERATOR_SELECTED': error_info(_('No moderator selected.')),
'NOT_ALLOWED': error_info(_('Not allowed to create mailing list under this domain.')),
'NO_SUCH_ACCOUNT': error_info(_('Account does not exist.')),
'EMAIL_CHANGED': success_info( _('Email address was changed.')),
'MEMBERS_ADDED': success_info( _('Members has been added to mailing list.')),
'CONFIRM_MAIL_SENT': success_info( _('Confirm email has been sent to new members. Members will appear below after they confirmed the subscription.')),
'MIGRATED': success_info( _('Successfully migrated.')),
'PERMISSION_DENIED': error_info(_('Permission denied.')),
}
%}
{% if msg == 'CREATED' %}
<div class='notification note-success'><a href='#' class='close'></a>
<p><i class="far fa-check-circle fa-lg fa-fw"></i>
{{ _('Mailing list created.') }} <a href="{{ctx.homepath}}/create/ml/{{mail.split('@', 1)[-1]}}">{{ _('Add one more?') }}</a>
</p>
</div>
{% else %}
{% if msg in handlers %}
{{ handlers[msg] }}
{% else %}
{{ error_info(msg) }}
{% endif %}
{% endif %}
{% endif %}
{%- endmacro %}
{% macro alias_msg_handler(msg) -%}
{% if msg is defined and msg is not sameas none and msg|string != '' %}
{% set handlers = {
'ALREADY_EXISTS': error_info(_('Account already exists, please choose another one.')),
'UPDATED': success_info(_('Profile has been updated.')),
'INVALID_MAIL': error_info(_('Invalid mail address.')),
'INVALID_ACTION': error_info(_('Invalid action.')),
'NO_DOMAIN_AVAILABLE': general_info(_('No domain under control.')),
'DELETED': success_info(_('Selected accounts were deleted.')),
'DISABLED': success_info(_('Selected accounts were disabled.')),
'ENABLED': success_info(_('Selected accounts were enabled.')),
'MEMBER_ASSIGNED': success_info(_('Member assigned success.')),
'MEMBER_REMOVED': success_info(_('Member removed success.')),
'UPDATED_FAILED': error_info(_('Profile updated failed.')),
'EMPTY_LISTNAME': error_info(_('Empty address is not allowed.')),
'NOT_ALLOWED': error_info(_('Not allowed to create mail alias under this domain.')),
'NO_SUCH_ACCOUNT': error_info(_('Account does not exist.')),
'EMAIL_CHANGED': success_info( _('Email address was changed.')),
}
%}
{% if msg == 'CREATED' %}
<div class='notification note-success'><a href='#' class='close'></a>
<p><i class="far fa-check-circle fa-lg fa-fw"></i>
{{ _('Mail alias created.') }} <a href="{{ctx.homepath}}/create/alias/{{mail.split('@', 1)[-1]}}">{{ _('Add one more?') }}</a>
</p>
</div>
{% else %}
{% if msg in handlers %}
{{ handlers[msg] }}
{% else %}
{{ error_info(msg) }}
{% endif %}
{% endif %}
{% endif %}
{%- endmacro %}
{% macro log_msg_handler(msg) -%}
{% if msg is defined and msg is not sameas none and msg|string != '' %}
{% if msg == 'DELETED' %}
{{ success_info( _('Selected log records were deleted.') ) }}
{% elif msg == 'INVALID_PRODUCT_ID' %}
{{ error_info( _('Invalid product id.') ) }}
{% else %}
{{ error_info( msg ) }}
{% endif %}
{% endif %}
{%- endmacro %}
{% macro amavisd_msg_handler(msg) -%}
{% if msg is defined and msg is not sameas none and msg|string != '' %}
{% set handlers = {
'WBLIST_CREATED': success_info( _('Records were successfully added.')),
'WBLIST_UPDATED': success_info( _('Records were successfully updated.')),
'DELETED': success_info(_('Selected log records were deleted.')),
'RELEASED': success_info(_('Mails were released.')),
'RELEASED_WL_SENDER': success_info(_('Mails were released, and sender(s) were whitelisted.')),
'RELEASED_WL_SENDER_DOMAIN': success_info(_('Mails were released, and sender domain(s) were whitelisted.')),
'RELEASED_WL_SENDER_SUBDOMAIN': success_info(_('Mails were released, sender domain(s) and sub-domains were whitelisted.')),
'DELETED': success_info(_('Mails were deleted.')),
'DELETED_WL_SENDER': success_info(_('Mails were deleted, and sender(s) were whitelisted.')),
'DELETED_WL_SENDER_DOMAIN': success_info(_('Mails were deleted, and sender domain(s) were whitelisted.')),
'DELETED_WL_SENDER_SUBDOMAIN': success_info(_('Mails were deleted, sender domain(s) and sub-domain(s) were whitelisted.')),
'DELETED_BL_SENDER': success_info(_('Mails were deleted, and sender(s) were blacklisted.')),
'DELETED_BL_SENDER_DOMAIN': success_info(_('Mails were deleted, and sender domain(s) were blacklisted.')),
'DELETED_BL_SENDER_SUBDOMAIN': success_info(_('Mails were deleted, sender domain(s) and sub-domain(s) were blacklisted.')),
'DELETED_WL_RCPT': success_info(_('Mails were deleted, and recipient(s) were whitelisted.')),
'DELETED_WL_RCPT_DOMAIN': success_info(_('Mails were deleted, and recipient domain(s) were whitelisted.')),
'DELETED_WL_RCPT_SUBDOMAIN': success_info(_('Mails were deleted, recipient domain(s) and sub-domain(s) were whitelisted.')),
'DELETED_BL_RCPT': success_info(_('Mails were deleted, and recipient(s) were blacklisted.')),
'DELETED_BL_RCPT_DOMAIN': success_info(_('Mails were deleted, and recipient domain(s) were blacklisted.')),
'DELETED_BL_RCPT_SUBDOMAIN': success_info(_('Mails were deleted, recipient domain(s) and sub-domain(s) were blacklisted.')),
'INVALID_ACCOUNT': error_info(_('Invalid domain name or mail address.')),
'INVALID_ACTION': error_info(_('Invalid action.')),
'INVALID_MAILID': error_info(_('Invalid request data.')),
'PERMISSION_DENIED': error_info(_('Permission denied.')),
}
%}
{% if msg in handlers %}
{{ handlers[msg] }}
{% else %}
{{ error_info(msg) }}
{% endif %}
{% endif %}
{%- endmacro %}
{# Search accounts #}
{% macro search_msg_handler(msg) -%}
{% if msg is defined and msg is not sameas none and msg|string != '' %}
{% if msg == 'SUCCESS' %}
{{ success_info( _('Operation completed.') ) }}
{% elif msg == 'EMPTY_STRING' %}
{{ error_info( _('Search keyword could not be empty.') ) }}
{% elif msg == 'INVALID_MAIL' %}
{{ error_info( _('Invalid mail address.') ) }}
{% elif msg == 'INVALID_ACTION' %}
{{ error_info(_('Invalid action.')) }}
{% else %}
{{ error_info( msg ) }}
{% endif %}
{% endif %}
{%- endmacro %}
{% macro throttle_msg_handler(msg) -%}
{% if msg %}
{% set handlers = {
'CREATED': success_info( _('Records were successfully added.') ),
'UPDATED': success_info(_('Profile has been updated.')),
'DELETED': success_info( _('Selected records were deleted.') ),
'INVALID_ACTION': error_info(_('Invalid action.')),
} %}
{% if msg in handlers %}
{{ handlers[msg] }}
{% else %}
{{ error_info(msg) }}
{% endif %}
{% endif %}
{%- endmacro %}
{% macro greylist_msg_handler(msg) -%}
{% if msg %}
{% if msg == 'GL_UPDATED' %}
{{ success_info(_('Greylisting settings have been updated.')) }}
{% else %}
{{ error_info( msg ) }}
{% endif %}
{% endif %}
{%- endmacro %}
{% macro wblist_msg_handler(msg) -%}
{% if msg %}
{% if msg == 'UPDATED' %}
{{ success_info(_('Profile has been updated.')) }}
{% else %}
{{ error_info( msg ) }}
{% endif %}
{% endif %}
{%- endmacro %}
{% macro domain_ownership_msg_handler(msg) -%}
{% if msg %}
{% if msg == 'PERMISSION_DENIED' %}
{{ error_info(_('Permission denied.')) }}
{% else %}
{{ error_info( msg ) }}
{% endif %}
{% endif %}
{%- endmacro %}
{# NOTE: newsletter error page use different CSS framework, do not use macros
like `success_info()`, `error_info()` defined in this Jinja2 template
file.
#}
{% macro newsletter_error_msg_handler(msg) -%}
{% if msg %}
{% set handlers = {
'INVALID_NEWSLETTER': _('Oops, the newsletter you want to subscribe does not exist.'),
'INVALID_ACTION': _('Oops, invalid action.'),
'TOKEN_INVALID': _('Oops, confirm link is invalid.'),
'TOKEN_EXPIRED': _('Oops, confirm link expired. Please re-subscribe.'),
'INVALID_SUBSCRIBER_EMAIL_ADDRESS': _('Error, you entered an invalid email address.'),
'INTERNAL_SERVER_ERROR': _('Internal server error, please contact server admin to fix it.'),
} %}
{% if msg in handlers %}
{{ handlers[msg] }}
{% else %}
{{ msg | e }}
{% endif %}
{% endif %}
{%- endmacro %}

View File

@@ -0,0 +1,210 @@
{% from "macros/general.html" import
set_account_status_img
with context
%}
{% macro display_all_domains(managedDomains=None, allDomains=None) -%}
{% if not managedDomains %}
{% set managedDomains = [] %}
{% endif %}
{% if not allDomains %}
{% set allDomains = [] %}
{% endif %}
<div class="columns clear normal_admin_create_domain_options">
<div class="col2-3">
<div class="form-field clear">
<h4 class="size-250 fl-space">{{ _('Managed Domains') }}</h4>
<div class="checklist clear">
<div class="checklist-item clear">
{{ _('%d of %d in total.') | format(managedDomains |length, allDomains | length) }}
{{ _('Filter:') }} <input type="text" size="15" id="domain_search" style="width: auto;" />
<hr />
</div>
<table id="all_domains">
{# thead will be hidden. #}
<thead>
<tr>
<th width="1%"></th>
<th></th>
</tr>
</thead>
<tbody>
{% for r in allDomains %}
{% set domain = r.domain |e %}
<tr>
<td width="1%"><input type="checkbox"
name="domainName"
value="{{ domain }}"
{% if domain in managedDomains %}checked="checked"{% endif %}
/>
</td>
<td>
<a href="{{ctx.homepath}}/profile/domain/general/{{domain}}" title="{{ _('Edit account profile') }}">{{ domain }}</a>
{% if r.description %}({{ r.description |cut_string |e }}){% endif %}
</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
</div>
</div>{#-- .col2-3 --#}
{% if session.get('is_global_admin') %}
<div class="col1-3 lastcol">
<div class="mark_blue bt-space10">
<ul class="standard clean-padding bt-space10">
<li class="bt-space5"><a href="{{ctx.homepath}}/create/domain" class="action_add">{{ _('Add domain') }}</a></li>
</ul>
</div>
</div>
{% endif %}
</div>{#-- .columns --#}
{%- endmacro %}
{% macro display_enabled_user_services(profile, greylisted=False) -%}
{% set available_services = [
('checkbox', 'enabledeliver', _('Accepting mails sent to this account on mail server')),
('checkbox', 'enablesmtp', _('Sending mails via SMTP')),
('checkbox', 'enablesmtpsecured', _('Sending mails via SMTP over TLS/SSL')),
('checkbox', 'enablepop3', _('Fetching mails via POP3')),
('checkbox', 'enablepop3secured', _('Fetching mails via POP3 over TLS/SSL')),
('checkbox', 'enableimap', _('Fetching mails via IMAP')),
('checkbox', 'enableimapsecured', _('Fetching mails via IMAP over TLS/SSL')),
('checkbox', 'enablemanagesieve', _('Customize mail filter rule')),
('checkbox', 'enablemanagesievesecured', _('Customize mail filter rule over TLS/SSL')),
('checkbox', 'enablesogo', _('SOGo Groupware (Webmail, Calendar, ActiveSync)')),
('checkbox', 'enablesogowebmail', _('SOGo Webmail')),
('checkbox', 'enablesogocalendar', _('SOGo Calendar')),
('checkbox', 'enablesogoactivesync', _('SOGo ActiveSync')),
] %}
<div class="columns clear">
<div class="col2-3">
<div class="form-field clear">
<h4 class="size-250 fl-space">{{ _('Enabled Services') }}</h4>
{% for srv in available_services %}
{% if not loop.first %}
<h4 class="size-250 fl-space">&nbsp;</h4>
{% endif %}
{% set name = srv[1] %}
<div class="form-checkbox-item clear">
{% if name in ["enablesogowebmail", "enablesogocalendar", "enablesogoactivesync"] %}
&nbsp;&nbsp;&nbsp;&nbsp;|-
{% endif %}
<input name="enabledService"
type="{{ srv[0] }}"
value="{{ srv[1] }}"
class="{{ srv[0] }}"
rel="checkboxhorizont"
{% if name in profile %}
{% set value = profile[name] %}
{% if name in ["enablesogowebmail", "enablesogocalendar", "enablesogoactivesync"] %}
{# value is "y" (or "n") #}
{% if value == "y" %}
checked="checked"
{% endif %}
{% else %}
{% if value == 1 %}
checked="checked"
{% endif %}
{% endif %}
{% endif %}
/>
<label>{{ srv[2] }}</label>
</div>
{% endfor %}
</div>
</div>{# col2-3 #}
</div>{# columns #}
{%- endmacro %}
{% macro display_enabled_domain_services(enabled_services) -%}
{% set available_services = [
('checkbox', 'self-service', _('Self-service')),
] %}
<div class="columns clear">
<div class="col2-3">
<div class="form-field clear">
<h4 class="size-250 fl-space">{{ _('Enabled Services') }}</h4>
{% for srv in available_services %}
{% if not loop.first %}
<h4 class="size-250 fl-space">&nbsp;</h4>
{% endif %}
<div class="form-checkbox-item clear">
<input type="{{ srv[0] }}"
name="enabledService"
value="{{ srv[1] }}"
class="{{ srv[0] }}"
rel="checkboxhorizont"
{% if srv[1] in enabled_services %}checked="checked"{% endif %}
/>
<label>{{ srv[2] }}</label>
</div>
{% endfor %}
</div>
</div> {# .col2-3 #}
</div> {# .columns #}
{%- endmacro %}
{% macro display_mls(maillists, profile_base_url, domain=None) %}
<table class="style1">
<thead>
<tr>
<th class="checkbox"><input type="checkbox" class="checkbox select-all" /></th>
<th data-sort="string-ins">{{ _('Display Name') }}</th>
<th data-sort="string-ins">{{ _('Mail Address') }}</th>
<th data-sort="string-ins">{{ _('Mail Deliver Restriction') }}</th>
</tr>
</thead>
<tbody>
{% if maillists|length > 0 %}
{% for r in maillists %}
{% set address = r.address |e %}
{% set name = r.name |e %}
{% set access_policy = r.accesspolicy |e %}
{% set account_status = r.active %}
<tr>
<td class="checkbox"><input type="checkbox" class="checkbox" name="mail" value="{{ address }}" /></td>
<td>
<a href="{{ profile_base_url }}/members/{{ address }}"><i class="fa fa-users fa-lg fr-space" title="{{ _('View members') }}"></i></a>
<a href="{{ profile_base_url }}/general/{{ address }}"><i class="fa fa-cog fa-lg fr-space" title="{{ _('Edit account profile') }}"></i></a>
{{ set_account_status_img(account_status) }}
<a href="{{ profile_base_url }}/general/{{ address }}" title="{{ _('Edit account profile') }}">{% if name %}{{ name |cut_string |e }}{% else %}{{ address.split('@', 1)[0] }}{% endif %}</a>
</td>
<td>{{ highlight_username_in_mail(address) }}</td>
<td>{{ display_list_access_policy_name(policy=access_policy) }}</td>
</tr>
{% endfor %}
{% else %}
<tr>
<td class="checkbox"></td>
<td colspan="4">{{ _('No mailing list available.') }}
{% if (not session['account_is_mail_user']) and domain %}
{% if not first_char %}
<a href="{{ ctx.homepath }}/create/ml/{{ domain }}">{{ _('Add one') }}</a>?
{% endif %}
{% endif %}
</td>
</tr>
{% endif %}
</tbody>
</table>
{% endmacro %}

View File

@@ -0,0 +1,16 @@
{% extends "mlmmj/layout.html" %}
{% from "macros/msg_handlers.html" import newsletter_error_msg_handler with context %}
{% block title %}{{ _('Error') }}{% endblock %}
{% block main %}
<div class="container" style="width: 600px; margin-left: auto; margin-right: auto;">
<div class="empty" style="padding-top: 50px;">
<div class="toast toast-error">
<i class="icon icon-stop"></i>
{{ newsletter_error_msg_handler(msg) }}
</div>
</div>
</div>
{% endblock main %}

View File

@@ -0,0 +1,21 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
<meta http-equiv="imagetoolbar" content="no"/>
<title>{% block title %}{%endblock%}</title>
<link rel="stylesheet" type="text/css" href="{{ctx.homepath}}/static/{{skin}}/css/spectre.min.css" />
<link rel="stylesheet" type="text/css" href="{{ctx.homepath}}/static/{{skin}}/css/spectre-icons.min.css" />
<link rel="icon" type="image/x-icon" href="{{ctx.homepath}}/static/{% if brand_favicon %}{{ brand_favicon }}{% else %}favicon.ico{% endif %}" />
<style type="text/css">
body { background: #f8f9fa; }
</style>
</head>
<body>
{% block main %}{% endblock %}
</body>
</html>

View File

@@ -0,0 +1,80 @@
{% extends "mlmmj/layout.html" %}
{% block title %}
{%- if action == 'subscribe' -%}
{{ _('Subscribe') }}
{%- else -%}
{{ _('Unsubscribe') }}
{%- endif -%}
{% endblock title %}
{% block main %}
<form method="post" action="{{ newsletter_base_url }}/{{ action }}/{{ mlid }}">
<div class="container" style="width: 600px; margin-left: auto; margin-right: auto;">
<div class="empty" style="padding-top: 50px;">
<div class="empty-icon" style="padding-top: 10px;">
<i class="icon icon-4x icon-mail"></i>
</div>
{# Display custom name or default text. #}
{% if name %}
<p class="empty-title h5">{{ name |e }}</p>
{% else %}
<p class="empty-title h5">
{%- if action == 'subscribe' -%}
{{ _('Subscribe to newsletter') }}
{%- else -%}
{{ _('Unsubscribe from newsletter') }}
{%- endif -%}
</p>
{% endif %}
{# Display description of the newsletter. #}
{% if description %}
<p class="empty-subtitle">{{ description }}</p>
{% endif %}
{% if msg == 'SUBSCRIBED' %}
<div class="toast toast-success"><i class="icon icon-2x icon-emoji"></i> <span style="vertical-align: 20%;">{{ _('Thank you for subscribing.') }}</span></div>
{% elif msg == 'UNSUBSCRIBED' %}
<div class="toast toast-success"><i class="icon icon-2x icon-emoji"></i> <span style="vertical-align: 20%;">{{ _('Successfully unsubscribed.') }}</span></div>
{% elif msg in ['WAIT_FOR_SUBCONFIRM', 'WAIT_FOR_UNSUBCONFIRM'] %}
<div class="toast toast-primary">
<i class="icon icon-2x icon-time"></i>
<span style="vertical-align: 20%;">{{ _('Almost finished.') }}</span>
</div>
<div class="empty-action text-left">
<span class="text-left">
{%- if action == 'subscribe' -%}
{{ _('We need to confirm your email address. To complete the subscription process, please click the link in the email we just sent you.') }}
{%- else -%}
{{ _('We need to confirm your email address. To complete the unsubscription process, please click the link in the email we just sent you.') }}
{%- endif -%}
</span>
</div>
{% else %}
<div class="empty-action input-group input-inline">
<input type="text" class="form-input" size="30" name="subscriber" placeholder="Email Address">
<button class="btn btn-primary input-group-btn">
{%- if action == 'subscribe' -%}
{{ _('Subscribe') }}
{%- else -%}
{{ _('Unsubscribe') }}
{%- endif -%}
</button>
</div>
<div class="empty-action">
{{ _('Or') }}&nbsp;&nbsp;
{%- if action == 'subscribe' -%}
<a href="{{ newsletter_base_url }}/unsubscribe/{{ mlid }}">{{ _('Unsubscribe') }}</a>
{%- else -%}
<a href="{{ newsletter_base_url }}/subscribe/{{ mlid }}">{{ _('Subscribe') }}</a>
{%- endif -%}
</div>
{% endif %}
</div>
</div>
</form>
{% endblock main %}

View File

@@ -0,0 +1,113 @@
{% extends "layout.html" %}
{% from "macros/msg_handlers.html" import domain_ownership_msg_handler with context %}
{% block title %}{{ _('Domain ownership verification') }}{% endblock %}
{% block navlinks_system %}class="active"{% endblock %}
{% block main %}
{# Show system message #}
{{ domain_ownership_msg_handler(msg) }}
<div class="content-box">
<div class="box-body">
<div class="box-header clear">
<h2>{{ _('Domain ownership verification') }}</h2>
</div>
<div class="box-wrap clear">
<div class="columns clear">
<p>{{ _('Please verify mail domains listed below, to ensure that it is an valid domain and you have the required privileges in the domain to manage the email services. Mail services are disabled for pending domains, and will be enabled automatically after verified.') }}</p>
<p>{{ _('To verify domain ownership, please choose one of methods listed below:') }}</p>
<ul class="standard clean-padding bt-space20">
<li>{{ _('Create a text file under top directory of your web site, both file name and file content must be same as verify code') }}</li>
<li>{{ _('Create a TXT type DNS record of the domain name, use the verify code as its value') }}</li>
</ul>
<form id="form_ownership" method="post" action="{{ctx.homepath}}/verify/domain_ownership">
<table class="style1">
<thead>
<tr>
<th class="checkbox"><input type="checkbox" class="checkbox select-all" /></th>
<th>{{ _('Domain') }}</th>
<th style="white-space: nowrap;">{{ _('Verify code') }}</th>
{% if session.get('is_global_admin') %}
<th>{{ _('Admin') }}</th>
{% endif %}
<th>{{ _('Last verify status') }}</th>
<th>{{ _('Last verify time') }}</th>
</tr>
</thead>
<tbody>
{% if ownership_verify_codes %}
{% for r in ownership_verify_codes %}
{% if r.alias_domain %}
{% set verify_domain = r.alias_domain |e |lower %}
{% else %}
{% set verify_domain = r.domain |e |lower %}
{% endif %}
<tr>
<td class="checkbox vcenter">
<input type="checkbox"
class="checkbox"
name="domain"
value="{{ verify_domain }}" />
</td>
{% set verify_code = r.verify_code |e %}
{% set tip_http = 'http://' + verify_domain + '/' + verify_code %}
{% set tip_https = 'https://' + verify_domain + '/' + verify_code %}
{% set tip_dns = 'nslookup -type=txt ' + verify_domain %}
{% set tooltip = "<ul style='list-style-type: circle; padding-left: 10px;'>" +
"<li class='bt-space20'>" + _('Visit URLs below with a web browser should display verify code as page content:') +
' <a href="' + tip_http + '"/>' + '<pre>' + tip_http + '</pre>' + '</a>' +
' <pre>' + tip_https + '</pre>' + '</li>' +
"<li class='bt-space20'>" + _('DNS query result should contain the verify code:') +
' <pre>' + tip_dns + '</pre></li>' +
"</ul>"
%}
<td>{{ verify_domain }}</td>
<td style="white-space: nowrap;"><span title="{{ tooltip }}">{{ verify_code |e }}</span></td>
{% if session.get('is_global_admin') %}
<td>{% if r.admin %}{{ r.admin |e }}{% endif %}</td>
{% endif %}
<td>{% if r.message %}{{ r.message |e }}{% endif %}</td>
<td style="white-space: nowrap;">{% if r.last_verify %}{{ r.last_verify |set_datetime_format | utc_to_timezone(timezone=session['timezone']) }}{% endif %}</td>
</tr>
{% endfor %}
{% else %}
<tr>
<td></td>
<td colspan="{% if session.get('is_global_admin') %}5{% else %}4{% endif %}">{{ _('No pending mail domain ownership verification.') }}</td>
</tr>
{% endif %}
</tbody>
</table>
{% if ownership_verify_codes %}
<div class="tab-footer clear f1">
{% if session.get('is_global_admin') or session.get('create_new_domains') %}
<div class="fl">
<input type="submit" name="verify" value="{{ _('Verify Now') }}" class="button blue fl-space" />
{% if session.get('is_global_admin') %}
<input type="submit" name="enable_without_verification" value="{{ _('Enable selected domain without verification') }}" class="button green fl-space" />
{% endif %}
</div>
{% endif %}
</div>
{% endif %}
</form>
</div>
</div>
</div>
</div>
{% endblock main %}

View File

@@ -0,0 +1,93 @@
{% extends "layout.html" %}
{% block title %}{{ _('License') }}{% endblock %}
{% block navlinks_system %}class="active"{% endblock %}
{% block main %}
<div class="content-box">
<div class="box-body">
<div class="box-header clear">
<h2>{{ _('License') }}</h2>
</div>
<div class="box-wrap clear">
<div class="columns clear">
<div class="col2-3">
{% if info is defined %}
<div class="form-field clear">
<h4 class="size-250 fl-space">{{ _('License status') }}</h4>
<span class="clean-padding bt-space20">
{% if info['status'] == 'active' %}
<i class="fa fa-check-circle" style="color: #4dc049;"></i> {{ _('License is active') }}
{% elif info['status'] == 'expired' %}
<i class="fa fa-exclamation-triangle" style="color: red;"></i> {{ _('Expired') }}
{% endif %}
</span>
</div>
<div class="form-field clear">
<h4 class="size-250 fl-space">{{ _('Product name') }}</h4>
<span class="clean-padding bt-space20">{{ info['product'] }}</span>
</div>
<div class="form-field clear">
<h4 class="size-250 fl-space">{{ _('License Key') }}</h4>
<span class="clean-padding bt-space20">{{ info['licensekey'] }}</span>
</div>
<div class="form-field clear">
<h4 class="size-250 fl-space">{{ _('Purchase date') }}</h4>
<span class="clean-padding bt-space20">{{ info['purchased'] }}</span>
</div>
<div class="form-field clear">
<h4 class="size-250 fl-space">{{ _('Expire date') }}</h4>
<span class="clean-padding bt-space20">
{{ info['expired'] }}
{% if info['expired'] == '2099-12-31' %}
({{ _('Lifetime license') }})
{% endif %}
</span>
</div>
<div class="form-field clear">
<h4 class="size-250 fl-space">{{ _('License owner(s)') }}</h4>
<span class="clean-padding bt-space20">{{ info['contacts'] }}</span>
</div>
<div class="form-field clear">
<h4 class="size-250 fl-space">{{ _('Latest version') }}</h4>
<span class="clean-padding bt-space20">{{ info['latestversion'] }} ({{ _('You are running version %s') |format(version |e) }})</span>
</div>
{% endif %}
{% if error is defined %}
{{ _('Error while getting license info:') }} {{ error |e }}
{% endif %}
</div>{# col2-3 #}
{% if info is defined %}
<div class="col1-3 lastcol">
<div class="mark_blue bt-space10">
<ul class="standard clean-padding bt-space10">
{% if info['status'] == 'active' %}
{%- if session.get('new_version_available') -%}
<li class="bt-space5" style="list-style-type: none;">
<form name="download" method="post" action="https://lic.iredmail.org/check_version/downloadlink/{{ info['id'] }}" style="display: inline;">
<input type="submit" class="button green" value="{{ _('Send me an email with download link') }}" />
</form>
</li>
{%- endif -%}
{% endif %}
<li class="bt-space5"><a href="{{ info['releasenotes'] }}" target="_blank" rel="noopener">{{ _('Release Notes and Upgrade Tutorials') }}</a></li>
</ul>
</div>
</div>{# col1-3 #}
{% endif %}
</div>{# columns #}
</div>{# box-wrap #}
</div>{# box-body #}
</div>{# content-box #}
{% endblock main %}

View File

@@ -0,0 +1,143 @@
{% extends "layout.html" %}
{% from "macros/form_inputs.html" import
input_csrf_token
with context
%}
{% from "macros/general.html" import
show_pages,
show_event_name
with context
%}
{% from "macros/msg_handlers.html" import log_msg_handler with context %}
{% block title %}{{ _('Admin Log') }}{% endblock %}
{% block navlinks_activities %}class="active"{% endblock %}
{% block main %}
{{ log_msg_handler(msg) }}
<div class="content-box">
<div class="box-body">
<div class="box-header clear">
<h2>{{ _('Admin Log') }}
{% if total > 0 %}
({{ (cur_page-1)*page_size_limit + 1 }}-{{ (cur_page-1)*page_size_limit + (entries |length) }}/{{ total }})
{% endif %}
</h2>
</div>
<div class="clear"></div>
{# List all pages. #}
<div class="top-space5 bt-space5 left-space5">
<form name="pages" method="get" action="{{ctx.homepath}}/activities/admins">
<i class="fa fa-filter"></i> {{ _('Filter:') }}
<select name="domain">
<option value="all">{{ _('Domains') }}</option>
{% for d in all_domain_names %}
<option value="{{ d |e }}" {% if d == domain %}selected{% endif %}>{{ d |e }}</option>
{% endfor %}
</select>
{% if session.get('is_global_admin') %}
<select name="admin">
<option value="all">{{ _('Admins') }}</option>
{% for a in all_admin_emails %}
<option value="{{ a |e }}" {% if a == admin %}selected{% endif %}>{{ a |e }}</option>
{% endfor %}
</select>
{% endif %}
<select name="event">
{% for evt in log_events %}
<option value="{{ evt |e }}" {% if evt == event %}selected{% endif %}>{{ show_event_name(event=evt) }}</option>
{% endfor %}
</select>
<input type="submit" value="{{ _('Submit') }}" class="button" />
</form>
</div>
{# List all logs #}
<form name="log" id="list_table" method="post" action="{{ctx.homepath}}/activities/admins">
{{ input_csrf_token() }}
<input type="hidden" name="domain" value="{{ domain |e }}" />
<input type="hidden" name="admin" value="{{ admin |e }}" />
<input type="hidden" name="event" value="{{ event |e }}" />
<table class="style1">
<thead>
<tr>
{% if session.get('is_global_admin') %}
<th class="checkbox"><input type="checkbox" class="checkbox select-all" /></th>
{% endif %}
<th data-sort="string-ins">{{ _('Time') }}</th>
<th data-sort="string-ins">{{ _('Admin') }}</th>
<th data-sort="string-ins">{{ _('IP Address') }}</th>
<th data-sort="string-ins">{{ _('Message') }}</th>
</tr>
</thead>
{# List domain attributes/avalues. #}
<tbody>
{% if entries |length > 0 %}
{% for log in entries %}
<tr>
{% if session.get('is_global_admin') %}
<td class="checkbox"><input type="checkbox" name="id" value="{{ log.id }}" class="checkbox" /></td>
{% endif %}
<td style="white-space: nowrap;">{{ log.timestamp |set_datetime_format | utc_to_timezone(timezone=session['timezone'])}}</td>
{% set log_admin = log.admin | string | e%}
{% if '@' in log_admin %}
<td><a href="{{ctx.homepath}}/activities/admins?admin={{ log_admin }}">{{ log_admin }}</a></td>
{% elif log_admin.startswith('cron_backup') %}
<td><a href="{{ctx.homepath}}/activities/admins?event=backup">{{ log_admin }}</a></td>
{% elif log_admin == 'delete_mailboxes' %}
<td><a href="{{ctx.homepath}}/activities/admins?event=delete_mailboxes">{{ log_admin }}</a></td>
{% else %}
<td>{{ log_admin }}</td>
{% endif %}
<td>{{ log.ip |e }}</td>
<td class="{{ log.event |e }}_{{ log.loglevel |e }}">{{ log.msg |e }}</td>
</tr>
{% endfor %}
{% else %}
<tr>
{% if session.get('is_global_admin') %}
<td class="checkbox"></td>
{% endif %}
<td colspan="4">{{ _('No admin log.') }}</td>
</tr>
{% endif %}
</tbody>
</table>
<div class="tab-footer clear f1">
{% if session.get('is_global_admin') %}
<div class="fl">
<select name="action" class="fl-space">
<option>{{ _('Choose Action') }}</option>
<option disabled>----</option>
<option value="delete">{{ _('Delete selected log') }}</option>
<option value="deleteAll">{{ _('Delete all in database') }}</option>
</select>
<input type="submit" value="{{ _('Apply') }}" class="button fl-space" />
</div>
{% endif %}
{{ show_pages(baseurl=ctx.homepath + '/activities/admins?domain=' + domain + '&event=' + event + '&admin=' + admin,
total=total,
cur_page=cur_page,
sep='&page=') }}
</div>
</form>
</div>
</div>
{% endblock main %}

View File

@@ -0,0 +1,159 @@
{% extends "layout.html" %}
{% from "macros/form_inputs.html" import
input_text,
input_checkbox,
input_radios,
input_select,
input_textarea,
input_submit,
input_csrf_token
with context
%}
{% from "macros/general.html" import
show_pages,
show_event_name
with context
%}
{% from "macros/msg_handlers.html" import log_msg_handler with context %}
{% block title %}{{ _('System Settings') }}{% endblock %}
{% block navlinks_system %}class="active"{% endblock %}
{% block main %}
<div class="content-box">
<div class="box-body">
<div class="box-header clear">
<h2>{{ _('System Settings') }}</h2>
<ul class="tabs clear">
<li class="active"><a href="{{ctx.homepath}}/system/settings">{{ _('System Settings') }}</a></li>
<li><a href="{{ctx.homepath}}/activities/admins">{{ _('Admin Log') }}</a></li>
{% if session.get('amavisd_enable_logging') and (session.get('disable_viewing_mail_log') is not sameas true) %}
<li><a href="{{ctx.homepath}}/activities/sent">{{ _('Sent Mails') }}</a></li>
<li><a href="{{ctx.homepath}}/activities/received">{{ _('Received Mails') }}</a></li>
{% endif %}
{% if session.get('amavisd_enable_quarantine') and (session.get('disable_managing_quarantined_mails') is not sameas true) %}
<li><a href="{{ctx.homepath}}/activities/quarantined">{{ _('Quarantined Mails') }}</a></li>
{% endif %}
</ul>
</div>{# .box-header #}
<div class="box-wrap clear">
<form name="general" method="post" action="{{ctx.homepath}}/system/settings">
{{ input_csrf_token() }}
<h2>{{ _('Mailbox') }}</h2>
<div class="rule"></div>
{% set mailbox_format_options = [
('maildir', _('Maildir (One message per file). Recommended.')),
('mdbox', _('Mdbox (Multiple messages per file)')),
] %}
<div class="columns clear">
<div class="col2-3">
{{ input_radios(label=_('Default mailbox format'),
input_name='mailbox_format',
options=mailbox_format_options,
value=db_settings.get('mailbox_format')) }}
{{ input_text(label=_('Default mailbox folder'),
input_name='mailbox_folder',
value=db_settings.get('mailbox_folder'),
comment=_('Only letters (case sensitive) and digits are allowed, max 20 chars.'),
size=20,
maxlength=20) }}
</div>
<div class="col1-3 lastcol">
<div class="mark_blue bt-space10">
<ul class="standard clean-padding bt-space10">
<li>{{ _('It affects newly created mailboxes, not existing ones.') }}</li>
<li>{{ _('Maildir is easy to migrate, backup and restore.') }}</li>
<li>{{ _('Mdbox has better performance, but corrupted/lost index files will cause data lose and can not be recovered.') }}</li>
</ul>
</div>
</div>{# .col1-3 #}
</div>{# .columns #}
<h2>{{ _('Password') }}</h2>
<div class="rule"></div>
{{ input_text(label=_('Minimum password length'),
input_name='min_passwd_length',
value=db_settings.get('min_passwd_length'),
size=4) }}
{{ input_text(label=_('Maximum password length'),
input_name='max_passwd_length',
value=db_settings.get('max_passwd_length'),
size=4) }}
{{ input_checkbox(label=_('Require at least one letter'),
input_name='password_has_letter',
checked=db_settings.get('password_has_letter')) }}
{{ input_checkbox(label=_('Require at least one uppercase letter'),
input_name='password_has_uppercase',
checked=db_settings.get('password_has_uppercase')) }}
{{ input_checkbox(label=_('Require at least one digit number'),
input_name='password_has_number',
checked=db_settings.get('password_has_number')) }}
{{ input_checkbox(label=_('Require at least one special character'),
input_name='password_has_special_char',
checked=db_settings.get('password_has_special_char')) }}
<h2>{{ _('Login Restrictions') }}</h2>
<div class="rule"></div>
{{ input_textarea(label=_('All admins can only login from specified IP addresses or networks'),
input_name='admin_login_ip_list',
value=db_settings.get('admin_login_ip_list'),
is_list_of_ip_or_network=true,
rows=4) }}
{{ input_textarea(label=_('Global admin can only login from specified IP addresses or networks'),
input_name='global_admin_ip_list',
value=db_settings.get('global_admin_ip_list'),
is_list_of_ip_or_network=true,
rows=4) }}
{{ input_textarea(label=_('RESTful API is accessible only from specified IP addresses or networks'),
input_name='restful_api_clients',
value=db_settings.get('restful_api_clients'),
is_list_of_ip_or_network=true,
rows=4) }}
<h2 id="data_cleanup">{{ _('Data Clean Up') }}</h2>
<div class="rule"></div>
{{ input_text(label=_('Remove log of inbound/outbound mails older than'),
input_name='amavisd_remove_maillog_in_days',
value=db_settings.get('amavisd_remove_maillog_in_days'),
comment=_('Days'),
comment_as_text=true,
size=4) }}
{{ input_text(label=_('Remove quarantined mails older than'),
input_name='amavisd_remove_quarantined_in_days',
value=db_settings.get('amavisd_remove_quarantined_in_days'),
comment=_('Days'),
comment_as_text=true,
size=4) }}
{{ input_submit() }}
</form>
</div>{# .box-wrap #}
</div>{# .box-body #}
</div>{# .content-box #}
{% endblock main %}

View File

@@ -0,0 +1,74 @@
{% extends "layout.html" %}
{% from "macros/form_inputs.html" import
input_submit,
input_csrf_token
with context
%}
{% from "macros/general.html" import
display_random_password,
display_preferred_language,
display_add_admin,
display_domain_creation_options_of_normal_admin
with context %}
{% from "macros/msg_handlers.html" import admin_msg_handler with context %}
{% block navlinks_create %}class="active"{% endblock %}
{% block title %}{{ _('Add admin') }}{% endblock title %}
{% block main %}
{# Show system message #}
{% if msg %}
{% if msg.startswith('PW_') %}
{% set _pw_errors = msg.split(',') %}
{% for _err in _pw_errors %}
{{ admin_msg_handler(_err) }}
{% endfor %}
{% else %}
{{ admin_msg_handler(msg) }}
{% endif %}
{% endif %}
<div class="content-box">
<div class="box-body">
<div class="box-header clear">
{# -- Tabs -- #}
<ul class="tabs clear">
<li><a href="{{ctx.homepath}}/admins">{{ _('All admins') }}</a></li>
<li class="active"><a href="{{ctx.homepath}}/create/admin"><i class="fa fa-plus"></i>&nbsp;{{ _('Add admin') }}</a></li>
</ul>
<h2>{{ _('Add admin') }}</h2>
</div>
<div class="columns clear">
<div class="col2-3">
<div id="admin_add" class="box-wrap clear">
<form name="create" method="post" action="{{ctx.homepath}}/create/admin">
{{ input_csrf_token() }}
{{ display_add_admin(min_passwd_length=min_passwd_length,
max_passwd_length=max_passwd_length,
lang=default_language,
languagemaps=languagemaps) }}
{{ display_domain_creation_options_of_normal_admin(admin_settings={}) }}
{{ input_submit(label=_('Add')) }}
</form>
</div>
</div>
<div class="box-wrap clear">
<div class="col1-3 lastcol">
{{ display_random_password(password_length=min_passwd_length,
password_policies=password_policies) }}
</div>
</div>
</div>
</div>
</div>
{% endblock main %}

View File

@@ -0,0 +1,118 @@
{% extends "layout.html" %}
{% from "macros/form_inputs.html" import
input_csrf_token
with context
%}
{% from "macros/general.html" import
set_account_status_img,
highlight_username_in_mail,
set_admin_type_img,
show_pages
with context
%}
{% from "macros/msg_handlers.html" import admin_msg_handler with context %}
{% block title %}{{ _('Domain Admins') }}{% endblock %}
{% block navlinks_admins %}class="active"{% endblock %}
{% block main %}
{# Show system message #}
{{ admin_msg_handler(msg) }}
{# List admins #}
{#{% if admins|length > 0 %}#}
{% if admins is not string %}
<div class="content-box">
<div class="box-body">
<div class="box-header clear">
{% if session.get('is_global_admin') %}
<ul class="tabs clear">
<li><a href="{{ctx.homepath}}/create/admin"><i class="fa fa-plus"></i>&nbsp;{{ _('Add admin') }}</a></li>
</ul>
{% endif %}
<h2>{{ _('All admins') }}
{% if total is defined and admins|length > 0 %}
({{ (cur_page-1) * page_size_limit + 1 }}-{{ (cur_page-1) * page_size_limit + admins|length}}/{{ total }})
{% endif %}
</h2>
</div>
<form name="admins" id="list_table" method="post" action="{{ctx.homepath}}/admins">
{{ input_csrf_token() }}
<table class="style1">
<thead>
<tr>
<th class="checkbox"><input type="checkbox" class="checkbox select-all" /></th>
<th data-sort="string-ins">{{ _('Display Name') }}</th>
<th data-sort="string-ins">{{ _('Mail Address') }}</th>
<th data-sort="string-ins">{{ _('Global Admin') }}</th>
</tr>
</thead>
<tbody>
{% for r in admins %}
{% set mail = r.username |e %}
{% set name = r.name |e %}
<tr>
<td class="checkbox">
<input type="checkbox"
name="mail"
class="checkbox"
value="{{ mail }}"
{% if mail == session.get('username') %}disabled="disabled"{% endif %}
/>
</td>
<td>
<a href="{{ctx.homepath}}/profile/{% if r.get('isadmin') is not sameas none %}user{% else %}admin{% endif %}/general/{{ mail }}"><i class="fa fa-cog fa-lg fr-space" title="{{ _('Edit account profile') }}"></i></a>
{{ set_account_status_img(r.active) }}
{# -- Show name -- #}
<a href="{{ctx.homepath}}/profile/{% if r.get('isadmin') is not sameas none %}user{% else %}admin{% endif %}/general/{{ mail }}" title="{{ _('Edit account profile') }}">{% if name == '' %}{{ mail.split('@', 1)[0] }}{% else %}{{ name |cut_string }}{% endif %}</a>
</td>
<td>{{ mail }}</td>
{% if r.get('isglobaladmin') is not sameas none %}
{# users marked as admin #}
{% if r.get('isglobaladmin') == 1 %}
<td>{{ set_admin_type_img('yes') }}</td>
{% else %}
<td>{{ set_admin_type_img('no') }}</td>
{% endif %}
{% else %}
{# Separate admin accounts #}
{% if mail in allGlobalAdmins %}
<td>{{ set_admin_type_img('yes') }}</td>
{% else %}
<td>{{ set_admin_type_img('no') }}</td>
{% endif %}
{% endif %}
</tr>
{% endfor %}
</tbody>
</table>
<div class="tab-footer clear f1">
<div class="fl">
<select name="action" class="fl-space">
<option>{{ _('Choose Action') }}</option>
<option value="enable">{{ _('Enable') }}</option>
<option value="disable">{{ _('Disable') }}</option>
<option value="delete">{{ _('Delete') }}</option>
</select>
<input type="submit" value="{{ _('Apply') }}" class="button fl-space" />
</div>
{{ show_pages(baseurl=ctx.homepath + '/admins', total=total, cur_page=cur_page) }}
</div>
</form>
</div>{# -- box body -- #}
</div>{# -- content box -- #}
{% endif %}
{% endblock main %}

View File

@@ -0,0 +1,165 @@
{% extends "layout.html" %}
{% from "macros/form_inputs.html" import
input_submit,
input_csrf_token
with context
%}
{% from "macros/general.html" import
display_subnav,
set_account_status_img,
display_account_status,
display_input_cn,
display_preferred_language,
display_timezones,
display_reset_password,
display_random_password,
display_input_global_admin,
display_domain_creation_options_of_normal_admin
with context
%}
{% from "macros/sql.html" import
display_all_domains
with context
%}
{% from "macros/msg_handlers.html" import admin_msg_handler with context %}
{% block title %}{{ _('Edit account profile') }}{% endblock %}
{% block navlinks_admins %}class="active"{% endblock %}
{% block breadcrumb %}
{% if session.get('is_global_admin') %}
{% set crumbs = [(ctx.homepath + '/admins', _('All admins')),
('active', ctx.homepath + '/profile/admin/general/' + mail, _('Profile of admin:') + '&nbsp;' + mail)] %}
{% else %}
{% set crumbs = [('active', ctx.homepath + '/profile/admin/general/' + mail, _('Profile of admin:') + '&nbsp;' + mail)] %}
{% endif %}
{{ display_subnav(crumbs) }}
{% endblock %}
{% block main %}
{# Show system message #}
{% if msg %}
{% if msg.startswith('PW_') %}
{% set _pw_errors = msg.split(',') %}
{% for _err in _pw_errors %}
{{ admin_msg_handler(_err) }}
{% endfor %}
{% else %}
{{ admin_msg_handler(msg) }}
{% endif %}
{% endif %}
{% set navlinks = [
('general', _('General'), []),
('password', _('Password'), []),
]
%}
<div class="content-box">
<div class="box-body">
<div class="box-header clear">
<ul class="tabs clear">
{% for nav in navlinks %}
{% if not false in nav[2] and not none in nav[2] %}
<li><a href="#profile_{{ nav[0] }}">{{ nav[1] }}</a></li>
{% endif %}
{% endfor %}
</ul>
<h2>{{ _('Profile of admin:') }} {{ mail }}</h2>
</div>
<div class="box-wrap clear">
<div id="profile_general">
<form name="general" method="post" action="{{ctx.homepath}}/profile/admin/general/{{mail}}">
{{ input_csrf_token() }}
<div class="columns clear">
<div class="col2-3">
{% if session.get('is_global_admin') %}
{{ display_account_status(profile.active) }}
{% endif %}
{{ display_input_cn(value=profile.name, account_type='admin') }}
{{ display_preferred_language(value=profile.get('language', 'en_US') |e,
languagemaps=languagemaps) }}
{{ display_timezones(value=admin_settings.get('timezone'), timezones=timezones) }}
{% if session.get('is_global_admin') %}
<div class="rule"></div>
{{ display_input_global_admin(value=is_global_admin) }}
{% endif %}
</div>
{% if session.get('is_global_admin') %}
<div class="col2-3">
{{ display_domain_creation_options_of_normal_admin(admin_settings=admin_settings) }}
</div>
<div class="col1-3 lastcol normal_admin_create_domain_options">
<div class="mark_blue bt-space10">
<p>{{ _('All domains managed by this admin share the mailbox quota and limit of mail accounts.') }}</p>
</div>
</div>{# .col1-3 #}
{% endif %}
{% if session.get('is_global_admin') %}
{{ display_all_domains(managedDomains=managedDomains, allDomains=allDomains) }}
{% endif %}
</div>{# .columns #}
{{ input_submit() }}
</form>
</div>
<div id="profile_password">
<form name="password" method="post" action="{{ctx.homepath}}/profile/admin/password/{{mail}}">
{{ input_csrf_token() }}
<div class="columns clear">
<div class="col3-4">
{% if session.get('is_global_admin') %}
{{ display_reset_password(
min_passwd_length=min_passwd_length,
max_passwd_length=max_passwd_length,
show_confirmpw=true,
store_password_in_plain_text=store_password_in_plain_text) }}
{% else %}
{{ display_reset_password(
min_passwd_length=min_passwd_length,
max_passwd_length=max_passwd_length,
show_oldpw=true,
show_confirmpw=true,
store_password_in_plain_text=store_password_in_plain_text) }}
{% endif %}
</div>
<div class="col1-4 lastcol">
{{ display_random_password(password_length=min_passwd_length,
password_policies=password_policies) }}
</div>
</div>
{{ input_submit() }}
</form>
</div>
</div>{# .box-wrap #}
</div>{# .box-body #}
</div>{#-- .content-box --#}
{% endblock main %}
{% block extra_js %}
<script type="text/javascript">
$(document).ready(function() {
$(".tabs li").idTabs("profile_{{ profile_type }}");
$('#domain_search').quickfilter('#all_domains tr');
});
</script>
{% endblock extra_js %}

View File

@@ -0,0 +1,135 @@
{% extends "layout.html" %}
{% from "macros/form_inputs.html" import input_csrf_token with context %}
{% from "macros/general.html" import
display_subnav,
display_input_cn,
display_list_access_policies
with context %}
{% from "macros/msg_handlers.html" import alias_msg_handler, warning_info with context %}
{% block title %}{{ _('Add mail alias') }}{% endblock title %}
{% block navlinks_create %}class="active"{% endblock %}
{% block breadcrumb %}
{% set crumbs = [
(ctx.homepath + '/domains', _('All domains')),
(ctx.homepath + '/profile/domain/general/' + cur_domain, cur_domain),
(ctx.homepath + '/users/' + cur_domain, _('Users')),
(ctx.homepath + '/mls/' + cur_domain, _('Mailing Lists')),
(ctx.homepath + '/aliases/' + cur_domain, _('Aliases')),
(ctx.homepath + '/admins/' + cur_domain, _('Admins')),
]
%}
{% if backend != "pgsql" %}
{% set crumbs = crumbs + [(ctx.homepath + '/users/' + cur_domain + '/last_logins', _('Last Logins'))] %}
{% endif %}
{{ display_subnav(crumbs) }}
{% endblock %}
{% block main %}
{# Show system message #}
{{ alias_msg_handler(msg) }}
{% set createNewAccount = true %}
{% set numberOfSpareAccounts = profile.aliases - num_existing_aliases %}
{% if profile.aliases == -1 %}
{% set createNewAccount = false %}
{% set whyDisabledCreation = _('Not allowed to create mail alias under this domain.') %}
{% elif profile.aliases > 0 and numberOfSpareAccounts <= 0 %}
{% set createNewAccount = false %}
{% set whyDisabledCreation = _('Already exceed max number of account limit (%d).') |format(profile.aliases |int) %}
{% endif %}
{% if not createNewAccount %}
<div class="notification note-error">
<p>
<strong>{{ _('Error:') }}</strong> {{ _("You can't create mail aliases under domain %s.") |format('<a href="' + ctx.homepath + '/profile/domain/general/' + cur_domain + '#accountLimit"><strong>' + cur_domain + '</strong></a>') }}
{{ whyDisabledCreation }}
</p>
</div>
{% else %}
{% if profile.aliases > 0 and numberOfSpareAccounts > 0 %}
<div class="notification note-info">
<p>{{ _('You can create <strong>%d</strong> more mail alias(es) under domain %s.') |format(numberOfSpareAccounts |int, '<a href="' + ctx.homepath + '/profile/domain/general/' + cur_domain + '"><strong>' + cur_domain + '</strong></a>') }}</p>
</div>
{% endif %}
{% endif %}
<div class="content-box">
<div class="box-body">
<div class="box-header clear">
<ul class="tabs clear">
<li><a href="{{ctx.homepath}}/create/user/{{cur_domain}}"><i class="fa fa-plus"></i> {{ _('User') }}</a>
<li><a href="{{ctx.homepath}}/create/ml/{{cur_domain}}"><i class="fa fa-plus"></i> {{ _('Mailing List') }}</a>
<li class="active"><a href="{{ctx.homepath}}/create/alias/{{cur_domain}}"><i class="fa fa-plus"></i> {{ _('Alias') }}</a>
</ul>
<h2>
{{ _('Add mail alias') }}
<a href="{{ctx.homepath}}/profile/domain/general/{{cur_domain}}"><i class="fa fa-cog fa-lg" title="{{ _('Edit domain profile') }}"></i></a>
</h2>
</div>
<div id="alias_add" class="box-wrap clear">
<div class="columns clear">
{{ warning_info( _("It's better create a subscribable mailing list, so that you can restrict the mail posting and delivery.") ) }}
<form name="create" method="post" action="{{ctx.homepath}}/create/alias/{{cur_domain}}">
{{ input_csrf_token() }}
<div class="form-field clear">
<h4 class="size-250 fl-space">{{ _('Add mail alias under domain') }} <span class="required">*</span></h4>
<span class="clean-padding">
<select name="domainName" onchange="change_url(this, baseurl='{{ctx.homepath}}/create/alias/');">
{% for d in allDomains %}
<option value="{{ d |e }}" {% if d == cur_domain %}selected{%endif%}>{{ d |e }}</option>
{% endfor %}
</select>
</span>
</div>
<div class="form-field clear">
<h4 class="size-250 fl-space">{{ _('Mail Address') }} <span class="required">*</span></h4>
<span class="clean-padding">
<input type="text" size="35"
name="listname"
value="{{ listname |e }}"
class="text fl-space {% if not createNewAccount %}disabled{% endif %}"
{% if not createNewAccount %}disabled="disabled"{% endif %}
/>@{{ cur_domain }}
</span>
</div>
{{ display_input_cn(value=cn, enable_input=createNewAccount) }}
<div class="rule"></div>
{{ display_list_access_policies(policy=None, enable_input=createNewAccount) }}
<div class="rule2"></div>
<div class="form-field clear">
<h4 class="size-250 fl-space">&nbsp;</h4>
<span class="clean-padding bt-space20">
<input type="submit"
value="{{ _('Add') }}"
{% if not createNewAccount %}
class="button color-grey" disabled="disabled"
{% else %}
class="button green"
{% endif %}
/>
</span>
</div>
</form>
</div>{# .columns #}
</div>{# .box-wrap #}
</div>{# .content-box #}
</div>{# .box-body #}
{% endblock main %}

View File

@@ -0,0 +1,152 @@
{% extends "layout.html" %}
{% from "macros/form_inputs.html" import
input_csrf_token
with context
%}
{% from "macros/general.html" import
display_subnav,
set_account_status_img,
set_account_activity_img,
highlight_username_in_mail,
display_filter_by_first_char,
display_list_access_policy_name,
show_pages
with context
%}
{% from "macros/msg_handlers.html" import alias_msg_handler with context %}
{% block title %}{{ _('Mail Aliases') }}{% endblock %}
{% block navlinks_domains %}class="active"{% endblock %}
{% block breadcrumb %}
{% set crumbs = [
(ctx.homepath + '/domains', _('All domains')),
(ctx.homepath + '/profile/domain/general/' + cur_domain, cur_domain),
(ctx.homepath + '/users/' + cur_domain, _('Users')),
(ctx.homepath + '/mls/' + cur_domain, _('Mailing Lists')),
('active', ctx.homepath + '/aliases/' + cur_domain, _('Aliases')),
] %}
{% if session.get('is_global_admin') %}
{% set crumbs = crumbs + [(ctx.homepath + '/admins/' + cur_domain, _('Admins'))] %}
{% endif %}
{% if backend != "pgsql" %}
{% set crumbs = crumbs + [(ctx.homepath + '/users/' + cur_domain + '/last_logins', _('Last Logins'))] %}
{% endif %}
{{ display_subnav(crumbs) }}
{% endblock %}
{% block main %}
{# Show system message #}
{{ alias_msg_handler(msg) }}
{% if aliases is defined %}
{% if aliases or (not aliases and first_char) %}
{{ display_filter_by_first_char(baseurl=ctx.homepath + '/aliases/' + cur_domain,
available_chars=all_first_chars,
first_char=first_char,
disabled_only=disabled_only) }}
{% endif %}
<div class="content-box">
<div class="box-body">
<div class="box-header clear">
<ul class="tabs clear">
<li><a href="{{ctx.homepath}}/create/user/{{cur_domain}}"><i class="fa fa-plus"></i> {{ _('User') }}</a>
<li><a href="{{ctx.homepath}}/create/ml/{{cur_domain}}"><i class="fa fa-plus"></i> {{ _('Mailing List') }}</a>
<li><a href="{{ctx.homepath}}/create/alias/{{cur_domain}}"><i class="fa fa-plus"></i> {{ _('Alias') }}</a>
</ul>
<h2>
{{ _('Aliases under domain: %s.') |format(cur_domain) }}
{% if total is defined and aliases %}
({{ (cur_page-1) * page_size_limit + 1 }}-{{ (cur_page-1) * page_size_limit + aliases|length}}/{{total}})
{% endif %}
<a href="{{ctx.homepath}}/profile/domain/general/{{cur_domain}}"><i class="fa fa-cog fa-lg" title="{{ _('Edit domain profile') }}"></i></a>
{{ set_account_activity_img('sent', 'domain', cur_domain, float=false) }}
</h2>
</div>{# -- box-header -- #}
{# List all aliases. #}
<form name="aliases" id="list_table" action="{{ctx.homepath}}/aliases/{{cur_domain}}" method="post">
{{ input_csrf_token() }}
<table class="style1">
<thead>
<tr>
<th class="checkbox"><input type="checkbox" class="checkbox select-all" /></th>
<th data-sort="string-ins">{{ _('Display Name') }}</th>
<th data-sort="string-ins">{{ _('Mail Address') }}</th>
<th data-sort="string-ins">{{ _('Mail Deliver Restriction') }}</th>
</tr>
</thead>
{# List alias attributes/avalues. #}
<tbody>
{% if aliases |length > 0 %}
{% for r in aliases %}
{% set address = r.address |e %}
{% set name = r.name |e %}
<tr>
<td class="checkbox"><input type="checkbox" class="checkbox" name="mail" value="{{ address }}" /></td>
<td>
<a href="{{ctx.homepath}}/profile/alias/general/{{address}}"><i class="fa fa-cog fa-lg fr-space" title="{{ _('Edit account profile') }}"></i></a>
{{ set_account_status_img(r.active) }}
<a href="{{ctx.homepath}}/profile/alias/general/{{address}}" title="{{ _('Edit account profile') }}">{% if name %}{{ name |cut_string |e }}{% else %}{{ address.split('@', 1)[0] }}{% endif %}</a>
</td>
<td>{{ highlight_username_in_mail(address) }}</td>
<td>{{ display_list_access_policy_name(policy=r.accesspolicy) }}</td>
</tr>
{% endfor %}
{% else %}
<tr>
<td class="checkbox"></td>
<td colspan="3">{{ _('No mail alias available.') }}
{% if not first_char %}
<a href="{{ctx.homepath}}/create/alias/{{ cur_domain }}">{{ _('Add one') }}</a>?
{% endif %}
</td>
</tr>
{% endif %}
</tbody>
</table>
{% if aliases %}
<div class="tab-footer clear f1">
<div class="fl">
<select name="action" class="fl-space">
<option>{{ _('Choose Action') }}</option>
<option disabled>----</option>
<option value="enable">{{ _('Enable') }}</option>
<option value="disable">{{ _('Disable') }}</option>
<option value="delete">{{ _('Delete') }}</option>
</select>
<input type="submit" value="{{ _('Apply') }}" class="button fl-space" />
</div>
{% set baseurl = ctx.homepath + '/aliases/' + cur_domain %}
{% if disabled_only %}
{% set baseurl = baseurl + '/disabled' %}
{% endif %}
{% set url_suffix = '' %}
{% if first_char %}
{% set url_suffix = '?starts_with=' + first_char %}
{% endif %}
{{ show_pages(baseurl=baseurl, total=total, cur_page=cur_page, url_suffix=url_suffix) }}
</div>
{% endif %}
</form>
</div>{# -- box-body -- #}
</div>{# -- content-body -- #}
{% endif %}
{% endblock main %}

View File

@@ -0,0 +1,142 @@
{% extends "layout.html" %}
{% from "macros/form_inputs.html" import
input_submit,
input_csrf_token
with context
%}
{% from "macros/general.html" import
display_subnav,
display_input_cn,
display_change_email_address,
display_migrate_alias_to_ml,
display_account_status,
set_account_status_img,
display_list_access_policies
with context
%}
{% from "macros/msg_handlers.html" import alias_msg_handler with context %}
{% block title %}{{ _('Edit account profile') }}{% endblock %}
{% block navlinks_domains %}class="active"{% endblock %}
{% block breadcrumb %}
{% set crumbs = [
(ctx.homepath + '/domains', _('All domains')),
(ctx.homepath + '/profile/domain/general/' + cur_domain, cur_domain),
(ctx.homepath + '/users/' + cur_domain, _('Users')),
(ctx.homepath + '/mls/' + cur_domain, _('Mailing Lists')),
(ctx.homepath + '/aliases/' + cur_domain, _('Aliases')),
('active', ctx.homepath + '/profile/alias/general/' + mail, _('Profile of alias:') + '&nbsp;' + mail),
(ctx.homepath + '/admins/' + cur_domain, _('Admins')),
]
%}
{% if backend != "pgsql" %}
{% set crumbs = crumbs + [(ctx.homepath + '/users/' + cur_domain + '/last_logins', _('Last Logins'))] %}
{% endif %}
{{ display_subnav(crumbs) }}
{% endblock %}
{% block main %}
{# Show system message #}
{{ alias_msg_handler(msg) }}
{% set navlinks = [
('general', _('General'), [true,]),
]
%}
<div class="content-box">
<div class="box-body">
<div class="box-header clear">
<h2>{{ _('Profile of alias:') }} {{ mail }}</h2>
<ul class="tabs clear">
{% for nav in navlinks %}
{% if not false in nav[2] and not none in nav[2] %}
<li><a href="#profile_{{nav[0]}}">{{ nav[1] }}</a></li>
{% endif %}
{% endfor %}
</ul>
</div>{# -- box-header -- #}
{# modal window used to change email address #}
{{ display_change_email_address(current_domain=cur_domain,
post_url=ctx.homepath + '/profile/alias/rename/' + mail ) }}
{{ display_migrate_alias_to_ml(mail=mail) }}
<div class="box-wrap clear">
<div id="profile_general">
<form name="general" id="list_table" method="post" action="{{ctx.homepath}}/profile/alias/{{profile_type}}/{{mail}}">
{{ input_csrf_token() }}
<div class="columns clear">
<div class="col2-3 clear">
{{ display_account_status(profile.active) }}
{{ display_input_cn(value=profile.name) }}
</div>
<div class="col1-3 lastcol">
<div class="mark_blue bt-space10">
<ul class="standard clean-padding bt-space10">
<li><a href="#change_email_address" class="modal-link"><span class="text">{{ _('Change email address') }}</span></a></li>
<li><a href="#migrate_alias_to_ml" class="modal-link"><span class="text">{{ _('Migrate to subscribable mailing list') }}</span></a></li>
</ul>
</div>
</div>
</div>
<div class="columns clear">
<div class="col3-4 clear">
<div class="bt-space20"></div>
{# -- Access policy -- #}
{% set accessPolicy = profile.get('accesspolicy', 'public').lower() |e %}
{% if accessPolicy == '' %}
{% set accessPolicy = 'public' %}
{% endif %}
{{ display_list_access_policies(policy=accessPolicy) }}
</div>{# col3-4 #}
</div>{# .columns #}
<div class="bt-space0">&nbsp;</div>
{# List all members. #}
<div class="form-field clear">
<h4 class="size-250 fl-space">{{ _('Members') }}<a name="members">&nbsp;</a></h4>
<small>{{ _('One mail address per line. Invalid address will be discarded.') }}</small>
<textarea name="members"
class="textarea"
rows="6"
style="width: 40%;">{% for addr in profile.members %}{{ addr }}
{% endfor -%}
</textarea>
</div>{#-- .form-field --#}
<div class="bt-space0">&nbsp;</div>
{# List all moderators. #}
<div class="form-field clear">
<h4 class="size-250 fl-space">{{ _('Moderators') }}<a name="moderators">&nbsp;</a></h4>
<small>{{ _('One mail address per line. Invalid address will be discarded.') }}</small>
<textarea name="moderators"
class="textarea"
rows="6"
style="width: 40%;">{% for addr in profile.moderators %}{{ addr }}
{% endfor -%}
</textarea>
</div>{#-- .form-field --#}
{{ input_submit() }}
</form>
</div>{# #profile_general #}
</div>{#-- .box-wrap --#}
</div>{#-- .box-body --#}
</div>{#-- .content-box --#}
{% endblock main %}

View File

@@ -0,0 +1,62 @@
{% extends "layout.html" %}
{% from "macros/general.html" import display_add_domain with context %}
{% from "macros/msg_handlers.html" import
domain_msg_handler,
creation_limit_msg_handler
with context %}
{% block title %}{{ _('Add domain') }}{% endblock title %}
{% block navlinks_create %}class="active"{% endblock %}
{% block main %}
{# Show system message #}
{{ domain_msg_handler(msg) }}
{% if creation_limits['error_code'] %}
{% for err in creation_limits['error_code'] %}
{{ creation_limit_msg_handler(err) }}
{% endfor %}
{% endif %}
{% if creation_limits['create_new_domain'] %}
{# num_spare_domains: -1 means no limit #}
{% if creation_limits['num_spare_domains'] > 0 %}
<div class="notification note-info">
<p>{{ _('You can create <strong>%d</strong> more mail domains (Existing: %d, Max: %d)') |format(creation_limits['num_spare_domains'], creation_limits['num_managed_domains'], creation_limits['num_max_domains']) }}</p>
</div>
<div class="bt-space0"></div>
{% endif %}
{% endif %}
<div class="content-box">
<div class="box-body">
<div class="box-header clear">
<h2>{{ _('Add domain') }}</h2>
</div>
{{ display_add_domain(label=false,
preferred_language=preferred_language,
languagemaps=languagemaps,
timezones=timezones,
create_new_domain=creation_limits['create_new_domain'],
num_max_domains=creation_limits['num_max_domains'],
num_managed_domains=creation_limits['num_managed_domains'],
num_spare_domains=creation_limits['num_spare_domains'],
num_max_quota=creation_limits['num_max_quota'],
num_allocated_quota=creation_limits['num_allocated_quota'],
num_spare_quota=creation_limits['num_spare_quota'],
num_max_users=creation_limits['num_max_users'],
num_allocated_users=creation_limits['num_allocated_users'],
num_spare_users=creation_limits['num_spare_users'],
num_max_aliases=creation_limits['num_max_aliases'],
num_allocated_aliases=creation_limits['num_allocated_aliases'],
num_spare_aliases=creation_limits['num_spare_aliases'],
num_max_lists=creation_limits['num_max_lists'],
num_allocated_lists=creation_limits['num_allocated_lists'],
num_spare_lists=creation_limits['num_spare_lists']) }}
</div>
</div>
{% endblock main %}

View File

@@ -0,0 +1,286 @@
{% extends "layout.html" %}
{% from "macros/form_inputs.html" import
input_csrf_token
with context
%}
{% from "macros/general.html" import
set_account_status_img,
set_account_activity_img,
set_alias_domain_img,
display_number_of_account_limited,
display_progress_bar,
display_filter_by_first_char,
display_add_domain,
show_pages,
display_remove_mailbox_days
with context
%}
{% from "macros/msg_handlers.html" import domain_msg_handler with context %}
{% block title %}{{ _('Domains and Accounts') }}{% endblock %}
{% block navlinks_domains %}class="active"{% endblock %}
{% block main %}
{# Show system message #}
{{ domain_msg_handler(msg) }}
{{ display_filter_by_first_char(baseurl=ctx.homepath + '/domains',
first_char=first_char,
available_chars=all_first_chars,
account_type='domain',
disabled_only=disabled_only) }}
{# List all domains under control. #}
<div class="content-box">
<div class="box-body">
<div class="box-header clear">
{% if session.get('is_global_admin') or session.get('create_new_domains') %}
<ul class="tabs clear">
<li><a href="{{ctx.homepath}}/create/domain"><i class="fa fa-plus"></i> {{ _('Add domain') }}</a></li>
</ul>
{% endif %}
<h2>
{{ _('All domains under your control.') }} {% if disabled_only %}({{ _('Disabled') }}){% endif %}
{% if total is defined and all_domain_profiles | length > 0 %}
({{ (cur_page-1) * page_size_limit + 1 }}-{{ (cur_page-1) * page_size_limit + all_domain_profiles | length}}/{{ total }})
{% endif %}
</h2>
</div>
<form id="form_domains" method="post" action="{{ctx.homepath}}/domains">
{{ input_csrf_token() }}
<table class="style1">
<thead>
<tr>
{% if session.get('is_global_admin') or session.get('create_new_domains') %}
<th class="checkbox"><input type="checkbox" class="checkbox select-all" /></th>
{% endif %}
<th data-sort="string-ins">{{ _('Domain') }}</th>
<th data-sort="string-ins">{{ _('Display Name') }}</th>
<th data-sort="int">{{ _('Quota') }}</th>
<th data-sort="int">{{ _('Users') }}</th>
<th data-sort="int">{{ _('Mailing Lists') }}</th>
<th data-sort="int">{{ _('Aliases') }}</th>
</tr>
</thead>
<tbody>
{% if all_domain_profiles %}
{% for r in all_domain_profiles %}
{% set domain = r.domain |e %}
<tr>
{% if session.get('is_global_admin') or session.get('create_new_domains') %}
<td class="checkbox vcenter">
<input type="checkbox"
class="checkbox"
name="domainName"
value="{{ domain }}" />
</td>
{% endif %}
<td class="vcenter">
<a href="{{ctx.homepath}}/profile/domain/general/{{ domain }}"
title="{{ _('Edit domain profile') }}"
>{{ domain }}</a>
<a href="{{ctx.homepath}}/profile/domain/general/{{ domain }}">
<i class="fa fa-cog fa-lg fr-space" title="{{ _('Edit domain profile') }}"></i>
</a>
<a href="{{ctx.homepath}}/export/domain/{{domain}}"><i class="fas fa-download fr-space" title="{{ _('Export accounts') }}"></i></a>
{% set _alias_domains = all_alias_domains.get(domain, []) %}
{% set _pending_alias_domains = [] %}
{% for d in _alias_domains %}
{% if d in pending_domains %}
{% do _pending_alias_domains.append(d) %}
{% endif %}
{% endfor %}
{{ set_account_activity_img('sent', 'domain', domain) }}
{# Check whether domain is a real backup mx #}
{% set is_real_backupmx = false %}
{% if r.backupmx == 1 and r.transport.startswith('relay:') %}
{% set is_real_backupmx = true %}
{% endif %}
{{ set_account_status_img(status=r.active,
account_type='domain',
is_relay=r.transport not in local_transports,
relay=r.transport,
backupmx=r.backupmx,
is_backupmx=is_real_backupmx) }}
{{ set_alias_domain_img(alias_domains=_alias_domains) }}
{% if (domain in pending_domains) or _pending_alias_domains %}
<span class="fr-space small_label bgcolor-red"
style="vertical-align: middle;"
><a href="{{ctx.homepath}}/verify/domain_ownership"
style="text-decoration: none; color: white;"
>{{ _('PLEASE VERIFY OWNERSHIP') }}</a>
</span>
{% endif %}
</td>
<td class="vcenter">{% if r.description %}{{ r.description |cut_string |e }}{% endif %}</td>
{#-- Domain Quota --#}
<td class="vcenter" data-sort-value="{{ r.maxquota }}">
{% set used_quota = domain_used_quota.get(domain, {}).get('size', 0) %}
{% if r.maxquota > 0 %}
{% set percent_allocated = r.quota_count |convert_to_percentage(r.maxquota) %}
{% set percent_used_quota = (used_quota/1024/1024) |convert_to_percentage(r.maxquota) %}
{% if session.get('is_global_admin') %}
{#-- Link to domain profile page. --#}
<a href="{{ctx.homepath}}/profile/domain/general/{{domain}}" style="text-decoration: none;"><span title="{{ _('Edit quota setting') }}">{{ percent_allocated }}%</span> <span class="color-grey"><span title="{{ _('Used') }}">({{ used_quota | file_size_format }}</span> / <span title="{{ _('Allocated') }}">{{ r.quota_count |file_size_format(base_mb=True) }}</span>) <span title="{{ _('Total') }}">{{ display_number_of_account_limited(r.maxquota |file_size_format(base_mb=True)) }}</span></a>
{% else %}
<span>{{ percent_allocated }}%</span> <span class="color-grey"><span title="{{ _('Used') }}">({{ used_quota | file_size_format }}</span> / <span title="{{ _('Allocated') }}">{{ r.quota_count |file_size_format(base_mb=True) }}</span>) <span title="{{ _('Total') }}">{{ display_number_of_account_limited(r.maxquota |file_size_format(base_mb=True)) }}</span></span>
{% endif %}
{{ display_progress_bar(percent_used_quota, tooltip=_('Used'), style='thin') }}
{{ display_progress_bar(percent_allocated, tooltip=_('Allocated'), style='thin') }}
{% else %}
{% if session.get('is_global_admin') %}
<span title="{{ _('Used') }}">{{ used_quota | file_size_format }}</span> / <span title="{{ _('Allocated') }}">{{ r.quota_count |file_size_format(base_mb=True) }}</span> / <a href="{{ctx.homepath}}/profile/domain/general/{{domain}}" title="{{ _('Edit quota setting') }}" style="text-decoration: none;">{{ _('Unlimited') }}</a>
{% else %}
<span title="{{ _('Used') }}">{{ used_quota | file_size_format }}</span> / <span title="{{ _('Allocated') }}">{{ r.quota_count |file_size_format(base_mb=True) }}</span> / <span title="{{ _('Total') }}">{{ _('Unlimited') }}</span>
{% endif %}
{% endif %}
</td>
{#-- Users --#}
<td class="vcenter" data-sort-value="{{ r.mailboxes }}">
{% if r.num_existing_users %}
{% set num_existing_users = r.num_existing_users | int %}
{% else %}
{% set num_existing_users = 0 %}
{% endif %}
{% if r.mailboxes > 0 %}
{% set percentOfNumberOfUsers = num_existing_users |convert_to_percentage(r.mailboxes) %}
<a href="{{ctx.homepath}}/users/{{domain}}" title="{{ _('List all mail users.') }}" style="text-decoration: none; display: block; padding: 0 10px 0 10px;">{{ percentOfNumberOfUsers }}% <span class="color-grey">({% if num_existing_users is not sameas none %}{{ num_existing_users }}{% else %}0{% endif %} {{ display_number_of_account_limited(r.mailboxes) }})</span></a>
{{ display_progress_bar(percentOfNumberOfUsers, style='thin') }}
{% elif r.mailboxes == -1 %}
<span class="color-grey"><em>{{ _('DISABLED') }}</em></span>
{% else %}
<a href="{{ctx.homepath}}/users/{{domain}}" title="{{ _('List all mail users.') }}" style="text-decoration: none; display: block; padding: 0 10px 0 10px;">{% if num_existing_users is not sameas none %}{{ num_existing_users }}{% else %}0{% endif %}</a>
{% endif %}
</td>
{#-- Mailing list --#}
<td class="vcenter" data-sort-value="{{ r.maillists }}">
{% if r.num_existing_maillists %}
{% set num_existing_maillists = r.num_existing_maillists | int %}
{% else %}
{% set num_existing_maillists = 0 %}
{% endif %}
{% if r.maillists > 0 %}
{% set percentOfNumberOfMaillists= num_existing_maillists |convert_to_percentage(r.maillists) %}
<a href="{{ctx.homepath}}/mls/{{domain}}"
title="{{ _('List all mailing lists.') }}"
style="text-decoration: none; display: block; padding: 0 10px 0 10px;"
>{{ percentOfNumberOfMaillists }}% <span class="color-grey">({{ num_existing_maillists }} {{ display_number_of_account_limited(r.maillists) }})</span></a>
{{ display_progress_bar(percentOfNumberOfMaillists, style='thin') }}
{% elif r.maillists == -1 %}
<span class="color-grey"><em>{{ _('DISABLED') }}</em></span>
{% else %}
<a href="{{ctx.homepath}}/mls/{{domain}}"
title="{{ _('List all mailing lists.') }}"
style="text-decoration: none; display: block; padding: 0 10px 0 10px;">{% if num_existing_maillists is not sameas none %}{{ num_existing_maillists }}{% else %}0{% endif %}</a>
{% endif %}
</td>
{#-- Aliases --#}
<td class="vcenter" data-sort-value="{{ r.aliases }}">
{% if r.num_existing_aliases %}
{% set num_existing_aliases = r.num_existing_aliases | int %}
{% else %}
{% set num_existing_aliases = 0 %}
{% endif %}
{% if r.aliases > 0 %}
{% set percentOfNumberOfAliases = num_existing_aliases |convert_to_percentage(r.aliases) %}
<a href="{{ctx.homepath}}/aliases/{{domain}}" title="{{ _('List all mail aliases.') }}" style="text-decoration: none; display: block; padding: 0 10px 0 10px;">{{ percentOfNumberOfAliases }}% <span class="color-grey">({{ num_existing_aliases }} {{ display_number_of_account_limited(r.aliases) }})</span></a>
{{ display_progress_bar(percentOfNumberOfAliases, style='thin') }}
{% elif r.aliases == -1 %}
<span class="color-grey"><em>{{ _('DISABLED') }}</em></span>
{% else %}
<a href="{{ctx.homepath}}/aliases/{{domain}}" title="{{ _('List all mail aliases.') }}" style="text-decoration: none; display: block; padding: 0 10px 0 10px;">{% if num_existing_aliases is not sameas none %}{{ num_existing_aliases }}{% else %}0{% endif %}</a>
{% endif %}
</td>
</tr>
{% endfor %}
{% else %}
<tr>
{% if session.get('is_global_admin') or session.get('create_new_domains') %}
<td class="checkbox"></td>
<td class="vcenter" colspan="5">{{ _('No mail domain available.') }}
{% if not (first_char or disabled_only) %}
<a href="{{ctx.homepath}}/create/domain">{{ _('Add one') }}</a>?
{% endif %}
</td>
{% else %}
<td class="vcenter" colspan="5">{{ _('No mail domain available.') }}</td>
{% endif %}
</tr>
{% endif %}
</tbody>
</table>
<div class="tab-footer clear f1">
{% if session.get('is_global_admin') or session.get('create_new_domains') %}
<div class="fl">
<select name="action" class="fl-space" id="account_list_actions" >
<option>{{ _('Choose Action') }}</option>
<option disabled>----</option>
<option value="enable">{{ _('Enable') }}</option>
<option value="disable">{{ _('Disable') }}</option>
<option value="delete">{{ _('Delete') }}</option>
</select>
<select name="keep_mailbox_days" class="fl-space" id="account_delete_date">
{% for _day in days_to_keep_removed_mailbox %}
<option value="{{ _day }}">{{ display_remove_mailbox_days(_day) }}</option>
{% endfor %}
</select>
<input type="submit" name="submit_domains" value="{{ _('Apply') }}" class="button fl-space" />
</div>
{% endif %}
{% set baseurl = ctx.homepath + '/domains' %}
{% if disabled_only %}
{% set baseurl = ctx.homepath + '/domains/disabled' %}
{% endif %}
{% set url_suffix = '' %}
{% if first_char %}
{% set url_suffix = url_suffix + '?starts_with=' + first_char %}
{% endif %}
{{ show_pages(baseurl=baseurl,
total=total,
cur_page=cur_page,
url_suffix=url_suffix) }}
</div>
</form>
</div>
</div>
{% endblock main %}

View File

@@ -0,0 +1,773 @@
{% extends "layout.html" %}
{% from "macros/form_inputs.html" import
input_submit,
input_csrf_token,
input_text
with context
%}
{% from "macros/general.html" import
display_subnav,
set_account_status_img,
set_account_activity_img,
display_domain_cn,
display_preferred_language,
display_timezones,
display_account_status,
display_domain_backupmx,
display_relay,
display_sender_relayhost,
display_domain_quota,
display_domain_default_userquota,
display_domain_max_user_quota,
display_recipient_bcc,
display_sender_bcc,
display_disabled_account_profiles,
display_disabled_domain_mail_services,
display_per_account_wblist_all
with context
%}
{% from "macros/sql.html" import
display_enabled_domain_services
with context %}
{% from "macros/iredapd.html" import
display_throttle_setting,
display_greylisting_setting,
display_greylisting_whitelists
with context
%}
{% from "macros/amavisd.html" import display_spam_policy with context %}
{% from "macros/msg_handlers.html" import domain_msg_handler with context %}
{% block title %}{{ _('Edit account profile') }}{% endblock %}
{% block navlinks_domains %}class="active"{% endblock %}
{% block breadcrumb %}
{% set crumbs = [
(ctx.homepath + '/domains', _('All domains')),
('active', ctx.homepath + '/profile/domain/general/' + cur_domain, _('Profile of domain:') + '&nbsp;' + cur_domain),
(ctx.homepath + '/users/' + cur_domain, _('Users')),
(ctx.homepath + '/mls/' + cur_domain, _('Mailing Lists')),
(ctx.homepath + '/aliases/' + cur_domain, _('Aliases')),
(ctx.homepath + '/admins/' + cur_domain, _('Admins')),
]
%}
{% if backend != "pgsql" %}
{% set crumbs = crumbs + [(ctx.homepath + '/users/' + cur_domain + '/last_logins', _('Last Logins'))] %}
{% endif %}
{{ display_subnav(crumbs) }}
{% endblock %}
{# Domain profile. #}
{% block main %}
{% if pending_domains %}
<div class="notification note-attention">
<p><strong>{{ _('Mail services are disabled for domain(s): %s, please <a href="%s/verify/domain_ownership">verify domain ownership</a> first.' | format(pending_domains |join(', '), ctx.homepath)) }}</strong></p>
</div>
{% endif %}
{# Show system message #}
{{ domain_msg_handler(msg) }}
{% set enabled_services = domain_settings.get('enabled_services', []) %}
{% set disabled_mail_services = domain_settings.get('disabled_mail_services', []) %}
{% set disabled_domain_profiles = domain_settings.get('disabled_domain_profiles', []) %}
{% set disabled_user_profiles = domain_settings.get('disabled_user_profiles', []) %}
{% set disabled_user_preferences = domain_settings.get('disabled_user_preferences', []) %}
{% if session.get('is_global_admin') %}
{% set navlinks = [
('general', _('General'), [true]),
('bcc', _('BCC'), [true]),
('relay', _('Relay'), [true]),
('catchall', _('Catch-all'), [true]),
('aliases', _('Aliases'), [true]),
('throttle', _('Throttling'), [session.get('iredapd_enabled')]),
('greylisting', _('Greylisting'), [session.get('iredapd_enabled')]),
('wblist', _('White/Blacklist'), [session.get('amavisd_enable_policy_lookup')]),
('spampolicy', _('Spam Policy'), [session.get('amavisd_enable_policy_lookup')]),
('backupmx', _('Backup MX'), [true]),
('advanced', _('Advanced'), [true]),
]
%}
{% else %}
{% set navlinks = [
('general', _('General'), [true]),
('bcc', _('BCC'), ['bcc' not in disabled_domain_profiles]),
('relay', _('Relay'), ['relay' not in disabled_domain_profiles]),
('catchall', _('Catch-all'), ['catchall' not in disabled_domain_profiles]),
('aliases', _('Aliases'), ['aliases' not in disabled_domain_profiles]),
('throttle', _('Throttling'), ['throttle' not in disabled_domain_profiles, session.get('iredapd_enabled')]),
('greylisting', _('Greylisting'), ['greylisting' not in disabled_domain_profiles, session.get('iredapd_enabled')]),
('wblist', _('White/Blacklist'), [(session.get('amavisd_enable_policy_lookup') and 'wblist' not in disabled_domain_profiles)]),
('spampolicy', _('Spam Policy'), [(session.get('amavisd_enable_policy_lookup') and 'spampolicy' not in disabled_domain_profiles)]),
('backupmx', _('Backup MX'), ['backupmx' not in disabled_domain_profiles]),
('advanced', _('Advanced'), [true]),
]
%}
{% endif %}
<div class="content-box">
<div class="box-body">
{#-- Links --#}
<div class="box-header clear">
<ul class="tabs clear">
{% for nav in navlinks %}
{% if not false in nav[2] and not none in nav[2] %}
<li><a href="#profile_{{ nav[0] }}">{{ nav[1] }}</a></li>
{% endif %}
{% endfor %}
</ul>
<h2>{{ set_account_activity_img('sent', 'domain', cur_domain, float=false) }}</h2>
</div>{# .box-header #}
<div class="box-wrap clear">
{# profile_type: general #}
<div id="profile_general">
<form name="general" method="post" action="{{ctx.homepath}}/profile/domain/general/{{cur_domain}}">
{{ input_csrf_token() }}
<div class="columns clear">
<div class="col3-4 ">
{% if cur_domain not in pending_domains %}
{# normal admin, and not domain ownership verification required #}
{{ display_account_status(profile.active, account_type='domain') }}
{% endif %}
{{ display_domain_cn(cn=profile.description) }}
</div>{# .col2-3 #}
</div>
{% if session.get('is_global_admin') or session.get('create_new_domains') %}
<div class="columns clear">
<div class="col2-3">
{{ display_domain_quota(
quota=profile.maxquota | int,
required=(session.get('create_new_domains') and (creation_limits['num_max_quota'] > 0)),
num_allocated_quota=creation_limits['num_allocated_quota'],
num_max_quota=creation_limits['num_max_quota'],
num_spare_quota=creation_limits['num_spare_quota'],
) }}
</div>{# .col2-3 #}
{% if session.get('is_global_admin') %}
<div class="col1-3 lastcol">
<div class="mark_blue bt-space10">
<ul class="standard clean-padding bt-space10">
<li class="bt-space5">{{ _('Set to 0 for unlimited.') }}</li>
</ul>
</div>
</div>
{% endif %}
</div>{# .columns #}
{% endif %}
<div class="rule">&nbsp;</div>
<div class="columns clear">
<div class="col2-3">
{% set default_user_quota = domain_settings.get('default_user_quota', '0') | int %}
{% set max_user_quota = domain_settings.get('max_user_quota', 0) | int %}
{{ display_domain_default_userquota(default_user_quota, max_user_quota=max_user_quota) }}
{% if session.get('is_global_admin') %}
{{ display_domain_max_user_quota(max_user_quota) }}
{% endif %}
</div>{# .col2-3 #}
{% if session.get('is_global_admin') %}
<div class="col1-3 lastcol">
<div class="mark_blue bt-space10">
<ul class="standard clean-padding bt-space10">
<li class="bt-space5">{{ _('Domain admin cannot assign more than max quota to a mail user.') }}</li>
</ul>
</div>
</div>{# .col1-3 #}
{% endif %}
</div>{# .columns #}
{{ input_submit() }}
</form>
</div><!-- . profile_general -->
{# profile_type: bcc #}
{% if session.get('is_global_admin') or 'bcc' not in disabled_domain_profiles %}
<div id="profile_bcc">
<form name="bcc" method="post" action="{{ctx.homepath}}/profile/domain/bcc/{{cur_domain}}">
{{ input_csrf_token() }}
<div class="columns clear">
<div class="col2-3 ">
{{ display_recipient_bcc(address=profile.rbcc_addr) }}
{{ display_sender_bcc(address=profile.sbcc_addr) }}
</div>{#-- .col2-3 --#}
<div class="col1-3 lastcol">
<div class="mark_blue bt-space10">
<ul class="standard clean-padding bt-space10">
<li class="bt-space5">{{ _('Multiple addresses are NOT supported.') }}</li>
<li class="bt-space5">{{ _('Per-user bcc settings has higher priority than per-domain bcc settings.') }}</li>
</ul>
</div>
</div>{#-- .col1-3 --#}
</div>{#-- .columns --#}
{{ input_submit() }}
</form>
</div><!-- #profile_bcc -->
{% endif %}
{# profile_type: relay #}
{% if session.get('is_global_admin') or 'relay' not in disabled_domain_profiles %}
<div id="profile_relay">
<form name="relay" method="post" action="{{ctx.homepath}}/profile/domain/relay/{{cur_domain}}">
{{ input_csrf_token() }}
{{ display_relay(transport=profile.transport |string,
default_mta_transport=default_mta_transport,
is_backupmx=profile.backupmx) }}
<div class="rule"></div>
{{ display_sender_relayhost(relayhost=profile.relayhost) }}
{{ input_submit() }}
</form>
</div><!-- #profile_relay -->
{% endif %}
{# profile_type: catchall #}
{% if session.get('is_global_admin') or 'catchall' not in disabled_domain_profiles %}
<div id="profile_catchall">
<form name="catchall" method="post" action="{{ctx.homepath}}/profile/domain/catchall/{{cur_domain}}">
{{ input_csrf_token() }}
<div class="columns clear">
<div class="col2-3 ">
<div class="form-field clear">
<h4 class="size-250 fl-space">{{ _('Catch-all Addresses') }}</h4>
<small>{{ _('One mail address per line. Invalid address will be discarded.') }}</small>
<textarea name="catchall_addresses"
rows="6"
style="width: 50%"
class="textarea" >{%- for addr in profile.catchall |sort %}{{ addr |e }}
{% endfor -%}
</textarea>
</div>
</div>{#-- .col2-3 --#}
<div class="col1-3 lastcol">
<div class="notification note-attention">
<p>{{ _('Catch-all address may receive many spam emails.') }}</p>
</div>
<div class="mark_blue bt-space10">
<ul class="standard clean-padding bt-space10">
<li class="bt-space5">{{ _('Emails delivered to non-exist mail accounts will be forwarded to catch-all address(es).') }}</li>
</ul>
</div>
</div>{#-- .col1-3 --#}
</div>{#-- .columns --#}
{{ input_submit() }}
</form>
</div><!-- #profile_catchall -->
{% endif %}
{# profile_type: aliases #}
{% if session.get('is_global_admin') or 'aliases' not in disabled_domain_profiles %}
<div id="profile_aliases">
<form name="aliases" method="post" action="{{ctx.homepath}}/profile/domain/aliases/{{cur_domain}}">
{{ input_csrf_token() }}
<div class="columns clear">
<div class="col2-3 ">
<div class="form-field clear">
<h4 class="size-250 fl-space">{{ _('Alias domains') }}</h4>
{% if alias_domains %}
{% for d in alias_domains |sort %}
{% if not loop.first %}
</div>
<div class="form-field clear">
<h4 class="size-250 fl-space">&nbsp;</h4>
{% endif %}
<input type="text" name="domainAliasName" value="{{ d |e }}" size="35" class="text" />
{% if d in pending_domains %}<small>&nbsp;{{ _('Domain ownership verification required') }}</small>{% endif %}
{% endfor %}
{% else %}
<input type="text" name="domainAliasName" value="" size="35" class="text" />
{% endif %}
</div>
{#-- Always display an empty input field to add new value --#}
<div class="form-field clear">
{% if domainAliasName |length == 0 %}
<h4 class="size-250 fl-space">&nbsp;</h4>
{% else %}
<h4 class="size-250 fl-space">&nbsp;</h4>
{% endif %}
<input type="text" name="domainAliasName" value="{{ d |e }}" size="35" class="text" />
</div>
</div>{# .col2-3 #}
<div class="col1-3 lastcol">
<div class="mark_blue bt-space10">
<ul class="standard clean-padding bt-space10">
<li class="bt-space5">{{ _('Emails sent to <em><strong>user@[ALIAS_DOMAIN]</strong></em> will be delivered to <em><strong>user@%s</strong></em>.') |format(cur_domain) }}</li>
</ul>
</div>
</div>{#-- .col1-3 --#}
</div>{#-- .columns --#}
{{ input_submit() }}
</form>
</div>
{% endif %}
{# profile_type: throttling #}
{% if session.get('is_global_admin') or 'throttle' not in disabled_domain_profiles %}
<div id="profile_throttle">
<form name="throttle" method="post" action="{{ctx.homepath}}/profile/domain/throttle/{{cur_domain}}">
{{ input_csrf_token() }}
{% if session.get('iredapd_enabled') %}
{# Throttling with iRedAPD #}
<div class="columns clear">
{{ input_csrf_token() }}
{{ display_throttle_setting(account='@' + cur_domain,
setting=outbound_throttle_setting,
inout_type='outbound') }}
{{ display_throttle_setting(account='@' + cur_domain,
setting=inbound_throttle_setting,
inout_type='inbound',
with_left_border=true) }}
<div class="col1-3 lastcol">
<div class="mark_blue bt-space10">
<ul class="standard clean-padding bt-space10">
<li class="bt-space5">{{ _('This throttle setting will be applied to all individual accounts under domain %s.') |format(cur_domain) }}</li>
<li class="bt-space5">{{ _('You can set per-user throttling in account profile page.') }}</li>
<li class="bt-space5">{{ _('Per-user throttle setting has higher priority.') }}</li>
</ul>
</div>
</div>{#-- .col1-3 --#}
</div>{# .columns #}
{% endif %}
{{ input_submit() }}
</form>
</div>{# #profile_throttle #}
{% endif %}
{# profile_type: greylisting, with iRedAPD #}
{% if session.get('is_global_admin') or 'greylisting' not in disabled_domain_profiles %}
{% if session.get('iredapd_enabled') %}
<div id="profile_greylisting">
<form name="greylisting" method="post" action="{{ctx.homepath}}/profile/domain/greylisting/{{cur_domain}}">
{{ input_csrf_token() }}
{{ display_greylisting_setting(account='@' + cur_domain, gl_setting=gl_setting) }}
{{ display_greylisting_whitelists(account='@' + cur_domain, gl_whitelists=gl_whitelists) }}
{{ input_submit() }}
</form>
</div>
{% endif %}
{% endif %}
{# wblist #}
{% if session.get('amavisd_enable_policy_lookup') and (session.get('is_global_admin') or ('wblist' not in disabled_domain_profiles)) %}
<div id="profile_wblist">
<form name="wblist" method="post" action="{{ctx.homepath}}/profile/domain/wblist/{{cur_domain}}">
{{ input_csrf_token() }}
{{ display_per_account_wblist_all(inbound_whitelists=whitelists,
inbound_blacklists=blacklists,
outbound_whitelists=outbound_whitelists,
outbound_blacklists=outbound_blacklists) }}
{{ input_submit() }}
</form>
</div>
{% endif %}
{# profile_type: spampolicy #}
{% if session.get('amavisd_enable_policy_lookup') and (session.get('is_global_admin') or ('spampolicy' not in disabled_domain_profiles)) %}
<div id="profile_spampolicy">
<form name="spampolicy" method="post" action="{{ctx.homepath}}/system/spampolicy/{{cur_domain}}">
{{ input_csrf_token() }}
{{ display_spam_policy(account_type='domain',
spampolicy=spampolicy,
custom_ban_rules=custom_ban_rules,
global_spam_score=global_spam_score) }}
{{ input_submit() }}
</form>
</div>
{% endif %}
{# profile_type: advanced #}
<div id="profile_advanced">
<form name="advanced" method="post" action="{{ctx.homepath}}/profile/domain/advanced/{{cur_domain}}">
{{ input_csrf_token() }}
{% if session.get('is_global_admin') or session.get('create_new_domains') %}
<div class="columns clear">
<div class="col2-3 ">
<div class="form-field clear">
<a name="accountLimit">&nbsp;</a>
<h4 class="size-250 fl-space">{{ _('Number of max mail users') }}
{% if session.get('create_new_domains') %}
{% if creation_limits['num_max_users'] > 0 -%}<span class="required">*</span>{% endif %}
{% endif %}
</h4>
<span class="clean-padding fl-space">
<input type="text" size="8"
name="numberOfUsers"
value="{% if profile.mailboxes != 0 %}{{ profile.mailboxes |e }}{% endif %}"
class="text fl-space" />
{% if session.get('is_global_admin') %}
<label>{{ _('%s account(s) exist.') |format(profile.num_existing_users |e) }}</label>
{% elif session.get('create_new_domains') %}
{% if creation_limits['num_max_users'] > 0 %}
<label>{{ _('Max:') }} {{ profile.mailboxes |int + creation_limits['num_spare_users'] }}</label>
{% endif %}
{% endif %}
</span>
</div>
<div class="form-field clear">
<h4 class="size-250 fl-space">{{ _('Number of max mail aliases') }}
{% if session.get('create_new_domains') %}
{% if creation_limits['num_max_aliases'] > 0 -%}<span class="required">*</span>{% endif %}
{% endif %}
</h4>
<span class="clean-padding">
<input type="text" size="8"
name="numberOfAliases"
value="{% if profile.aliases != 0 %}{{ profile.aliases |e }}{% endif %}"
class="text fl-space" />
{% if session.get('is_global_admin') %}
<label>{{ _('%s account(s) exist.') |format(all_alias_accounts |length |string) }}</label>
{% elif session.get('create_new_domains') %}
{% if creation_limits['num_max_aliases'] > 0 %}
<label>{{ _('Max:') }} {{ profile.aliases |int + creation_limits['num_spare_aliases'] }}</label>
{% endif %}
{% endif %}
</span>
</div>
<div class="form-field clear">
<h4 class="size-250 fl-space">{{ _('Number of max mailing lists') }}
{% if session.get('create_new_domains') %}
{% if creation_limits['num_max_lists'] > 0 -%}<span class="required">*</span>{% endif %}
{% endif %}
</h4>
<span class="clean-padding">
<input type="text" size="8"
name="numberOfLists"
value="{% if profile.maillists != 0 %}{{ profile.maillists |e }}{% endif %}"
class="text fl-space" />
{% if session.get('is_global_admin') %}
<label>{{ _('%s account(s) exist.') |format(mails_of_all_mailing_lists |length |string) }}</label>
{% elif session.get('create_new_domains') %}
{% if creation_limits['num_max_lists'] > 0 %}
<label>{{ _('Max:') }} {{ profile.maillists |int + creation_limits['num_spare_lists'] }}</label>
{% endif %}
{% endif %}
</span>
</div>
<div class="clear bt-space">&nbsp;</div>
</div><!-- .col2-3 -->
<div class="col1-3 lastcol">
<div class="mark_blue bt-space10">
<ul class="standard clean-padding bt-space10">
{% if session.get('is_global_admin') %}
<li class="bt-space5">{{ _('Set value to 0 or leave it empty for unlimited.') }}</li>
<li class="bt-space5">{{ _('Set value to -1 means not allowed to create this kind of account.') }}</li>
{% elif session.get('create_new_domains') %}
<li class="bt-space5">{{ _('Leave it empty to use max value.') }}</li>
{% endif %}
</ul>
</div>
</div><!-- .col1-3 -->
</div><!-- .columns -->
{% endif %}
{# Password length #}
{% if session.get('is_global_admin') or ('password_policies' not in disabled_domain_profiles) %}
<div class="columns clear">
<div class="col2-3 ">
{% set min_passwd_length = domain_settings.get('min_passwd_length') %}
{% set max_passwd_length = domain_settings.get('max_passwd_length') %}
{% if session.get('is_global_admin') %}
{% set comment_min_passwd_length = none %}
{% set comment_max_passwd_length = none %}
{% else %}
{% if global_min_passwd_length > 0 %}
{% set comment_min_passwd_length = _('Can not be shorter than') + ' ' + (global_min_passwd_length | string ) %}
{% else %}
{% set comment_min_passwd_length = none %}
{% endif %}
{% if global_max_passwd_length > 0 %}
{% if global_min_passwd_length > 0 %}
{% set comment_max_passwd_length = _('Can not be shorter than') + ' ' + (global_min_passwd_length | string ) + ' ' + _('or longer than') + ' ' + (global_max_passwd_length | string) %}
{% else %}
{% set comment_max_passwd_length = _('Can not be longer than') + ' ' + (global_max_passwd_length | string) %}
{% endif %}
{% else %}
{% if global_min_passwd_length > 0 %}
{% set comment_max_passwd_length = _('Can not be shorter than') + ' ' + (global_min_passwd_length | string ) %}
{% else %}
{% set comment_max_passwd_length = none %}
{% endif %}
{% endif %}
{% endif %}
{{ input_text(label=_('Minimum password length'),
input_name='minPasswordLength',
value=min_passwd_length,
size=8,
comment=comment_min_passwd_length,
comment_as_text=True) }}
{{ input_text(label=_('Maximum password length'),
input_name='maxPasswordLength',
value=max_passwd_length,
size=8,
comment=comment_max_passwd_length,
comment_as_text=True) }}
</div>{# .col2-3 #}
<div class="col1-3 lastcol">
<div class="mark_blue bt-space10">
<ul class="standard clean-padding bt-space10">
<li class="bt-space5">{{ _('Leave it empty to use server-wide default setting.') }}</li>
</ul>
</div>
</div>{#-- .col1-3 --#}
</div>{#-- .columns --#}
{% endif %}
<div class="rule"></div>
<div class="columns clear">
<div class="col2-3 ">
{{ display_preferred_language(
value=domain_settings.get('default_language'),
languagemaps=languagemaps,
label=_('Default language for new user')) }}
{{ display_timezones(value=domain_settings.get('timezone'), timezones=timezones) }}
</div>
</div>
{% if session.get('is_global_admin') or 'bcc' not in disabled_domain_profiles %}
<div class="rule"></div>
<div class="columns clear">
<div class="col2-3 ">
{{ display_recipient_bcc(address=domain_settings.get('default_recipient_bcc', ''), label=_('Default bcc address for incoming emails for new user')) }}
{{ display_sender_bcc(address=domain_settings.get('default_sender_bcc', ''), label=_('Default bcc address for outgoing emails for new user')) }}
</div><!-- .col2-3 -->
<div class="col1-3 lastcol">
<div class="mark_blue bt-space10">
<ul class="standard clean-padding bt-space10">
<li class="bt-space5">{{ _('These addresses will be assigned to newly created mail user as per-user bcc address.') }}</li>
</ul>
</div>
</div><!-- .col1-3 -->
</div>
{% endif %}
<div class="columns clear">
<div class="col2-3 ">
<div class="form-field clear">
<h4 class="size-250 fl-space">{{ _('Default mailing list(s) of new user') }}</h4>
<div class="checklist clear">
<fieldset>
{% if domain_settings.get('default_mailing_lists', []) %}
{% set default_mailing_lists = domain_settings.get('default_mailing_lists') %}
{% else %}
{% set default_mailing_lists = [] %}
{% endif %}
{# Show non-exist lists which still stored in default_mailing_lists #}
{% for addr in default_mailing_lists |sort %}
{% if addr and addr not in mails_of_all_mailing_lists %}
<div class="checklist-item">
<span class="clean-padding">
<input type="checkbox"
name="default_mail_list"
class="checkbox fl-space"
rel="checkboxhorizont"
checked="checked"
value="{{ addr |e }}"
/>
</span>
<label>{{ addr |e }} (<span class="required">{{ _('Warning') }}: {{ _('Account does not exist.') }}</span>)</label>
</div>
<div class="clear"></div>
{% endif %}
{% endfor %}
{% for rcd in all_mailing_lists %}
<div class="checklist-item">
<span class="clean-padding">
<input type="checkbox"
name="default_mail_list"
class="checkbox fl-space"
rel="checkboxhorizont"
value="{{ rcd.address |e }}"
{% if rcd.address in default_mailing_lists %}checked="checked"{% endif %}
/>
</span>
<label>
<a href="{{ctx.homepath}}/profile/ml/general/{{ rcd.address |e }}">{% if rcd.name %}{{ rcd.name |e }}{% else %}{{ rcd.address.split('@', 1)[0] }}{% endif %}</a>&nbsp;({{ rcd.address |e }})
</label>
</div>
<div class="clear"></div>
{% endfor %}
</fieldset>
</div>
</div><!-- .form-field -->
</div><!-- .col2-3 -->
<div class="col1-3 lastcol">
<div class="mark_blue bt-space10">
<ul class="standard clean-padding bt-space10">
<li class="bt-space5"><a href="{{ctx.homepath}}/create/ml/{{ cur_domain }}" class="action_add">{{ _('Add mailing list') }}</a></li>
</ul>
</div>
</div><!-- .col1-3 -->
</div><!-- .columns -->
<div class="columns clear">
<div class="col2-3 ">
<div class="form-field clear">
<h4 class="size-250 fl-space">{{ _('Default mail alias(es) of new user') }}</h4>
<div class="checklist clear">
<fieldset>
{% if domain_settings.get('default_groups', []) %}
{% set default_groups = domain_settings.get('default_groups') %}
{% else %}
{% set default_groups = [] %}
{% endif %}
{# Show non-exist lists which still stored in default_groups #}
{% for addr in default_groups |sort %}
{% if addr and addr not in mails_of_all_alias_accounts %}
<div class="checklist-item">
<span class="clean-padding">
<input type="checkbox"
name="defaultList"
class="checkbox fl-space"
rel="checkboxhorizont"
checked="checked"
value="{{ addr |e }}"
/>
</span>
<label>{{ addr |e }} (<span class="required">{{ _('Warning') }}: {{ _('Account does not exist.') }}</span>)</label>
</div>
<div class="clear"></div>
{% endif %}
{% endfor %}
{% for rcd in all_alias_accounts %}
<div class="checklist-item">
<span class="clean-padding">
<input type="checkbox"
name="defaultList"
class="checkbox fl-space"
rel="checkboxhorizont"
value="{{ rcd.address |e }}"
{% if rcd.address in default_groups %}checked="checked"{% endif %}
/>
</span>
<label>
<a href="{{ctx.homepath}}/profile/alias/general/{{ rcd.address |e }}">{% if rcd.name %}{{ rcd.name |e }}{% else %}{{ rcd.address.split('@', 1)[0] }}{% endif %}</a>&nbsp;({{ rcd.address |e }})
</label>
</div>
<div class="clear"></div>
{% endfor %}
</fieldset>
</div>
</div><!-- .form-field -->
</div><!-- .col2-3 -->
<div class="col1-3 lastcol">
<div class="mark_blue bt-space10">
<ul class="standard clean-padding bt-space10">
<li class="bt-space5"><a href="{{ctx.homepath}}/create/alias/{{ cur_domain }}" class="action_add">{{ _('Add mail alias') }}</a></li>
</ul>
</div>
</div><!-- .col1-3 -->
</div><!-- .columns -->
<div class="rule"></div>
{# Enabled services #}
{{ display_enabled_domain_services(enabled_services=enabled_services) }}
{# Disabled per-domain mail services #}
{% if session.get('is_global_admin') or 'disabled_mail_services' not in disabled_domain_profiles %}
<div class="rule"></div>
{{ display_disabled_domain_mail_services(disabled_mail_services=disabled_mail_services) }}
{% endif %}
{% if session.get('is_global_admin') %}
<div class="rule"></div>
{# Disabled domain profiles #}
{{ display_disabled_account_profiles(account_type='domain',
disabled_profiles=disabled_domain_profiles) }}
<div class="rule"></div>
{# Disabled user profiles #}
{{ display_disabled_account_profiles(account_type='user',
disabled_profiles=disabled_user_profiles) }}
{% endif %}
<div class="rule"></div>
{# Disabled user profiles #}
{{ display_disabled_account_profiles(account_type='user_preference',
disabled_profiles=disabled_user_preferences) }}
{{ input_submit() }}
</form>
</div><!-- #profile_advanced -->
{# profile_type: backupmx #}
{% if session.get('is_global_admin') or 'backupmx' not in disabled_domain_profiles %}
<div id="profile_backupmx">
<form name="backupmx" method="post" action="{{ctx.homepath}}/profile/domain/backupmx/{{cur_domain}}">
{{ input_csrf_token() }}
{{ display_domain_backupmx(domain=cur_domain,
backupmx=profile.backupmx,
transport=profile.transport) }}
{{ input_submit() }}
</form>
</div><!-- #profile_backupmx -->
{% endif %}
</div><!-- .box-wrap -->
</div><!-- .box-body -->
</div><!-- .content-box -->
{% endblock main %}
{% block extra_js %}
<script type="text/javascript">
$(document).ready(function() {
$(".tabs li").idTabs("profile_{{ profile_type }}")
});
</script>
{% endblock extra_js %}

View File

@@ -0,0 +1,131 @@
{% extends "layout.html" %}
{% from "macros/form_inputs.html" import input_csrf_token with context %}
{% from "macros/general.html" import
display_subnav,
display_input_cn
with context
%}
{% from "macros/mlmmj.html" import display_maillist_basic_profile with context %}
{% from "macros/msg_handlers.html" import maillist_msg_handler with context %}
{% block title %}{{ _('Add mailing list') }}{% endblock title %}
{% block navlinks_create %}class="active"{% endblock %}
{% block breadcrumb %}
{% set crumbs = [
(ctx.homepath + '/domains', _('All domains')),
(ctx.homepath + '/profile/domain/general/' + cur_domain, cur_domain),
(ctx.homepath + '/users/' + cur_domain, _('Users')),
(ctx.homepath + '/mls/' + cur_domain, _('Mailing Lists')),
(ctx.homepath + '/aliases/' + cur_domain, _('Aliases')),
(ctx.homepath + '/admins/' + cur_domain, _('Admins')),
]
%}
{% if backend != "pgsql" %}
{% set crumbs = crumbs + [(ctx.homepath + '/users/' + cur_domain + '/last_logins', _('Last Logins'))] %}
{% endif %}
{{ display_subnav(crumbs) }}
{% endblock %}
{% block main %}
{# Show system message #}
{{ maillist_msg_handler(msg) }}
{% set createNewAccount = true %}
{% set numberOfSpareAccounts = profile.maillists - num_existing_maillists %}
{% if profile.maillists == -1 %}
{% set createNewAccount = false %}
{% set whyDisabledCreation = _('Not allowed to create mailing list under this domain.') %}
{% elif profile.maillists > 0 and numberOfSpareAccounts <= 0 %}
{% set createNewAccount = false %}
{% set whyDisabledCreation = _('Already exceed max number of account limit (%d).') |format(profile.maillists |int) %}
{% endif %}
{% if not createNewAccount %}
<div class="notification note-error">
<p>
<strong>{{ _('Error:') }}</strong> {{ _("You can't create mailing lists under domain %s.") |format('<a href="' + ctx.homepath + '/profile/domain/general/' + cur_domain + '#accountLimit"><strong>' + cur_domain + '</strong></a>') }}
{{ whyDisabledCreation }}
</p>
</div>
{% else %}
{% if profile.maillists > 0 and numberOfSpareAccounts > 0 %}
<div class="notification note-info">
<p>{{ _('You can create <strong>%d</strong> more mailing list(s) under domain %s.') |format(numberOfSpareAccounts |int, '<a href="' + ctx.homepath + '/profile/domain/general/' + cur_domain + '"><strong>' + cur_domain + '</strong></a>') }}</p>
</div>
{% endif %}
{% endif %}
<div class="content-box">
<div class="box-body">
<div class="box-header clear">
<ul class="tabs clear">
<li><a href="{{ctx.homepath}}/create/user/{{cur_domain}}"><i class="fa fa-plus"></i> {{ _('User') }}</a>
<li class="active"><a href="{{ctx.homepath}}/create/ml/{{cur_domain}}"><i class="fa fa-plus"></i> {{ _('Mailing List') }}</a>
<li><a href="{{ctx.homepath}}/create/alias/{{cur_domain}}"><i class="fa fa-plus"></i> {{ _('Alias') }}</a>
</ul>
<h2>{{ _('Add mailing list') }}</h2>
</div>
<div id="maillist_add" class="box-wrap clear">
<div class="columns clear">
<form name="create" method="post" action="{{ctx.homepath}}/create/ml/{{cur_domain}}">
{{ input_csrf_token() }}
<div class="form-field clear">
<h4 class="size-250 fl-space">{{ _('Add mailing list under domain') }} <span class="required">*</span></h4>
<span class="clean-padding">
<select name="domainName" onchange="change_url(this, baseurl='{{ctx.homepath}}/create/ml/');">
{% for d in allDomains %}
<option value="{{ d |e }}" {% if d == cur_domain %}selected{%endif%}>{{ d |e }}</option>
{% endfor %}
</select>
</span>
</div>
<div class="form-field clear">
<h4 class="size-250 fl-space">{{ _('Mail Address') }} <span class="required">*</span></h4>
<span class="clean-padding">
<input type="text" size="35"
name="listname"
value="{{ listname |e }}"
class="text fl-space {% if not createNewAccount %}disabled{% endif %}"
{% if not createNewAccount %}disabled="disabled"{% endif %}
/>@{{ cur_domain }}
</span>
</div>
{{ display_input_cn(value=cn, input_name='name', enable_input=createNewAccount) }}
{{ display_maillist_basic_profile(profile=default_creation_settings) }}
<div class="rule2"></div>
<div class="form-field clear">
<h4 class="size-250 fl-space">&nbsp;</h4>
<span class="clean-padding bt-space20">
<input type="submit"
value="{{ _('Add') }}"
{% if not createNewAccount %}
class="button color-grey" disabled="disabled"
{% else %}
class="button green"
{% endif %}
/>
</span>
</div>
</form>
</div>{# .columns #}
</div>{# .box-wrap #}
</div>{# .content-box #}
</div>{# .box-body #}
{% endblock main %}

View File

@@ -0,0 +1,155 @@
{% extends "layout.html" %}
{% from "macros/form_inputs.html" import
input_csrf_token
with context
%}
{% from "macros/general.html" import
display_subnav,
set_account_status_img,
set_account_activity_img,
highlight_username_in_mail,
display_filter_by_first_char,
display_list_access_policy_name,
show_pages
with context
%}
{% from "macros/msg_handlers.html" import maillist_msg_handler with context %}
{% block title %}{{ _('Mailing Lists') }}{% endblock %}
{% block navlinks_domains %}class="active"{% endblock %}
{% block breadcrumb %}
{% set crumbs = [
(ctx.homepath + '/domains', _('All domains')),
(ctx.homepath + '/profile/domain/general/' + cur_domain, cur_domain),
(ctx.homepath + '/users/' + cur_domain, _('Users')),
('active', ctx.homepath + '/mls/' + cur_domain, _('Mailing Lists')),
(ctx.homepath + '/aliases/' + cur_domain, _('Aliases')),
] %}
{% if session.get('is_global_admin') %}
{% set crumbs = crumbs + [(ctx.homepath + '/admins/' + cur_domain, _('Admins'))] %}
{% endif %}
{% if backend != "pgsql" %}
{% set crumbs = crumbs + [(ctx.homepath + '/users/' + cur_domain + '/last_logins', _('Last Logins'))] %}
{% endif %}
{{ display_subnav(crumbs) }}
{% endblock %}
{% block main %}
{# Show system message #}
{{ maillist_msg_handler(msg) }}
{% if maillists is defined %}
{% if maillists or (not maillists and first_char) %}
{{ display_filter_by_first_char(baseurl=ctx.homepath + '/mls/' + cur_domain,
available_chars=all_first_chars,
first_char=first_char,
disabled_only=disabled_only) }}
{% endif %}
<div class="content-box">
<div class="box-body">
<div class="box-header clear">
<ul class="tabs clear">
<li><a href="{{ctx.homepath}}/create/user/{{cur_domain}}"><i class="fa fa-plus"></i> {{ _('User') }}</a>
<li><a href="{{ctx.homepath}}/create/ml/{{cur_domain}}"><i class="fa fa-plus"></i> {{ _('Mailing List') }}</a>
<li><a href="{{ctx.homepath}}/create/alias/{{cur_domain}}"><i class="fa fa-plus"></i> {{ _('Alias') }}</a>
</ul>
<h2>
{{ _('Mailing lists under domain: %s.') |format(cur_domain) }}
{% if total is defined and maillists %}
({{ (cur_page-1) * page_size_limit + 1 }}-{{ (cur_page-1) * page_size_limit + maillists |length}}/{{total}})
{% endif %}
<a href="{{ctx.homepath}}/profile/domain/general/{{cur_domain}}"><i class="fa fa-cog fa-lg" title="{{ _('Edit domain profile') }}"></i></a>
{{ set_account_activity_img('sent', 'domain', cur_domain, float=false) }}
</h2>
</div>{# -- box-header -- #}
{# List all mailing lists. #}
<form name="maillists" id="list_table" action="{{ctx.homepath}}/mls/{{cur_domain}}" method="post">
{{ input_csrf_token() }}
<table class="style1">
<thead>
<tr>
<th class="checkbox"><input type="checkbox" class="checkbox select-all" /></th>
<th data-sort="string-ins">{{ _('Display Name') }}</th>
<th data-sort="string-ins">{{ _('Mail Address') }}</th>
<th data-sort="string-ins">{{ _('Mail Deliver Restriction') }}</th>
</tr>
</thead>
<tbody>
{% if maillists|length > 0 %}
{% for r in maillists %}
{% set address = r.address |e %}
{% set name = r.name |e %}
{% set access_policy = r.accesspolicy |e %}
<tr>
<td class="checkbox"><input type="checkbox" class="checkbox" name="mail" value="{{ address }}" /></td>
<td>
<a href="{{ctx.homepath}}/profile/ml/members/{{address}}"><i class="fa fa-users fa-lg fr-space" title="{{ _('View members') }}"></i></a>
<a href="{{ctx.homepath}}/profile/ml/general/{{address}}"><i class="fa fa-cog fa-lg fr-space" title="{{ _('Edit account profile') }}"></i></a>
{{ set_account_status_img(r.active) }}
<a href="{{ctx.homepath}}/profile/ml/general/{{address}}" title="{{ _('Edit account profile') }}">{% if name %}{{ name |cut_string |e }}{% else %}{{ address.split('@', 1)[0] }}{% endif %}</a>
</td>
<td>{{ highlight_username_in_mail(address) }}</td>
<td>{{ display_list_access_policy_name(policy=access_policy) }}</td>
</tr>
{% endfor %}
{% else %}
<tr>
<td class="checkbox"></td>
<td colspan="4">{{ _('No mailing list available.') }}
{% if not first_char %}
<a href="{{ctx.homepath}}/create/ml/{{ cur_domain }}">{{ _('Add one') }}</a>?
{% endif %}
</td>
</tr>
{% endif %}
</tbody>
</table>
{% if maillists %}
<div class="tab-footer clear f1">
<div class="fl">
<select name="action" class="fl-space">
<option>{{ _('Choose Action') }}</option>
<option disabled>----</option>
<option value="enable">{{ _('Enable') }}</option>
<option value="disable">{{ _('Disable') }}</option>
<option value="delete">{{ _('Delete and archive') }}</option>
<option disabled>----</option>
<option value="delete_without_archiving">{{ _('Delete without archiving') }}</option>
</select>
<input type="submit" value="{{ _('Apply') }}" class="button fl-space" />
</div>
{% set baseurl = ctx.homepath + '/mls/' + cur_domain %}
{% if disabled_only %}
{% set baseurl = baseurl + '/disabled' %}
{% endif %}
{% set url_suffix = '' %}
{% if first_char %}
{% set url_suffix = '?starts_with=' + first_char %}
{% endif %}
{{ show_pages(baseurl=baseurl, total=total, cur_page=cur_page, url_suffix=url_suffix) }}
</div>
{% endif %}
</form>
</div>{# -- box-body -- #}
</div>{# -- content-body -- #}
{% endif %}
{% endblock main %}

View File

@@ -0,0 +1,185 @@
{% extends "layout.html" %}
{% from "macros/form_inputs.html" import
input_submit,
input_csrf_token
with context
%}
{% from "macros/general.html" import
display_subnav,
display_input_cn,
display_change_email_address,
display_account_status,
display_per_account_alias_addresses,
set_account_status_img
with context
%}
{% from "macros/mlmmj.html" import
display_maillist_basic_profile,
display_maillist_owners,
display_maillist_moderators,
display_maillist_subscription_moderators,
display_modal_add_subscribers,
display_maillist_subscribers,
display_modal_newsletter_html_code,
display_maillist_newsletter_profile
with context
%}
{% from "macros/msg_handlers.html" import maillist_msg_handler with context %}
{% block title %}{{ _('Edit account profile') }}{% endblock %}
{% block navlinks_domains %}class="active"{% endblock %}
{% block breadcrumb %}
{% set crumbs = [
(ctx.homepath + '/domains', _('All domains')),
(ctx.homepath + '/profile/domain/general/' + cur_domain, cur_domain),
(ctx.homepath + '/users/' + cur_domain, _('Users')),
(ctx.homepath + '/mls/' + cur_domain, _('Mailing Lists')),
('active', ctx.homepath + '/profile/ml/general/' + mail, _('Profile of mailing list:') + '&nbsp;' + mail),
(ctx.homepath + '/aliases/' + cur_domain, _('Aliases')),
(ctx.homepath + '/admins/' + cur_domain, _('Admins')),
]
%}
{% if backend != "pgsql" %}
{% set crumbs = crumbs + [(ctx.homepath + '/users/' + cur_domain + '/last_logins', _('Last Logins'))] %}
{% endif %}
{{ display_subnav(crumbs) }}
{% endblock %}
{% block main %}
{# Show system message #}
{{ maillist_msg_handler(msg) }}
{% set navlinks = [
('general', _('General'), [true]),
('aliases', _('Aliases'), [true]),
('members', _('Members'), [true]),
('owners', _('Owners and Moderators'), [true]),
('newsletter', _('Newsletter'), [true]),
]
%}
{# modal window used to add subscriber #}
{% set form_post_url = ctx.homepath + "/profile/ml/add_subscribers/" + mail %}
{{ display_modal_add_subscribers(form_post_url=form_post_url) }}
{% if profile.mlid %}
{{ display_modal_newsletter_html_code(mlid=profile.mlid) }}
{% endif %}
<div class="content-box">
<div class="box-body">
<div class="box-header clear">
<h2>{{ _('Profile of mailing list:') }} {{ mail }} ({{ subscribers | length }} {{ _('Members') }})</h2>
<ul class="tabs clear">
{% for nav in navlinks %}
{% if not false in nav[2] and not none in nav[2] %}
<li><a href="#profile_{{ nav[0] }}">{{ nav[1] }}</a></li>
{% endif %}
{% endfor %}
</ul>
</div>{# -- box-header -- #}
<div class="box-wrap clear">
<div id="profile_general">
<form name="general" method="post" action="{{ctx.homepath}}/profile/ml/general/{{mail}}">
{{ input_csrf_token() }}
<div class="columns clear">
<div class="col2-3 clear">
{{ display_account_status(profile.active) }}
{{ display_input_cn(value=profile.name, input_name='name') }}
</div>
<div class="col1-3 lastcol">
{% if profile.active %}
<div class="mark_blue bt-space10">
<p class="bt-space"><i class="fa fa-plus fa-lg"></i> <a href="#add_subscribers" class="modal-link"><span class="text">{{ _('Add new members') }}</span></a></p>
</div>
{% else %}
<div class="notification note-attention">
<p class="bt-space"> {{ _('To add new members, please enable mailing list account first.') }}</p>
</div>
{% endif %}
</div>
</div>
<div class="columns clear">
{{ display_maillist_basic_profile(profile=profile, access_policy=profile.accesspolicy, mail=mail) }}
</div>
{{ input_submit() }}
</form>
</div>{# #profile_general #}
{# Aliases #}
<div id="profile_aliases">
<form name="aliases" method="post" action="{{ctx.homepath}}/profile/ml/aliases/{{mail}}">
{{ input_csrf_token() }}
{{ display_per_account_alias_addresses(mail=mail, alias_addresses=alias_addresses) }}
{{ input_submit() }}
</form>
</div>
{#
# Members
#}
<div id="profile_members" style="margin-left: -10px; margin-right: -10px; margin-bottom: -10px;">
<form name="members" method="post" action="{{ctx.homepath}}/profile/ml/members/{{mail}}">
{{ input_csrf_token() }}
{{ display_maillist_subscribers(mail=mail, subscribers=subscribers, account_is_enabled=profile.active) }}
</form>
</div>{# #profile_general #}
<div id="profile_owners">
<form name="owners" method="post" action="{{ctx.homepath}}/profile/ml/owners/{{mail}}">
{{ input_csrf_token() }}
{# parameter name is 'owner', not 'owners' #}
{{ display_maillist_owners(mail=mail, addresses=profile.get('owner')) }}
<div class="rule"></div>
{{ display_maillist_moderators(mail=mail, addresses=profile.get('moderators')) }}
<div class="rule"></div>
{{ display_maillist_subscription_moderators(mail=mail,
profile=profile,
addresses=profile.get('subscription_moderators')) }}
{{ input_submit() }}
</form>
</div>{# #profile_owners #}
<div id="profile_newsletter">
<form name="newsletter" method="post" action="{{ctx.homepath}}/profile/ml/newsletter/{{mail}}">
{{ input_csrf_token() }}
{{ display_maillist_newsletter_profile(is_newsletter=profile.is_newsletter,
description=profile.description) }}
{{ input_submit() }}
</form>
</div>{# #profile_newsletter #}
</div>{#-- .box-wrap --#}
</div>{#-- .box-body --#}
</div>{#-- .content-box --#}
{% endblock main %}
{% block extra_js %}
<script type="text/javascript">
$(document).ready(function(){
$(".tabs li").idTabs("profile_{{ profile_type }}");
$('#subscriber_search').quickfilter('#subscribers_tbody tr');
});
</script>
{% endblock extra_js %}

View File

@@ -0,0 +1,469 @@
{#
@queryResult List which stores LDAP query results
#}
{% extends "layout.html" %}
{% from "macros/form_inputs.html" import
input_csrf_token
with context
%}
{% from "macros/general.html" import
display_progress_bar,
set_account_status_img,
set_account_activity_img,
set_alias_address_img,
set_forwarding_address_img,
set_assigned_groups_img,
set_admin_type_img,
highlight_username_in_mail,
display_number_of_account_limited,
display_remove_mailbox_days
with context %}
{% from "macros/msg_handlers.html" import search_msg_handler with context %}
{% block title %}{{ _('Search') }}{% endblock %}
{% block navlinks_active_search %}class="active"{% endblock %}
{% block main %}
{{ search_msg_handler(msg) }}
<div class="content-box">
<div class="box-body">
<div class="box-wrap clear">
<form name="search" method="post" action="{{ctx.homepath}}/search">
{{ input_csrf_token() }}
<div class="form-field clear">
<h4 class="size-150 fl-space">{{ _('Keyword') }} <span class="required">*</span></h4>
<input type="text" name="searchString" value="{{ searchString |e }}" size="30" class="text" />
<input type="submit" value="{{ _('Search') }}" size="30" class="button green" />
</div>
<div class="form-field clear">
<h4 class="size-150 fl-space">{{ _('Account type') }}</h4>
<input type="checkbox" name="account_type" value="user" rel="checkboxvert" class="checkbox" checked="checked" /> <label>{{ _('User') }}</label>
<input type="checkbox" name="account_type" value="alias" rel="checkboxvert" class="checkbox" checked="checked" /> <label>{{ _('Alias') }}</label>
<input type="checkbox" name="account_type" value="ml" rel="checkboxvert" class="checkbox" checked="checked" /> <label>{{ _('Mailing List') }}</label>
{% if session.get('is_global_admin') %}
<input type="checkbox" name="account_type" value="domain" rel="checkboxvert" class="checkbox" /> <label>{{ _('Domain') }}</label>
<input type="checkbox" name="account_type" value="admin" rel="checkboxvert" class="checkbox" /> <label>{{ _('Admin') }}</label>
{% endif %}
</div>
<div class="form-field clear">
<h4 class="size-150 fl-space">{{ _('Account status') }}</h4>
<input type="checkbox"
name="accountStatus"
value="active"
rel="checkboxvert"
class="checkbox"
checked="checked"
/>
<label>{{ _('Active') }}</label>
<input type="checkbox"
name="accountStatus"
value="disabled"
rel="checkboxvert"
class="checkbox"
checked="checked"
/>
<label>{{ _('Disabled') }}</label>
</div>
</form>
</div>
</div>
</div>
{% if total_results is defined %}
<div class="content-box">
<div class="box-body">
<div class="box-header clear">
<h2>{{ _('Search results.') }}</h2>
</div>
<div class="box-wrap clear">
{% if total_results > 0 %}
{% if session.get('is_global_admin') %}
{% if domains |length > 0 %}
<h2>{{ _('%d domain(s) found.') |format(domains |length) }}</h2>
<form name="domains" id="domain_table" method="post" action="{{ctx.homepath}}/domains">
{{ input_csrf_token() }}
<table class="style1">
<thead>
<tr>
<th class="checkbox"><input type="checkbox" class="checkbox select-all" /></th>
<th data-sort="string-ins">{{ _('Domain') }}</th>
<th data-sort="string-ins">{{ _('Display Name') }}</th>
<th data-sort="int">{{ _('Quota') }}</th>
<th data-sort="int">{{ _('Users') }}</th>
<th data-sort="int">{{ _('Aliases') }}</th>
</tr>
</thead>
<tbody>
{% for r in domains %}
{% set domain = r.domain |e %}
<tr>
<td class="checkbox"><input type="checkbox" class="checkbox " name="domainName" value="{{ domain }}" /></td>
<td>
<a href="{{ctx.homepath}}/profile/domain/general/{{domain}}"><i class="fa fa-cog fa-lg fr-space" title="{{ _('Edit account profile') }}"></i></a>
{{ set_account_activity_img('sent', 'domain', domain) }}
{{ set_account_status_img(r.active) }}
<a href="{{ctx.homepath}}/profile/domain/general/{{domain}}" title="{{ _('Edit account profile') }}">{{ domain }}</a>
</td>
{% if r.description %}
<td class="vcenter">{{ r.description |cut_string |e }}</td>
{% else %}
<td class="vcenter">&nbsp;</td>
{% endif %}
{# Quota #}
<td class="vcenter">
{{ display_number_of_account_limited(r.maxquota |file_size_format(base_mb=True), hide_unlimited=false, hide_slash=true) }}
</td>
{# Mailboxes #}
<td class="vcenter" data-sort-value="{{ r.mailboxes |e }}">
{% if (r.mailboxes |int) >= 0 %}
<a href="{{ctx.homepath}}/users/{{domain}}" title="{{ _('List all mail users.') }}" style="text-decoration: none;">{{ display_number_of_account_limited(r.mailboxes, hide_unlimited=false, hide_slash=true) }}</a>
{% elif (r.mailboxes |int) == -1 %}
<span class="color-grey"><em>{{ _('DISABLED') }}</em></span>
{% endif %}
</td>
{# Aliases #}
<td class="vcenter" data-sort-value="{{ r.aliases |e }}">
{% if (r.aliases |int) >= 0 %}
<a href="{{ctx.homepath}}/aliases/{{domain}}" title="{{ _('List all mail aliases.') }}" style="text-decoration: none;">{{ display_number_of_account_limited(r.aliases, hide_unlimited=false, hide_slash=true) }}</a>
{% elif (r.aliases |int) == -1 %}
<span class="color-grey"><em>{{ _('DISABLED') }}</em></span>
{% endif %}
</td>
</tr>
{% endfor %}
</tbody>
</table>
<div class="tab-footer clear f1">
<div class="fl">
<select name="action" class="fl-space" id="domain_list_actions">
<option>{{ _('Choose Action') }}</option>
<option disabled>----</option>
<option value="enable">{{ _('Enable') }}</option>
<option value="disable">{{ _('Disable') }}</option>
<option value="delete">{{ _('Delete') }}</option>
</select>
<select name="keep_mailbox_days" class="fl-space" id="domain_delete_date">
{% for _day in days_to_keep_removed_mailbox %}
<option value="{{ _day }}">{{ display_remove_mailbox_days(_day) }}</option>
{% endfor %}
</select>
<input type="submit" value="{{ _('Apply') }}" class="button fl-space" />
</div>
</div>
</form>
<div class="bt-space20"></div>
{% endif %} {# domains #}
{% if admins |length > 0 %}
<h2>{{ _('%d admin(s) found.') |format(admins |length) }}</h2>
<form name="admins" id="admin_table" method="post" action="{{ctx.homepath}}/admins">
{{ input_csrf_token() }}
<table class="style1">
<thead>
<tr>
<th class="checkbox"><input type="checkbox" class="checkbox select-all" /></th>
<th data-sort="string-ins">{{ _('Display Name') }}</th>
<th data-sort="string-ins">{{ _('Mail Address') }}</th>
<th data-sort="string-ins">{{ _('Global Admin') }}</th>
</tr>
</thead>
<tbody>
{% for r in admins %}
{% set username = r.username |e %}
{% set name = r.name |e %}
<tr>
<td class="checkbox"><input type="checkbox" name="mail" value="{{ username }}" {% if username == session.get('username') %}disabled="disabled"{% endif %}/></td>
<td>
<a href="{{ctx.homepath}}/profile/admin/general/{{ username }}"><i class="fa fa-cog fa-lg fr-space" title="{{ _('Edit account profile') }}"></i></a>
{{ set_account_status_img(r.active) }}
{# -- Show name -- #}
{% if name == '' %}
{{ username.split('@', 1)[0] }}
{% else %}
{{ name |cut_string }}
{% endif %}
</td>
<td><a href="{{ctx.homepath}}/profile/admin/general/{{username}}" title="{{ _('Edit account profile') }}">{{ username }}</a></td>
{% if username in allGlobalAdmins %}
<td>{{ set_admin_type_img('yes') }}</td>
{% else %}
<td>{{ set_admin_type_img('no') }}</td>
{% endif %}
</tr>
{% endfor %}
</tbody>
</table>
<div class="tab-footer clear f1">
<div class="fl">
<select name="action" class="fl-space">
<option>{{ _('Choose Action') }}</option>
<option disabled>----</option>
<option value="enable">{{ _('Enable') }}</option>
<option value="disable">{{ _('Disable') }}</option>
<option value="delete">{{ _('Delete') }}</option>
</select>
<input type="submit" value="{{ _('Apply') }}" class="button fl-space" />
</div>
</div>
</form>
<div class="bt-space20"></div>
{% endif %} {# admins #}
{% endif %} {# domainGlobalAdmin #}
{# List all users. #}
{% if users %}
<h2>{{ _('%d user(s) found.') |format( users |length ) }}</h2>
<form name="users" id="user_table" method="post" action="{{ctx.homepath}}/action/user">
{{ input_csrf_token() }}
<table class="style1">
<thead>
<tr>
<th class="checkbox"><input type="checkbox" class="checkbox select-all" /></th>
<th data-sort="string-ins">{{ _('Display Name') }}</th>
<th data-sort="string-ins">{{ _('Mail Address') }}</th>
<th data-sort="string-ins">{{ _('User/Employee ID') }}</th>
<th data-sort="int">{{ _('Quota') }}</th>
{% if last_logins %}
<th data-sort="int">{{ _('Last Login') }}</th>
{% endif %}
</tr>
</thead>
<tbody>
{% for r in users %}
{% set mail = r.username |e %}
<tr>
<td class="checkbox"><input type="checkbox" name="mail" value="{{mail}}" /></td>
<td class="vcenter">
<a href="{{ctx.homepath}}/profile/user/general/{{mail}}"><i class="fa fa-cog fa-lg fr-space" title="{{ _('Edit account profile') }}"></i></a>
{{ set_account_activity_img('sent', 'user', mail) }}
{{ set_account_status_img(r.active) }}
{{ set_assigned_groups_img(addresses=user_assigned_groups.get(mail, [])) }}
{{ set_forwarding_address_img(user=mail, addresses=user_forwarding_addresses.get(mail, [])) }}
{{ set_alias_address_img(addresses=user_alias_addresses.get(mail, [])) }}
<a href="{{ctx.homepath}}/profile/user/general/{{mail}}" title="{{ _('Edit account profile') }}">{% if r.name %}{{ r.name |cut_string |e }}{% else %}{{ mail.split('@', 1)[0] }}{% endif %}</a>
</td>
<td class="vcenter">{{ highlight_username_in_mail(mail) }}</td>
<td class="vcenter">{% if r.employeeid %}{{ r.employeeid |e }}{% endif %}</td>
{% if (r.quota |int) == 0 %}
<td class="vcenter" data-sort-value="0">{{ _('Unlimited') }}</td>
{% else %}
<td class="vcenter" data-sort-value="{{ r.quota |e }}">{{ r.quota | file_size_format(base_mb=True) }}</td>
{% endif %}
{# last login #}
{% if last_logins %}
{% if mail in last_logins %}
{% set _times = last_logins.get(mail, {}) %}
{# values may be None, so we use `or 0` to set it to `0` #}
{% set _imap = _times.get('imap', 0) or 0 %}
{% set _pop3 = _times.get('pop3', 0) or 0 %}
{% set _lda = _times.get('lda', 0) or 0 %}
{# imap or pop3 login time #}
{% set _login_time = 0 %}
{% set _login_service = None %}
{% if (_imap > 0) and (_pop3 > 0) %}
{% if _imap > _pop3 %}
{% set _login_time = _imap %}
{% set _login_service = 'imap' %}
{% else %}
{% set _login_time = _pop3 %}
{% set _login_service = 'pop3' %}
{% endif %}
{% elif _imap > 0 %}
{% set _login_time = _imap %}
{% set _login_service = 'imap' %}
{% elif _pop3 > 0 %}
{% set _login_time = _pop3 %}
{% set _login_service = 'pop3' %}
{% endif %}
<td data-sort-value="{{ _login_time }}">
{% if _login_time %}
<span title="{% if _imap %}{{ _('IMAP Login:') }} {{ _imap | epoch_seconds_to_gmt | utc_to_timezone(timezone=session.get('timezone')) }}<br/>{% endif %}{% if _pop3 %}{{ _('POP3 Login:') }} {{ _pop3 | epoch_seconds_to_gmt | utc_to_timezone(timezone=session.get('timezone')) }}<br/>{% endif %}{% if _lda %}{{ _('New Mail Delivered:') }} {{ _lda | epoch_seconds_to_gmt | utc_to_timezone(timezone=session.get('timezone')) }}{% endif %}">
{{ _login_time | epoch_seconds_to_gmt | utc_to_timezone(timezone=session.get('timezone')) }}
{% if _login_service %}
{{ _login_service | upper }}
{% endif %}
</span>
{% endif %}
</td>
{% else %}
<td data-sort-value="0"></td>
{% endif %}
{% endif %}
</tr>
{% endfor %}
</tbody>
</table>
<div class="tab-footer clear f1">
<div class="fl">
<select name="action" class="fl-space" id="account_list_actions">
<option>{{ _('Choose Action') }}</option>
<option disabled>----</option>
<option value="enable">{{ _('Enable') }}</option>
<option value="disable">{{ _('Disable') }}</option>
<option value="delete">{{ _('Delete') }}</option>
</select>
<select name="keep_mailbox_days" class="fl-space" id="account_delete_date">
{% for _day in days_to_keep_removed_mailbox %}
<option value="{{ _day }}">{{ display_remove_mailbox_days(_day) }}</option>
{% endfor %}
</select>
<input type="submit" value="{{ _('Apply') }}" class="button fl-space" />
</div>
</div>
</form>
<div class="bt-space20"></div>
{% endif %}
{# List all mailing lists. #}
{% if mls |length > 0 %}
<h2>{{ _('%d mailing list(s) found.') |format( mls |length ) }}</h2>
<form name="mls" id="ml_table" method="post" action="{{ctx.homepath}}/action/ml">
{{ input_csrf_token() }}
<table class="style1">
<thead>
<tr>
<th class="checkbox"><input type="checkbox" class="checkbox select-all" /></th>
<th data-sort="string-ins">{{ _('Display Name') }}</th>
<th data-sort="string-ins">{{ _('Mail Address') }}</th>
</tr>
</thead>
<tbody>
{% for r in mls %}
{% set address = r.address |e %}
{% set name = r.name |e %}
{% set active = r.active |int %}
<tr>
<td class="checkbox"><input type="checkbox" name="mail" value="{{ address }}" /></td>
<td>
<a href="{{ctx.homepath}}/profile/ml/general/{{address}}"><i class="fa fa-cog fa-lg fr-space" title="{{ _('Edit account profile') }}"></i></a>
{{ set_account_status_img(active) }}
<a href="{{ctx.homepath}}/profile/ml/general/{{address}}">{% if name %}{{ name |cut_string |e }}{% else %}{{ address.split('@', 1)[0] }}{% endif %}</a>
</td>
<td><a href="{{ctx.homepath}}/profile/ml/general/{{address}}">{{ highlight_username_in_mail(address) }}</a></td>
</tr>
{% endfor %}
</tbody>
</table>
<div class="tab-footer clear f1">
<div class="fl">
<select name="action" class="fl-space">
<option>{{ _('Choose Action') }}</option>
<option disabled>----</option>
<option value="enable">{{ _('Enable') }}</option>
<option value="disable">{{ _('Disable') }}</option>
<option value="delete">{{ _('Delete') }}</option>
</select>
<input type="submit" value="{{ _('Apply') }}" class="button fl-space" />
</div>
</div>
</form>
{% endif %}
{# List all mail aliases. #}
{% if aliases |length > 0 %}
<h2>{{ _('%d mail alias(es) found.') |format( aliases |length ) }}</h2>
<form name="aliases" id="alias_table" method="post" action="{{ctx.homepath}}/action/alias">
{{ input_csrf_token() }}
<table class="style1">
<thead>
<tr>
<th class="checkbox"><input type="checkbox" class="checkbox select-all" /></th>
<th data-sort="string-ins">{{ _('Display Name') }}</th>
<th data-sort="string-ins">{{ _('Mail Address') }}</th>
</tr>
</thead>
{# List alias attributes/avalues. #}
<tbody>
{% for r in aliases %}
{% set address = r.address |e %}
{% set name = r.name |e %}
<tr>
<td class="checkbox"><input type="checkbox" name="mail" value="{{ address }}" /></td>
<td>
<a href="{{ctx.homepath}}/profile/alias/general/{{address}}"><i class="fa fa-cog fa-lg fr-space" title="{{ _('Edit account profile') }}"></i></a>
{{ set_account_status_img(r.active) }}
<a href="{{ctx.homepath}}/profile/alias/general/{{address}}">{% if name %}{{ name |cut_string |e }}{% else %}{{ address.split('@', 1)[0] }}{% endif %}</a>
</td>
<td><a href="{{ctx.homepath}}/profile/alias/general/{{address}}">{{ highlight_username_in_mail(address) }}</a></td>
</tr>
{% endfor %}
</tbody>
</table>
<div class="tab-footer clear f1">
<div class="fl">
<select name="action" class="fl-space">
<option>{{ _('Choose Action') }}</option>
<option disabled>----</option>
<option value="enable">{{ _('Enable') }}</option>
<option value="disable">{{ _('Disable') }}</option>
<option value="delete">{{ _('Delete') }}</option>
</select>
<input type="submit" value="{{ _('Apply') }}" class="button fl-space" />
</div>
</div>
</form>
{% endif %}
{% else %}
<p>{{ _('Your search returned no hits.') }}</p>
{% endif %}
</div>{# .box-wrap #}
</div>{# .box-body #}
</div>{# .content-box #}
{% endif %}
{% endblock main %}

View File

@@ -0,0 +1,74 @@
{% extends "layout_user.html" %}
{% from "macros/form_inputs.html" import
input_csrf_token
with context
%}
{% from "macros/general.html" import
display_subnav,
highlight_username_in_mail,
display_filter_by_first_char,
display_list_access_policy_name,
show_pages
with context
%}
{% from "macros/sql.html" import
display_mls
with context
%}
{% from "macros/msg_handlers.html" import maillist_msg_handler with context %}
{% block title %}{{ _('Mailing Lists') }}{% endblock %}
{% block navlinks_manageml %}class="active"{% endblock %}
{% block main %}
{# Show system message #}
{{ maillist_msg_handler(msg) }}
{% if maillists %}
{{ display_filter_by_first_char(baseurl=ctx.homepath + '/self-service/mls',
account_type="managed_ml",
available_chars=all_first_chars,
first_char=first_char,
disabled_only=False) }}
{% endif %}
<div class="content-box">
<div class="box-body">
<div class="box-header clear">
<h2>
{{ _('Managed mailing lists.') }}
{% if total > 0 %}
({{ (cur_page-1) * page_size_limit + 1 }}-{{ (cur_page-1) * page_size_limit + (maillists |length) }}/{{total}})
{% endif %}
</h2>
</div>
{# List all mailing lists. #}
<form name="maillists" id="list_table" action="{{ctx.homepath}}/self-service/mls" method="post">
{{ input_csrf_token() }}
{{ display_mls(maillists=maillists,
profile_base_url=ctx.homepath + "/self-service/ml/profile",
domain=None) }}
{% if maillists %}
<div class="tab-footer clear f1">
{% set baseurl = ctx.homepath + '/self-service/mls' %}
{% set url_suffix = '' %}
{% if first_char %}
{% set url_suffix = '?starts_with=' + first_char %}
{% endif %}
{{ show_pages(baseurl=baseurl, total=total, cur_page=cur_page, url_suffix=url_suffix) }}
</div>
{% endif %}
</form>
</div>{# -- box-body -- #}
</div>{# -- content-body -- #}
{% endblock main %}

View File

@@ -0,0 +1,127 @@
{% extends "layout_user.html" %}
{% from "macros/form_inputs.html" import
input_submit,
input_csrf_token
with context
%}
{% from "macros/general.html" import
display_subnav,
display_input_cn,
with context
%}
{% from "macros/mlmmj.html" import
display_maillist_basic_profile,
display_modal_add_subscribers,
display_maillist_subscribers,
display_modal_newsletter_html_code,
display_maillist_newsletter_profile
with context
%}
{% from "macros/msg_handlers.html" import maillist_msg_handler with context %}
{% block title %}{{ _('Edit account profile') }}{% endblock %}
{% block navlinks_manageml %}class="active"{% endblock %}
{% block main %}
{# Show system message #}
{{ maillist_msg_handler(msg) }}
{% set navlinks = [
('general', _('General'), [true]),
('members', _('Members'), [true]),
('newsletter', _('Newsletter'), [true]),
]
%}
{# modal window used to add subscriber #}
{% set form_post_url = ctx.homepath + "/self-service/ml/profile/add_subscribers/" + mail %}
{{ display_modal_add_subscribers(form_post_url=form_post_url) }}
{% if profile.mlid %}
{{ display_modal_newsletter_html_code(mlid=profile.mlid) }}
{% endif %}
<div class="content-box">
<div class="box-body">
<div class="box-header clear">
<h2>{{ _('Profile of mailing list:') }} {{ mail }} ({{ subscribers | length }} {{ _('Members') }})</h2>
<ul class="tabs clear">
{% for nav in navlinks %}
{% if not false in nav[2] and not none in nav[2] %}
<li><a href="#profile_{{ nav[0] }}">{{ nav[1] }}</a></li>
{% endif %}
{% endfor %}
</ul>
</div>{# -- box-header -- #}
<div class="box-wrap clear">
<div id="profile_general">
<form name="general" method="post" action="{{ctx.homepath}}/self-service/ml/profile/general/{{mail}}">
{{ input_csrf_token() }}
<div class="columns clear">
<div class="col2-3 clear">
{{ display_input_cn(value=profile.name, input_name='name') }}
</div>
<div class="col1-3 lastcol">
{% if profile.active %}
<div class="mark_blue bt-space10">
<p class="bt-space"><i class="fa fa-plus fa-lg"></i> <a href="#add_subscribers" class="modal-link"><span class="text">{{ _('Add new members') }}</span></a></p>
</div>
{% else %}
<div class="notification note-attention">
<p class="bt-space"> {{ _('To add new members, please enable mailing list account first.') }}</p>
</div>
{% endif %}
</div>
</div>
<div class="columns clear">
{{ display_maillist_basic_profile(profile=profile, access_policy=profile.accesspolicy, mail=mail) }}
</div>
{{ input_submit() }}
</form>
</div>{# #profile_general #}
{#
# Members
#}
<div id="profile_members" style="margin-left: -10px; margin-right: -10px; margin-bottom: -10px;">
<form name="members" method="post" action="{{ctx.homepath}}/self-service/ml/profile/members/{{mail}}">
{{ input_csrf_token() }}
{{ display_maillist_subscribers(mail=mail, subscribers=subscribers, account_is_enabled=profile.active) }}
</form>
</div>{# #profile_general #}
<div id="profile_newsletter">
<form name="newsletter" method="post" action="{{ctx.homepath}}/self-service/ml/profile/newsletter/{{mail}}">
{{ input_csrf_token() }}
{{ display_maillist_newsletter_profile(is_newsletter=profile.is_newsletter,
description=profile.description) }}
{{ input_submit() }}
</form>
</div>{# #profile_newsletter #}
</div>{#-- .box-wrap --#}
</div>{#-- .box-body --#}
</div>{#-- .content-box --#}
{% endblock main %}
{% block extra_js %}
<script type="text/javascript">
$(document).ready(function(){
$(".tabs li").idTabs("profile_{{ profile_type }}");
$('#subscriber_search').quickfilter('#subscribers_tbody tr');
});
</script>
{% endblock extra_js %}

View File

@@ -0,0 +1,138 @@
{% extends "layout_user.html" %}
{% from "macros/form_inputs.html" import
input_submit,
input_csrf_token
with context
%}
{% from "macros/general.html" import
display_subnav,
set_account_activity_img,
display_progress_bar,
display_input_cn,
display_preferred_language,
display_timezones,
display_account_status,
display_reset_password,
display_random_password,
display_user_forwarding
with context
%}
{% from "macros/msg_handlers.html" import user_msg_handler with context %}
{% block title %}{{ _('Preferences') }}{% endblock %}
{% block navlinks_preferences %}class="active"{% endblock %}
{% block main %}
{# Show system message #}
{% if msg %}
{% if msg.startswith('PW_') %}
{% set _pw_errors = msg.split(',') %}
{% for _err in _pw_errors %}
{{ user_msg_handler(_err) }}
{% endfor %}
{% else %}
{{ user_msg_handler(msg) }}
{% endif %}
{% endif %}
{% set navlinks = [('general', _('General'), [true]),
('forwarding', _('Forwarding'), ['forwarding' not in disabled_user_preferences]),
('password', _('Password'), ['password' not in disabled_user_preferences])]
%}
<div class="content-box">
<div class="box-body">
<div class="box-header clear">
<ul class="tabs clear">
{% for nav in navlinks %}
{% if not false in nav[2] and not none in nav[2] %}
<li><a href="#profile_{{nav[0]}}">{{ nav[1] }}</a></li>
{% endif %}
{% endfor %}
</ul>
<h2>{{ _('Preferences') }}</h2>
</div>
<div class="box-wrap clear">
<div id="profile_general">
<form name="profile" method="post" action="{{ctx.homepath}}/preferences/general">
{{ input_csrf_token() }}
<div class="columns clear">
<div class="col2-3">
{% if 'personal_info' not in disabled_user_preferences %}
{{ display_input_cn(value=profile.name) }}
{% endif %}
{{ display_preferred_language(value=profile.get('language'), languagemaps=languagemaps) }}
{{ display_timezones(value=user_settings.get('timezone'), timezones=timezones) }}
</div>
{% if profile.quota %}
<div class="col1-3 lastcol">
<div class="mark_blue bt-space10">
{% set percent = used_quota_bytes |convert_to_percentage(profile.quota |int * 1024 * 1024) %}
<h4>{{ _('Mailbox Quota') }} ({{ profile.quota | file_size_format(base_mb=True) }}, {{ percent }}% {{ _('Used') }})</h4>
{{ display_progress_bar(percent, style='thin', show_zero=true, width='70%') }}
<div>&nbsp;</div>
</div>
</div>
{% endif %}
</div>
{{ input_submit() }}
</form>
</div>
{% if 'forwarding' not in disabled_user_preferences %}
<div id="profile_forwarding">
<form name="profile" method="post" action="{{ctx.homepath}}/preferences/forwarding">
{{ input_csrf_token() }}
<div class="columns clear">
{{ display_user_forwarding(mail=mail,
enabled=profile.alias_active,
forwarding_addresses=profile.forwardings) }}
</div>{#-- .columns --#}
{{ input_submit() }}
</form>
</div>
{% endif %}
{% if 'password' not in disabled_user_preferences %}
<div id="profile_password">
<form name="profile" method="post" action="{{ctx.homepath}}/preferences/password">
{{ input_csrf_token() }}
<div class="columns clear">
<div class="col2-3">
{{ display_reset_password(show_confirmpw=true,
min_passwd_length=min_passwd_length,
max_passwd_length=max_passwd_length,
store_password_in_plain_text=store_password_in_plain_text) }}
</div>
<div class="col1-3 lastcol">
{{ display_random_password(password_length=min_passwd_length,
password_policies=password_policies) }}
</div>
</div>
{{ input_submit() }}
</form>
</div>
{% endif %}
</div>
</div>
</div>
{% endblock main %}
{% block extra_js %}
<script type="text/javascript">
$(document).ready(function() {
$(".tabs li").idTabs("profile_{{ profile_type }}")
});
</script>
{% endblock extra_js %}

View File

@@ -0,0 +1,167 @@
{% extends "layout.html" %}
{% from "macros/form_inputs.html" import
input_csrf_token
with context
%}
{% from "macros/general.html" import
display_subnav,
set_account_status_img,
set_forwarding_address_img,
with context
%}
{% from "macros/msg_handlers.html" import user_msg_handler with context %}
{% block title %}{{ _('Last Logins') }}{% endblock %}
{% block navlinks_domains %}class="active"{% endblock %}
{% block breadcrumb %}
{% if all_are_admins %}
{% set crumbs = [
(ctx.homepath + '/domains', _('All domains')),
(ctx.homepath + '/profile/domain/general/' + cur_domain, cur_domain),
(ctx.homepath + '/users/' + cur_domain, _('Users')),
(ctx.homepath + '/mls/' + cur_domain, _('Mailing Lists')),
(ctx.homepath + '/aliases/' + cur_domain, _('Aliases')),
(ctx.homepath + '/admins/' + cur_domain, _('Admins')),
]
%}
{% else %}
{% set crumbs = [
(ctx.homepath + '/domains', _('All domains')),
(ctx.homepath + '/profile/domain/general/' + cur_domain, cur_domain),
(ctx.homepath + '/users/' + cur_domain, _('Users')),
(ctx.homepath + '/mls/' + cur_domain, _('Mailing Lists')),
(ctx.homepath + '/aliases/' + cur_domain, _('Aliases')),
] %}
{% if session.get('is_global_admin') %}
{% set crumbs = crumbs + [(ctx.homepath + '/admins/' + cur_domain, _('Admins'))] %}
{% endif %}
{% endif %}
{% if backend != "pgsql" %}
{% set crumbs = crumbs + [('active', ctx.homepath + '/users/' + cur_domain + '/last_logins', _('Last Logins'))] %}
{% endif %}
{{ display_subnav(crumbs) }}
{% endblock %}
{% block main %}
{# Show system message #}
{{ user_msg_handler(msg) }}
<div class="content-box">
<div class="box-body">
<div class="box-header clear">
<h2>{{ _("Last Logins") }}</h2>
</div>
<div class="box-wrapper clear">
<div id="all_last_logins">
<table class="style1">
<thead>
<tr>
<th data-sort="string-ins">{{ _("Display Name") }}</th>
<th data-sort="string-ins">{{ _("Mail Address") }}</th>
<th data-sort="int" data-sort-default="desc" data-sort-onload="yes">IMAP</th>
<th data-sort="int" data-sort-default="desc">POP3</th>
<th data-sort="int" data-sort-default="desc">{{ _("Last Email Delivery") }}</th>
<th></th>
</tr>
</thead>
<tbody>
{% if last_logins %}
{% for email in last_logins %}
{% set active = last_logins[email]["active"] %}
{% set forwardings = last_logins[email]["forwardings"] %}
{% set name = last_logins[email]["name"] %}
{% set imap = last_logins[email]["imap"] %}
{% set pop3 = last_logins[email]["pop3"] %}
{% set lda = last_logins[email]["lda"] %}
<tr id="row_{{ loop.index }}">
<td>{% if name %}{{ name | e }}{% endif %}</td>
<td id="td_status_{{ loop.index }}">
<a href="{{ ctx.homepath }}/profile/user/general/{{ email }}"
title="{{ _('Edit account profile') }}"
>{{ email }}</a>
<a href="{{ ctx.homepath }}/profile/user/general/{{ email }}" title="{{ _('Edit account profile') }}"><i class="fa fa-cog fa-lg fr-space"></i></a>
{{ set_account_status_img(active) }}
{% if forwardings %}
{{ set_forwarding_address_img(email, forwardings) }}
{% endif %}
</td>
<td data-sort-value="{{ imap }}">
{% if imap > 0 %}
{{ imap | epoch_seconds_to_gmt | utc_to_timezone(timezone=session['timezone']) }}
{% endif %}
</td>
<td data-sort-value="{{ pop3 }}">
{% if pop3 > 0 %}
{{ pop3 | epoch_seconds_to_gmt | utc_to_timezone(timezone=session['timezone']) }}
{% endif %}
</td>
<td data-sort-value="{{ lda }}">
{% if lda > 0 %}
{{ lda | epoch_seconds_to_gmt | utc_to_timezone(timezone=session['timezone']) }}
{% endif %}
</td>
<td>
{% if active %}
<span
id="btn_disable_{{ loop.index }}"
class="button"
onclick='disable_user("{{ loop.index }}", "{{ email }}")'
>{{ _("Disable") }}</span>
{% endif %}
</td>
</tr>
{% endfor %}
{% else %}
<tr>
<td colspan="5">{{ _("No any login or mail delivery yet.") }}</td>
</tr>
{% endif %}
</tbody>
</table>
</div>{# .all_last_logins #}
</div>{# .box-wrapper #}
</div>{# .box-body #}
</div>{# .content-box #}
{% endblock main %}
{% block extra_js %}
<script type="text/javascript">
function disable_user(id, email) {
$.ajax({
type: "PUT",
url: '{{ ctx.homepath }}/apiproxy/user/' + email,
data: "accountStatus=disabled",
success: function (ret) {
if (ret._success) {
$('#td_status_' + id + ' i').
attr("title", '{{ _("Disabled") }}').
removeClass().
toggleClass("fas fa-times-circle fa-lg color-red fr-space");
$('#btn_disable_' + id).
text('{{ _("Disabled") }}').
addClass("grey").
attr('disabled','disabled');
} else {
alert(ret._msg);
}
}
});
};
</script>
{% endblock extra_js %}

View File

@@ -0,0 +1,186 @@
{% extends "layout.html" %}
{% from "macros/form_inputs.html" import input_csrf_token with context %}
{% from "macros/general.html" import
display_subnav,
display_input_cn,
display_preferred_language,
display_reset_password,
display_random_password,
display_quota
with context
%}
{% from "macros/msg_handlers.html" import user_msg_handler with context %}
{% block title %}{{ _('Add mail user') }}{% endblock title %}
{% block navlinks_create %}class="active"{% endblock %}
{% block breadcrumb %}
{% set crumbs = [
(ctx.homepath + '/domains', _('All domains')),
(ctx.homepath + '/profile/domain/general/' + cur_domain, cur_domain),
(ctx.homepath + '/users/' + cur_domain, _('Users')),
(ctx.homepath + '/mls/' + cur_domain, _('Mailing Lists')),
(ctx.homepath + '/aliases/' + cur_domain, _('Aliases')),
(ctx.homepath + '/admins/' + cur_domain, _('Admins')),
]
%}
{% if backend != "pgsql" %}
{% set crumbs = crumbs + [(ctx.homepath + '/users/' + cur_domain + '/last_logins', _('Last Logins'))] %}
{% endif %}
{{ display_subnav(crumbs) }}
{% endblock %}
{% block main %}
{# Show system message #}
{% if msg %}
{% if msg.startswith('PW_') %}
{% set _pw_errors = msg.split(',') %}
{% for _err in _pw_errors %}
{{ user_msg_handler(_err) }}
{% endfor %}
{% else %}
{{ user_msg_handler(msg) }}
{% endif %}
{% endif %}
{# -- Allow to create new account --#}
{% set createNewAccount = true %}
{% set numberOfSpareAccounts = profile.mailboxes - num_existing_users %}
{% set spareQuotaBytes = (profile.maxquota - usedQuotaSize) * 1024 * 1024 %}
{% if profile.mailboxes == -1 %}
{% set createNewAccount = false %}
{% set whyDisabledCreation = _('Not allowed to create mail alias under this domain.') %}
{% elif profile.mailboxes > 0 and numberOfSpareAccounts <= 0 %}
{% set createNewAccount = false %}
{% set whyDisabledCreation = _('Already exceed max number of account limit (%d).') |format(profile.mailboxes |int) %}
{% endif %}
{% if profile.maxquota > 0 and spareQuotaBytes <= 0 %}
{% set createNewAccount = false %}
{% set whyDisabledCreation = _('No free domain quota left.') %}
{% endif %}
{# Display input field for adding new user. #}
{% if not createNewAccount %}
<div class="notification note-error">
<p>
<strong>{{ _('Error:') }}</strong> {{ _('You can NOT create more users under domain %s.') |format('<a href="' + ctx.homepath + '/profile/domain/general/' + cur_domain + '"><strong>' + cur_domain + '</strong></a>') }} {{ whyDisabledCreation }}
{# Show link to change limit #}
{% if session.get('is_global_admin') %}
{% if profile.mailboxes > 0 and numberOfSpareAccounts <= 0 %}
<a href='{{ctx.homepath}}/profile/domain/advanced/{{cur_domain}}#domainQuota'>{{ _('Increase it now?') }}</a>
{% endif %}
{% endif %}
</p>
</div>
{% else %}
{% if profile.mailboxes > 0 and numberOfSpareAccounts > 0 %}
<div class="notification note-info">
<p>{{ _('You can create <strong>%d</strong> more mail user(s) under domain %s.') |format(numberOfSpareAccounts, '<a href="' + ctx.homepath + '/profile/domain/general/' + cur_domain + '"><strong>' + cur_domain + '</strong></a>') }}</p>
</div>
<div class="bt-space0"></div>
{% endif %}
{% endif %}
<div class="content-box">
<div class="box-body">
<div class="box-header clear">
<ul class="tabs clear">
<li class="active"><a href="#user_add"><i class="fa fa-plus"></i> {{ _('User') }}</a>
<li><a href="{{ctx.homepath}}/create/ml/{{cur_domain}}"><i class="fa fa-plus"></i> {{ _('Mailing List') }}</a>
<li><a href="{{ctx.homepath}}/create/alias/{{cur_domain}}"><i class="fa fa-plus"></i> {{ _('Alias') }}</a>
</ul>
<h2>{{ _('Add mail user') }}</h2>
</div>
<div id="user_add" class="box-wrap clear">
<form name="form_add_user" method="post" action="{{ctx.homepath}}/create/user/{{cur_domain}}">
{{ input_csrf_token() }}
<div class="columns clear">
<div class="col3-4">
<div class="form-field clear">
<h4 class="size-250 fl-space">{{ _('Add mail user under domain') }} <span class="required">*</span></h4>
<span class="clean-padding">
<select
name="domainName"
onchange="change_url(this, baseurl='{{ctx.homepath}}/create/user/');"
{% if not createNewAccount %}disabled{% endif %}
>
{% for d in all_domains %}
<option value="{{ d |e }}" {% if d == cur_domain %}selected{%endif%}>{{ d |e }}</option>
{% endfor %}
</select>
</span>
</div>
<div class="form-field clear">
<h4 class="size-250 fl-space">{{ _('Mail Address') }} <span class="required">*</span></h4>
<span class="clean-padding">
<input type="text" size="35"
name="username"
autocomplete="off"
value=""
class="text fl-space {% if not createNewAccount %}disabled{% endif %}"
{% if not createNewAccount %}disabled="disabled"{% endif %} />@{{ cur_domain }}
</span>
</div>
<div class="bt-space5">&nbsp;</div>
{{ display_reset_password(
min_passwd_length=min_passwd_length,
max_passwd_length=max_passwd_length,
store_password_in_plain_text=store_password_in_plain_text,
enable_input=createNewAccount,
) }}
<div class="bt-space5">&nbsp;</div>
{{ display_input_cn(
value=cn,
account_type='user',
enable_input=createNewAccount,
) }}
{{ display_preferred_language(
value=domain_settings.get('default_language', 'en_US'),
languagemaps=languagemaps,
enable_input=createNewAccount,
) }}
{{ display_quota(value=domain_settings.get('default_user_quota', 0),
spare_quota_bytes=spareQuotaBytes,
show_spare_quota=true,
show_value_in_input=true,
show_used_quota=false,
enable_input=createNewAccount) }}
</div>{# .col2-3 #}
<div class="col1-4 lastcol">
{{ display_random_password(password_length=min_passwd_length,
password_policies=password_policies) }}
</div>
</div>{# .columns #}
<div class="rule2"></div>
<div class="form-field clear">
<h4 class="size-250 fl-space">&nbsp;</h4>
<span>
<input type="submit" name="submit_add_user" value="{{ _('Add') }}" {% if not createNewAccount %}class="button color-grey" disabled="disabled"{% else %}class="button green"{% endif %} />
</span>
</div>
</form>
</div>{# -- End box-wrap -- #}
</div>{# -- End content-box -- #}
</div>{# -- End box-body -- #}
{% endblock main %}

View File

@@ -0,0 +1,332 @@
{% extends "layout.html" %}
{% from "macros/form_inputs.html" import
input_csrf_token
with context
%}
{% from "macros/general.html" import
display_subnav,
set_account_status_img,
set_account_activity_img,
set_forwarding_address_img,
set_alias_address_img,
set_assigned_groups_img,
set_user_admin_type_img,
highlight_username_in_mail,
display_progress_bar,
display_filter_by_first_char,
show_pages,
display_remove_mailbox_days
with context
%}
{% from "macros/msg_handlers.html" import user_msg_handler with context %}
{% block title %}{{ _('Mail Users') }}{% endblock %}
{% block navlinks_domains %}class="active"{% endblock %}
{% block breadcrumb %}
{% if all_are_admins %}
{% set crumbs = [
(ctx.homepath + '/domains', _('All domains')),
(ctx.homepath + '/profile/domain/general/' + cur_domain, cur_domain),
(ctx.homepath + '/users/' + cur_domain, _('Users')),
(ctx.homepath + '/mls/' + cur_domain, _('Mailing Lists')),
(ctx.homepath + '/aliases/' + cur_domain, _('Aliases')),
('active', ctx.homepath + '/admins/' + cur_domain, _('Admins')),
]
%}
{% else %}
{% set crumbs = [
(ctx.homepath + '/domains', _('All domains')),
(ctx.homepath + '/profile/domain/general/' + cur_domain, cur_domain),
('active', ctx.homepath + '/users/' + cur_domain, _('Users')),
(ctx.homepath + '/mls/' + cur_domain, _('Mailing Lists')),
(ctx.homepath + '/aliases/' + cur_domain, _('Aliases')),
] %}
{% if session.get('is_global_admin') %}
{% set crumbs = crumbs + [(ctx.homepath + '/admins/' + cur_domain, _('Admins'))] %}
{% endif %}
{% endif %}
{% if backend != "pgsql" %}
{% set crumbs = crumbs + [(ctx.homepath + '/users/' + cur_domain + '/last_logins', _('Last Logins'))] %}
{% endif %}
{{ display_subnav(crumbs) }}
{% endblock %}
{% block main %}
{# Show system message #}
{{ user_msg_handler(msg) }}
{% if users is defined %}
{% if users or (not users and first_char) %}
{% if all_are_admins %}
{{ display_filter_by_first_char(baseurl=ctx.homepath + '/admins/' + cur_domain,
first_char=first_char,
account_type='admin',
disabled_only=disabled_only) }}
{% else %}
{{ display_filter_by_first_char(baseurl=ctx.homepath + '/users/' + cur_domain,
available_chars=all_first_chars,
first_char=first_char,
account_type='user',
disabled_only=disabled_only) }}
{% endif %}
{% endif %}
{# List all users. #}
<div class="content-box">
<div class="box-body">
<div class="box-header clear">
<ul class="tabs clear">
<li><a href="{{ctx.homepath}}/create/user/{{cur_domain}}"><i class="fa fa-plus"></i> {{ _('User') }}</a>
<li><a href="{{ctx.homepath}}/create/ml/{{cur_domain}}"><i class="fa fa-plus"></i> {{ _('Mailing List') }}</a>
<li><a href="{{ctx.homepath}}/create/alias/{{cur_domain}}"><i class="fa fa-plus"></i> {{ _('Alias') }}</a>
</ul>
<h2>
{% if all_are_admins %}
{{ _('Admins under domain: %s') |format(cur_domain) }}
{% else %}
{{ _('Users under domain: %s') |format(cur_domain) }}
{% endif %}
{% if total is defined and users|length > 0 %}
({{ (cur_page-1) * page_size_limit + 1 }}-{{ (cur_page-1) * page_size_limit + users|length}}/{{ total }})
{% endif %}
<a href="{{ctx.homepath}}/profile/domain/general/{{cur_domain}}"><i class="fa fa-cog fa-lg" title="{{ _('Edit domain profile') }}"></i></a>
{{ set_account_activity_img('sent', 'domain', cur_domain, float=false) }}
</h2>
</div>
<div class="box-wrapper clear">
<div id="user_list">
<form name="form_users" id="account_list" method="post" action="{{ctx.homepath}}/users/{{cur_domain}}/page/{{ cur_page }}">
{# Control whether we should redirect to /admins/[domain] or /usrs/[domain] #}
{% if all_are_admins %}
<input type="hidden" name="redirect_to_admin_list" value="yes">
{% endif %}
{{ input_csrf_token() }}
<table class="style1">
<thead>
<tr>
<th class="checkbox"><input type="checkbox" class="checkbox select-all" /></th>
<th data-sort="string-ins"><a href="{{ctx.homepath}}/users/{{cur_domain}}?order_name=name&order_by={% if order_name == 'name' and not order_by_desc %}desc{% else %}asc{% endif %}">{{ _('Display Name') }}</a></th>
<th data-sort="string-ins">{{ _('Mail Address') }}</th>
<th data-sort="string-ins">{{ _('User/Employee ID') }}</th>
{#
<th data-sort="string-ins">{{ _('Job Title') }}</th>
#}
{% if all_are_admins %}
<th data-sort="int">{{ _('Quota') }}</th>
{% else %}
<th data-sort="int"><a href="{{ctx.homepath}}/users/{{cur_domain}}?order_name=quota&order_by={% if order_name == 'quota' and order_by_desc %}asc{% else %}desc{% endif %}">{{ _('Quota') }}</a></th>
{% endif %}
{% if last_logins %}
<th data-sort="int">
{{ _('Last Login') }}
{% if backend != "pgsql" %}
(<a href="{{ ctx.homepath }}/users/{{ cur_domain }}/last_logins">{{ _("All users") }}</a>)
{% endif %}
</th>
{% endif %}
</tr>
</thead>
<tbody>
{% if users %}
{% for r in users %}
{% set mail = r.username |e %}
<tr>
<td class="checkbox">
<input type="checkbox"
name="mail"
class="checkbox"
value="{{ mail }}"
alt="{% if r.active %}active{% else %}disabled{% endif %}"
{% if session.get('is_global_admin') %}
{% if mail == session.get('username') %}disabled="disabled"{% endif %}
{% else %}
{# Normal admin is NOT allowed to enable/disable/delete itself and global admin accounts. #}
{% if mail == session.get('username') or r.isglobaladmin == 1 %}disabled="disabled"{% endif %}
{% endif %}
/>
</td>
<td class="vcenter">
<a href="{{ctx.homepath}}/profile/user/general/{{mail}}">
<i class="fa fa-cog fa-lg fr-space" title="{{ _('Edit account profile') }}{% if r.passwordlastchange %}<br/>{{ _('Password last change:') }} {{ r.passwordlastchange | utc_to_timezone(timezone=session.get('timezone')) }}{% endif %}"></i>
</a>
{{ set_account_activity_img('sent', 'user', mail) }}
{{ set_account_status_img(r.active) }}
{% if r.isglobaladmin %}
{{ set_user_admin_type_img('globaladmin') }}
{% elif r.isadmin %}
{{ set_user_admin_type_img('domainadmin') }}
{% endif %}
{{ set_assigned_groups_img(addresses=user_assigned_groups.get(mail, [])) }}
{{ set_forwarding_address_img(user=mail, addresses=user_forwardings.get(mail, [])) }}
{{ set_alias_address_img(addresses=user_alias_addresses.get(mail, [])) }}
<a href="{{ctx.homepath}}/profile/user/general/{{mail}}" title="{{ _('Edit account profile') }}">{% if r.name %}{{ r.name |cut_string |e }}{% else %}{{ mail.split('@', 1)[0] }}{% endif %}</a>
</td>
<td class="vcenter">{{ highlight_username_in_mail(mail) }}</td>
<td class="vcenter">{% if r.employeeid %}{{ r.employeeid |e }}{% endif %}</td>
{# mail quota #}
{% set usedQuotaBytes = used_quotas.get(mail, {}).get('bytes', 0) %}
{% set usedQuotaMessages = used_quotas.get(mail, {}).get('messages', 0) %}
{% if r.quota == 0 %}
{% if session.get('show_used_quota') %}
<td class="vcenter" data-sort-value="0">{{ usedQuotaBytes |file_size_format }} / {{ _('Unlimited') }}</td>
{% else %}
<td class="vcenter" data-sort-value="0">{{ _('Unlimited') }}</td>
{% endif %}
{% else %}
{% set percent = usedQuotaBytes |convert_to_percentage(r.quota |int * 1024 * 1024) %}
<td class="vcenter" data-sort-value="{{ r.quota }}">
<div>
<span title="{{ _('Edit quota setting') }}"><a href="{{ctx.homepath}}/profile/user/general/{{mail}}">{{ percent }}%</a></span>
<span class="color-grey">(<span title="{{ _('Stored') }}">{{ usedQuotaMessages }} {{_('Emails') }} / {{ usedQuotaBytes |file_size_format }}</span>) / <span title="{{ _('Allocated') }}">{{ r.quota |file_size_format(base_mb=True) }}</span></span>
</div>
{{ display_progress_bar(percent, show_zero=true, width='60%', style='thin') }}
</td>
{% endif %}
{% if last_logins %}
{% if mail in last_logins %}
{% set _times = last_logins.get(mail, {}) %}
{% set _imap = _times.get('imap') or 0 %}
{% set _pop3 = _times.get('pop3') or 0 %}
{% set _lda = _times.get('lda') or 0 %}
{# imap or pop3 login time #}
{% set _login_time = 0 %}
{% set _login_service = None %}
{% if (_imap > 0) and (_pop3 > 0) %}
{% if _imap > _pop3 %}
{% set _login_time = _imap %}
{% set _login_service = 'imap' %}
{% else %}
{% set _login_time = _pop3 %}
{% set _login_service = 'pop3' %}
{% endif %}
{% elif _imap > 0 %}
{% set _login_time = _imap %}
{% set _login_service = 'imap' %}
{% elif _pop3 > 0 %}
{% set _login_time = _pop3 %}
{% set _login_service = 'pop3' %}
{% endif %}
<td data-sort-value="{{ _login_time }}">
{% if _login_time %}
<span title="{% if _imap %}{{ _('IMAP Login:') }} {{ _imap | epoch_seconds_to_gmt | utc_to_timezone(timezone=session.get('timezone')) }}<br/>{% endif %}{% if _pop3 %}{{ _('POP3 Login:') }} {{ _pop3 | epoch_seconds_to_gmt | utc_to_timezone(timezone=session.get('timezone')) }}<br/>{% endif %}{% if _lda %}{{ _('New Mail Delivered:') }} {{ _lda | epoch_seconds_to_gmt | utc_to_timezone(timezone=session.get('timezone')) }}{% endif %}">
{{ _login_time | epoch_seconds_to_gmt | utc_to_timezone(timezone=session.get('timezone')) }}
{% if _login_service %}
{{ _login_service | upper }}
{% endif %}
</span>
{% endif %}
</td>
{% else %}
<td data-sort-value="0"></td>
{% endif %}
{% endif %}
</tr>
{% endfor %}
{% else %}
<tr>
<td class="checkbox"></td>
{% if all_are_admins %}
<td colspan="4">{{ _('No mail admin assigned.') }}</td>
{% else %}
<td colspan="4">{{ _('No mail user available.') }}
{% if not (first_char or disabled_only) %}
<a href="{{ctx.homepath}}/create/user/{{ cur_domain }}">{{ _('Add one') }}</a>?
{% endif %}
</td>
{% endif %}
</tr>
{% endif %}
</tbody>
</table>
<input type="hidden" name="cur_page" value="{{cur_page}}" />
{% if users %}
<div class="tab-footer clear f1">
<div class="fl">
<select name="action" class="fl-space" id="account_list_actions" >
<option>{{ _('Choose Action') }}</option>
<option disabled>----</option>
<option value="enable">{{ _('Enable') }}</option>
<option value="disable">{{ _('Disable') }}</option>
<option value="delete">{{ _('Delete') }}</option>
<option disabled>----</option>
<option value="markasadmin">{{ _('Mark as domain admin') }}</option>
<option value="unmarkasadmin">{{ _('Unmark as domain admin') }}</option>
{% if session.get('is_global_admin') %}
<option disabled>----</option>
<option value="markasglobaladmin">{{ _('Mark as global admin') }}</option>
<option value="unmarkasglobaladmin">{{ _('Unmark as global admin') }}</option>
{% endif %}
</select>
<select name="keep_mailbox_days" class="fl-space" id="account_delete_date">
{% for _day in days_to_keep_removed_mailbox %}
<option value="{{ _day }}">{{ display_remove_mailbox_days(_day) }}</option>
{% endfor %}
</select>
<input type="submit" name="submit_users" value="{{ _('Apply') }}" class="button fl-space" />
</div>
{% if all_are_admins %}
{% set baseurl = ctx.homepath + '/admins/' + cur_domain %}
{% else %}
{% set baseurl = ctx.homepath + '/users/' + cur_domain %}
{% endif %}
{% if disabled_only %}
{% set baseurl = baseurl + '/disabled' %}
{% endif %}
{% if all_are_admins %}
{{ show_pages(baseurl=baseurl,
total=total,
cur_page=cur_page) }}
{% else %}
{{ show_pages(baseurl=baseurl,
total=total,
cur_page=cur_page,
url_suffix=ctx.query) }}
{% endif %}
</div>
{% endif %}
</form>
</div>{# #user_list #}
</div>{# .box-wrapper #}
</div>{# -- End id=user_list -- #}
</div>
{% endif %}
{% endblock main %}

View File

@@ -0,0 +1,606 @@
{% extends "layout.html" %}
{% from "macros/form_inputs.html" import
input_submit,
input_csrf_token
with context
%}
{% from "macros/general.html" import
display_subnav,
set_account_activity_img,
display_input_cn,
display_preferred_language,
display_timezones,
display_quota,
display_change_email_address,
display_input_employeeid,
display_account_status,
display_mark_user_as_admin,
display_reset_password,
display_random_password,
display_user_forwarding,
display_recipient_bcc,
display_sender_bcc,
display_relay,
display_sender_relayhost,
display_per_account_wblist_all,
display_allow_nets
with context
%}
{% from "macros/sql.html" import
display_enabled_user_services,
display_all_domains
with context
%}
{% from "macros/iredapd.html" import
display_throttle_setting,
display_greylisting_setting,
display_greylisting_whitelists
with context
%}
{% from "macros/amavisd.html" import display_spam_policy with context %}
{% from "macros/msg_handlers.html" import warning_info, user_msg_handler with context %}
{% block title %}{{ _('Edit account profile') }}{% endblock %}
{% block navlinks_domains %}class="active"{% endblock %}
{% block breadcrumb %}
{% set tmp_crumbs = [
(ctx.homepath + '/domains', _('All domains')),
(ctx.homepath + '/profile/domain/general/' + cur_domain, cur_domain),
(ctx.homepath + '/users/' + cur_domain, _('Users')),
('active', ctx.homepath + '/profile/user/general/' + mail, _('Profile of user:') + '&nbsp;' + mail),
(ctx.homepath + '/mls/' + cur_domain, _('Mailing Lists')),
(ctx.homepath + '/aliases/' + cur_domain, _('Aliases')),
] %}
{% if session.get('is_global_admin') %}
{% set crumbs = tmp_crumbs + [(ctx.homepath + '/admins/' + cur_domain, _('Admins'))] %}
{% else %}
{% set crumbs = tmp_crumbs %}
{% endif %}
{% if backend != "pgsql" %}
{% set crumbs = crumbs + [(ctx.homepath + '/users/' + cur_domain + '/last_logins', _('Last Logins'))] %}
{% endif %}
{{ display_subnav(crumbs) }}
{% endblock %}
{% block main %}
{# Show system message #}
{% if msg %}
{% if msg.startswith('PW_') %}
{% set _pw_errors = msg.split(',') %}
{% for _err in _pw_errors %}
{{ user_msg_handler(_err) }}
{% endfor %}
{% else %}
{{ user_msg_handler(msg) }}
{% endif %}
{% endif %}
{% if discarded_aliases %}
{% set _msg = _('Some addresses have been discarded because they have been used: %s.') |format(discarded_aliases | join(', ')) %}
{{ warning_info(msg=_msg, removable=true) }}
{% endif %}
{% if session.get('is_global_admin') %}
{% set navlinks = [
('general', _('General'), [true]),
('forwarding', _('Forwarding'), [true]),
('bcc', _('BCC'), [true]),
('relay', _('Relay'), [true]),
('aliases', _('Aliases'), [true]),
('throttle', _('Throttling'), [session.get('iredapd_enabled')]),
('greylisting', _('Greylisting'), [session.get('iredapd_enabled')]),
('wblist', _('White/Blacklists'), [session.get('amavisd_enable_policy_lookup')]),
('spampolicy', _('Spam Policy'), [session.get('amavisd_enable_policy_lookup')]),
('password', _('Password'), [true]),
('advanced', _('Advanced'), [true]),
]
%}
{% else %}
{% set navlinks = [
('general', _('General'), [true]),
('forwarding', _('Forwarding'), ['forwarding' not in disabled_user_profiles]),
('bcc', _('BCC'), ['bcc' not in disabled_user_profiles]),
('relay', _('Relay'), ['relay' not in disabled_user_profiles]),
('aliases', _('Aliases'), ['aliases' not in disabled_user_profiles]),
('throttle', _('Throttling'), ['throttle' not in disabled_user_profiles, session.get('iredapd_enabled')]),
('greylisting', _('Greylisting'), ['greylisting' not in disabled_user_profiles, session.get('iredapd_enabled')]),
('wblist', _('White/Blacklists'), [session.get('amavisd_enable_policy_lookup'), 'wblist' not in disabled_user_profiles]),
('spampolicy', _('Spam Policy'), [session.get('amavisd_enable_policy_lookup'), 'spampolicy' not in disabled_user_profiles]),
('password', _('Password'), [true]),
('advanced', _('Advanced'), [true]),
]
%}
{% endif %}
<div class="content-box">
<div class="box-body">
<div class="box-header clear">
<ul class="tabs clear">
{% for nav in navlinks %}
{% if not false in nav[2] and not none in nav[2] %}
<li><a href="#profile_{{nav[0]}}">{{ nav[1] }}</a></li>
{% endif %}
{% endfor %}
</ul>
<h2>{{ set_account_activity_img('sent', 'user', mail, float=false) }}</h2>
</div>
{# modal window used to change email address #}
{{ display_change_email_address(current_domain=cur_domain,
post_url=ctx.homepath + '/profile/user/rename/' + mail ) }}
<div class="box-wrap clear">
<div id="profile_general">
<form name="general" method="post" action="{{ctx.homepath}}/profile/user/general/{{mail}}">
{{ input_csrf_token() }}
{# imap or pop3 login time #}
{% set _login_time = 0 %}
{% set _login_service = None %}
{% set _times = last_logins.get(mail, {}) %}
{# values may be None, so we use `or 0` to set it to `0` #}
{% set _imap = _times.get('imap', 0) or 0 %}
{% set _pop3 = _times.get('pop3', 0) or 0 %}
{% set _lda = _times.get('lda', 0) or 0 %}
{% if (_imap > 0) and (_pop3 > 0) %}
{% if _imap > _pop3 %}
{% set _login_time = _imap %}
{% set _login_service = 'imap' %}
{% else %}
{% set _login_time = _pop3 %}
{% set _login_service = 'pop3' %}
{% endif %}
{% elif _imap > 0 %}
{% set _login_time = _imap %}
{% set _login_service = 'imap' %}
{% elif _pop3 > 0 %}
{% set _login_time = _pop3 %}
{% set _login_service = 'pop3' %}
{% endif %}
<div class="columns clear">
<div class="col2-3">
{{ display_account_status(profile.active,
last_login_epoch_seconds=_login_time,
last_login_service=_login_service) }}
<div class="bt-space10"></div>
{{ display_input_cn(value=profile.name, email=mail, empty_if_equal_to_username=true) }}
{% set stored_mailbox_size = used_quota.get(mail, {}).get('bytes', 0) %}
{% set stored_mailbox_messages = used_quota.get(mail, {}).get('messages', 0) %}
{{ display_quota(value=profile.quota,
show_value_in_input=true,
used_quota=stored_mailbox_size,
stored_messages=stored_mailbox_messages,
show_used_quota=true) }}
{{ display_preferred_language(value=profile.get('language'), languagemaps=languagemaps) }}
{{ display_timezones(value=user_settings.get('timezone'), timezones=timezones) }}
<div class="bt-space10"></div>
{{ display_input_employeeid(profile.employeeid) }}
</div>{#-- .col2-3 --#}
<div class="col1-3 lastcol">
{% if _login_time or _lda %}
<div class="mark_blue bt-space10">
<ul class="standard clean-padding bt-space10">
{% if _imap %}
<li class="bt-space5">{{ _('IMAP Login:') }} {{ _imap | epoch_seconds_to_gmt | utc_to_timezone(timezone=session.get('timezone')) }}</li>
{% endif %}
{% if _pop3 %}
<li class="bt-space5">{{ _('POP3 Login:') }} {{ _pop3 | epoch_seconds_to_gmt | utc_to_timezone(timezone=session.get('timezone')) }}</li>
{% endif %}
{% if _lda %}
<li class="bt-space5">{{ _('New Mail Delivered:') }} {{ _lda | epoch_seconds_to_gmt | utc_to_timezone(timezone=session.get('timezone')) }}</li>
{% endif %}
</ul>
</div>
{% endif %}
<div class="mark_blue bt-space10">
<ul class="standard clean-padding bt-space10">
<li><a href="#change_email_address" class="modal-link"><span class="text">{{ _('Change email address') }}</span></a></li>
<li class="bt-space5">{{ _('You can enable self-service (per-domain setting) to allow users to manage their own preferences and more.') }}</li>
</ul>
</div>
</div>{# .col1-3 #}
</div>{#-- .columns --#}
<div class="rule"></div>
<div class="columns clear">
<div class="col2-3">
<div class="form-field clear">
<h4 class="size-250 fl-space">{{ _('Member of Mailing Lists') }}</h4>
<div class="checklist clear">
<fieldset>
{% for ml_profile in all_maillist_profiles %}
{% set ml_mail = ml_profile.address |e %}
{% set ml_name = ml_profile.name |e %}
<div class="checklist-item">
<span class="fl-space">
<input type="checkbox" name="subscribed_list" value="{{ ml_mail }}" {% if ml_mail in all_subscribed_lists %}checked="checked"{% endif %} />
</span>
<label>
{%- if ml_name -%}
<a href="{{ctx.homepath}}/profile/ml/general/{{ ml_mail }}">{{ ml_name }}</a>&nbsp;({{ ml_mail }})
{%- else -%}
<a href="{{ctx.homepath}}/profile/ml/general/{{ ml_mail }}">{{ ml_mail }}</a>
{%- endif -%}
</label>
</div>
<div class="clear"></div>
{% endfor %}
</fieldset>
</div>{#-- .checklist --#}
</div>{#-- form-field --#}
</div>{#-- End col2-3 -- #}
<div class="col1-3 lastcol">
<div class="mark_blue bt-space10">
<ul class="standard clean-padding bt-space10">
<li class="bt-space5"><a href="{{ctx.homepath}}/create/ml/{{ cur_domain }}">{{ _('Add mailing list') }}</a></li>
</ul>
</div>
</div>{# .col1-3 #}
</div>{#-- .columns --#}
<div class="rule"></div>
<div class="columns clear">
<div class="col2-3">
<div class="form-field clear">
<h4 class="size-250 fl-space">{{ _('Member of Mail Aliases') }}</h4>
<div class="checklist clear">
<fieldset>
{% for _profile in all_aliases %}
{% set _name = _profile.name |e %}
{% set _mail = _profile.address |e %}
<div class="checklist-item">
<span class="fl-space">
<input type="checkbox" name="memberOfGroup" value="{{ _mail }}" {% if _mail in assigned_aliases %}checked="checked"{% endif %} />
</span>
<label><a href="{{ctx.homepath}}/profile/alias/general/{{ _mail }}">{{ _name }}</a>&nbsp;({{ _mail }})</label>
</div>
<div class="clear"></div>
{% endfor %}
{# Display assigned aliases which is not in same domain as current user #}
{% for _mail in assigned_aliases %}
{% if not _mail.endswith('@' + cur_domain) %}
<div class="checklist-item">
<span class="fl-space">
<input type="checkbox" name="memberOfGroup" value="{{ _mail }}" checked="checked" />
</span>
<label><a href="{{ctx.homepath}}/profile/alias/general/{{ _mail }}">{{ _mail }}</a></label>
</div>
<div class="clear"></div>
{% endif %}
{% endfor %}
</fieldset>
</div>{#-- .checklist --#}
</div>{#-- form-field --#}
</div>{#-- End col2-3 -- #}
<div class="col1-3 lastcol">
<div class="mark_blue bt-space10">
<ul class="standard clean-padding bt-space10">
<li class="bt-space5"><a href="{{ctx.homepath}}/create/alias/{{ cur_domain }}">{{ _('Add mail alias') }}</a></li>
</ul>
</div>
</div>{# .col1-3 #}
</div>{#-- .columns --#}
{% if session.get('is_global_admin') or session.get('allowed_to_grant_admin') %}
<div class="rule"></div>
<div class="columns clear">
<div class="col2-3">
{{ display_mark_user_as_admin(is_domain_admin=profile.get('isadmin', 0),
is_global_admin=profile.get('isglobaladmin', 0),
allowed_to_grant_admin=user_settings.get('grant_admin', 'no'),
user_settings=user_settings) }}
</div>
{% if session.get('is_global_admin') %}
<div class="col1-3 lastcol normal_admin_options">
<div class="mark_blue bt-space10">
<ul class="standard clean-padding bt-space10">
<li>{{ _('All domains managed by this admin share the mailbox quota and limit of mail accounts.') }}</li>
<li>{{ _('Domain ownership verification is recommended if you can not fully trust this admin, because if domains like gmail.com, hotmail.com were added locally, all emails sent to gmail.com/hotmail.com will be delivered locally on your server instead of the real Gmail/Hotmail servers.') }}</li>
</ul>
</div>
</div>{# .col1-3 #}
{% endif %}
</div>
{{ display_all_domains(managedDomains=managed_domains, allDomains=all_domains) }}
{% endif %}
{{ input_submit() }}
</form>
</div>{# #profile_general #}
{# profile_type == 'forwarding' #}
{% if session.get('is_global_admin') or 'forwarding' not in disabled_user_profiles %}
<div id="profile_forwarding">
<form name="forwarding" method="post" action="{{ctx.homepath}}/profile/user/forwarding/{{mail}}">
{{ input_csrf_token() }}
{{ display_user_forwarding(mail=mail,
enabled=none,
forwarding_addresses=profile.forwardings) }}
{{ input_submit() }}
</form>
</div>{# #profile_forwarding #}
{% endif %}
{# profile_type: bcc #}
{% if session.get('is_global_admin') or 'bcc' not in disabled_user_profiles %}
<div id="profile_bcc">
<form name="bcc" method="post" action="{{ctx.homepath}}/profile/user/bcc/{{mail}}">
{{ input_csrf_token() }}
{# BCC #}
<div class="columns clear">
<div class="col2-3 ">
<div class="form-field clear">
<h4 class="size-250 fl-space">{{ _('Monitor incoming emails via BCC') }}</h4>
<div class="clear">
<input type="checkbox"
name="recipientbcc"
class="checkbox"
rel="checkboxhorizont"
{% if profile.rbcc_active in [1, '1'] %}checked="checked"{%endif%}
/>
</div>
</div>
<div class="form-field clear">
<h4 class="size-250 fl-space">{{ _('Monitor outgoing emails via BCC') }}</h4>
<div class="clear">
<input type="checkbox"
name="senderbcc"
{% if profile.sbcc_active in [1, '1'] %}checked="checked"{%endif%}
class="checkbox"
rel="checkboxhorizont"
/>
</div>
</div>
{{ display_recipient_bcc(address=profile.recipient_bcc_address) }}
{{ display_sender_bcc(address=profile.sender_bcc_address) }}
</div>
<div class="col1-3 lastcol">
<div class="mark_blue bt-space10">
<ul class="standard clean-padding bt-space10">
<li class="bt-space5">{{ _('Multiple addresses are NOT supported.') }}</li>
<li class="bt-space5">{{ _('Per-user bcc settings has higher priority than per-domain bcc settings.') }}</li>
<li class="bt-space5">{{ _('Invalid email addresses will be silently discarded.') }}</li>
</ul>
</div>
</div>{#-- .col1-3 --#}
</div>
{{ input_submit() }}
</form>
</div>
{% endif %}
{# Relay #}
{% if session.get('is_global_admin') or 'relay' not in disabled_user_profiles %}
<div id="profile_relay">
<form name="relay" method="post" action="{{ctx.homepath}}/profile/user/relay/{{mail}}">
{{ input_csrf_token() }}
{{ display_relay(profile.transport |default('') |e,
account_type='user',
url=ctx.homepath + '/profile/domain/relay/' + cur_domain) }}
<div class="rule"></div>
{{ display_sender_relayhost(relayhost=relayhost) }}
{{ input_submit() }}
</form>
</div>
{% endif %}
{# Aliases #}
{% if session.get('is_global_admin') or 'aliases' not in disabled_user_profiles %}
<div id="profile_aliases">
<form name="aliases" method="post" action="{{ctx.homepath}}/profile/user/aliases/{{mail}}">
{{ input_csrf_token() }}
<div class="columns clear">
<div class="col2-3">
<div class="form-field clear">
<h4 class="size-250 fl-space">{{ _('Email addresses of alias accounts') }}</h4>
<small>{{ _('One mail address per line. Invalid address will be discarded.') }}</small>
</div>
<div class="form-field clear">
<h4 class="size-250 fl-space"></h4>
<textarea name="user_alias_addresses"
rows="6"
style="width: 50%"
class="textarea"
>{%- for addr in user_alias_addresses %}{{ addr |e }}
{% endfor -%}
</textarea>
</div>
</div>{#-- .col2-3 --#}
<div class="col1-3 lastcol">
<div class="mark_blue bt-space10">
<ul class="standard clean-padding bt-space10">
<li class="bt-space5">{{ _('Emails sent to alias addresses will be delivered to %s.') |format('<strong>' + mail + '</strong>') }}</li>
{% if user_alias_cross_all_domains is sameas false %}
<li class="bt-space5">{{ _('Email address of alias account must end with domain name(s): %s.') |format('<strong>' + cur_domain + '</strong>') }}</li>
{% endif %}
</ul>
</div>
</div>
</div>{#-- .columns --#}
{{ input_submit() }}
</form>
</div>
{% endif %}
{# Throttling #}
{% if session.get('iredapd_enabled') and (session.get('is_global_admin') or ('throttle' not in disabled_user_profiles)) %}
<div id="profile_throttle">
<form name="throttle" method="post" action="{{ctx.homepath}}/profile/user/throttle/{{mail}}">
{{ input_csrf_token() }}
{# Throttling in iRedAPD#}
<div class="columns clear">
{{ display_throttle_setting(account=mail,
setting=outbound_throttle_setting,
inout_type='outbound') }}
{{ display_throttle_setting(account=mail,
setting=inbound_throttle_setting,
inout_type='inbound',
with_left_border=true) }}
<div class="col1-3 lastcol">
<div class="mark_blue bt-space10">
<ul class="standard clean-padding bt-space10">
<li class="bt-space5">{{ _('You can set per-domain throttling in domain profile page.') }}</li>
</ul>
</div>
</div>{#-- .col1-3 --#}
</div>{# .columns #}
{{ input_submit() }}
</form>
</div>{# #profile_throttle #}
{% endif %}
{# profile_type: greylisting, with iRedAPD #}
{% if 'greylisting' not in disabled_user_profiles %}
{% if session.get('iredapd_enabled') %}
<div id="profile_greylisting">
<form name="greylisting" method="post" action="{{ctx.homepath}}/profile/user/greylisting/{{mail}}">
{{ input_csrf_token() }}
{{ display_greylisting_setting(account=mail, gl_setting=gl_setting) }}
{{ display_greylisting_whitelists(account=mail, gl_whitelists=gl_whitelists) }}
{{ input_submit() }}
</form>
</div>
{% endif %}
{% endif %}
{# wblist #}
{% if session.get('amavisd_enable_policy_lookup') and (session.get('is_global_admin') or ('wblist' not in disabled_user_profiles)) %}
<div id="profile_wblist">
<form name="wblist" method="post" action="{{ctx.homepath}}/profile/user/wblist/{{mail}}">
{{ input_csrf_token() }}
{{ display_per_account_wblist_all(inbound_whitelists=whitelists,
inbound_blacklists=blacklists,
outbound_whitelists=outbound_whitelists,
outbound_blacklists=outbound_blacklists) }}
{{ input_submit() }}
</form>
</div>
{% endif %}
{# Spam Policy#}
{% if session.get('amavisd_enable_policy_lookup') and (session.get('is_global_admin') or ('spampolicy' not in disabled_user_profiles)) %}
<div id="profile_spampolicy">
<form name="spampolicy" method="post" action="{{ctx.homepath}}/profile/user/spampolicy/{{mail}}">
{{ input_csrf_token() }}
<div class="columns clear">
{{ display_spam_policy(account_type='user',
spampolicy=spampolicy,
custom_ban_rules=custom_ban_rules,
global_spam_score=global_spam_score) }}
{{ input_submit() }}
</div>
</form>
</div>
{% endif %}
{# Password #}
<div id="profile_password">
<form name="password" method="post" action="{{ctx.homepath}}/profile/user/password/{{mail}}">
{{ input_csrf_token() }}
<div class="columns clear">
<div class="col3-4">
{{ display_reset_password(show_confirmpw=true,
min_passwd_length=min_passwd_length,
max_passwd_length=max_passwd_length,
store_password_in_plain_text=store_password_in_plain_text) }}
</div>
<div class="col1-4 lastcol">
{{ display_random_password(password_length=min_passwd_length,
password_policies=password_policies,
password_last_change_date=profile.passwordlastchange) }}
</div>
</div>
{{ input_submit() }}
</form>
</div>
<div id="profile_advanced">
<form name="advanced" method="post" action="{{ctx.homepath}}/profile/user/advanced/{{mail}}">
{{ input_csrf_token() }}
{{ display_enabled_user_services(profile=profile, greylisted=greylisted) }}
<div class="rule"></div>
{{ display_allow_nets(allow_nets=allow_nets) }}
<div class="rule"></div>
{% if session.get('is_global_admin') %}
{# Maildir path #}
<div class="form-field clear">
<h4 class="size-250 fl-space">{{ _('Path to mailbox') }}</h4>
<input type="text" name="storageBaseDirectory" value="{{ profile.storagebasedirectory |default('') |e }}" size="{{ storageBaseDirectory |length}}" class="fl-space text" />
<span class="vcenter">/</span>
<input type="text" name="storageNode" value="{{ profile.storagenode |default('') |e }}" />
<span class="vcenter">/</span>
<input type="text" name="mailMessageStore" value="{{ profile.maildir |default('') }}" size="{{ profile.maildir |length }}" class="text" />
</div>
{% endif %}
{{ input_submit() }}
</form>
</div>
</div>
</div>
</div>
{% endblock main %}
{% block extra_js %}
<script type="text/javascript">
$(document).ready(function() {
$(".tabs li").idTabs("profile_{{ profile_type }}");
$('#domain_search').quickfilter('#all_domains tr');
});
</script>
{% endblock extra_js %}