745 lines
40 KiB
HTML
745 lines
40 KiB
HTML
<!-- Modal subscription -->
|
|
<div class="modal fade" id="subscriptionRequiredModal" tabindex="-1" role="dialog">
|
|
<div class="modal-dialog">
|
|
<div class="modal-content">
|
|
<div class="modal-header">
|
|
<h4 class="modal-title">Subscription required</h4>
|
|
</div>
|
|
<div class="modal-body">
|
|
<p>To add more mailboxes, please setup a paid plain.</p>
|
|
</div>
|
|
<div class="modal-footer">
|
|
<button type="button" class="btn btn-default" data-dismiss="modal">Cancel</button>
|
|
<button type="button" class="btn btn-success" ng-click="openSubscriptionSetup()">Setup Subscription</button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Modal enable email -->
|
|
<div class="modal fade" id="enableEmailModal" tabindex="-1" role="dialog">
|
|
<div class="modal-dialog">
|
|
<div class="modal-content">
|
|
<div class="modal-header">
|
|
<h4 class="modal-title">Enable Email for {{domain.domain}}?</h4>
|
|
</div>
|
|
<div class="modal-body">
|
|
<div>This will configure Cloudron to receive emails for <b>{{domain.domain}}</b>. See the
|
|
documentation for opening up the <a ng-href="https://docs.cloudron.io/email/#required-ports" target="_blank">required ports</a>
|
|
for Cloudron Email.
|
|
</div>
|
|
<br/>
|
|
|
|
<div ng-show="domain.provider === 'noop' || domain.provider === 'manual'">
|
|
No DNS provider is setup. The DNS records listed in the Status tab have to be setup manually.<br/><br/>
|
|
</div>
|
|
<div class="text-danger" ng-show="adminDomain.provider === 'cloudflare'">
|
|
The domain <code>{{ config.adminDomain }}</code> is managed by Cloudflare.
|
|
Please verify that Cloudflare proxying is disabled for <code>{{ config.mailFqdn }}</code> and set to <code>DNS only</code>.
|
|
This is required because Cloudflare does not proxy email.<br/><br/>
|
|
</div>
|
|
|
|
<div ng-hide="domain.provider === 'noop' || domain.provider === 'manual'">
|
|
<p>
|
|
<label class="control-label">
|
|
<input type="checkbox" ng-model="incomingEmail.setupDns"> Setup Mail DNS records now
|
|
</label>
|
|
</p>
|
|
|
|
Use this option to automatically setup Email related DNS records. Leaving this option unchecked
|
|
is useful for creating mail boxes and <a ng-href="https://docs.cloudron.io/email/#import-email">importing email</a>
|
|
before going live.
|
|
</div>
|
|
</div>
|
|
<div class="modal-footer">
|
|
<button type="button" class="btn btn-default" data-dismiss="modal">Cancel</button>
|
|
<button type="button" class="btn btn-success" ng-click="incomingEmail.enable()">Enable</button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Modal disable email -->
|
|
<div class="modal fade" id="disableEmailModal" tabindex="-1" role="dialog">
|
|
<div class="modal-dialog">
|
|
<div class="modal-content">
|
|
<div class="modal-header">
|
|
<h4 class="modal-title">Disable Email Server for {{domain.domain}}?</h4>
|
|
</div>
|
|
<div class="modal-body">
|
|
<div>This will configure Cloudron to stop receiving emails for <b>{{domain.domain}}</b>. Mailboxes and lists associated with this
|
|
domain will not be deleted.
|
|
</div>
|
|
<br/>
|
|
</div>
|
|
<div class="modal-footer">
|
|
<button type="button" class="btn btn-default" data-dismiss="modal">Cancel</button>
|
|
<button type="button" class="btn btn-danger" ng-click="incomingEmail.disable()">Disable</button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Modal add mailbox -->
|
|
<div class="modal fade" id="mailboxAddModal" tabindex="-1" role="dialog">
|
|
<div class="modal-dialog">
|
|
<div class="modal-content">
|
|
<div class="modal-header">
|
|
<h4 class="modal-title">Add Mailbox</h4>
|
|
</div>
|
|
<div class="modal-body">
|
|
<form name="mailboxadd_form" role="form" ng-submit="mailboxes.add.submit()" autocomplete="off">
|
|
<input type="password" style="display: none;">
|
|
<div class="form-group" ng-class="{ 'has-error': mailboxes.add.error }">
|
|
<label class="control-label">Name</label>
|
|
<div class="control-label" ng-show="mailboxes.add.error">
|
|
<small>{{ mailboxes.add.error.message }}</small>
|
|
</div>
|
|
<div class="input-group form-inline" style="margin-top: 10px;">
|
|
<input type="text" class="form-control" ng-model="mailboxes.add.name" placeholder="Name" required autofocus autocomplete="off"/>
|
|
<div class="input-group-addon">@{{ domain.domain }}</div>
|
|
</div>
|
|
</div>
|
|
<div class="form-group">
|
|
<label class="control-label">Mailbox Owner</label>
|
|
<select class="form-control" ng-model="mailboxes.add.owner" ng-options="u.display for u in users track by u.id" required></select>
|
|
</div>
|
|
<input class="hide" type="submit" ng-disabled="mailboxadd_form.$invalid || mailboxes.add.busy"/>
|
|
</form>
|
|
</div>
|
|
<div class="modal-footer">
|
|
<button type="button" class="btn btn-default" data-dismiss="modal">Cancel</button>
|
|
<button type="button" class="btn btn-success" ng-click="mailboxes.add.submit()" ng-disabled="mailboxadd_form.$invalid || mailboxes.add.busy"><i class="fa fa-circle-notch fa-spin" ng-show="mailboxes.add.busy"></i> Save</button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Modal edit mailbox -->
|
|
<div class="modal fade" id="mailboxEditModal" tabindex="-1" role="dialog">
|
|
<div class="modal-dialog">
|
|
<div class="modal-content">
|
|
<div class="modal-header">
|
|
<h4 class="modal-title">Edit mailbox {{ mailboxes.edit.name }}@{{domain.domain}}</h4>
|
|
</div>
|
|
<div class="modal-body">
|
|
<form name="mailboxedit_form" role="form" ng-submit="mailboxes.edit.submit()" autocomplete="off">
|
|
<input type="password" style="display: none;">
|
|
<div class="form-group">
|
|
<label class="control-label">Mailbox Owner</label>
|
|
<select class="form-control" ng-model="mailboxes.edit.owner" ng-options="u.display for u in users track by u.id" autofocus></select>
|
|
</div>
|
|
|
|
<div class="form-group aliases">
|
|
<label class="control-label">Aliases</label>
|
|
<div class="has-error" ng-show="mailboxes.edit.error">{{ mailboxes.edit.error.message }}</div>
|
|
|
|
<div class="row" ng-repeat="alias in mailboxes.edit.aliases">
|
|
<div class="col col-lg-11">
|
|
<div class="input-group">
|
|
<input type="text" class="form-control" ng-model="alias.name">
|
|
|
|
<div class="input-group-btn">
|
|
<button type="button" class="btn btn-default dropdown-toggle" data-toggle="dropdown">
|
|
<span>{{ alias.domain }}</span>
|
|
<span class="caret"></span>
|
|
</button>
|
|
<ul class="dropdown-menu dropdown-menu-right" role="menu">
|
|
<li ng-repeat="incomingDomain in incomingDomains">
|
|
<a href="" ng-click="alias.domain = incomingDomain.domain">{{ incomingDomain.domain }}</a>
|
|
</li>
|
|
</ul>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="col col-lg-1">
|
|
<button class="btn btn-danger btn-sm" ng-click="mailboxes.edit.delAlias($event, $index)"><i class="far fa-trash-alt"></i></button>
|
|
</div>
|
|
</div>
|
|
<div ng-show="mailboxes.edit.aliases.length === 0">
|
|
No aliases are configured. <a href="" ng-click="mailboxes.edit.addAlias($event)">Add an alias</a>
|
|
</div>
|
|
<div ng-show="mailboxes.edit.aliases.length > 0" style="margin-top: 5px;">
|
|
<a href="" ng-click="mailboxes.edit.addAlias($event)">Add another alias</a>
|
|
</div>
|
|
</div>
|
|
|
|
<input class="hide" type="submit" ng-disabled="mailboxedit_form.$invalid || mailboxes.edit.busy || !mailboxes.edit.owner"/>
|
|
</form>
|
|
</div>
|
|
<div class="modal-footer">
|
|
<button type="button" class="btn btn-default" data-dismiss="modal">Cancel</button>
|
|
<button type="button" class="btn btn-success" ng-click="mailboxes.edit.submit()" ng-disabled="mailboxedit_form.$invalid || mailboxes.edit.busy || !mailboxes.edit.owner"><i class="fa fa-circle-notch fa-spin" ng-show="mailboxes.edit.busy"></i> Save</button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Modal remove mailbox -->
|
|
<div class="modal fade" id="mailboxRemoveModal" tabindex="-1" role="dialog">
|
|
<div class="modal-dialog">
|
|
<div class="modal-content">
|
|
<div class="modal-header">
|
|
<h4 class="modal-title">Delete mailbox {{ mailboxes.remove.mailbox.name }}@{{domain.domain}}</h4>
|
|
</div>
|
|
<div class="modal-body">
|
|
<p style="margin-bottom: 30px">After deletion, emails to this mailbox will bounce. You can choose to not delete emails in this mailbox for archival purposes. Archived emails are located
|
|
at <code>/home/yellowtent/boxdata/mail/vmail</code> on the server.
|
|
</p>
|
|
<p class="checkbox">
|
|
<label>
|
|
<input type="checkbox" ng-model="mailboxes.remove.deleteMails">Delete all mails & filters inside this mailbox</input>
|
|
</label>
|
|
</p>
|
|
</div>
|
|
<div class="modal-footer">
|
|
<button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
|
|
<button type="button" class="btn btn-danger" ng-click="mailboxes.remove.submit()" ng-disabled="mailboxes.remove.busy"><i class="fa fa-circle-notch fa-spin" ng-show="mailboxes.remove.busy"></i> Delete</button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Modal add mailinglist -->
|
|
<div class="modal fade" id="mailinglistAddModal" tabindex="-1" role="dialog">
|
|
<div class="modal-dialog">
|
|
<div class="modal-content">
|
|
<div class="modal-header">
|
|
<h4 class="modal-title">Add Mailing list</h4>
|
|
</div>
|
|
<div class="modal-body">
|
|
<form name="mailinglistadd_form" role="form" ng-submit="mailinglists.add.submit()" autocomplete="off">
|
|
<input type="password" style="display: none;">
|
|
<div class="form-group" ng-class="{ 'has-error': mailinglists.add.error.name }">
|
|
<label class="control-label">Name</label>
|
|
<div class="control-label" ng-show="mailinglists.add.error.name"><small>{{ mailinglists.add.error.name }}</small></div>
|
|
<div class="input-group form-inline" style="margin-top: 10px;">
|
|
<input type="text" class="form-control" ng-model="mailinglists.add.name" placeholder="Name" required autofocus autocomplete="off"/>
|
|
<div class="input-group-addon">@{{ domain.domain }}</div>
|
|
</div>
|
|
</div>
|
|
<div class="form-group">
|
|
<label class="control-label">List Members</label><br/>
|
|
<div class="has-error control-label" ng-show="mailinglists.add.error.members"><small>{{ mailinglists.add.error.members }}</small></div>
|
|
<textarea ng-model="mailinglists.add.membersTxt" class="form-control" rows="5"></textarea>
|
|
<small>Separate email addresses with a newline</small>
|
|
</div>
|
|
<div class="checkbox">
|
|
<label>
|
|
<input type="checkbox" ng-model="mailinglists.add.membersOnly">Restrict posting to members only</input>
|
|
</label>
|
|
</div>
|
|
<input class="hide" type="submit" ng-disabled="mailinglistadd_form.$invalid || mailinglists.add.membersTxt.length === 0 || mailinglists.add.busy"/>
|
|
</form>
|
|
</div>
|
|
<div class="modal-footer">
|
|
<button type="button" class="btn btn-default" data-dismiss="modal">Cancel</button>
|
|
<button type="button" class="btn btn-success" ng-click="mailinglists.add.submit()" ng-disabled="mailinglistadd_form.$invalid || mailinglists.add.membersTxt.length === 0 || mailinglists.add.busy"><i class="fa fa-circle-notch fa-spin" ng-show="mailinglists.add.busy"></i> Save</button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Modal edit mailinglist -->
|
|
<div class="modal fade" id="mailinglistEditModal" tabindex="-1" role="dialog">
|
|
<div class="modal-dialog">
|
|
<div class="modal-content">
|
|
<div class="modal-header">
|
|
<h4 class="modal-title">Edit Mailing list {{ mailinglists.edit.name }}@{{domain.domain}}</h4>
|
|
</div>
|
|
<div class="modal-body">
|
|
<form name="mailinglistedit_form" role="form" ng-submit="mailinglists.edit.submit()" autocomplete="off">
|
|
<input type="password" style="display: none;">
|
|
<div class="form-group" ng-class="{ 'has-error': mailinglists.edit.error.members }">
|
|
<label class="control-label">List Members</label><br/>
|
|
<div class="has-error control-label" ng-show="mailinglists.edit.error.members"><small>{{ mailinglists.edit.error.members }}</small></div>
|
|
<textarea ng-model="mailinglists.edit.membersTxt" class="form-control" rows="5"></textarea>
|
|
<small>Separate email addresses with a newline</small>
|
|
</div>
|
|
<div class="checkbox">
|
|
<label>
|
|
<input type="checkbox" ng-model="mailinglists.edit.membersOnly">Restrict posting to members only</input>
|
|
</label>
|
|
</div>
|
|
<input class="hide" type="submit" ng-disabled="mailinglistedit_form.$invalid || mailinglists.edit.busy"/>
|
|
</form>
|
|
</div>
|
|
<div class="modal-footer">
|
|
<button type="button" class="btn btn-default" data-dismiss="modal">Cancel</button>
|
|
<button type="button" class="btn btn-success" ng-click="mailinglists.edit.submit()" ng-disabled="mailinglistedit_form.$invalid || mailinglists.edit.busy"><i class="fa fa-circle-notch fa-spin" ng-show="mailinglists.edit.busy"></i> Save</button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Modal remove mailinglist -->
|
|
<div class="modal fade" id="mailinglistRemoveModal" tabindex="-1" role="dialog">
|
|
<div class="modal-dialog">
|
|
<div class="modal-content">
|
|
<div class="modal-header">
|
|
<h4 class="modal-title">Delete mailing list {{ mailinglists.remove.list.name }}@{{domain.domain}}</h4>
|
|
</div>
|
|
<div class="modal-body">
|
|
<p>Really delete mailinglist <b>{{ mailinglists.remove.list.name }}@{{domain.domain}}</b>?</p>
|
|
</div>
|
|
<div class="modal-footer">
|
|
<button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
|
|
<button type="button" class="btn btn-danger" ng-click="mailinglists.remove.submit()" ng-disabled="mailinglists.remove.busy"><i class="fa fa-circle-notch fa-spin" ng-show="mailinglist.remove.busy"></i> Delete</button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div ng-show="!ready" class="loading-banner">
|
|
<h1><i class="fa fa-circle-notch fa-spin"></i></h1>
|
|
</div>
|
|
|
|
<div class="content" ng-show="ready">
|
|
<a href="/#/email" class="back-to-view-link"><i class="fas fa-arrow-left"></i> Back to Email</a>
|
|
|
|
<br/>
|
|
|
|
<div class="text-left">
|
|
<h3>
|
|
Email configuration <b>{{ domain.domain }}</b>
|
|
</h3>
|
|
</div>
|
|
|
|
<br/>
|
|
|
|
<uib-tabset>
|
|
<uib-tab index="0" heading="Mailboxes">
|
|
<div class="card card-large" style="margin-bottom: 15px;">
|
|
<h4>Incoming Email</h4>
|
|
|
|
<div class="row">
|
|
<div class="col-md-10">
|
|
Cloudron <a ng-href="https://docs.cloudron.io/email/" target="_blank">Email Server</a> allows users to receive email for this domain.
|
|
<a href="/#/appstore/net.rainloop.cloudronapp">Rainloop</a>, <a href="/#/appstore/nu.sogo.cloudronapp2">SOGo</a>,
|
|
<a href="/#/appstore/net.roundcube.cloudronapp">Roundcube</a> are pre-configured to access Cloudron Email. Use <a href="" data-toggle="collapse" data-parent="#accordion" data-target="#mail_settings">these settings</a>
|
|
to configure other email clients.
|
|
</div>
|
|
<div class="col-md-2">
|
|
<button ng-class="domain.mailConfig.enabled ? 'btn btn-danger' : 'btn btn-primary'" ng-click="domain.provider !== 'caas' && incomingEmail.toggleEmailEnabled()" ng-disabled="domain.provider === 'caas' || incomingEmail.busy">
|
|
<i class="fa fa-circle-notch fa-spin" ng-show="incomingEmail.busy"></i>
|
|
{{ domain.mailConfig.enabled ? "Disable" : "Enable" }}
|
|
</button>
|
|
</div>
|
|
<div class="col-md-12" ng-show="domain.provider === 'caas'">
|
|
<br/>
|
|
<span class="text-danger text-bold">This feature is only available for custom domains.</span>
|
|
</div>
|
|
</div>
|
|
<div class="row">
|
|
<div class="col-md-12">
|
|
<div id="mail_settings" class="panel-collapse collapse">
|
|
<br/>
|
|
<p><b>Incoming Mail (IMAP)</b><br/>Server: <span ng-click-select>{{config.mailFqdn}}</span><br/>Port: 993 (TLS)</p>
|
|
<p><b>Outgoing Mail (SMTP)</b><br/>Server: <span ng-click-select>{{config.mailFqdn}}</span><br/>Port: 587 (STARTTLS)</p>
|
|
<p><b>ManageSieve</b><br/>Server: <span ng-click-select>{{config.mailFqdn}}</span><br/>Port: 4190 (STARTTLS)</p>
|
|
<p>Use <i>mailboxname</i>@{{ domain.domain }} and the mailbox owner password to access mailboxes of this domain</p>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<br/>
|
|
</div>
|
|
|
|
<br/>
|
|
|
|
<div class="text-left">
|
|
<h3 style="margin-bottom: 15px;">Mailboxes
|
|
<button class="btn btn-primary btn-outline pull-right" ng-click="mailboxes.add.show()" ng-disabled="!domain.mailConfig.enabled" tooltip-enable="!domain.mailConfig.enabled" uib-tooltip="Email is disabled for this domain"><i class="fa fa-inbox"></i> Add</button>
|
|
|
|
<div class="pull-right">
|
|
<button class="btn btn-default btn-outline" ng-click="mailboxes.showPrevPage()" ng-disabled="mailboxes.busy || mailboxes.currentPage <= 1"><i class="fa fa-angle-double-left"></i> prev</button>
|
|
<button class="btn btn-default btn-outline" ng-click="mailboxes.showNextPage()" ng-disabled="mailboxes.busy || mailboxes.perPage > mailboxes.mailboxes.length">next <i class="fa fa-angle-double-right"></i></button>
|
|
</div>
|
|
|
|
<input class="form-control pull-right" style="width: 200px;" placeholder="Search" type="text" ng-model="mailboxes.search" ng-model-options="{ debounce: 1000 }" ng-change="mailboxes.updateFilter()" />
|
|
</h3>
|
|
</div>
|
|
|
|
<div class="card card-large" style="margin-bottom: 15px;">
|
|
<div class="row">
|
|
<div class="col-md-12">
|
|
|
|
<table class="table table-hover">
|
|
<thead>
|
|
<tr>
|
|
<th>Name</th>
|
|
<th>Owner</th>
|
|
<th>Aliases</th>
|
|
<th>Usage</th>
|
|
<th class="text-right">Action</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody>
|
|
<tr ng-repeat="mailbox in mailboxes.mailboxes | filter:mailboxes.search">
|
|
<td class="hand" ng-click="mailboxes.edit.show(mailbox)">
|
|
{{ mailbox.name }}
|
|
</td>
|
|
<td class="hand" ng-click="mailboxes.edit.show(mailbox)">
|
|
{{ mailbox.ownerDisplayName }}
|
|
</td>
|
|
<td class="hand" ng-click="mailboxes.edit.show(mailbox)">
|
|
<span ng-repeat="alias in mailbox.aliases"> {{ alias.name + '@' + alias.domain }}</span>
|
|
</td>
|
|
<td class="hand no-wrap" ng-click="mailboxes.edit.show(mailbox)">
|
|
{{ mailbox.usage | prettyByteSize }}
|
|
</td>
|
|
<td class="text-right no-wrap">
|
|
<button class="btn btn-xs btn-default" ng-click="mailboxes.edit.show(mailbox)"><i class="fa fa-pencil-alt"></i></button>
|
|
<button class="btn btn-xs btn-danger" ng-click="mailboxes.remove.show(mailbox)"><i class="far fa-trash-alt"></i></button>
|
|
</td>
|
|
</tr>
|
|
</tbody>
|
|
</table>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<br/>
|
|
|
|
<div class="text-left">
|
|
<h3 style="margin-bottom: 15px;">Mailing Lists
|
|
<button class="btn btn-primary btn-outline pull-right" ng-click="mailinglists.add.show()" ng-disabled="!domain.mailConfig.enabled" tooltip-enable="!domain.mailConfig.enabled" uib-tooltip="Email is disabled for this domain"><i class="fa fa-list"></i> Add</button>
|
|
<div class="pull-right">
|
|
<button class="btn btn-default btn-outline" ng-click="mailinglists.showPrevPage()" ng-disabled="mailinglists.busy || mailinglists.currentPage <= 1"><i class="fa fa-angle-double-left"></i> prev</button>
|
|
<button class="btn btn-default btn-outline" ng-click="mailinglists.showNextPage()" ng-disabled="mailinglists.busy || mailinglists.perPage > mailinglists.mailinglists.length">next <i class="fa fa-angle-double-right"></i></button>
|
|
</div>
|
|
|
|
<input class="form-control pull-right" style="width: 200px;" placeholder="Search" type="text" ng-model="mailinglists.search" ng-model-options="{ debounce: 1000 }" ng-change="mailinglists.updateFilter()" />
|
|
</h3>
|
|
</div>
|
|
|
|
<div class="card card-large" style="margin-bottom: 15px;">
|
|
<div class="row">
|
|
<div class="col-md-12">
|
|
A Mailing list forwards all emails to it's members.
|
|
|
|
<br/>
|
|
<br/>
|
|
|
|
<table class="table table-hover">
|
|
<thead>
|
|
<tr>
|
|
<th style="width: 0.5%;"></th>
|
|
<th>Name</th>
|
|
<th>List Members</th>
|
|
<th class="text-right">Action</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody>
|
|
<tr ng-repeat="list in mailinglists.mailinglists | filter:mailinglists.search | orderBy:'name'">
|
|
<td>
|
|
<i class="fas fa-door-closed" ng-show="list.membersOnly" uib-tooltip="Posting restricted to members only" tooltip-class="long nowrap"></i>
|
|
<i class="fas fa-door-open" ng-show="!list.membersOnly" uib-tooltip="Posting allowed by non-members" tooltip-class="long nowrap"></i>
|
|
</td>
|
|
<td class="hand" ng-click="mailinglists.edit.show(list)">
|
|
{{ list.name }}
|
|
</td>
|
|
<td class="hand" ng-click="mailinglists.edit.show(list)">
|
|
{{ list.members.join(', ') }}
|
|
</td>
|
|
<td class="text-right no-wrap">
|
|
<button class="btn btn-xs btn-default" ng-click="mailinglists.edit.show(list)"><i class="fa fa-pencil-alt"></i></button>
|
|
<button class="btn btn-xs btn-danger" ng-click="mailinglists.remove.show(list)"><i class="far fa-trash-alt"></i></button>
|
|
</td>
|
|
</tr>
|
|
</tbody>
|
|
</table>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<br/>
|
|
|
|
<div class="text-left">
|
|
<h3>Catch-all</h3>
|
|
</div>
|
|
|
|
<div class="card card-large" style="margin-bottom: 15px;">
|
|
<div class="row">
|
|
<div class="col-md-12">
|
|
Emails sent to non existing addresses will be forwarded to the following mailboxes.
|
|
</div>
|
|
</div>
|
|
<br/>
|
|
|
|
<div class="row" ng-hide="config.features.emailPremium">
|
|
<div class="col-md-12">
|
|
This feature is only available in the paid plans. <a href="" class="pull-right" ng-click="openSubscriptionSetup()">Setup Subscription Now</a>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="row" ng-show="config.features.emailPremium">
|
|
<div class="col-md-6">
|
|
<multiselect ng-model="catchall.mailboxes" options="mailbox.name for mailbox in mailboxes.mailboxes" data-compare-by="name" data-multiple="true" filter-after-rows="5" scroll-after-rows="10"></multiselect>
|
|
<button class="btn btn-outline btn-primary" ng-click="catchall.submit()" ng-disabled="catchall.busy || !domain.mailConfig.enabled"
|
|
tooltip-enable="!domain.mailConfig.enabled" uib-tooltip="Email is disabled for this domain">
|
|
<i class="fa fa-circle-notch fa-spin" ng-show="catchall.busy"></i> Save
|
|
</button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</uib-tab>
|
|
|
|
<uib-tab index="1" heading="Outbound">
|
|
<div class="card card-large" style="margin-bottom: 15px;">
|
|
<h4>Email Relay <sup><a ng-href="https://docs.cloudron.io/email/#relay-outbound-mails" class="help" target="_blank"><i class="fa fa-question-circle"></i></a></sup> </h4>
|
|
|
|
<div class="row">
|
|
<div class="col-md-12">
|
|
Cloudron will use this mail server (Smart host) to send the outbound mails of apps installed under this domain.
|
|
</div>
|
|
</div>
|
|
|
|
<br/>
|
|
|
|
<div class="row">
|
|
<div class="col-md-12">
|
|
<div class="form-group">
|
|
<select class="form-control" style="width: 50%;" ng-model="mailRelay.preset" ng-options="a.name for a in mailRelayPresets track by a.provider" ng-change="mailRelay.presetChanged()"></select>
|
|
</div>
|
|
|
|
<p class="small text-danger" ng-show="mailRelay.preset.provider === 'noop'">
|
|
<span ng-if="domain.domain === config.adminDomain">
|
|
Cloudron cannot send user invites, password reset and other notifications when email is disabled on the primary domain
|
|
</span>
|
|
<span ng-if="domain.domain !== config.adminDomain">
|
|
Cloudron cannot provide email sending for apps hosted under this domain when email is disabled
|
|
</span>
|
|
</p>
|
|
|
|
</div>
|
|
</div>
|
|
|
|
<div class="row" ng-show="usesExternalServer(mailRelay.preset.provider)">
|
|
<div class="col-md-6">
|
|
<div>
|
|
<form name="mailRelayForm" role="form" ng-submit="mailRelay.submit()" autocomplete="off" novalidate>
|
|
<div class="form-group" ng-class="{ 'has-error': (mailRelayForm.host.$dirty && mailRelayForm.host.$invalid) }">
|
|
<label class="control-label">SMTP Host</label>
|
|
<div class="control-label" ng-show="(!mailRelayForm.host.$dirty && mailRelay.error.host) || (mailRelayForm.host.$dirty && mailRelayForm.host.$invalid)">
|
|
<small ng-show="!mailRelayForm.host.$dirty && mailRelay.error.host">{{ mailRelay.error.host }}</small>
|
|
</div>
|
|
<input type="text" class="form-control" ng-model="mailRelay.relay.host" name="host" required>
|
|
</div>
|
|
<div class="form-group" ng-class="{ 'has-error': (mailRelayForm.port.$dirty && mailRelayForm.port.$invalid) }">
|
|
<label class="control-label">SMTP Port (STARTTLS)</label>
|
|
<div class="control-label" ng-show="(!mailRelayForm.port.$dirty && mailRelay.error.port) || (mailRelayForm.port.$dirty && mailRelayForm.port.$invalid)">
|
|
<small ng-show="!mailRelayForm.port.$dirty && mailRelay.error.port">{{ mailRelay.error.port }}</small>
|
|
</div>
|
|
<input type="number" class="form-control" ng-model="mailRelay.relay.port" name="port" required>
|
|
</div>
|
|
|
|
<div class="checkbox" ng-show="mailRelay.relay.provider === 'external-smtp' || mailRelay.relay.provider === 'external-smtp-noauth'" >
|
|
<label>
|
|
<input type="checkbox" ng-model="mailRelay.relay.acceptSelfSignedCerts">Accept Self-signed certificate</input>
|
|
</label>
|
|
</div>
|
|
|
|
<!-- Postmark, Sendgrid, SparkPost -->
|
|
<div ng-show="usesTokenAuth(mailRelay.relay.provider)" class="form-group" ng-class="{ 'has-error': (mailRelayForm.serverApiToken.$dirty && mailRelayForm.serverApiToken.$invalid) }">
|
|
<label class="control-label">API Token/Key</label>
|
|
<div class="control-label" ng-show="(!mailRelayForm.serverApiToken.$dirty && mailRelay.error.serverApiToken) || (mailRelayForm.serverApiToken.$dirty && mailRelayForm.serverApiToken.$invalid)">
|
|
<small ng-show="!mailRelayForm.serverApiToken.$dirty && mailRelay.error.serverApiToken">{{ mailRelay.error.serverApiToken }}</small>
|
|
</div>
|
|
<input type="text" class="form-control" ng-model="mailRelay.relay.serverApiToken" name="serverApiToken" ng-required="usesTokenAuth(mailRelay.relay.provider)">
|
|
</div>
|
|
|
|
<!-- Other -->
|
|
<div ng-show="usesPasswordAuth(mailRelay.relay.provider)" class="form-group" ng-class="{ 'has-error': (mailRelayForm.username.$dirty && mailRelayForm.username.$invalid) }">
|
|
<label class="control-label">Username</label>
|
|
<div class="control-label" ng-show="(!mailRelayForm.username.$dirty && mailRelay.error.username) || (mailRelayForm.username.$dirty && mailRelayForm.username.$invalid)">
|
|
<small ng-show="!mailRelayForm.username.$dirty && mailRelay.error.username">{{ mailRelay.error.username }}</small>
|
|
</div>
|
|
<input type="text" class="form-control" ng-model="mailRelay.relay.username" name="username" ng-required="usesPasswordAuth(mailRelay.relay.provider)">
|
|
</div>
|
|
|
|
<div ng-show="usesPasswordAuth(mailRelay.relay.provider)" class="form-group" ng-class="{ 'has-error': (mailRelayForm.password.$dirty && mailRelayForm.password.$invalid) }">
|
|
<label class="control-label">Password</label>
|
|
<div class="control-label" ng-show="(!mailRelayForm.password.$dirty && mailRelay.error.password) || (mailRelayForm.password.$dirty && mailRelayForm.password.$invalid)">
|
|
<small ng-show="!mailRelayForm.password.$dirty && mailRelay.error.password">{{ mailRelay.error.password }}</small>
|
|
</div>
|
|
<input type="password" class="form-control" ng-model="mailRelay.relay.password" name="password" ng-required="usesPasswordAuth(mailRelay.relay.provider)">
|
|
</div>
|
|
|
|
<input class="ng-hide" type="submit" ng-disabled="mailRelayForm.$invalid"/>
|
|
</form>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="row">
|
|
<div class="col-md-12">
|
|
<button class="btn btn-primary" ng-click="mailRelay.submit()" ng-disabled="(usesExternalServer(mailRelay.preset.provider) && (!mailRelayForm.$dirty || mailRelayForm.$invalid)) || mailRelay.busy"><i class="fa fa-circle-notch fa-spin" ng-show="mailRelay.busy"></i> Save</button>
|
|
|
|
<span class="has-error text-center" ng-show="mailRelay.error">{{ mailRelay.error }}</span>
|
|
<span class="text-success text-center text-bold" ng-show="mailRelay.success">Saved</span>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="row" ng-if="mailRelay.preset.spfDoc">
|
|
<br/>
|
|
<div class="col-md-12">
|
|
<span class="text-info">
|
|
Cloudron does not automatically setup SPF record. Set it up manually by following the <a ng-href="{{mailRelay.preset.spfDoc}}" target="_blank">{{ mailRelay.preset.name }} docs</a>.
|
|
</span>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
</uib-tab>
|
|
|
|
<uib-tab index="2" heading="Settings">
|
|
<div class="card card-large" style="margin-bottom: 15px;">
|
|
<h4>Enable Masquerading</h4>
|
|
|
|
<div class="row">
|
|
<div class="col-md-10">
|
|
Masquerading allows users and apps to send emails with an arbitrary username in the FROM address
|
|
</div>
|
|
<div class="col-md-2">
|
|
<button ng-class="domain.mailConfig.mailFromValidation ? 'btn btn-danger' : 'btn btn-primary'" ng-disabled="mailFromValidation.busy" ng-click="mailFromValidation.submit()">
|
|
<i class="fa fa-circle-notch fa-spin" ng-show="mailFromValidation.busy"></i>
|
|
{{ domain.mailConfig.mailFromValidation ? "Enable" : "Disable" }}
|
|
</button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="card card-large">
|
|
<h4>Signature</h4>
|
|
<p>The text here will be attached to all emails going out from this domain.</p>
|
|
|
|
<div class="row" ng-hide="config.features.emailPremium">
|
|
<div class="col-md-12">
|
|
This feature is only available in the paid plans. <a href="" class="pull-right" ng-click="openSubscriptionSetup()">Setup Subscription Now</a>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="row" ng-show="config.features.emailPremium">
|
|
<div class="col-md-12">
|
|
<form role="form" name="bannerForm" ng-submit="banner.submit()" autocomplete="off">
|
|
<fieldset>
|
|
<div class="form-group">
|
|
<label class="control-label" style="width: 100%">Text format</label>
|
|
<textarea ng-model="banner.text" class="form-control" rows="4"></textarea>
|
|
</div>
|
|
|
|
<div class="form-group">
|
|
<label class="control-label" style="width: 100%">HTML format (Optional)</label>
|
|
<textarea ng-model="banner.html" class="form-control" rows="4"></textarea>
|
|
</div>
|
|
|
|
<input class="ng-hide" type="submit" ng-disabled="banner.$invalid || banner.busy"/>
|
|
</fieldset>
|
|
</form>
|
|
</div>
|
|
</div>
|
|
<div class="row">
|
|
<div class="col-md-12 text-right">
|
|
<button class="btn btn-outline btn-primary pull-right" ng-click="banner.submit()" ng-disabled="banner.$invalid || banner.busy">
|
|
<i class="fa fa-circle-notch fa-spin" ng-show="banner.busy"></i> Save
|
|
</button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</uib-tab>
|
|
|
|
<uib-tab index="3" heading="Status">
|
|
<!-- nothing to show if incoming mail is disabled and using a relay -->
|
|
<div class="card card-large" style="margin-bottom: 15px;" ng-hide="!domain.mailConfig.enabled && domain.mailConfig.relay.provider !== 'cloudron-smtp'">
|
|
<div class="row">
|
|
<div class="col-md-12">
|
|
<h4>DNS Status
|
|
<button class="btn btn-xs btn-primary btn-outline pull-right" ng-click="incomingEmail.setDnsRecords()">
|
|
<i class="fa fa-circle-notch fa-spin" ng-show="incomingEmail.setupDnsBusy"></i> Re-setup DNS
|
|
</button>
|
|
</h4>
|
|
|
|
Status of DNS Records may show an error while DNS is propagating (~5 minutes). See the
|
|
<a ng-href="https://docs.cloudron.io/troubleshooting/#mail-dns" target="_blank">troubleshooting</a> docs for help.
|
|
|
|
<br/><br/>
|
|
|
|
<div ng-repeat="record in expectedDnsRecordsTypes">
|
|
<div class="row" ng-if="expectedDnsRecords[record.value].expected">
|
|
<div class="col-xs-12">
|
|
<p class="text-muted">
|
|
<i ng-hide="refreshBusy" ng-class="expectedDnsRecords[record.value].status ? 'fa fa-check-circle text-success' : 'fa fa-exclamation-triangle text-danger'"></i>
|
|
<a href="" data-toggle="collapse" data-parent="#accordion" data-target="#collapse_dns_{{ record.value }}">{{ record.name }} record</a>
|
|
<button class="btn btn-xs btn-default" ng-click="refreshStatus()" ng-disabled="refreshBusy" ng-show="!expectedDnsRecords[record.value].status"><i class="fa fa-sync-alt" ng-class="{ 'fa-pulse': refreshBusy }"></i></button>
|
|
</p>
|
|
<div id="collapse_dns_{{ record.value }}" class="panel-collapse collapse">
|
|
<div class="panel-body">
|
|
<p ng-show="record.name === 'MX' && domain.provider === 'namecheap'">Namecheap requires manual steps for MX records
|
|
<sup><a ng-href="https://docs.cloudron.io/domains/#namecheap-dns" class="help" target="_blank"><i class="fa fa-question-circle"></i></a></sup>
|
|
</p>
|
|
<p ng-show="record.name === 'PTR'">The PTR record is set by your VPS provider and not by your DNS provider.
|
|
<sup><a ng-href="https://docs.cloudron.io/troubleshooting/#ptr-record" class="help" target="_blank"><i class="fa fa-question-circle"></i></a></sup>
|
|
</p>
|
|
<p ng-show="expectedDnsRecords[record.value].name">Hostname: <b ng-click-select><tt>{{ expectedDnsRecords[record.value].name }}</tt></b></p>
|
|
<p ng-hide="expectedDnsRecords[record.value].name">Domain: <b ng-click-select><tt>{{ expectedDnsRecords[record.value].domain }}</tt></b></p>
|
|
<p>Record type: <b ng-click-select><tt>{{ expectedDnsRecords[record.value].type }}</tt></b></p>
|
|
<p style="overflow: auto; white-space: nowrap;">Expected value: <b ng-click-select><tt>{{ expectedDnsRecords[record.value].expected }}</tt></b></p>
|
|
<p style="overflow: auto; white-space: nowrap;">Current value: <b ng-click-select><tt>{{ expectedDnsRecords[record.value].value ? expectedDnsRecords[record.value].value : '[not set]' }}</tt></b></p>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="card card-large" style="margin-bottom: 15px;" ng-if="domain.mailConfig.relay.provider !== 'noop'">
|
|
<div class="row">
|
|
<div class="col-md-12">
|
|
<h4>SMTP Status <sup><a ng-href="https://docs.cloudron.io/troubleshooting/#mail-smtp" class="help" target="_blank"><i class="fa fa-question-circle"></i></a></sup></h4>
|
|
|
|
<div class="row">
|
|
<div class="col-xs-12">
|
|
<p class="text-muted">
|
|
<i ng-hide="refreshBusy" ng-class="domain.mailStatus.relay.status ? 'fa fa-check-circle text-success' : 'fa fa-exclamation-triangle text-danger'"></i>
|
|
<a href="" data-toggle="collapse" data-parent="#accordion" data-target="#collapse_outbound_smtp">
|
|
{{ domain.mailConfig.relay.provider === 'cloudron-smtp' ? 'Outbound SMTP (Direct)' : 'Outbound SMTP (Relay)' }}
|
|
</a>
|
|
<button class="btn btn-xs btn-default" ng-click="refreshStatus()" ng-disabled="refreshBusy" ng-show="!domain.mailStatus.relay.status"><i class="fa fa-sync-alt" ng-class="{ 'fa-pulse': refreshBusy }"></i></button>
|
|
</p>
|
|
<div id="collapse_outbound_smtp" class="panel-collapse collapse">
|
|
<div class="panel-body">
|
|
<p><b> {{ domain.mailStatus.relay.value }} </b> </p>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="row" ng-show="domain.mailConfig.relay.provider === 'cloudron-smtp'">
|
|
<div class="col-xs-12">
|
|
<p class="text-muted">
|
|
<i ng-hide="refreshBusy" ng-class="domain.mailStatus.rbl.status ? 'fa fa-check-circle text-success' : 'fa fa-exclamation-triangle text-danger'"></i>
|
|
<a href="" data-toggle="collapse" data-parent="#accordion" data-target="#collapse_rbl">
|
|
IP Address Blacklist Check
|
|
</a>
|
|
<button class="btn btn-xs btn-default" ng-click="refreshStatus()" ng-disabled="refreshBusy" ng-show="!domain.mailStatus.rbl.status"><i class="fa fa-sync-alt" ng-class="{ 'fa-pulse': refreshBusy }"></i></button>
|
|
</p>
|
|
<div id="collapse_rbl" class="panel-collapse collapse">
|
|
<div class="panel-body">
|
|
<div>This server's IP {{ domain.mailStatus.rbl.ip }} is <b ng-hide="domain.mailStatus.rbl.servers.length">not</b> blacklisted.</div>
|
|
<div ng-repeat="server in domain.mailStatus.rbl.servers">
|
|
<a ng-href="{{server.site}}" target="_blank">{{ server.name }}</a>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
</uib-tab>
|
|
</uib-tabset>
|
|
</div>
|