Merge branch 'master' into postfix-logging
commit
567b5ef172
@ -0,0 +1,446 @@
|
|||||||
|
name: CI
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
branches:
|
||||||
|
- staging
|
||||||
|
- testing
|
||||||
|
- '1.5'
|
||||||
|
- '1.6'
|
||||||
|
- '1.7'
|
||||||
|
- '1.8'
|
||||||
|
- master
|
||||||
|
# version tags, e.g. 1.7.1
|
||||||
|
- '[1-9].[0-9].[0-9]'
|
||||||
|
# pre-releases, e.g. 1.8-pre1
|
||||||
|
- 1.8-pre[0-9]
|
||||||
|
# test branches, e.g. test-debian
|
||||||
|
- test-*
|
||||||
|
|
||||||
|
###############################################
|
||||||
|
# REQUIRED secrets
|
||||||
|
# DOCKER_UN: ${{ secrets.Docker_Login }}
|
||||||
|
# Username of docker login for pushing the images to repo $DOCKER_ORG and $DOCKER_ORG_TESTS
|
||||||
|
# DOCKER_PW: ${{ secrets.Docker_Password }}
|
||||||
|
# Password of docker login for pushing the images to repo $DOCKER_ORG and $DOCKER_ORG_TESTS
|
||||||
|
# DOCKER_ORG: ${{ secrets.DOCKER_ORG }}
|
||||||
|
# The docker repository where the images are pushed to.
|
||||||
|
# DOCKER_ORG_TESTS: ${{ secrets.DOCKER_ORG_TESTS }}
|
||||||
|
# The docker repository for test images. Only used for the branch TESTING (BORS try).
|
||||||
|
# Add the above secrets to your github repo to determine where the images will be pushed.
|
||||||
|
################################################
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
build:
|
||||||
|
name: Build images
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v2
|
||||||
|
- name: Extract branch name
|
||||||
|
shell: bash
|
||||||
|
run: |
|
||||||
|
echo "BRANCH=${GITHUB_REF#refs/heads/}" >> $GITHUB_ENV
|
||||||
|
#For branch TESTING, we set the image tag to PR-xxxx
|
||||||
|
- name: Derive MAILU_VERSION for branch testing
|
||||||
|
if: ${{ env.BRANCH == 'testing' }}
|
||||||
|
shell: bash
|
||||||
|
env:
|
||||||
|
COMMIT_MESSAGE: ${{ github.event.head_commit.message }}
|
||||||
|
run: |
|
||||||
|
echo "MAILU_VERSION=pr-${COMMIT_MESSAGE//[!0-9]/}" >> $GITHUB_ENV
|
||||||
|
echo "DOCKER_ORG=${{ secrets.DOCKER_ORG_TESTS }}" >> $GITHUB_ENV
|
||||||
|
- name: Derive MAILU_VERSION for other branches than testing
|
||||||
|
if: ${{ env.BRANCH != 'testing' }}
|
||||||
|
shell: bash
|
||||||
|
env:
|
||||||
|
MAILU_BRANCH: ${{ env.BRANCH }}
|
||||||
|
run: |
|
||||||
|
echo "MAILU_VERSION=${{ env.MAILU_BRANCH }}" >> $GITHUB_ENV
|
||||||
|
echo "DOCKER_ORG=${{ secrets.DOCKER_ORG }}" >> $GITHUB_ENV
|
||||||
|
- name: Create folder for storing images
|
||||||
|
run: |
|
||||||
|
sudo mkdir -p /images
|
||||||
|
sudo chmod 777 /images
|
||||||
|
- name: Configure images folder for caching
|
||||||
|
uses: actions/cache@v2
|
||||||
|
with:
|
||||||
|
path: /images
|
||||||
|
key: ${{ env.BRANCH }}-${{ github.run_id }}-${{ github.run_number }}
|
||||||
|
- name: Check docker-compose version
|
||||||
|
run: docker-compose -v
|
||||||
|
- name: Login docker
|
||||||
|
env:
|
||||||
|
DOCKER_UN: ${{ secrets.Docker_Login }}
|
||||||
|
DOCKER_PW: ${{ secrets.Docker_Password }}
|
||||||
|
DOCKER_ORG: ${{ env.DOCKER_ORG }}
|
||||||
|
run: echo "$DOCKER_PW" | docker login --username $DOCKER_UN --password-stdin
|
||||||
|
- name: Build all docker images
|
||||||
|
env:
|
||||||
|
MAILU_VERSION: ${{ env.MAILU_VERSION }}
|
||||||
|
TRAVIS_BRANCH: ${{ env.BRANCH }}
|
||||||
|
DOCKER_ORG: ${{ env.DOCKER_ORG }}
|
||||||
|
run: docker-compose -f tests/build.yml build
|
||||||
|
- name: Save all docker images
|
||||||
|
run: docker save ${{ env.DOCKER_ORG }}/admin ${{ env.DOCKER_ORG }}/clamav ${{ env.DOCKER_ORG }}/docs ${{ env.DOCKER_ORG }}/dovecot ${{ env.DOCKER_ORG }}/fetchmail ${{ env.DOCKER_ORG }}/nginx ${{ env.DOCKER_ORG }}/none ${{ env.DOCKER_ORG }}/postfix ${{ env.DOCKER_ORG }}/postgresql ${{ env.DOCKER_ORG }}/radicale ${{ env.DOCKER_ORG }}/rainloop ${{ env.DOCKER_ORG }}/roundcube ${{ env.DOCKER_ORG }}/rspamd ${{ env.DOCKER_ORG }}/setup ${{ env.DOCKER_ORG }}/traefik-certdumper ${{ env.DOCKER_ORG }}/unbound -o /images/images.tar.gz
|
||||||
|
|
||||||
|
test-core:
|
||||||
|
name: Perform core tests
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
needs:
|
||||||
|
- build
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v2
|
||||||
|
- name: Extract branch name
|
||||||
|
shell: bash
|
||||||
|
run: |
|
||||||
|
echo "BRANCH=${GITHUB_REF#refs/heads/}" >> $GITHUB_ENV
|
||||||
|
- name: Derive MAILU_VERSION for branch testing
|
||||||
|
if: ${{ env.BRANCH == 'testing' }}
|
||||||
|
shell: bash
|
||||||
|
env:
|
||||||
|
COMMIT_MESSAGE: ${{ github.event.head_commit.message }}
|
||||||
|
run: |
|
||||||
|
echo "MAILU_VERSION=pr-${COMMIT_MESSAGE//[!0-9]/}" >> $GITHUB_ENV
|
||||||
|
echo "DOCKER_ORG=${{ secrets.DOCKER_ORG_TESTS }}" >> $GITHUB_ENV
|
||||||
|
- name: Derive MAILU_VERSION for other branches than testing
|
||||||
|
if: ${{ env.BRANCH != 'testing' }}
|
||||||
|
shell: bash
|
||||||
|
env:
|
||||||
|
MAILU_BRANCH: ${{ env.BRANCH }}
|
||||||
|
run: |
|
||||||
|
echo "MAILU_VERSION=${{ env.MAILU_BRANCH }}" >> $GITHUB_ENV
|
||||||
|
echo "DOCKER_ORG=${{ secrets.DOCKER_ORG }}" >> $GITHUB_ENV
|
||||||
|
- name: Create folder for storing images
|
||||||
|
run: |
|
||||||
|
sudo mkdir -p /images
|
||||||
|
sudo chmod 777 /images
|
||||||
|
- name: Configure images folder for caching
|
||||||
|
uses: actions/cache@v2
|
||||||
|
with:
|
||||||
|
path: /images
|
||||||
|
key: ${{ env.BRANCH }}-${{ github.run_id }}-${{ github.run_number }}
|
||||||
|
- name: Load docker images
|
||||||
|
run: docker load -i /images/images.tar.gz
|
||||||
|
- name: Install python packages
|
||||||
|
run: python3 -m pip install -r tests/requirements.txt
|
||||||
|
- name: Copy all certs
|
||||||
|
run: sudo -- sh -c 'mkdir -p /mailu && cp -r tests/certs /mailu && chmod 600 /mailu/certs/*'
|
||||||
|
- name: Test core suite
|
||||||
|
run: python tests/compose/test.py core 2
|
||||||
|
env:
|
||||||
|
MAILU_VERSION: ${{ env.MAILU_VERSION }}
|
||||||
|
TRAVIS_BRANCH: ${{ env.BRANCH }}
|
||||||
|
DOCKER_ORG: ${{ env.DOCKER_ORG }}
|
||||||
|
|
||||||
|
test-fetchmail:
|
||||||
|
name: Perform fetchmail tests
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
needs:
|
||||||
|
- build
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v2
|
||||||
|
- name: Extract branch name
|
||||||
|
shell: bash
|
||||||
|
run: |
|
||||||
|
echo "BRANCH=${GITHUB_REF#refs/heads/}" >> $GITHUB_ENV
|
||||||
|
- name: Derive MAILU_VERSION for branch testing
|
||||||
|
if: ${{ env.BRANCH == 'testing' }}
|
||||||
|
shell: bash
|
||||||
|
env:
|
||||||
|
COMMIT_MESSAGE: ${{ github.event.head_commit.message }}
|
||||||
|
run: |
|
||||||
|
echo "MAILU_VERSION=pr-${COMMIT_MESSAGE//[!0-9]/}" >> $GITHUB_ENV
|
||||||
|
echo "DOCKER_ORG=${{ secrets.DOCKER_ORG_TESTS }}" >> $GITHUB_ENV
|
||||||
|
- name: Derive MAILU_VERSION for other branches than testing
|
||||||
|
if: ${{ env.BRANCH != 'testing' }}
|
||||||
|
shell: bash
|
||||||
|
env:
|
||||||
|
MAILU_BRANCH: ${{ env.BRANCH }}
|
||||||
|
run: |
|
||||||
|
echo "MAILU_VERSION=${{ env.MAILU_BRANCH }}" >> $GITHUB_ENV
|
||||||
|
echo "DOCKER_ORG=${{ secrets.DOCKER_ORG }}" >> $GITHUB_ENV
|
||||||
|
- name: Create folder for storing images
|
||||||
|
run: |
|
||||||
|
sudo mkdir -p /images
|
||||||
|
sudo chmod 777 /images
|
||||||
|
- name: Configure images folder for caching
|
||||||
|
uses: actions/cache@v2
|
||||||
|
with:
|
||||||
|
path: /images
|
||||||
|
key: ${{ env.BRANCH }}-${{ github.run_id }}-${{ github.run_number }}
|
||||||
|
- name: Load docker images
|
||||||
|
run: docker load -i /images/images.tar.gz
|
||||||
|
- name: Install python packages
|
||||||
|
run: python3 -m pip install -r tests/requirements.txt
|
||||||
|
- name: Copy all certs
|
||||||
|
run: sudo -- sh -c 'mkdir -p /mailu && cp -r tests/certs /mailu && chmod 600 /mailu/certs/*'
|
||||||
|
- name: Test fetch
|
||||||
|
run: python tests/compose/test.py fetchmail 2
|
||||||
|
env:
|
||||||
|
MAILU_VERSION: ${{ env.MAILU_VERSION }}
|
||||||
|
TRAVIS_BRANCH: ${{ env.BRANCH }}
|
||||||
|
DOCKER_ORG: ${{ env.DOCKER_ORG }}
|
||||||
|
|
||||||
|
test-filters:
|
||||||
|
name: Perform filter tests
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
needs:
|
||||||
|
- build
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v2
|
||||||
|
- name: Extract branch name
|
||||||
|
shell: bash
|
||||||
|
run: |
|
||||||
|
echo "BRANCH=${GITHUB_REF#refs/heads/}" >> $GITHUB_ENV
|
||||||
|
- name: Derive MAILU_VERSION for branch testing
|
||||||
|
if: ${{ env.BRANCH == 'testing' }}
|
||||||
|
shell: bash
|
||||||
|
env:
|
||||||
|
COMMIT_MESSAGE: ${{ github.event.head_commit.message }}
|
||||||
|
run: |
|
||||||
|
echo "MAILU_VERSION=pr-${COMMIT_MESSAGE//[!0-9]/}" >> $GITHUB_ENV
|
||||||
|
echo "DOCKER_ORG=${{ secrets.DOCKER_ORG_TESTS }}" >> $GITHUB_ENV
|
||||||
|
- name: Derive MAILU_VERSION for other branches than testing
|
||||||
|
if: ${{ env.BRANCH != 'testing' }}
|
||||||
|
shell: bash
|
||||||
|
env:
|
||||||
|
MAILU_BRANCH: ${{ env.BRANCH }}
|
||||||
|
run: |
|
||||||
|
echo "MAILU_VERSION=${{ env.MAILU_BRANCH }}" >> $GITHUB_ENV
|
||||||
|
echo "DOCKER_ORG=${{ secrets.DOCKER_ORG }}" >> $GITHUB_ENV
|
||||||
|
- name: Create folder for storing images
|
||||||
|
run: |
|
||||||
|
sudo mkdir -p /images
|
||||||
|
sudo chmod 777 /images
|
||||||
|
- name: Configure images folder for caching
|
||||||
|
uses: actions/cache@v2
|
||||||
|
with:
|
||||||
|
path: /images
|
||||||
|
key: ${{ env.BRANCH }}-${{ github.run_id }}-${{ github.run_number }}
|
||||||
|
- name: Load docker images
|
||||||
|
run: docker load -i /images/images.tar.gz
|
||||||
|
- name: Install python packages
|
||||||
|
run: python3 -m pip install -r tests/requirements.txt
|
||||||
|
- name: Copy all certs
|
||||||
|
run: sudo -- sh -c 'mkdir -p /mailu && cp -r tests/certs /mailu && chmod 600 /mailu/certs/*'
|
||||||
|
- name: Test clamvav
|
||||||
|
run: python tests/compose/test.py filters 3
|
||||||
|
env:
|
||||||
|
MAILU_VERSION: ${{ env.MAILU_VERSION }}
|
||||||
|
TRAVIS_BRANCH: ${{ env.BRANCH }}
|
||||||
|
DOCKER_ORG: ${{ env.DOCKER_ORG }}
|
||||||
|
|
||||||
|
test-rainloop:
|
||||||
|
name: Perform rainloop tests
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
needs:
|
||||||
|
- build
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v2
|
||||||
|
- name: Extract branch name
|
||||||
|
shell: bash
|
||||||
|
run: |
|
||||||
|
echo "BRANCH=${GITHUB_REF#refs/heads/}" >> $GITHUB_ENV
|
||||||
|
- name: Derive MAILU_VERSION for branch testing
|
||||||
|
if: ${{ env.BRANCH == 'testing' }}
|
||||||
|
shell: bash
|
||||||
|
env:
|
||||||
|
COMMIT_MESSAGE: ${{ github.event.head_commit.message }}
|
||||||
|
run: |
|
||||||
|
echo "MAILU_VERSION=pr-${COMMIT_MESSAGE//[!0-9]/}" >> $GITHUB_ENV
|
||||||
|
echo "DOCKER_ORG=${{ secrets.DOCKER_ORG_TESTS }}" >> $GITHUB_ENV
|
||||||
|
- name: Derive MAILU_VERSION for other branches than testing
|
||||||
|
if: ${{ env.BRANCH != 'testing' }}
|
||||||
|
shell: bash
|
||||||
|
env:
|
||||||
|
MAILU_BRANCH: ${{ env.BRANCH }}
|
||||||
|
run: |
|
||||||
|
echo "MAILU_VERSION=${{ env.MAILU_BRANCH }}" >> $GITHUB_ENV
|
||||||
|
echo "DOCKER_ORG=${{ secrets.DOCKER_ORG }}" >> $GITHUB_ENV
|
||||||
|
- name: Create folder for storing images
|
||||||
|
run: |
|
||||||
|
sudo mkdir -p /images
|
||||||
|
sudo chmod 777 /images
|
||||||
|
- name: Configure images folder for caching
|
||||||
|
uses: actions/cache@v2
|
||||||
|
with:
|
||||||
|
path: /images
|
||||||
|
key: ${{ env.BRANCH }}-${{ github.run_id }}-${{ github.run_number }}
|
||||||
|
- name: Load docker images
|
||||||
|
run: docker load -i /images/images.tar.gz
|
||||||
|
- name: Install python packages
|
||||||
|
run: python3 -m pip install -r tests/requirements.txt
|
||||||
|
- name: Copy all certs
|
||||||
|
run: sudo -- sh -c 'mkdir -p /mailu && cp -r tests/certs /mailu && chmod 600 /mailu/certs/*'
|
||||||
|
- name: Test rainloop
|
||||||
|
run: python tests/compose/test.py rainloop 2
|
||||||
|
env:
|
||||||
|
MAILU_VERSION: ${{ env.MAILU_VERSION }}
|
||||||
|
TRAVIS_BRANCH: ${{ env.BRANCH }}
|
||||||
|
DOCKER_ORG: ${{ env.DOCKER_ORG }}
|
||||||
|
|
||||||
|
test-roundcube:
|
||||||
|
name: Perform roundcube tests
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
needs:
|
||||||
|
- build
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v2
|
||||||
|
- name: Extract branch name
|
||||||
|
shell: bash
|
||||||
|
run: |
|
||||||
|
echo "BRANCH=${GITHUB_REF#refs/heads/}" >> $GITHUB_ENV
|
||||||
|
- name: Derive MAILU_VERSION for branch testing
|
||||||
|
if: ${{ env.BRANCH == 'testing' }}
|
||||||
|
shell: bash
|
||||||
|
env:
|
||||||
|
COMMIT_MESSAGE: ${{ github.event.head_commit.message }}
|
||||||
|
run: |
|
||||||
|
echo "MAILU_VERSION=pr-${COMMIT_MESSAGE//[!0-9]/}" >> $GITHUB_ENV
|
||||||
|
echo "DOCKER_ORG=${{ secrets.DOCKER_ORG_TESTS }}" >> $GITHUB_ENV
|
||||||
|
- name: Derive MAILU_VERSION for other branches than testing
|
||||||
|
if: ${{ env.BRANCH != 'testing' }}
|
||||||
|
shell: bash
|
||||||
|
env:
|
||||||
|
MAILU_BRANCH: ${{ env.BRANCH }}
|
||||||
|
run: |
|
||||||
|
echo "MAILU_VERSION=${{ env.MAILU_BRANCH }}" >> $GITHUB_ENV
|
||||||
|
echo "DOCKER_ORG=${{ secrets.DOCKER_ORG }}" >> $GITHUB_ENV
|
||||||
|
- name: Create folder for storing images
|
||||||
|
run: |
|
||||||
|
sudo mkdir -p /images
|
||||||
|
sudo chmod 777 /images
|
||||||
|
- name: Configure images folder for caching
|
||||||
|
uses: actions/cache@v2
|
||||||
|
with:
|
||||||
|
path: /images
|
||||||
|
key: ${{ env.BRANCH }}-${{ github.run_id }}-${{ github.run_number }}
|
||||||
|
- name: Load docker images
|
||||||
|
run: docker load -i /images/images.tar.gz
|
||||||
|
- name: Install python packages
|
||||||
|
run: python3 -m pip install -r tests/requirements.txt
|
||||||
|
- name: Copy all certs
|
||||||
|
run: sudo -- sh -c 'mkdir -p /mailu && cp -r tests/certs /mailu && chmod 600 /mailu/certs/*'
|
||||||
|
- name: Test roundcube
|
||||||
|
run: python tests/compose/test.py roundcube 2
|
||||||
|
env:
|
||||||
|
MAILU_VERSION: ${{ env.MAILU_VERSION }}
|
||||||
|
TRAVIS_BRANCH: ${{ env.BRANCH }}
|
||||||
|
DOCKER_ORG: ${{ env.DOCKER_ORG }}
|
||||||
|
|
||||||
|
test-webdav:
|
||||||
|
name: Perform webdav tests
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
needs:
|
||||||
|
- build
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v2
|
||||||
|
- name: Extract branch name
|
||||||
|
shell: bash
|
||||||
|
run: |
|
||||||
|
echo "BRANCH=${GITHUB_REF#refs/heads/}" >> $GITHUB_ENV
|
||||||
|
- name: Derive MAILU_VERSION for branch testing
|
||||||
|
if: ${{ env.BRANCH == 'testing' }}
|
||||||
|
shell: bash
|
||||||
|
env:
|
||||||
|
COMMIT_MESSAGE: ${{ github.event.head_commit.message }}
|
||||||
|
run: |
|
||||||
|
echo "MAILU_VERSION=pr-${COMMIT_MESSAGE//[!0-9]/}" >> $GITHUB_ENV
|
||||||
|
echo "DOCKER_ORG=${{ secrets.DOCKER_ORG_TESTS }}" >> $GITHUB_ENV
|
||||||
|
- name: Derive MAILU_VERSION for other branches than testing
|
||||||
|
if: ${{ env.BRANCH != 'testing' }}
|
||||||
|
shell: bash
|
||||||
|
env:
|
||||||
|
MAILU_BRANCH: ${{ env.BRANCH }}
|
||||||
|
run: |
|
||||||
|
echo "MAILU_VERSION=${{ env.MAILU_BRANCH }}" >> $GITHUB_ENV
|
||||||
|
echo "DOCKER_ORG=${{ secrets.DOCKER_ORG }}" >> $GITHUB_ENV
|
||||||
|
- name: Create folder for storing images
|
||||||
|
run: |
|
||||||
|
sudo mkdir -p /images
|
||||||
|
sudo chmod 777 /images
|
||||||
|
- name: Configure images folder for caching
|
||||||
|
uses: actions/cache@v2
|
||||||
|
with:
|
||||||
|
path: /images
|
||||||
|
key: ${{ env.BRANCH }}-${{ github.run_id }}-${{ github.run_number }}
|
||||||
|
- name: Load docker images
|
||||||
|
run: docker load -i /images/images.tar.gz
|
||||||
|
- name: Install python packages
|
||||||
|
run: python3 -m pip install -r tests/requirements.txt
|
||||||
|
- name: Copy all certs
|
||||||
|
run: sudo -- sh -c 'mkdir -p /mailu && cp -r tests/certs /mailu && chmod 600 /mailu/certs/*'
|
||||||
|
- name: Test webdav
|
||||||
|
run: python tests/compose/test.py webdav 2
|
||||||
|
env:
|
||||||
|
MAILU_VERSION: ${{ env.MAILU_VERSION }}
|
||||||
|
TRAVIS_BRANCH: ${{ env.BRANCH }}
|
||||||
|
DOCKER_ORG: ${{ env.DOCKER_ORG }}
|
||||||
|
|
||||||
|
deploy:
|
||||||
|
name: Deploy images
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
needs:
|
||||||
|
- build
|
||||||
|
- test-core
|
||||||
|
- test-fetchmail
|
||||||
|
- test-filters
|
||||||
|
- test-rainloop
|
||||||
|
- test-roundcube
|
||||||
|
- test-webdav
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v2
|
||||||
|
- name: Extract branch name
|
||||||
|
shell: bash
|
||||||
|
run: |
|
||||||
|
echo "BRANCH=${GITHUB_REF#refs/heads/}" >> $GITHUB_ENV
|
||||||
|
#For branch TESTING, we set the image tag to PR-xxxx
|
||||||
|
- name: Derive MAILU_VERSION for branch testing
|
||||||
|
if: ${{ env.BRANCH == 'testing' }}
|
||||||
|
shell: bash
|
||||||
|
env:
|
||||||
|
COMMIT_MESSAGE: ${{ github.event.head_commit.message }}
|
||||||
|
run: |
|
||||||
|
echo "MAILU_VERSION=pr-${COMMIT_MESSAGE//[!0-9]/}" >> $GITHUB_ENV
|
||||||
|
echo "DOCKER_ORG=${{ secrets.DOCKER_ORG_TESTS }}" >> $GITHUB_ENV
|
||||||
|
- name: Derive MAILU_VERSION for other branches than testing
|
||||||
|
if: ${{ env.BRANCH != 'testing' }}
|
||||||
|
shell: bash
|
||||||
|
env:
|
||||||
|
MAILU_BRANCH: ${{ env.BRANCH }}
|
||||||
|
run: |
|
||||||
|
echo "MAILU_VERSION=${{ env.MAILU_BRANCH }}" >> $GITHUB_ENV
|
||||||
|
echo "DOCKER_ORG=${{ secrets.DOCKER_ORG }}" >> $GITHUB_ENV
|
||||||
|
- name: Create folder for storing images
|
||||||
|
run: |
|
||||||
|
sudo mkdir -p /images
|
||||||
|
sudo chmod 777 /images
|
||||||
|
- name: Configure images folder for caching
|
||||||
|
# For staging we do not deploy images. So we do not have to load them from cache.
|
||||||
|
if: ${{ env.BRANCH != 'staging' }}
|
||||||
|
uses: actions/cache@v2
|
||||||
|
with:
|
||||||
|
path: /images
|
||||||
|
key: ${{ env.BRANCH }}-${{ github.run_id }}-${{ github.run_number }}
|
||||||
|
- name: Load docker images
|
||||||
|
if: ${{ env.BRANCH != 'staging' }}
|
||||||
|
run: docker load -i /images/images.tar.gz
|
||||||
|
- name: Deploy built docker images
|
||||||
|
env:
|
||||||
|
DOCKER_UN: ${{ secrets.Docker_Login }}
|
||||||
|
DOCKER_PW: ${{ secrets.Docker_Password }}
|
||||||
|
DOCKER_ORG: ${{ env.DOCKER_ORG }}
|
||||||
|
MAILU_VERSION: ${{ env.MAILU_VERSION }}
|
||||||
|
TRAVIS_BRANCH: ${{ env.BRANCH }}
|
||||||
|
run: bash tests/deploy.sh
|
||||||
|
|
||||||
|
# This job is watched by bors. It only complets if building,testing and deploy worked.
|
||||||
|
ci-success:
|
||||||
|
name: CI-Done
|
||||||
|
#Returns true when none of the **previous** steps have failed or been canceled.
|
||||||
|
if: ${{ success() }}
|
||||||
|
needs:
|
||||||
|
- deploy
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- name: CI/CD succeeded.
|
||||||
|
run: exit 0
|
@ -1,55 +0,0 @@
|
|||||||
branches:
|
|
||||||
only:
|
|
||||||
- staging
|
|
||||||
- testing
|
|
||||||
- '1.5'
|
|
||||||
- '1.6'
|
|
||||||
- '1.7'
|
|
||||||
- '1.8'
|
|
||||||
- master
|
|
||||||
# version tags, e.g. 1.7.1
|
|
||||||
- /^1\.[5678]\.\d+$/
|
|
||||||
# pre-releases, e.g. 1.8-pre1
|
|
||||||
- /^1\.8-pre\d+$/
|
|
||||||
# test branches, e.g. test-debian
|
|
||||||
- /^test-[\w\-\.]+$/
|
|
||||||
|
|
||||||
sudo: required
|
|
||||||
services: docker
|
|
||||||
addons:
|
|
||||||
apt:
|
|
||||||
packages:
|
|
||||||
- docker-ce
|
|
||||||
|
|
||||||
env:
|
|
||||||
- MAILU_VERSION=${TRAVIS_BRANCH////-}
|
|
||||||
|
|
||||||
language: python
|
|
||||||
python:
|
|
||||||
- "3.6"
|
|
||||||
install:
|
|
||||||
- pip install -r tests/requirements.txt
|
|
||||||
- sudo curl -L https://github.com/docker/compose/releases/download/1.23.0-rc3/docker-compose-`uname -s`-`uname -m` -o /usr/local/bin/docker-compose
|
|
||||||
- sudo chmod +x /usr/local/bin/docker-compose
|
|
||||||
|
|
||||||
before_script:
|
|
||||||
- docker-compose -v
|
|
||||||
- docker-compose -f tests/build.yml build
|
|
||||||
- sudo -- sh -c 'mkdir -p /mailu && cp -r tests/certs /mailu && chmod 600 /mailu/certs/*'
|
|
||||||
|
|
||||||
|
|
||||||
script:
|
|
||||||
# test.py, test name and timeout between start and tests.
|
|
||||||
- python tests/compose/test.py core 1
|
|
||||||
- python tests/compose/test.py fetchmail 1
|
|
||||||
- travis_wait python tests/compose/test.py filters 10
|
|
||||||
- python tests/compose/test.py rainloop 1
|
|
||||||
- python tests/compose/test.py roundcube 1
|
|
||||||
- python tests/compose/test.py webdav 1
|
|
||||||
|
|
||||||
deploy:
|
|
||||||
provider: script
|
|
||||||
script: bash tests/deploy.sh
|
|
||||||
on:
|
|
||||||
all_branches: true
|
|
||||||
condition: -n $DOCKER_UN
|
|
@ -1,3 +1,4 @@
|
|||||||
status = [
|
status = [
|
||||||
"continuous-integration/travis-ci/push"
|
"CI-Done"
|
||||||
]
|
]
|
||||||
|
|
||||||
|
@ -1,22 +1,59 @@
|
|||||||
.select2-search--inline .select2-search__field:focus {
|
/* mailu logo */
|
||||||
border: none;
|
.mailu-logo {
|
||||||
|
opacity: .8;
|
||||||
|
}
|
||||||
|
.bg-mailu-logo {
|
||||||
|
background-color: #2980b9!important;
|
||||||
}
|
}
|
||||||
|
|
||||||
.sidebar h4 {
|
/* user image */
|
||||||
padding-left: 5px;
|
.div-circle {
|
||||||
padding-right: 5px;
|
position: relative;
|
||||||
overflow: hidden;
|
width: 2.1rem;
|
||||||
text-overflow: ellipsis;
|
height: 2.1rem;
|
||||||
|
opacity: .8;
|
||||||
|
background-color: white;
|
||||||
|
border-radius: 50%;
|
||||||
|
}
|
||||||
|
.div-circle > i {
|
||||||
|
display: block;
|
||||||
|
position: absolute;
|
||||||
|
top: 50%;
|
||||||
|
left: 50%;
|
||||||
|
transform: translate(-50%, -50%)
|
||||||
}
|
}
|
||||||
|
|
||||||
.sidebar-collapse .sidebar h4 {
|
/* nice round preformatted configuration display */
|
||||||
display: none !important;
|
.pre-config {
|
||||||
|
padding: 9px;
|
||||||
|
margin: 0;
|
||||||
|
white-space: pre-wrap;
|
||||||
|
word-wrap: anywhere;
|
||||||
|
border-radius: 4px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.logo a {
|
/* fieldset */
|
||||||
color: #fff;
|
legend {
|
||||||
|
font-size: inherit;
|
||||||
|
}
|
||||||
|
fieldset:disabled :not(legend) label {
|
||||||
|
opacity: .5;
|
||||||
|
}
|
||||||
|
fieldset:disabled .form-control:disabled {
|
||||||
|
color: gray;
|
||||||
}
|
}
|
||||||
|
|
||||||
.sidebar-toggle {
|
/* fix animation for icons in menu text */
|
||||||
padding: unset !important;
|
.sidebar .nav-link p i {
|
||||||
|
transition: margin-left .3s linear,opacity .3s ease,visibility .3s ease;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* fix select2 text color */
|
||||||
|
.select2-container--default .select2-selection--multiple .select2-selection__choice {
|
||||||
|
color: black;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* range input spacing */
|
||||||
|
.input-group-text {
|
||||||
|
margin-right: 1em;
|
||||||
}
|
}
|
||||||
|
@ -1,10 +1,79 @@
|
|||||||
require('./app.css');
|
require('./app.css');
|
||||||
|
|
||||||
import 'select2';
|
import logo from './mailu.png';
|
||||||
jQuery("document").ready(function() {
|
import modules from "./*.json";
|
||||||
jQuery(".mailselect").select2({
|
|
||||||
tags: true,
|
// TODO: conditionally (or lazy) load select2 and dataTable
|
||||||
tokenSeparators: [',', ' ']
|
$('document').ready(function() {
|
||||||
})
|
|
||||||
|
// intercept anchors with data-clicked attribute and open alternate location instead
|
||||||
|
$('[data-clicked]').click(function(e) {
|
||||||
|
e.preventDefault();
|
||||||
|
window.location.href = $(this).data('clicked');
|
||||||
|
});
|
||||||
|
|
||||||
|
// use post for language selection
|
||||||
|
$('#mailu-languages > a').click(function(e) {
|
||||||
|
e.preventDefault();
|
||||||
|
$.post({
|
||||||
|
url: $(this).attr('href'),
|
||||||
|
success: function() {
|
||||||
|
window.location = window.location.href;
|
||||||
|
},
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
// allow en-/disabling of inputs in fieldset with checkbox in legend
|
||||||
|
$('fieldset legend input[type=checkbox]').change(function() {
|
||||||
|
var fieldset = $(this).parents('fieldset');
|
||||||
|
if (this.checked) {
|
||||||
|
fieldset.removeAttr('disabled');
|
||||||
|
fieldset.find('input,textarea').not(this).removeAttr('disabled');
|
||||||
|
} else {
|
||||||
|
fieldset.attr('disabled', '');
|
||||||
|
fieldset.find('input,textarea').not(this).attr('disabled', '');
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// display of range input value
|
||||||
|
$('input[type=range]').each(function() {
|
||||||
|
var value_element = $('#'+this.id+'_value');
|
||||||
|
if (value_element.length) {
|
||||||
|
value_element = $(value_element[0]);
|
||||||
|
var infinity = $(this).data('infinity');
|
||||||
|
var step = $(this).attr('step');
|
||||||
|
$(this).on('input', function() {
|
||||||
|
var num = (infinity && this.value == 0) ? '∞' : (this.value/step).toFixed(2);
|
||||||
|
if (num.endsWith('.00')) num = num.substr(0, num.length - 3);
|
||||||
|
value_element.text(num);
|
||||||
|
}).trigger('input');
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// init select2
|
||||||
|
$('.mailselect').select2({
|
||||||
|
tags: true,
|
||||||
|
tokenSeparators: [',', ' '],
|
||||||
|
});
|
||||||
|
|
||||||
|
// init dataTable
|
||||||
|
var d = $(document.documentElement);
|
||||||
|
$('.dataTable').DataTable({
|
||||||
|
'responsive': true,
|
||||||
|
language: {
|
||||||
|
url: d.data('static') + d.attr('lang') + '.json',
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
// init clipboard.js
|
||||||
|
new ClipboardJS('.btn-clip');
|
||||||
|
|
||||||
|
// disable login if not possible
|
||||||
|
var l = $('#login_needs_https');
|
||||||
|
if (l.length && window.location.protocol != 'https:') {
|
||||||
|
l.removeClass("d-none");
|
||||||
|
$('form :input').prop('disabled', true);
|
||||||
|
}
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
|
Binary file not shown.
After Width: | Height: | Size: 4.8 KiB |
@ -1,19 +1,24 @@
|
|||||||
// jQuery
|
|
||||||
import jQuery from 'jquery';
|
|
||||||
import 'select2/dist/css/select2.css';
|
|
||||||
|
|
||||||
// bootstrap
|
|
||||||
import 'bootstrap/less/bootstrap.less';
|
|
||||||
import 'bootstrap';
|
|
||||||
|
|
||||||
// FA
|
|
||||||
import 'font-awesome/scss/font-awesome.scss';
|
|
||||||
|
|
||||||
// AdminLTE
|
// AdminLTE
|
||||||
import 'admin-lte/build/less/AdminLTE-without-plugins.less';
|
import 'admin-lte/plugins/jquery/jquery.min.js';
|
||||||
import 'admin-lte/build/less/select2.less';
|
import 'admin-lte/plugins/bootstrap/js/bootstrap.bundle.min.js';
|
||||||
import 'admin-lte/build/less/skins/skin-blue.less';
|
import 'admin-lte/build/scss/adminlte.scss';
|
||||||
import 'admin-lte/build/js/Layout.js';
|
import 'admin-lte/build/js/AdminLTE.js';
|
||||||
import 'admin-lte/build/js/ControlSidebar.js';
|
|
||||||
import 'admin-lte/build/js/PushMenu.js';
|
// fontawesome plugin
|
||||||
import 'admin-lte/build/js/BoxRefresh.js';
|
import 'admin-lte/plugins/fontawesome-free/css/all.min.css';
|
||||||
|
|
||||||
|
// select2 plugin
|
||||||
|
import 'admin-lte/plugins/select2/css/select2.min.css';
|
||||||
|
import 'admin-lte/plugins/select2/js/select2.min.js';
|
||||||
|
|
||||||
|
// dataTables plugin
|
||||||
|
import 'admin-lte/plugins/datatables-bs4/css/dataTables.bootstrap4.min.css';
|
||||||
|
import 'admin-lte/plugins/datatables-responsive/css/responsive.bootstrap4.min.css';
|
||||||
|
import 'admin-lte/plugins/datatables/jquery.dataTables.min.js';
|
||||||
|
import 'admin-lte/plugins/datatables-bs4/js/dataTables.bootstrap4.min.js';
|
||||||
|
import 'admin-lte/plugins/datatables-responsive/js/dataTables.responsive.min.js';
|
||||||
|
import 'admin-lte/plugins/datatables-responsive/js/responsive.bootstrap4.min.js';
|
||||||
|
|
||||||
|
// clipboard.js
|
||||||
|
import 'clipboard/dist/clipboard.min.js';
|
||||||
|
|
||||||
|
@ -1,3 +1,3 @@
|
|||||||
__all__ = [
|
__all__ = [
|
||||||
'auth', 'postfix', 'dovecot', 'fetch'
|
'auth', 'postfix', 'dovecot', 'fetch', 'rspamd'
|
||||||
]
|
]
|
||||||
|
@ -0,0 +1,27 @@
|
|||||||
|
from mailu import models
|
||||||
|
from mailu.internal import internal
|
||||||
|
|
||||||
|
import flask
|
||||||
|
|
||||||
|
def vault_error(*messages, status=404):
|
||||||
|
return flask.make_response(flask.jsonify({'errors':messages}), status)
|
||||||
|
|
||||||
|
# rspamd key format:
|
||||||
|
# {"selectors":[{"pubkey":"...","domain":"...","valid_start":TS,"valid_end":TS,"key":"...","selector":"...","bits":...,"alg":"..."}]}
|
||||||
|
|
||||||
|
# hashicorp vault answer format:
|
||||||
|
# {"request_id":"...","lease_id":"","renewable":false,"lease_duration":2764800,"data":{...see above...},"wrap_info":null,"warnings":null,"auth":null}
|
||||||
|
|
||||||
|
@internal.route("/rspamd/vault/v1/dkim/<domain_name>", methods=['GET'])
|
||||||
|
def rspamd_dkim_key(domain_name):
|
||||||
|
selectors = []
|
||||||
|
if domain := models.Domain.query.get(domain_name):
|
||||||
|
if key := domain.dkim_key:
|
||||||
|
selectors.append(
|
||||||
|
{
|
||||||
|
'domain' : domain.name,
|
||||||
|
'key' : key.decode('utf8'),
|
||||||
|
'selector': flask.current_app.config.get('DKIM_SELECTOR', 'dkim'),
|
||||||
|
}
|
||||||
|
)
|
||||||
|
return flask.jsonify({'data': {'selectors': selectors}})
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,5 @@
|
|||||||
|
from flask import Blueprint
|
||||||
|
|
||||||
|
sso = Blueprint('sso', __name__, static_folder=None, template_folder='templates')
|
||||||
|
|
||||||
|
from mailu.sso.views import *
|
@ -0,0 +1,11 @@
|
|||||||
|
from wtforms import validators, fields
|
||||||
|
from flask_babel import lazy_gettext as _
|
||||||
|
import flask_wtf
|
||||||
|
|
||||||
|
class LoginForm(flask_wtf.FlaskForm):
|
||||||
|
class Meta:
|
||||||
|
csrf = False
|
||||||
|
email = fields.StringField(_('E-mail'), [validators.Email(), validators.DataRequired()])
|
||||||
|
pw = fields.PasswordField(_('Password'), [validators.DataRequired()])
|
||||||
|
submitAdmin = fields.SubmitField(_('Sign in'))
|
||||||
|
submitWebmail = fields.SubmitField(_('Sign in'))
|
@ -0,0 +1,86 @@
|
|||||||
|
{%- import "macros.html" as macros %}
|
||||||
|
{%- import "bootstrap/utils.html" as utils %}
|
||||||
|
<!doctype html>
|
||||||
|
<html lang="{{ session['language'] }}" data-static="/static/">
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8">
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||||
|
<meta name="description" content="{% trans %}Admin page for{% endtrans %} {{ config["SITENAME"] }}">
|
||||||
|
<meta http-equiv="x-ua-compatible" content="ie=edge">
|
||||||
|
<title>Mailu-Admin | {{ config["SITENAME"] }}</title>
|
||||||
|
<link rel="stylesheet" href="{{ url_for('static', filename='vendor.css') }}">
|
||||||
|
<link rel="stylesheet" href="{{ url_for('static', filename='app.css') }}">
|
||||||
|
</head>
|
||||||
|
<body class="hold-transition sidebar-mini layout-fixed">
|
||||||
|
<div class="wrapper">
|
||||||
|
<nav class="main-header navbar navbar-expand navbar-white navbar-light">
|
||||||
|
<ul class="navbar-nav">
|
||||||
|
<li class="nav-item">
|
||||||
|
<a class="nav-link" data-widget="pushmenu" href="#" role="button"><i class="fas fa-bars" title="{% trans %}toggle sidebar{% endtrans %}" aria-expanded="false"></i><span class="sr-only">{% trans %}toggle sidebar{% endtrans %}</span></a>
|
||||||
|
</li>
|
||||||
|
<li class="nav-item">
|
||||||
|
{%- for page, url in path %}
|
||||||
|
{%- if loop.index > 1 %}
|
||||||
|
<i class="fas fa-greater-than text-xs text-gray" aria-hidden="true"></i>
|
||||||
|
{%- endif %}
|
||||||
|
{%- if url %}
|
||||||
|
<a class="nav-link d-inline-block" href="{{ url }}" role="button">{{ page }}</a>
|
||||||
|
{%- else %}
|
||||||
|
<span class="nav-link d-inline-block">{{ page }}</span>
|
||||||
|
{%- endif %}
|
||||||
|
{%- endfor %}
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
<ul class="navbar-nav ml-auto">
|
||||||
|
<li class="nav-item dropdown">
|
||||||
|
<a class="nav-link" data-toggle="dropdown" href="#" aria-expanded="false">
|
||||||
|
<i class="fas fa-language text-xl" aria-hidden="true" title="{% trans %}change language{% endtrans %}"></i><span class="sr-only">Language</span>
|
||||||
|
<span class="badge badge-primary navbar-badge">{{ session['language'] }}</span></a>
|
||||||
|
<div class="dropdown-menu dropdown-menu-right p-0" id="mailu-languages">
|
||||||
|
{%- for locale in config.translations.values() %}
|
||||||
|
<a class="dropdown-item{% if locale|string() == session['language'] %} active{% endif %}" href="{{ url_for('sso.set_language', language=locale) }}">{{ locale.get_language_name().title() }}</a>
|
||||||
|
{%- endfor %}
|
||||||
|
</div>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</nav>
|
||||||
|
<aside class="main-sidebar sidebar-dark-primary nav-compact elevation-4">
|
||||||
|
<a class="brand-link bg-mailu-logo"{% if config["LOGO_BACKGROUND"] %} style="background-color:{{ config["LOGO_BACKGROUND"] }}!important;"{% endif %}>
|
||||||
|
<img src="{{ config["LOGO_URL"] if config["LOGO_URL"] else '/static/mailu.png' }}" width="33" height="33" alt="Mailu" class="brand-image mailu-logo img-circle elevation-3">
|
||||||
|
<span class="brand-text font-weight-light">{{ config["SITENAME"] }}</span>
|
||||||
|
</a>
|
||||||
|
{%- include "sidebar_sso.html" %}
|
||||||
|
</aside>
|
||||||
|
<div class="content-wrapper text-sm">
|
||||||
|
<section class="content-header">
|
||||||
|
<div class="container-fluid">
|
||||||
|
<div class="row mb-2">
|
||||||
|
<div class="col-sm-6">
|
||||||
|
<h1 class="m-0">{%- block title %}{%- endblock %}</h1>
|
||||||
|
<small>{% block subtitle %}{% endblock %}</small>
|
||||||
|
</div>
|
||||||
|
<div class="col-sm-6">
|
||||||
|
{%- block main_action %}{%- endblock %}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
<div class="content">
|
||||||
|
{{ utils.flashed_messages(container=False, default_category='success') }}
|
||||||
|
{%- block content %}{%- endblock %}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<footer class="main-footer">
|
||||||
|
Built with <i class="fa fa-heart text-danger" aria-hidden="true"></i><span class="sr-only">love</span>
|
||||||
|
using <a href="https://flask.palletsprojects.com/">Flask</a>
|
||||||
|
and <a href="https://adminlte.io/themes/v3/index3.html">AdminLTE</a>.
|
||||||
|
<span class="fa-pull-right">
|
||||||
|
<i class="fa fa-code-branch" aria-hidden="true"></i><span class="sr-only">fork</span>
|
||||||
|
on <a href="https://github.com/Mailu/Mailu">Github</a>
|
||||||
|
</span>
|
||||||
|
</footer>
|
||||||
|
</div>
|
||||||
|
<script src="{{ url_for('static', filename='vendor.js') }}"></script>
|
||||||
|
<script src="{{ url_for('static', filename='app.js') }}"></script>
|
||||||
|
</body>
|
||||||
|
</html>
|
@ -0,0 +1,11 @@
|
|||||||
|
{%- extends "base_sso.html" %}
|
||||||
|
|
||||||
|
{%- block content %}
|
||||||
|
{%- call macros.card() %}
|
||||||
|
<form class="form" method="post" role="form">
|
||||||
|
{{ macros.form_field(form.email) }}
|
||||||
|
{{ macros.form_field(form.pw) }}
|
||||||
|
{{ macros.form_fields(fields, label=False, class="btn btn-default") }}
|
||||||
|
</form>
|
||||||
|
{%- endcall %}
|
||||||
|
{%- endblock %}
|
@ -0,0 +1,5 @@
|
|||||||
|
{%- extends "form_sso.html" %}
|
||||||
|
|
||||||
|
{%- block title %}
|
||||||
|
{% trans %}Sign in{% endtrans %}
|
||||||
|
{%- endblock %}
|
@ -0,0 +1,55 @@
|
|||||||
|
<div class="sidebar text-sm">
|
||||||
|
<nav class="mt-2">
|
||||||
|
<ul class="nav nav-pills nav-sidebar flex-column" role="menu">
|
||||||
|
<li class="nav-header text-uppercase text-primary" role="none">{% trans %}Go to{% endtrans %}</li>
|
||||||
|
{%- if config['ADMIN'] %}
|
||||||
|
<li class="nav-item">
|
||||||
|
<a href="{{ url_for('ui.client') }}" class="nav-link">
|
||||||
|
<i class="nav-icon fa fa-laptop"></i>
|
||||||
|
<p class="text">{% trans %}Client setup{% endtrans %}</p>
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
{%- endif %}
|
||||||
|
<li class="nav-item" role="none">
|
||||||
|
<a href="{{ config["WEBSITE"] }}" target="_blank" class="nav-link" role="menuitem" rel="noreferrer">
|
||||||
|
<i class="nav-icon fa fa-globe"></i>
|
||||||
|
<p>{% trans %}Website{% endtrans %} <i class="fas fa-external-link-alt text-xs"></i></p>
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
<li class="nav-item" role="none">
|
||||||
|
<a href="https://mailu.io" target="_blank" class="nav-link" role="menuitem">
|
||||||
|
<i class="nav-icon fa fa-life-ring"></i>
|
||||||
|
<p class="text">{% trans %}Help{% endtrans %} <i class="fas fa-external-link-alt text-xs"></i></p>
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
{#-
|
||||||
|
Domain self-registration is only available when
|
||||||
|
- Admin is available
|
||||||
|
- Domain Self-registration is enabled
|
||||||
|
- The current user is not logged on
|
||||||
|
#}
|
||||||
|
{%- if config['DOMAIN_REGISTRATION'] and not current_user.is_authenticated and config['ADMIN'] %}
|
||||||
|
<li class="nav-item" role="none">
|
||||||
|
<a href="{{ url_for('ui.domain_signup') }}" class="nav-link" role="menuitem">
|
||||||
|
<i class="nav-icon fa fa-plus-square"></i>
|
||||||
|
<p class="text">{% trans %}Register a domain{% endtrans %}</p>
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
{%- endif %}
|
||||||
|
{#-
|
||||||
|
User self-registration is only available when
|
||||||
|
- Admin is available
|
||||||
|
- Self-registration is enabled
|
||||||
|
- The current user is not logged on
|
||||||
|
#}
|
||||||
|
{%- if not current_user.is_authenticated and signup_domains and config['ADMIN'] %}
|
||||||
|
<li class="nav-item" role="none">
|
||||||
|
<a href="{{ url_for('ui.user_signup') }}" class="nav-link" role="menuitem">
|
||||||
|
<i class="nav-icon fa fa-user-plus"></i>
|
||||||
|
<p class="text">{% trans %}Sign up{% endtrans %}</p>
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
{%- endif %}
|
||||||
|
</ul>
|
||||||
|
</nav>
|
||||||
|
</div>
|
@ -0,0 +1,3 @@
|
|||||||
|
__all__ = [
|
||||||
|
'base', 'languages'
|
||||||
|
]
|
@ -0,0 +1,57 @@
|
|||||||
|
from werkzeug.utils import redirect
|
||||||
|
from mailu import models, utils
|
||||||
|
from mailu.sso import sso, forms
|
||||||
|
from mailu.ui import access
|
||||||
|
|
||||||
|
from flask import current_app as app
|
||||||
|
import flask
|
||||||
|
import flask_login
|
||||||
|
|
||||||
|
@sso.route('/login', methods=['GET', 'POST'])
|
||||||
|
def login():
|
||||||
|
client_ip = flask.request.headers.get('X-Real-IP', flask.request.remote_addr)
|
||||||
|
form = forms.LoginForm()
|
||||||
|
form.submitAdmin.label.text = form.submitAdmin.label.text + ' Admin'
|
||||||
|
form.submitWebmail.label.text = form.submitWebmail.label.text + ' Webmail'
|
||||||
|
|
||||||
|
fields = []
|
||||||
|
if str(app.config["ADMIN"]).upper() != "FALSE":
|
||||||
|
fields.append(form.submitAdmin)
|
||||||
|
if str(app.config["WEBMAIL"]).upper() != "NONE":
|
||||||
|
fields.append(form.submitWebmail)
|
||||||
|
fields = [fields]
|
||||||
|
|
||||||
|
if form.validate_on_submit():
|
||||||
|
if form.submitAdmin.data:
|
||||||
|
destination = app.config['WEB_ADMIN']
|
||||||
|
elif form.submitWebmail.data:
|
||||||
|
destination = app.config['WEB_WEBMAIL']
|
||||||
|
device_cookie, device_cookie_username = utils.limiter.parse_device_cookie(flask.request.cookies.get('rate_limit'))
|
||||||
|
username = form.email.data
|
||||||
|
if username != device_cookie_username and utils.limiter.should_rate_limit_ip(client_ip):
|
||||||
|
flask.flash('Too many attempts from your IP (rate-limit)', 'error')
|
||||||
|
return flask.render_template('login.html', form=form)
|
||||||
|
if utils.limiter.should_rate_limit_user(username, client_ip, device_cookie, device_cookie_username):
|
||||||
|
flask.flash('Too many attempts for this user (rate-limit)', 'error')
|
||||||
|
return flask.render_template('login.html', form=form)
|
||||||
|
user = models.User.login(username, form.pw.data)
|
||||||
|
if user:
|
||||||
|
flask.session.regenerate()
|
||||||
|
flask_login.login_user(user)
|
||||||
|
response = flask.redirect(destination)
|
||||||
|
response.set_cookie('rate_limit', utils.limiter.device_cookie(username), max_age=31536000, path=flask.url_for('sso.login'), secure=app.config['SESSION_COOKIE_SECURE'], httponly=True)
|
||||||
|
flask.current_app.logger.info(f'Login succeeded for {username} from {client_ip}.')
|
||||||
|
return response
|
||||||
|
else:
|
||||||
|
utils.limiter.rate_limit_user(username, client_ip, device_cookie, device_cookie_username) if models.User.get(username) else utils.limiter.rate_limit_ip(client_ip)
|
||||||
|
flask.current_app.logger.warn(f'Login failed for {username} from {client_ip}.')
|
||||||
|
flask.flash('Wrong e-mail or password', 'error')
|
||||||
|
return flask.render_template('login.html', form=form, fields=fields)
|
||||||
|
|
||||||
|
@sso.route('/logout', methods=['GET'])
|
||||||
|
@access.authenticated
|
||||||
|
def logout():
|
||||||
|
flask_login.logout_user()
|
||||||
|
flask.session.destroy()
|
||||||
|
return flask.redirect(flask.url_for('.login'))
|
||||||
|
|
@ -0,0 +1,7 @@
|
|||||||
|
from mailu.sso import sso
|
||||||
|
import flask
|
||||||
|
|
||||||
|
@sso.route('/language/<language>', methods=['POST'])
|
||||||
|
def set_language(language=None):
|
||||||
|
flask.session['language'] = language
|
||||||
|
return flask.Response(status=200)
|
@ -0,0 +1,672 @@
|
|||||||
|
# Translations template for PROJECT.
|
||||||
|
# Copyright (C) 2018 ORGANIZATION
|
||||||
|
# This file is distributed under the same license as the PROJECT project.
|
||||||
|
# FIRST AUTHOR <EMAIL@ADDRESS>, 2018.
|
||||||
|
#
|
||||||
|
msgid ""
|
||||||
|
msgstr ""
|
||||||
|
"Project-Id-Version: PROJECT VERSION\n"
|
||||||
|
"Report-Msgid-Bugs-To: EMAIL@ADDRESS\n"
|
||||||
|
"POT-Creation-Date: 2018-04-22 12:10+0200\n"
|
||||||
|
"PO-Revision-Date: 2021-03-04 18:46+0000\n"
|
||||||
|
"Last-Translator: Jaume Barber <jaumebarber@gmail.com>\n"
|
||||||
|
"Language-Team: Basque <https://translate.tedomum.net/projects/mailu/admin/eu/"
|
||||||
|
">\n"
|
||||||
|
"Language: eu\n"
|
||||||
|
"MIME-Version: 1.0\n"
|
||||||
|
"Content-Type: text/plain; charset=utf-8\n"
|
||||||
|
"Content-Transfer-Encoding: 8bit\n"
|
||||||
|
"Plural-Forms: nplurals=2; plural=n != 1;\n"
|
||||||
|
"X-Generator: Weblate 4.0.1\n"
|
||||||
|
"Generated-By: Babel 2.5.3\n"
|
||||||
|
|
||||||
|
#: mailu/ui/forms.py:32
|
||||||
|
msgid "Invalid email address."
|
||||||
|
msgstr "baliogabeko helbide elektronikoa."
|
||||||
|
|
||||||
|
#: mailu/ui/forms.py:36
|
||||||
|
msgid "Confirm"
|
||||||
|
msgstr "Ados"
|
||||||
|
|
||||||
|
#: mailu/ui/forms.py:40 mailu/ui/forms.py:77
|
||||||
|
msgid "E-mail"
|
||||||
|
msgstr "E-mail"
|
||||||
|
|
||||||
|
#: mailu/ui/forms.py:41 mailu/ui/forms.py:78 mailu/ui/forms.py:90
|
||||||
|
#: mailu/ui/forms.py:109 mailu/ui/forms.py:162
|
||||||
|
#: mailu/ui/templates/client.html:32 mailu/ui/templates/client.html:59
|
||||||
|
msgid "Password"
|
||||||
|
msgstr "Pasahitza"
|
||||||
|
|
||||||
|
#: mailu/ui/forms.py:42 mailu/ui/templates/login.html:4
|
||||||
|
#: mailu/ui/templates/sidebar.html:111
|
||||||
|
msgid "Sign in"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: mailu/ui/forms.py:46 mailu/ui/forms.py:56
|
||||||
|
#: mailu/ui/templates/domain/details.html:27
|
||||||
|
#: mailu/ui/templates/domain/list.html:18 mailu/ui/templates/relay/list.html:17
|
||||||
|
msgid "Domain name"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: mailu/ui/forms.py:47
|
||||||
|
msgid "Maximum user count"
|
||||||
|
msgstr "Erabiltzaileen gehieneko kopurua"
|
||||||
|
|
||||||
|
#: mailu/ui/forms.py:48
|
||||||
|
msgid "Maximum alias count"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: mailu/ui/forms.py:49
|
||||||
|
msgid "Maximum user quota"
|
||||||
|
msgstr "Erabiltzaile bakoitzeko gehieneko espazioa"
|
||||||
|
|
||||||
|
#: mailu/ui/forms.py:50
|
||||||
|
msgid "Enable sign-up"
|
||||||
|
msgstr "Gaitu erregistroa"
|
||||||
|
|
||||||
|
#: mailu/ui/forms.py:51 mailu/ui/forms.py:72 mailu/ui/forms.py:83
|
||||||
|
#: mailu/ui/forms.py:128 mailu/ui/forms.py:140
|
||||||
|
#: mailu/ui/templates/alias/list.html:21 mailu/ui/templates/domain/list.html:21
|
||||||
|
#: mailu/ui/templates/relay/list.html:19 mailu/ui/templates/token/list.html:19
|
||||||
|
#: mailu/ui/templates/user/list.html:23
|
||||||
|
msgid "Comment"
|
||||||
|
msgstr "Iruzkindua"
|
||||||
|
|
||||||
|
#: mailu/ui/forms.py:52 mailu/ui/forms.py:61 mailu/ui/forms.py:66
|
||||||
|
#: mailu/ui/forms.py:73 mailu/ui/forms.py:132 mailu/ui/forms.py:141
|
||||||
|
msgid "Create"
|
||||||
|
msgstr "Sortu"
|
||||||
|
|
||||||
|
#: mailu/ui/forms.py:57
|
||||||
|
msgid "Initial admin"
|
||||||
|
msgstr "Administratzailea"
|
||||||
|
|
||||||
|
#: mailu/ui/forms.py:58
|
||||||
|
msgid "Admin password"
|
||||||
|
msgstr "Administratzaileko pasahitza"
|
||||||
|
|
||||||
|
#: mailu/ui/forms.py:59 mailu/ui/forms.py:79 mailu/ui/forms.py:91
|
||||||
|
msgid "Confirm password"
|
||||||
|
msgstr "Berretsi pasahitza"
|
||||||
|
|
||||||
|
#: mailu/ui/forms.py:65
|
||||||
|
msgid "Alternative name"
|
||||||
|
msgstr "Izen alternatiboa"
|
||||||
|
|
||||||
|
#: mailu/ui/forms.py:70
|
||||||
|
msgid "Relayed domain name"
|
||||||
|
msgstr "Igorritako domeinu izena"
|
||||||
|
|
||||||
|
#: mailu/ui/forms.py:71 mailu/ui/templates/relay/list.html:18
|
||||||
|
msgid "Remote host"
|
||||||
|
msgstr "Urruneko ostalaria"
|
||||||
|
|
||||||
|
#: mailu/ui/forms.py:80 mailu/ui/templates/user/list.html:22
|
||||||
|
#: mailu/ui/templates/user/signup_domain.html:16
|
||||||
|
msgid "Quota"
|
||||||
|
msgstr "Espazioa"
|
||||||
|
|
||||||
|
#: mailu/ui/forms.py:81
|
||||||
|
msgid "Allow IMAP access"
|
||||||
|
msgstr "Baimendu IMAP sarbidea"
|
||||||
|
|
||||||
|
#: mailu/ui/forms.py:82
|
||||||
|
msgid "Allow POP3 access"
|
||||||
|
msgstr "Baimendu POP3 sarbidea"
|
||||||
|
|
||||||
|
#: mailu/ui/forms.py:84
|
||||||
|
msgid "Enabled"
|
||||||
|
msgstr "Gaituta"
|
||||||
|
|
||||||
|
#: mailu/ui/forms.py:85
|
||||||
|
msgid "Save"
|
||||||
|
msgstr "Gorde"
|
||||||
|
|
||||||
|
#: mailu/ui/forms.py:89
|
||||||
|
msgid "Email address"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: mailu/ui/forms.py:93 mailu/ui/templates/sidebar.html:117
|
||||||
|
#: mailu/ui/templates/user/signup.html:4
|
||||||
|
#: mailu/ui/templates/user/signup_domain.html:4
|
||||||
|
msgid "Sign up"
|
||||||
|
msgstr "Erregistratu"
|
||||||
|
|
||||||
|
#: mailu/ui/forms.py:97
|
||||||
|
msgid "Displayed name"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: mailu/ui/forms.py:98
|
||||||
|
msgid "Enable spam filter"
|
||||||
|
msgstr "Gaitu spam iragazkia"
|
||||||
|
|
||||||
|
#: mailu/ui/forms.py:99
|
||||||
|
msgid "Spam filter tolerance"
|
||||||
|
msgstr "Spam iragazkiaren tolerantzia"
|
||||||
|
|
||||||
|
#: mailu/ui/forms.py:100
|
||||||
|
msgid "Enable forwarding"
|
||||||
|
msgstr "Gaitu birbidaltzea"
|
||||||
|
|
||||||
|
#: mailu/ui/forms.py:101
|
||||||
|
msgid "Keep a copy of the emails"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: mailu/ui/forms.py:103 mailu/ui/forms.py:139
|
||||||
|
#: mailu/ui/templates/alias/list.html:20
|
||||||
|
msgid "Destination"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: mailu/ui/forms.py:105
|
||||||
|
msgid "Save settings"
|
||||||
|
msgstr "Gorde ezarpenak"
|
||||||
|
|
||||||
|
#: mailu/ui/forms.py:110
|
||||||
|
msgid "Password check"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: mailu/ui/forms.py:111 mailu/ui/templates/sidebar.html:16
|
||||||
|
msgid "Update password"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: mailu/ui/forms.py:115
|
||||||
|
msgid "Enable automatic reply"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: mailu/ui/forms.py:116
|
||||||
|
msgid "Reply subject"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: mailu/ui/forms.py:117
|
||||||
|
msgid "Reply body"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: mailu/ui/forms.py:119
|
||||||
|
msgid "End of vacation"
|
||||||
|
msgstr "Oporren amaiera"
|
||||||
|
|
||||||
|
#: mailu/ui/forms.py:120
|
||||||
|
msgid "Update"
|
||||||
|
msgstr "Eguneratu"
|
||||||
|
|
||||||
|
#: mailu/ui/forms.py:125
|
||||||
|
msgid "Your token (write it down, as it will never be displayed again)"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: mailu/ui/forms.py:130 mailu/ui/templates/token/list.html:20
|
||||||
|
msgid "Authorized IP"
|
||||||
|
msgstr "Baimendutako IP"
|
||||||
|
|
||||||
|
#: mailu/ui/forms.py:136
|
||||||
|
msgid "Alias"
|
||||||
|
msgstr "Ezizenza"
|
||||||
|
|
||||||
|
#: mailu/ui/forms.py:138
|
||||||
|
msgid "Use SQL LIKE Syntax (e.g. for catch-all aliases)"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: mailu/ui/forms.py:145
|
||||||
|
msgid "Admin email"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: mailu/ui/forms.py:146 mailu/ui/forms.py:151 mailu/ui/forms.py:164
|
||||||
|
msgid "Submit"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: mailu/ui/forms.py:150
|
||||||
|
msgid "Manager email"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: mailu/ui/forms.py:155
|
||||||
|
msgid "Protocol"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: mailu/ui/forms.py:158
|
||||||
|
msgid "Hostname or IP"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: mailu/ui/forms.py:159 mailu/ui/templates/client.html:20
|
||||||
|
#: mailu/ui/templates/client.html:47
|
||||||
|
msgid "TCP port"
|
||||||
|
msgstr "TCP ataka"
|
||||||
|
|
||||||
|
#: mailu/ui/forms.py:160
|
||||||
|
msgid "Enable TLS"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: mailu/ui/forms.py:161 mailu/ui/templates/client.html:28
|
||||||
|
#: mailu/ui/templates/client.html:55 mailu/ui/templates/fetch/list.html:20
|
||||||
|
msgid "Username"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: mailu/ui/forms.py:163
|
||||||
|
msgid "Keep emails on the server"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: mailu/ui/forms.py:168
|
||||||
|
msgid "Announcement subject"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: mailu/ui/forms.py:170
|
||||||
|
msgid "Announcement body"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: mailu/ui/forms.py:172
|
||||||
|
msgid "Send"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: mailu/ui/templates/announcement.html:4
|
||||||
|
msgid "Public announcement"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: mailu/ui/templates/client.html:4 mailu/ui/templates/sidebar.html:82
|
||||||
|
msgid "Client setup"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: mailu/ui/templates/client.html:16 mailu/ui/templates/client.html:43
|
||||||
|
msgid "Mail protocol"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: mailu/ui/templates/client.html:24 mailu/ui/templates/client.html:51
|
||||||
|
msgid "Server name"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: mailu/ui/templates/confirm.html:4
|
||||||
|
msgid "Confirm action"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: mailu/ui/templates/confirm.html:13
|
||||||
|
#, python-format
|
||||||
|
msgid "You are about to %(action)s. Please confirm your action."
|
||||||
|
msgstr "Zu zara %(action)s-etan. Mesedez ekintza honen berretsi."
|
||||||
|
|
||||||
|
#: mailu/ui/templates/docker-error.html:4
|
||||||
|
msgid "Docker error"
|
||||||
|
msgstr "Docker-en errorea"
|
||||||
|
|
||||||
|
#: mailu/ui/templates/docker-error.html:12
|
||||||
|
msgid "An error occurred while talking to the Docker server."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: mailu/ui/templates/login.html:8
|
||||||
|
msgid "to access the administration tools"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: mailu/ui/templates/sidebar.html:11 mailu/ui/templates/user/list.html:34
|
||||||
|
msgid "Settings"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: mailu/ui/templates/sidebar.html:21 mailu/ui/templates/user/list.html:35
|
||||||
|
msgid "Auto-reply"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: mailu/ui/templates/fetch/list.html:4 mailu/ui/templates/sidebar.html:26
|
||||||
|
#: mailu/ui/templates/user/list.html:36
|
||||||
|
msgid "Fetched accounts"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: mailu/ui/templates/sidebar.html:31 mailu/ui/templates/token/list.html:4
|
||||||
|
msgid "Authentication tokens"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: mailu/ui/templates/sidebar.html:35
|
||||||
|
msgid "Administration"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: mailu/ui/templates/sidebar.html:44
|
||||||
|
msgid "Announcement"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: mailu/ui/templates/sidebar.html:49
|
||||||
|
msgid "Administrators"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: mailu/ui/templates/sidebar.html:54
|
||||||
|
msgid "Relayed domains"
|
||||||
|
msgstr "Igorritako domeinuak"
|
||||||
|
|
||||||
|
#: mailu/ui/templates/sidebar.html:59 mailu/ui/templates/user/settings.html:15
|
||||||
|
msgid "Antispam"
|
||||||
|
msgstr "Antispam"
|
||||||
|
|
||||||
|
#: mailu/ui/templates/sidebar.html:66
|
||||||
|
msgid "Mail domains"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: mailu/ui/templates/sidebar.html:72
|
||||||
|
msgid "Go to"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: mailu/ui/templates/sidebar.html:76
|
||||||
|
msgid "Webmail"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: mailu/ui/templates/sidebar.html:87
|
||||||
|
msgid "Website"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: mailu/ui/templates/sidebar.html:92
|
||||||
|
msgid "Help"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: mailu/ui/templates/domain/signup.html:4 mailu/ui/templates/sidebar.html:98
|
||||||
|
msgid "Register a domain"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: mailu/ui/templates/sidebar.html:105
|
||||||
|
msgid "Sign out"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: mailu/ui/templates/working.html:4
|
||||||
|
msgid "We are still working on this feature!"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: mailu/ui/templates/admin/create.html:4
|
||||||
|
msgid "Add a global administrator"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: mailu/ui/templates/admin/list.html:4
|
||||||
|
msgid "Global administrators"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: mailu/ui/templates/admin/list.html:9
|
||||||
|
msgid "Add administrator"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: mailu/ui/templates/admin/list.html:16 mailu/ui/templates/alias/list.html:18
|
||||||
|
#: mailu/ui/templates/alternative/list.html:18
|
||||||
|
#: mailu/ui/templates/domain/list.html:16 mailu/ui/templates/fetch/list.html:18
|
||||||
|
#: mailu/ui/templates/manager/list.html:18
|
||||||
|
#: mailu/ui/templates/relay/list.html:16 mailu/ui/templates/token/list.html:18
|
||||||
|
#: mailu/ui/templates/user/list.html:18
|
||||||
|
msgid "Actions"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: mailu/ui/templates/admin/list.html:17 mailu/ui/templates/alias/list.html:19
|
||||||
|
#: mailu/ui/templates/manager/list.html:19 mailu/ui/templates/user/list.html:20
|
||||||
|
msgid "Email"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: mailu/ui/templates/admin/list.html:22 mailu/ui/templates/alias/list.html:29
|
||||||
|
#: mailu/ui/templates/alternative/list.html:25
|
||||||
|
#: mailu/ui/templates/domain/list.html:31 mailu/ui/templates/fetch/list.html:31
|
||||||
|
#: mailu/ui/templates/manager/list.html:24
|
||||||
|
#: mailu/ui/templates/relay/list.html:27 mailu/ui/templates/token/list.html:26
|
||||||
|
#: mailu/ui/templates/user/list.html:31
|
||||||
|
msgid "Delete"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: mailu/ui/templates/alias/create.html:4
|
||||||
|
msgid "Create alias"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: mailu/ui/templates/alias/edit.html:4
|
||||||
|
msgid "Edit alias"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: mailu/ui/templates/alias/list.html:4
|
||||||
|
msgid "Alias list"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: mailu/ui/templates/alias/list.html:12
|
||||||
|
msgid "Add alias"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: mailu/ui/templates/alias/list.html:22
|
||||||
|
#: mailu/ui/templates/alternative/list.html:20
|
||||||
|
#: mailu/ui/templates/domain/list.html:22 mailu/ui/templates/fetch/list.html:24
|
||||||
|
#: mailu/ui/templates/relay/list.html:20 mailu/ui/templates/token/list.html:21
|
||||||
|
#: mailu/ui/templates/user/list.html:24
|
||||||
|
msgid "Created"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: mailu/ui/templates/alias/list.html:23 mailu/ui/templates/domain/list.html:23
|
||||||
|
#: mailu/ui/templates/fetch/list.html:25 mailu/ui/templates/relay/list.html:21
|
||||||
|
#: mailu/ui/templates/user/list.html:25
|
||||||
|
msgid "Last edit"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: mailu/ui/templates/alias/list.html:28 mailu/ui/templates/domain/list.html:30
|
||||||
|
#: mailu/ui/templates/fetch/list.html:30 mailu/ui/templates/relay/list.html:26
|
||||||
|
#: mailu/ui/templates/user/list.html:30
|
||||||
|
msgid "Edit"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: mailu/ui/templates/alternative/create.html:4
|
||||||
|
msgid "Create alternative domain"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: mailu/ui/templates/alternative/list.html:4
|
||||||
|
msgid "Alternative domain list"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: mailu/ui/templates/alternative/list.html:12
|
||||||
|
msgid "Add alternative"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: mailu/ui/templates/alternative/list.html:19
|
||||||
|
msgid "Name"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: mailu/ui/templates/domain/create.html:4
|
||||||
|
#: mailu/ui/templates/domain/list.html:9
|
||||||
|
msgid "New domain"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: mailu/ui/templates/domain/details.html:4
|
||||||
|
msgid "Domain details"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: mailu/ui/templates/domain/details.html:15
|
||||||
|
msgid "Regenerate keys"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: mailu/ui/templates/domain/details.html:17
|
||||||
|
msgid "Generate keys"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: mailu/ui/templates/domain/details.html:31
|
||||||
|
msgid "DNS MX entry"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: mailu/ui/templates/domain/details.html:35
|
||||||
|
msgid "DNS SPF entries"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: mailu/ui/templates/domain/details.html:42
|
||||||
|
msgid "DKIM public key"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: mailu/ui/templates/domain/details.html:46
|
||||||
|
msgid "DNS DKIM entry"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: mailu/ui/templates/domain/details.html:50
|
||||||
|
msgid "DNS DMARC entry"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: mailu/ui/templates/domain/edit.html:4
|
||||||
|
msgid "Edit domain"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: mailu/ui/templates/domain/list.html:4
|
||||||
|
msgid "Domain list"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: mailu/ui/templates/domain/list.html:17
|
||||||
|
msgid "Manage"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: mailu/ui/templates/domain/list.html:19
|
||||||
|
msgid "Mailbox count"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: mailu/ui/templates/domain/list.html:20
|
||||||
|
msgid "Alias count"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: mailu/ui/templates/domain/list.html:28
|
||||||
|
msgid "Details"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: mailu/ui/templates/domain/list.html:35
|
||||||
|
msgid "Users"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: mailu/ui/templates/domain/list.html:36
|
||||||
|
msgid "Aliases"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: mailu/ui/templates/domain/list.html:37
|
||||||
|
msgid "Managers"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: mailu/ui/templates/domain/list.html:39
|
||||||
|
msgid "Alternatives"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: mailu/ui/templates/domain/signup.html:13
|
||||||
|
msgid ""
|
||||||
|
"In order to register a new domain, you must first setup the\n"
|
||||||
|
" domain zone so that the domain <code>MX</code> points to this server"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: mailu/ui/templates/domain/signup.html:18
|
||||||
|
msgid ""
|
||||||
|
"If you do not know how to setup an <code>MX</code> record for your DNS "
|
||||||
|
"zone,\n"
|
||||||
|
" please contact your DNS provider or administrator. Also, please wait "
|
||||||
|
"a\n"
|
||||||
|
" couple minutes after the <code>MX</code> is set so the local server "
|
||||||
|
"cache\n"
|
||||||
|
" expires."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: mailu/ui/templates/fetch/create.html:4
|
||||||
|
msgid "Add a fetched account"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: mailu/ui/templates/fetch/edit.html:4
|
||||||
|
msgid "Update a fetched account"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: mailu/ui/templates/fetch/list.html:12
|
||||||
|
msgid "Add an account"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: mailu/ui/templates/fetch/list.html:19
|
||||||
|
msgid "Endpoint"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: mailu/ui/templates/fetch/list.html:21
|
||||||
|
msgid "Keep emails"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: mailu/ui/templates/fetch/list.html:22
|
||||||
|
msgid "Last check"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: mailu/ui/templates/fetch/list.html:35
|
||||||
|
msgid "yes"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: mailu/ui/templates/fetch/list.html:35
|
||||||
|
msgid "no"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: mailu/ui/templates/manager/create.html:4
|
||||||
|
msgid "Add a manager"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: mailu/ui/templates/manager/list.html:4
|
||||||
|
msgid "Manager list"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: mailu/ui/templates/manager/list.html:12
|
||||||
|
msgid "Add manager"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: mailu/ui/templates/relay/create.html:4
|
||||||
|
msgid "New relay domain"
|
||||||
|
msgstr "Igorritako domeinu berria"
|
||||||
|
|
||||||
|
#: mailu/ui/templates/relay/edit.html:4
|
||||||
|
msgid "Edit relayd domain"
|
||||||
|
msgstr "Editatu igorritako domeinua"
|
||||||
|
|
||||||
|
#: mailu/ui/templates/relay/list.html:4
|
||||||
|
msgid "Relayed domain list"
|
||||||
|
msgstr "Igorritako domeinuen zerrenda"
|
||||||
|
|
||||||
|
#: mailu/ui/templates/relay/list.html:9
|
||||||
|
msgid "New relayed domain"
|
||||||
|
msgstr "Igorritako domeinu berria"
|
||||||
|
|
||||||
|
#: mailu/ui/templates/token/create.html:4
|
||||||
|
msgid "Create an authentication token"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: mailu/ui/templates/token/list.html:12
|
||||||
|
msgid "New token"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: mailu/ui/templates/user/create.html:4
|
||||||
|
msgid "New user"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: mailu/ui/templates/user/create.html:15
|
||||||
|
msgid "General"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: mailu/ui/templates/user/create.html:22
|
||||||
|
msgid "Features and quotas"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: mailu/ui/templates/user/edit.html:4
|
||||||
|
msgid "Edit user"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: mailu/ui/templates/user/forward.html:4
|
||||||
|
msgid "Forward emails"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: mailu/ui/templates/user/list.html:4
|
||||||
|
msgid "User list"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: mailu/ui/templates/user/list.html:12
|
||||||
|
msgid "Add user"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: mailu/ui/templates/user/list.html:19 mailu/ui/templates/user/settings.html:4
|
||||||
|
msgid "User settings"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: mailu/ui/templates/user/list.html:21
|
||||||
|
msgid "Features"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: mailu/ui/templates/user/password.html:4
|
||||||
|
msgid "Password update"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: mailu/ui/templates/user/reply.html:4
|
||||||
|
msgid "Automatic reply"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: mailu/ui/templates/user/settings.html:22
|
||||||
|
msgid "Auto-forward"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: mailu/ui/templates/user/signup_domain.html:8
|
||||||
|
msgid "pick a domain for the new account"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: mailu/ui/templates/user/signup_domain.html:14
|
||||||
|
msgid "Domain"
|
||||||
|
msgstr "Domeinu izena"
|
||||||
|
|
||||||
|
#: mailu/ui/templates/user/signup_domain.html:15
|
||||||
|
msgid "Available slots"
|
||||||
|
msgstr ""
|
@ -1,6 +1,6 @@
|
|||||||
from flask import Blueprint
|
from flask import Blueprint
|
||||||
|
|
||||||
|
|
||||||
ui = Blueprint('ui', __name__, static_folder='static', template_folder='templates')
|
ui = Blueprint('ui', __name__, static_folder=None, template_folder='templates')
|
||||||
|
|
||||||
from mailu.ui.views import *
|
from mailu.ui.views import *
|
||||||
|
@ -1,15 +1,15 @@
|
|||||||
{% extends "base.html" %}
|
{%- extends "base.html" %}
|
||||||
|
|
||||||
{% block title %}
|
{%- block title %}
|
||||||
{% trans %}Add a global administrator{% endtrans %}
|
{% trans %}Add a global administrator{% endtrans %}
|
||||||
{% endblock %}
|
{%- endblock %}
|
||||||
|
|
||||||
{% block content %}
|
{%- block content %}
|
||||||
{% call macros.box() %}
|
{%- call macros.card() %}
|
||||||
<form class="form" method="post" role="form">
|
<form class="form" method="post" role="form">
|
||||||
{{ form.hidden_tag() }}
|
{{ form.hidden_tag() }}
|
||||||
{{ macros.form_field(form.admin, class_='mailselect') }}
|
{{ macros.form_field(form.admin, class_='mailselect') }}
|
||||||
{{ macros.form_field(form.submit) }}
|
{{ macros.form_field(form.submit) }}
|
||||||
</form>
|
</form>
|
||||||
{% endcall %}
|
{%- endcall %}
|
||||||
{% endblock %}
|
{%- endblock %}
|
||||||
|
@ -1,28 +1,32 @@
|
|||||||
{% extends "base.html" %}
|
{%- extends "base.html" %}
|
||||||
|
|
||||||
{% block title %}
|
{%- block title %}
|
||||||
{% trans %}Global administrators{% endtrans %}
|
{% trans %}Global administrators{% endtrans %}
|
||||||
{% endblock %}
|
{%- endblock %}
|
||||||
|
|
||||||
{% block main_action %}
|
{%- block main_action %}
|
||||||
<a class="btn btn-primary" href="{{ url_for('.admin_create') }}">
|
<a class="btn btn-primary float-right" href="{{ url_for('.admin_create') }}">
|
||||||
{% trans %}Add administrator{% endtrans %}
|
{% trans %}Add administrator{% endtrans %}
|
||||||
</a>
|
</a>
|
||||||
{% endblock %}
|
{%- endblock %}
|
||||||
|
|
||||||
{% block content %}
|
{%- block content %}
|
||||||
{% call macros.table() %}
|
{%- call macros.table() %}
|
||||||
|
<thead>
|
||||||
<tr>
|
<tr>
|
||||||
<th>{% trans %}Actions{% endtrans %}</th>
|
<th>{% trans %}Actions{% endtrans %}</th>
|
||||||
<th>{% trans %}Email{% endtrans %}</th>
|
<th>{% trans %}Email{% endtrans %}</th>
|
||||||
</tr>
|
</tr>
|
||||||
{% for admin in admins %}
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
{%- for admin in admins %}
|
||||||
<tr>
|
<tr>
|
||||||
<td>
|
<td>
|
||||||
<a href="{{ url_for('.admin_delete', admin=admin.email) }}" title="{% trans %}Delete{% endtrans %}"><i class="fa fa-trash"></i></a>
|
<a href="{{ url_for('.admin_delete', admin=admin.email) }}" title="{% trans %}Delete{% endtrans %}"><i class="fa fa-trash"></i></a>
|
||||||
</td>
|
</td>
|
||||||
<td>{{ admin }}</td>
|
<td>{{ admin }}</td>
|
||||||
</tr>
|
</tr>
|
||||||
{% endfor %}
|
{%- endfor %}
|
||||||
{% endcall %}
|
</tbody>
|
||||||
{% endblock %}
|
{%- endcall %}
|
||||||
|
{%- endblock %}
|
||||||
|
@ -1,22 +1,22 @@
|
|||||||
{% extends "base.html" %}
|
{%- extends "base.html" %}
|
||||||
|
|
||||||
{% block title %}
|
{%- block title %}
|
||||||
{% trans %}Create alias{% endtrans %}
|
{% trans %}Create alias{% endtrans %}
|
||||||
{% endblock %}
|
{%- endblock %}
|
||||||
|
|
||||||
{% block subtitle %}
|
{%- block subtitle %}
|
||||||
{{ domain }}
|
{{ domain }}
|
||||||
{% endblock %}
|
{%- endblock %}
|
||||||
|
|
||||||
{% block content %}
|
{%- block content %}
|
||||||
{% call macros.box() %}
|
{%- call macros.card() %}
|
||||||
<form class="form" method="post" role="form">
|
<form class="form" method="post" role="form">
|
||||||
{{ form.hidden_tag() }}
|
{{ form.hidden_tag() }}
|
||||||
{{ macros.form_field(form.localpart, append='<span class="input-group-addon">@'+domain.name+'</span>') }}
|
{{ macros.form_field(form.localpart, append='<span class="input-group-text">@'+domain.name+'</span>') }}
|
||||||
{{ macros.form_field(form.wildcard) }}
|
{{ macros.form_field(form.wildcard) }}
|
||||||
{{ macros.form_field(form.destination, class_='mailselect') }}
|
{{ macros.form_field(form.destination, class_='mailselect') }}
|
||||||
{{ macros.form_field(form.comment) }}
|
{{ macros.form_field(form.comment) }}
|
||||||
{{ macros.form_field(form.submit) }}
|
{{ macros.form_field(form.submit) }}
|
||||||
</form>
|
</form>
|
||||||
{% endcall %}
|
{%- endcall %}
|
||||||
{% endblock %}
|
{%- endblock %}
|
||||||
|
@ -1,9 +1,9 @@
|
|||||||
{% extends "alias/create.html" %}
|
{%- extends "alias/create.html" %}
|
||||||
|
|
||||||
{% block title %}
|
{%- block title %}
|
||||||
{% trans %}Edit alias{% endtrans %}
|
{% trans %}Edit alias{% endtrans %}
|
||||||
{% endblock %}
|
{%- endblock %}
|
||||||
|
|
||||||
{% block subtitle %}
|
{%- block subtitle %}
|
||||||
{{ alias }}
|
{{ alias }}
|
||||||
{% endblock %}
|
{%- endblock %}
|
||||||
|
@ -1,9 +1,9 @@
|
|||||||
{% extends "form.html" %}
|
{%- extends "form.html" %}
|
||||||
|
|
||||||
{% block title %}
|
{%- block title %}
|
||||||
{% trans %}Create alternative domain{% endtrans %}
|
{% trans %}Create alternative domain{% endtrans %}
|
||||||
{% endblock %}
|
{%- endblock %}
|
||||||
|
|
||||||
{% block subtitle %}
|
{%- block subtitle %}
|
||||||
{{ domain }}
|
{{ domain }}
|
||||||
{% endblock %}
|
{%- endblock %}
|
||||||
|
@ -1,32 +1,38 @@
|
|||||||
{% extends "base.html" %}
|
{%- extends "base.html" %}
|
||||||
|
|
||||||
{% block title %}
|
{%- block title %}
|
||||||
{% trans %}Alternative domain list{% endtrans %}
|
{% trans %}Alternative domain list{% endtrans %}
|
||||||
{% endblock %}
|
{%- endblock %}
|
||||||
|
|
||||||
{% block subtitle %}
|
{%- block subtitle %}
|
||||||
{{ domain.name }}
|
{{ domain.name }}
|
||||||
{% endblock %}
|
{%- endblock %}
|
||||||
|
|
||||||
{% block main_action %}
|
{%- block main_action %}
|
||||||
<a class="btn btn-primary" href="{{ url_for('.alternative_create', domain_name=domain.name) }}">{% trans %}Add alternative{% endtrans %}</a>
|
<a class="btn btn-primary float-right" href="{{ url_for('.alternative_create', domain_name=domain.name) }}">{% trans %}Add alternative{% endtrans %}</a>
|
||||||
{% endblock %}
|
{%- endblock %}
|
||||||
|
|
||||||
{% block content %}
|
{%- block content %}
|
||||||
{% call macros.table() %}
|
{%- call macros.table() %}
|
||||||
|
<thead>
|
||||||
<tr>
|
<tr>
|
||||||
<th>{% trans %}Actions{% endtrans %}</th>
|
<th>{% trans %}Actions{% endtrans %}</th>
|
||||||
<th>{% trans %}Name{% endtrans %}</th>
|
<th>{% trans %}Name{% endtrans %}</th>
|
||||||
<th>{% trans %}Created{% endtrans %}</th>
|
<th>{% trans %}Created{% endtrans %}</th>
|
||||||
|
<th>{% trans %}Last edit{% endtrans %}</th>
|
||||||
</tr>
|
</tr>
|
||||||
{% for alternative in domain.alternatives %}
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
{%- for alternative in domain.alternatives %}
|
||||||
<tr>
|
<tr>
|
||||||
<td>
|
<td>
|
||||||
<a href="{{ url_for('.alternative_delete', alternative=alternative.name) }}" title="{% trans %}Delete{% endtrans %}"><i class="fa fa-trash"></i></a>
|
<a href="{{ url_for('.alternative_delete', alternative=alternative.name) }}" title="{% trans %}Delete{% endtrans %}"><i class="fa fa-trash"></i></a>
|
||||||
</td>
|
</td>
|
||||||
<td>{{ alternative }}</td>
|
<td>{{ alternative }}</td>
|
||||||
<td>{{ alternative.created_at }}</td>
|
<td>{{ alternative.created_at | format_date }}</td>
|
||||||
|
<td>{{ alternative.updated_at | format_date }}</td>
|
||||||
</tr>
|
</tr>
|
||||||
{% endfor %}
|
{%- endfor %}
|
||||||
{% endcall %}
|
</tbody>
|
||||||
{% endblock %}
|
{%- endcall %}
|
||||||
|
{%- endblock %}
|
||||||
|
@ -1,16 +1,16 @@
|
|||||||
{% extends "base.html" %}
|
{%- extends "base.html" %}
|
||||||
|
|
||||||
{% block title %}
|
{%- block title %}
|
||||||
{% trans %}Public announcement{% endtrans %}
|
{% trans %}Public announcement{% endtrans %}
|
||||||
{% endblock %}
|
{%- endblock %}
|
||||||
|
|
||||||
{% block content %}
|
{%- block content %}
|
||||||
{% call macros.box() %}
|
{%- call macros.card() %}
|
||||||
<form class="form" method="post" role="form">
|
<form class="form" method="post" role="form">
|
||||||
{{ form.hidden_tag() }}
|
{{ form.hidden_tag() }}
|
||||||
{{ macros.form_field(form.announcement_subject) }}
|
{{ macros.form_field(form.announcement_subject) }}
|
||||||
{{ macros.form_field(form.announcement_body, rows=10) }}
|
{{ macros.form_field(form.announcement_body, rows=10) }}
|
||||||
{{ macros.form_field(form.submit) }}
|
{{ macros.form_field(form.submit) }}
|
||||||
</form>
|
</form>
|
||||||
{% endcall %}
|
{%- endcall %}
|
||||||
{% endblock %}
|
{%- endblock %}
|
||||||
|
@ -0,0 +1,15 @@
|
|||||||
|
{%- extends "base.html" %}
|
||||||
|
|
||||||
|
{%- block title %}
|
||||||
|
{% trans %}Antispam{% endtrans %}
|
||||||
|
{%- endblock %}
|
||||||
|
|
||||||
|
{%- block subtitle %}
|
||||||
|
{% trans %}RSPAMD status page{% endtrans %}
|
||||||
|
{%- endblock %}
|
||||||
|
|
||||||
|
{%- block content %}
|
||||||
|
<div class="embed-responsive embed-responsive-1by1">
|
||||||
|
<iframe class="embed-responsive-item" src="{{ config["WEB_ADMIN"] }}/antispam/"></iframe>
|
||||||
|
</div>
|
||||||
|
{%- endblock %}
|
@ -1,52 +1,86 @@
|
|||||||
{% import "macros.html" as macros %}
|
{%- import "macros.html" as macros %}
|
||||||
|
{%- import "bootstrap/utils.html" as utils %}
|
||||||
<!doctype html>
|
<!doctype html>
|
||||||
<html>
|
<html lang="{{ session['language'] }}" data-static="/static/">
|
||||||
<head>
|
<head>
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
<meta charset="utf-8">
|
||||||
<link rel="stylesheet" href="{{ url_for('.static', filename='vendor.css') }}">
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||||
<link rel="stylesheet" href="{{ url_for('.static', filename='app.css') }}">
|
<meta name="description" content="{% trans %}Admin page for{% endtrans %} {{ config["SITENAME"] }}">
|
||||||
<title>Mailu-Admin - {{ config["SITENAME"] }}</title>
|
<meta http-equiv="x-ua-compatible" content="ie=edge">
|
||||||
|
<title>Mailu-Admin | {{ config["SITENAME"] }}</title>
|
||||||
|
<link rel="stylesheet" href="{{ url_for('static', filename='vendor.css') }}">
|
||||||
|
<link rel="stylesheet" href="{{ url_for('static', filename='app.css') }}">
|
||||||
</head>
|
</head>
|
||||||
<body class="hold-transition skin-blue sidebar-mini">
|
<body class="hold-transition sidebar-mini layout-fixed">
|
||||||
<div class="wrapper">
|
<div class="wrapper">
|
||||||
<header class="main-header">
|
<nav class="main-header navbar navbar-expand navbar-white navbar-light">
|
||||||
<div class="logo">
|
<ul class="navbar-nav">
|
||||||
<a href="#" class="sidebar-toggle" data-toggle="push-menu" role="button">
|
<li class="nav-item">
|
||||||
<span class="sr-only">Toggle navigation</span>
|
<a class="nav-link" data-widget="pushmenu" href="#" role="button"><i class="fas fa-bars" title="{% trans %}toggle sidebar{% endtrans %}" aria-expanded="false"></i><span class="sr-only">{% trans %}toggle sidebar{% endtrans %}</span></a>
|
||||||
</a>
|
</li>
|
||||||
<a href="{{ config["WEB_ADMIN"] }}">
|
<li class="nav-item">
|
||||||
<span class="logo-lg">{{ config["SITENAME"] }}</span>
|
{%- for page, url in path %}
|
||||||
</a>
|
{%- if loop.index > 1 %}
|
||||||
|
<i class="fas fa-greater-than text-xs text-gray" aria-hidden="true"></i>
|
||||||
|
{%- endif %}
|
||||||
|
{%- if url %}
|
||||||
|
<a class="nav-link d-inline-block" href="{{ url }}" role="button">{{ page }}</a>
|
||||||
|
{%- else %}
|
||||||
|
<span class="nav-link d-inline-block">{{ page }}</span>
|
||||||
|
{%- endif %}
|
||||||
|
{%- endfor %}
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
<ul class="navbar-nav ml-auto">
|
||||||
|
<li class="nav-item dropdown">
|
||||||
|
<a class="nav-link" data-toggle="dropdown" href="#" aria-expanded="false">
|
||||||
|
<i class="fas fa-language text-xl" aria-hidden="true" title="{% trans %}change language{% endtrans %}"></i><span class="sr-only">Language</span>
|
||||||
|
<span class="badge badge-primary navbar-badge">{{ session['language'] }}</span></a>
|
||||||
|
<div class="dropdown-menu dropdown-menu-right p-0" id="mailu-languages">
|
||||||
|
{%- for locale in config.translations.values() %}
|
||||||
|
<a class="dropdown-item{% if locale|string() == session['language'] %} active{% endif %}" href="{{ url_for('.set_language', language=locale) }}">{{ locale.get_language_name().title() }}</a>
|
||||||
|
{%- endfor %}
|
||||||
</div>
|
</div>
|
||||||
</header>
|
</li>
|
||||||
<aside class="main-sidebar">
|
</ul>
|
||||||
{% block sidebar %}
|
</nav>
|
||||||
{% include "sidebar.html" %}
|
<aside class="main-sidebar sidebar-dark-primary nav-compact elevation-4">
|
||||||
{% endblock %}
|
<a href="{{ url_for('.domain_list' if current_user.manager_of or current_user.global_admin else '.user_settings') }}" class="brand-link bg-mailu-logo"{% if config["LOGO_BACKGROUND"] %} style="background-color:{{ config["LOGO_BACKGROUND"] }}!important;"{% endif %}>
|
||||||
|
<img src="{{ config["LOGO_URL"] if config["LOGO_URL"] else url_for('static', filename='mailu.png') }}" width="33" height="33" alt="Mailu" class="brand-image mailu-logo img-circle elevation-3">
|
||||||
|
<span class="brand-text font-weight-light">{{ config["SITENAME"] }}</span>
|
||||||
|
</a>
|
||||||
|
{%- include "sidebar.html" %}
|
||||||
</aside>
|
</aside>
|
||||||
<div class="content-wrapper">
|
<div class="content-wrapper text-sm">
|
||||||
<section class="content-header">
|
<section class="content-header">
|
||||||
<div class="pull-right">
|
<div class="container-fluid">
|
||||||
{% block main_action %}
|
<div class="row mb-2">
|
||||||
{% endblock %}
|
<div class="col-sm-6">
|
||||||
</div>
|
<h1 class="m-0">{%- block title %}{%- endblock %}</h1>
|
||||||
<h1>
|
|
||||||
{% block title %}{% endblock %}
|
|
||||||
<small>{% block subtitle %}{% endblock %}</small>
|
<small>{% block subtitle %}{% endblock %}</small>
|
||||||
</h1>
|
</div>
|
||||||
</section>
|
<div class="col-sm-6">
|
||||||
|
{%- block main_action %}{%- endblock %}
|
||||||
<section class="content">
|
</div>
|
||||||
{% block content %}{% endblock %}
|
</div>
|
||||||
|
</div>
|
||||||
</section>
|
</section>
|
||||||
|
<div class="content">
|
||||||
|
{{ utils.flashed_messages(container=False, default_category='success') }}
|
||||||
|
{%- block content %}{%- endblock %}
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<footer class="main-footer">
|
<footer class="main-footer">
|
||||||
Built with <i class="fa fa-heart"></i> using <a class="white-text" href="http://flask.pocoo.org/">Flask</a> and
|
Built with <i class="fa fa-heart text-danger" aria-hidden="true"></i><span class="sr-only">love</span>
|
||||||
<a class="white-text" href="https://almsaeedstudio.com/preview">AdminLTE</a>
|
using <a href="https://flask.palletsprojects.com/">Flask</a>
|
||||||
<span class="pull-right"><i class="fa fa-code-fork"></i> on <a class="white-text" href="https://github.com/Mailu/Mailu">Github</a></a></span>
|
and <a href="https://adminlte.io/themes/v3/index3.html">AdminLTE</a>.
|
||||||
|
<span class="fa-pull-right">
|
||||||
|
<i class="fa fa-code-branch" aria-hidden="true"></i><span class="sr-only">fork</span>
|
||||||
|
on <a href="https://github.com/Mailu/Mailu">Github</a>
|
||||||
|
</span>
|
||||||
</footer>
|
</footer>
|
||||||
</div>
|
</div>
|
||||||
<script src="{{ url_for('.static', filename='vendor.js') }}"></script>
|
<script src="{{ url_for('static', filename='vendor.js') }}"></script>
|
||||||
<script src="{{ url_for('.static', filename='app.js') }}"></script>
|
<script src="{{ url_for('static', filename='app.js') }}"></script>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
@ -1,16 +1,16 @@
|
|||||||
{% extends "base.html" %}
|
{%- extends "base.html" %}
|
||||||
|
|
||||||
{% block title %}
|
{%- block title %}
|
||||||
{% trans %}Confirm action{% endtrans %}
|
{% trans %}Confirm action{% endtrans %}
|
||||||
{% endblock %}
|
{%- endblock %}
|
||||||
|
|
||||||
{% block subtitle %}
|
{%- block subtitle %}
|
||||||
{{ action }}
|
{{ action }}
|
||||||
{% endblock %}
|
{%- endblock %}
|
||||||
|
|
||||||
{% block content %}
|
{%- block content %}
|
||||||
{% call macros.box(theme="warning") %}
|
{%- call macros.card(theme="warning") %}
|
||||||
<p>{% trans action %}You are about to {{ action }}. Please confirm your action.{% endtrans %}</p>
|
<p>{% trans action %}You are about to {{ action }}. Please confirm your action.{% endtrans %}</p>
|
||||||
{{ macros.form(form) }}
|
{{ macros.form(form) }}
|
||||||
{% endcall %}
|
{%- endcall %}
|
||||||
{% endblock %}
|
{%- endblock %}
|
||||||
|
@ -1,14 +1,14 @@
|
|||||||
{% extends "base.html" %}
|
{%- extends "base.html" %}
|
||||||
|
|
||||||
{% block title %}
|
{%- block title %}
|
||||||
{% trans %}Docker error{% endtrans %}
|
{% trans %}Docker error{% endtrans %}
|
||||||
{% endblock %}
|
{%- endblock %}
|
||||||
|
|
||||||
{% block subtitle %}
|
{%- block subtitle %}
|
||||||
{{ action }}
|
{{ action }}
|
||||||
{% endblock %}
|
{%- endblock %}
|
||||||
|
|
||||||
{% block content %}
|
{%- block content %}
|
||||||
<p>{% trans action %}An error occurred while talking to the Docker server.{% endtrans %}</p>
|
<p>{% trans action %}An error occurred while talking to the Docker server.{% endtrans %}</p>
|
||||||
<pre>{{ error }}</pre>
|
<pre class="pre-config border bg-light">{{ error }}</pre>
|
||||||
{% endblock %}
|
{%- endblock %}
|
||||||
|
@ -1,21 +1,20 @@
|
|||||||
{% extends "base.html" %}
|
{%- extends "base.html" %}
|
||||||
|
|
||||||
{% block title %}
|
{%- block title %}
|
||||||
{% trans %}New domain{% endtrans %}
|
{% trans %}New domain{% endtrans %}
|
||||||
{% endblock %}
|
{%- endblock %}
|
||||||
|
|
||||||
{% block content %}
|
{%- block content %}
|
||||||
{% call macros.box() %}
|
{%- call macros.card() %}
|
||||||
<form class="form" method="post" role="form">
|
<form class="form" method="post" role="form">
|
||||||
{{ form.hidden_tag() }}
|
{{ form.hidden_tag() }}
|
||||||
{{ macros.form_field(form.name) }}
|
{{ macros.form_field(form.name) }}
|
||||||
{{ macros.form_fields((form.max_users, form.max_aliases)) }}
|
{{ macros.form_fields((form.max_users, form.max_aliases)) }}
|
||||||
{{ macros.form_field(form.max_quota_bytes, step=1000000000, max=50000000000,
|
{{ macros.form_field(form.max_quota_bytes, step=10**9, max=50*10**9, data_infinity="true",
|
||||||
prepend='<span class="input-group-addon"><span id="quota">'+((form.max_quota_bytes.data//1000000000).__str__() if form.max_quota_bytes.data else '∞')+'</span> GiB</span>',
|
prepend='<span class="input-group-text"><span id="max_quota_bytes_value"></span> GB</span>') }}
|
||||||
oninput='$("#quota").text(this.value == 0 ? "∞" : this.value/1000000000);') }}
|
|
||||||
{{ macros.form_field(form.signup_enabled) }}
|
{{ macros.form_field(form.signup_enabled) }}
|
||||||
{{ macros.form_field(form.comment) }}
|
{{ macros.form_field(form.comment) }}
|
||||||
{{ macros.form_field(form.submit) }}
|
{{ macros.form_field(form.submit) }}
|
||||||
</form>
|
</form>
|
||||||
{% endcall %}
|
{%- endcall %}
|
||||||
{% endblock %}
|
{%- endblock %}
|
||||||
|
@ -1,54 +1,71 @@
|
|||||||
{% extends "base.html" %}
|
{%- extends "base.html" %}
|
||||||
|
|
||||||
{% block title %}
|
{%- block title %}
|
||||||
{% trans %}Domain details{% endtrans %}
|
{% trans %}Domain details{% endtrans %}
|
||||||
{% endblock %}
|
{%- endblock %}
|
||||||
|
|
||||||
{% block subtitle %}
|
{%- block subtitle %}
|
||||||
{{ domain.name }}
|
{{ domain.name }}
|
||||||
{% endblock %}
|
{%- endblock %}
|
||||||
|
|
||||||
{% block main_action %}
|
{%- block main_action %}
|
||||||
{% if current_user.global_admin %}
|
{%- if current_user.global_admin %}
|
||||||
<a class="btn btn-primary" href="{{ url_for(".domain_genkeys", domain_name=domain.name) }}">
|
<a class="btn btn-primary float-right" href="{{ url_for(".domain_genkeys", domain_name=domain.name) }}">
|
||||||
{% if domain.dkim_publickey %}
|
{%- if domain.dkim_publickey %}
|
||||||
{% trans %}Regenerate keys{% endtrans %}
|
{% trans %}Regenerate keys{% endtrans %}
|
||||||
{% else %}
|
{%- else %}
|
||||||
{% trans %}Generate keys{% endtrans %}
|
{% trans %}Generate keys{% endtrans %}
|
||||||
{% endif %}
|
{%- endif %}
|
||||||
</a>
|
</a>
|
||||||
{% endif %}
|
{%- endif %}
|
||||||
{% endblock %}
|
{%- endblock %}
|
||||||
|
|
||||||
{% block content %}
|
{%- block content %}
|
||||||
{% call macros.table() %}
|
{%- call macros.table(datatable=False) %}
|
||||||
{% set hostname = config["HOSTNAMES"].split(",")[0] %}
|
|
||||||
<tr>
|
<tr>
|
||||||
<th>{% trans %}Domain name{% endtrans %}</th>
|
<th>{% trans %}Domain name{% endtrans %}</th>
|
||||||
<td>{{ domain.name }}</td>
|
<td>{{ domain.name }}</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<th>{% trans %}DNS MX entry{% endtrans %} <i class="fa {{ 'fa-check-circle' if domain.check_mx() else 'fa-exclamation-circle' }}"></i></th>
|
<th>{% trans %}DNS MX entry{% endtrans %} <i class="fa {{ 'fa-check-circle text-success' if domain.check_mx() else 'fa-exclamation-circle text-danger' }}"></i></th>
|
||||||
<td><pre>{{ domain.name }}. 600 IN MX 10 {{ hostname }}.</pre></td>
|
<td>{{ macros.clip("dns_mx") }}<pre id="dns_mx" class="pre-config border bg-light">{{ domain.dns_mx }}</pre></td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<th>{% trans %}DNS SPF entries{% endtrans %}</th>
|
<th>{% trans %}DNS SPF entries{% endtrans %}</th>
|
||||||
<td><pre>
|
<td>{{ macros.clip("dns_spf") }}<pre id="dns_spf" class="pre-config border bg-light">{{ domain.dns_spf }}</pre>
|
||||||
{{ domain.name }}. 600 IN TXT "v=spf1 mx a:{{ hostname }} -all"</pre></td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
{% if domain.dkim_publickey %}
|
{%- if domain.dkim_publickey %}
|
||||||
<tr>
|
<tr>
|
||||||
<th>{% trans %}DKIM public key{% endtrans %}</th>
|
<th>{% trans %}DKIM public key{% endtrans %}</th>
|
||||||
<td><pre style="white-space: pre-wrap; word-wrap: break-word;">{{ domain.dkim_publickey }}</pre></td>
|
<td>{{ macros.clip("dkim_key") }}<pre id="dkim_key" class="pre-config border bg-light">{{ domain.dkim_publickey }}</pre></td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<th>{% trans %}DNS DKIM entry{% endtrans %}</th>
|
<th>{% trans %}DNS DKIM entry{% endtrans %}</th>
|
||||||
<td><pre style="white-space: pre-wrap; word-wrap: break-word;">{{ config["DKIM_SELECTOR"] }}._domainkey.{{ domain.name }}. 600 IN TXT "v=DKIM1; k=rsa; p={{ domain.dkim_publickey }}"</pre></td>
|
<td>{{ macros.clip("dns_dkim") }}<pre id="dns_dkim" class="pre-config border bg-light">{{ domain.dns_dkim }}</pre></td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<th>{% trans %}DNS DMARC entry{% endtrans %}</th>
|
<th>{% trans %}DNS DMARC entry{% endtrans %}</th>
|
||||||
<td><pre>_dmarc.{{ domain.name }}. 600 IN TXT "v=DMARC1; p=reject;{% if config["DMARC_RUA"] %} rua=mailto:{{ config["DMARC_RUA"] }}@{{ config["DOMAIN"] }};{% endif %}{% if config["DMARC_RUF"] %} ruf=mailto:{{ config["DMARC_RUF"] }}@{{ config["DOMAIN"] }};{% endif %} adkim=s; aspf=s"</pre></td>
|
<td>
|
||||||
|
{{ macros.clip("dns_dmarc") }}<pre id="dns_dmarc" class="pre-config border bg-light">{{ domain.dns_dmarc }}</pre>
|
||||||
|
{{ macros.clip("dns_dmarc_report") }}<pre id="dns_dmarc_report" class="pre-config border bg-light">{{ domain.dns_dmarc_report }}</pre>
|
||||||
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
{% endif %}
|
{%- endif %}
|
||||||
{% endcall %}
|
{%- set tlsa_record=domain.dns_tlsa %}
|
||||||
{% endblock %}
|
{%- if tlsa_record %}
|
||||||
|
<tr>
|
||||||
|
<th>{% trans %}DNS TLSA entry{% endtrans %}</br><span class="text-secondary text-xs font-weight-normal">Let's Encrypt</br>ISRG Root X1</span></th>
|
||||||
|
<td>{{ macros.clip("dns_tlsa") }}<pre id="dns_tlsa" class="pre-config border bg-light">{{ tlsa_record }}</pre></td>
|
||||||
|
</tr>
|
||||||
|
{%- endif %}
|
||||||
|
<tr>
|
||||||
|
<th>{% trans %}DNS client auto-configuration (RFC6186) entries{% endtrans %}</th>
|
||||||
|
<td>{{ macros.clip("dns_autoconfig") }}<pre id="dns_autoconfig" class="pre-config border bg-light">
|
||||||
|
{%- for line in domain.dns_autoconfig %}
|
||||||
|
{{ line }}
|
||||||
|
{%- endfor -%}
|
||||||
|
</pre></td>
|
||||||
|
</tr>
|
||||||
|
{%- endcall %}
|
||||||
|
{%- endblock %}
|
||||||
|
@ -1,9 +1,9 @@
|
|||||||
{% extends "domain/create.html" %}
|
{%- extends "domain/create.html" %}
|
||||||
|
|
||||||
{% block title %}
|
{%- block title %}
|
||||||
{% trans %}Edit domain{% endtrans %}
|
{% trans %}Edit domain{% endtrans %}
|
||||||
{% endblock %}
|
{%- endblock %}
|
||||||
|
|
||||||
{% block subtitle %}
|
{%- block subtitle %}
|
||||||
{{ domain }}
|
{{ domain }}
|
||||||
{% endblock %}
|
{%- endblock %}
|
||||||
|
@ -1,31 +1,31 @@
|
|||||||
{% extends "base.html" %}
|
{%- extends "base.html" %}
|
||||||
|
|
||||||
{% block title %}
|
{%- block title %}
|
||||||
{% trans %}Add a fetched account{% endtrans %}
|
{% trans %}Add a fetched account{% endtrans %}
|
||||||
{% endblock %}
|
{%- endblock %}
|
||||||
|
|
||||||
{% block subtitle %}
|
{%- block subtitle %}
|
||||||
{{ user }}
|
{{ user }}
|
||||||
{% endblock %}
|
{%- endblock %}
|
||||||
|
|
||||||
{% block content %}
|
{%- block content %}
|
||||||
<form class="form" method="post" role="form">
|
<form class="form" method="post" role="form">
|
||||||
{{ form.hidden_tag() }}
|
{{ form.hidden_tag() }}
|
||||||
{% call macros.box(title="Remote server") %}
|
{%- call macros.card(title="Remote server") %}
|
||||||
{{ macros.form_field(form.protocol) }}
|
{{ macros.form_field(form.protocol) }}
|
||||||
{{ macros.form_fields((form.host, form.port)) }}
|
{{ macros.form_fields((form.host, form.port)) }}
|
||||||
{{ macros.form_field(form.tls) }}
|
{{ macros.form_field(form.tls) }}
|
||||||
{% endcall %}
|
{%- endcall %}
|
||||||
|
|
||||||
{% call macros.box(title="Authentication") %}
|
{%- call macros.card(title="Authentication") %}
|
||||||
{{ macros.form_field(form.username) }}
|
{{ macros.form_field(form.username) }}
|
||||||
{{ macros.form_field(form.password) }}
|
{{ macros.form_field(form.password) }}
|
||||||
{% endcall %}
|
{%- endcall %}
|
||||||
|
|
||||||
{% call macros.box(title="Settings") %}
|
{%- call macros.card(title="Settings") %}
|
||||||
{{ macros.form_field(form.keep) }}
|
{{ macros.form_field(form.keep) }}
|
||||||
{% endcall %}
|
{%- endcall %}
|
||||||
|
|
||||||
{{ macros.form_field(form.submit) }}
|
{{ macros.form_field(form.submit) }}
|
||||||
</form>
|
</form>
|
||||||
{% endblock %}
|
{%- endblock %}
|
||||||
|
@ -1,9 +1,9 @@
|
|||||||
{% extends "fetch/create.html" %}
|
{%- extends "fetch/create.html" %}
|
||||||
|
|
||||||
{% block title %}
|
{%- block title %}
|
||||||
{% trans %}Update a fetched account{% endtrans %}
|
{% trans %}Update a fetched account{% endtrans %}
|
||||||
{% endblock %}
|
{%- endblock %}
|
||||||
|
|
||||||
{% block subtitle %}
|
{%- block subtitle %}
|
||||||
{{ user }}
|
{{ user }}
|
||||||
{% endblock %}
|
{%- endblock %}
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
{% extends "base.html" %}
|
{%- extends "base.html" %}
|
||||||
|
|
||||||
{% block content %}
|
{%- block content %}
|
||||||
{% call macros.box() %}
|
{%- call macros.card() %}
|
||||||
{{ macros.form(form) }}
|
{{ macros.form(form) }}
|
||||||
{% endcall %}
|
{%- endcall %}
|
||||||
{% endblock %}
|
{%- endblock %}
|
||||||
|
@ -1,9 +0,0 @@
|
|||||||
{% extends "form.html" %}
|
|
||||||
|
|
||||||
{% block title %}
|
|
||||||
{% trans %}Sign in{% endtrans %}
|
|
||||||
{% endblock %}
|
|
||||||
|
|
||||||
{% block subtitle %}
|
|
||||||
{% trans %}to access the administration tools{% endtrans %}
|
|
||||||
{% endblock %}
|
|
@ -1,98 +1,133 @@
|
|||||||
{% macro form_errors(form) %}
|
{%- macro form_errors(form) %}
|
||||||
{% if form.errors %}
|
{%- if form.errors %}
|
||||||
{% for fieldname, errors in form.errors.items() %}
|
{%- for fieldname, errors in form.errors.items() %}
|
||||||
{% if bootstrap_is_hidden_field(form[fieldname]) %}
|
{%- if bootstrap_is_hidden_field(form[fieldname]) %}
|
||||||
{% for error in errors %}
|
{%- for error in errors %}
|
||||||
<p class="error">{{error}}</p>
|
<p class="error">{{error}}</p>
|
||||||
{% endfor %}
|
{%- endfor %}
|
||||||
{% endif %}
|
{%- endif %}
|
||||||
{% endfor %}
|
{%- endfor %}
|
||||||
{% endif %}
|
{%- endif %}
|
||||||
{% endmacro %}
|
{%- endmacro %}
|
||||||
|
|
||||||
{% macro form_field_errors(field) %}
|
{%- macro form_field_errors(field) %}
|
||||||
{% if field.errors %}
|
{%- if field.errors %}
|
||||||
{% for error in field.errors %}
|
{%- for error in field.errors %}
|
||||||
<p class="help-block inline">{{ error }}</p>
|
<p class="help-block inline">{{ error }}</p>
|
||||||
{% endfor %}
|
{%- endfor %}
|
||||||
{% endif %}
|
{%- endif %}
|
||||||
{% endmacro %}
|
{%- endmacro %}
|
||||||
|
|
||||||
{% macro form_fields(fields, prepend='', append='', label=True) %}
|
{%- macro form_fields(fields, prepend='', append='', label=True) %}
|
||||||
{% set width = (12 / fields|length)|int %}
|
{%- set width = (12 / fields|length)|int %}
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<div class="row">
|
<div class="row">
|
||||||
{% for field in fields %}
|
{%- for field in fields %}
|
||||||
<div class="col-lg-{{ width }} col-xs-12 {{ 'has-error' if field.errors else '' }}">
|
<div class="col-lg-{{ width }} col-xs-12 {{ 'has-error' if field.errors else '' }}">
|
||||||
|
{%- if field.__class__.__name__ == 'list' %}
|
||||||
|
{%- for subfield in field %}
|
||||||
|
{{ form_individual_field(subfield, prepend=prepend, append=append, label=label, **kwargs) }}
|
||||||
|
{%- endfor %}
|
||||||
|
{%- else %}
|
||||||
{{ form_individual_field(field, prepend=prepend, append=append, label=label, **kwargs) }}
|
{{ form_individual_field(field, prepend=prepend, append=append, label=label, **kwargs) }}
|
||||||
|
{%- endif %}
|
||||||
</div>
|
</div>
|
||||||
{% endfor %}
|
{%- endfor %}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
{% endmacro %}
|
{%- endmacro %}
|
||||||
|
|
||||||
{% macro form_individual_field(field, prepend='', append='', label=True, class_="") %}
|
{%- macro form_individual_field(field, prepend='', append='', label=True, class_="") %}
|
||||||
{% if field.type == "BooleanField" %}
|
{%- if field.type == "BooleanField" %}
|
||||||
{{ field(**kwargs) }}<span> </span>
|
{{ field(**kwargs) }}<span> </span>{{ field.label if label else '' }}
|
||||||
{{ field.label if label else '' }}
|
{%- else %}
|
||||||
{% else %}
|
|
||||||
{{ field.label if label else '' }}{{ form_field_errors(field) }}
|
{{ field.label if label else '' }}{{ form_field_errors(field) }}
|
||||||
{% if prepend or append %}<div class="input-group">{% endif %}
|
{%- if prepend %}<div class="input-group-prepend">{%- elif append %}<div class="input-group-append">{%- endif %}
|
||||||
{{ prepend|safe }}{{ field(class_="form-control " + class_, **kwargs) }}{{ append|safe }}
|
{{ prepend|safe }}{{ field(class_=("form-control " + class_) if class_ else "form-control", **kwargs) }}{{ append|safe }}
|
||||||
{% if prepend or append %}</div>{% endif %}
|
{%- if prepend or append %}</div>{%- endif %}
|
||||||
{% endif %}
|
{%- endif %}
|
||||||
{% endmacro %}
|
{%- endmacro %}
|
||||||
|
|
||||||
{% macro form_field(field) %}
|
{%- macro form_field(field) %}
|
||||||
{% if field.type == 'SubmitField' %}
|
{%- if field.type == 'SubmitField' %}
|
||||||
{{ form_fields((field,), label=False, class="btn btn-default", **kwargs) }}
|
{{- form_fields((field,), label=False, class="btn btn-default", **kwargs) }}
|
||||||
{% else %}
|
{%- else %}
|
||||||
{{ form_fields((field,), **kwargs) }}
|
{{- form_fields((field,), **kwargs) }}
|
||||||
{% endif %}
|
{%- endif %}
|
||||||
{% endmacro %}
|
{%- endmacro %}
|
||||||
|
|
||||||
{% macro form(form) %}
|
{%- macro form(form) %}
|
||||||
<form class="form" method="post" role="form">
|
<form class="form" method="post" role="form">
|
||||||
{{ form.hidden_tag() }}
|
{{ form.hidden_tag() }}
|
||||||
{% for field in form %}
|
{%- for field in form %}
|
||||||
{% if bootstrap_is_hidden_field(field) %}
|
{%- if bootstrap_is_hidden_field(field) %}
|
||||||
{{ field() }}
|
{{ field() }}
|
||||||
{% else %}
|
{%- else %}
|
||||||
{{ form_field(field) }}
|
{{ form_field(field) }}
|
||||||
{% endif %}
|
{%- endif %}
|
||||||
{% endfor %}
|
{%- endfor %}
|
||||||
</form>
|
</form>
|
||||||
{% endmacro %}
|
{%- endmacro %}
|
||||||
|
|
||||||
{% macro box(title=None, theme="primary", header=True) %}
|
{%- macro card(title=None, theme="primary", header=True) %}
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col-lg-12">
|
<div class="col-lg-12">
|
||||||
<div class="box box-{{ theme }}">
|
<div class="card card-outline card-{{ theme }}">
|
||||||
{% if header %}
|
{%- if header %}
|
||||||
<div class="box-header">
|
<div class="card-header border-0">
|
||||||
{% if title %}
|
{%- if title %}
|
||||||
<h3 class="box-title">{{ title }}</h3>
|
<h3 class="card-title">{{ title }}</h3>
|
||||||
{% endif %}
|
{%- endif %}
|
||||||
</div>
|
</div>
|
||||||
{% endif %}
|
{%- endif %}
|
||||||
<div class="box-body">
|
<div class="card-body">
|
||||||
{{ caller() }}
|
{{- caller() }}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
{% endmacro %}
|
{%- endmacro %}
|
||||||
|
|
||||||
{% macro table(theme="primary") %}
|
{%- macro table(title=None, theme="primary", datatable=True) %}
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col-lg-12">
|
<div class="col-lg-12">
|
||||||
<div class="box box-{{ theme }}">
|
<div class="card card-outline card-{{ theme }}">
|
||||||
<table class="table table-bordered">
|
{%- if title %}
|
||||||
<tbody>
|
<div class="card-header border-0">
|
||||||
{{ caller() }}
|
<h3 class="card-title">{{ title }}</h3>
|
||||||
</tbody>
|
</div>
|
||||||
|
{%- endif %}
|
||||||
|
<div class="card-body">
|
||||||
|
<table class="table table-bordered{% if datatable %} dataTable{% endif %}">
|
||||||
|
{{- caller() }}
|
||||||
</table>
|
</table>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
{% endmacro %}
|
</div>
|
||||||
|
{%- endmacro %}
|
||||||
|
|
||||||
|
{%- macro fieldset(title=None, field=None, enabled=None, fields=None) %}
|
||||||
|
{%- if field or title %}
|
||||||
|
<fieldset{% if not enabled %} disabled{% endif %}>
|
||||||
|
{%- if field %}
|
||||||
|
<legend>{{ form_individual_field(field) }}</legend>
|
||||||
|
{%- else %}
|
||||||
|
<legend>{{ title }}</legend>
|
||||||
|
{%- endif %}
|
||||||
|
{%- endif %}
|
||||||
|
{{- caller() }}
|
||||||
|
{%- if fields %}
|
||||||
|
{%- set kwargs = {"enabled" if enabled else "disabled": ""} %}
|
||||||
|
{%- for field in fields %}
|
||||||
|
{{ form_field(field, **kwargs) }}
|
||||||
|
{%- endfor %}
|
||||||
|
{%- endif %}
|
||||||
|
</fieldset>
|
||||||
|
{%- endmacro %}
|
||||||
|
|
||||||
|
{%- macro clip(target, title=_("copy to clipboard"), icon="copy", color="primary", action="copy") %}
|
||||||
|
<button class="btn btn-{{ color }} btn-xs btn-clip float-right ml-2 mt-1" data-clipboard-action="{{ action }}" data-clipboard-target="#{{ target }}">
|
||||||
|
<i class="fas fa-{{ icon }}" title="{{ title }}" aria-expanded="false"></i><span class="sr-only">{{ title }}</span>
|
||||||
|
</button>
|
||||||
|
{%- endmacro %}
|
||||||
|
@ -1,19 +1,19 @@
|
|||||||
{% extends "base.html" %}
|
{%- extends "base.html" %}
|
||||||
|
|
||||||
{% block title %}
|
{%- block title %}
|
||||||
{% trans %}Add a manager{% endtrans %}
|
{% trans %}Add a manager{% endtrans %}
|
||||||
{% endblock %}
|
{%- endblock %}
|
||||||
|
|
||||||
{% block subtitle %}
|
{%- block subtitle %}
|
||||||
{{ domain }}
|
{{ domain }}
|
||||||
{% endblock %}
|
{%- endblock %}
|
||||||
|
|
||||||
{% block content %}
|
{%- block content %}
|
||||||
{% call macros.box() %}
|
{%- call macros.card() %}
|
||||||
<form class="form" method="post" role="form">
|
<form class="form" method="post" role="form">
|
||||||
{{ form.hidden_tag() }}
|
{{ form.hidden_tag() }}
|
||||||
{{ macros.form_field(form.manager, class_='mailselect') }}
|
{{ macros.form_field(form.manager, class_='mailselect') }}
|
||||||
{{ macros.form_field(form.submit) }}
|
{{ macros.form_field(form.submit) }}
|
||||||
</form>
|
</form>
|
||||||
{% endcall %}
|
{%- endcall %}
|
||||||
{% endblock %}
|
{%- endblock %}
|
||||||
|
@ -1,30 +1,34 @@
|
|||||||
{% extends "base.html" %}
|
{%- extends "base.html" %}
|
||||||
|
|
||||||
{% block title %}
|
{%- block title %}
|
||||||
{% trans %}Manager list{% endtrans %}
|
{% trans %}Manager list{% endtrans %}
|
||||||
{% endblock %}
|
{%- endblock %}
|
||||||
|
|
||||||
{% block subtitle %}
|
{%- block subtitle %}
|
||||||
{{ domain.name }}
|
{{ domain.name }}
|
||||||
{% endblock %}
|
{%- endblock %}
|
||||||
|
|
||||||
{% block main_action %}
|
{%- block main_action %}
|
||||||
<a class="btn btn-primary" href="{{ url_for('.manager_create', domain_name=domain.name) }}">{% trans %}Add manager{% endtrans %}</a>
|
<a class="btn btn-primary float-right" href="{{ url_for('.manager_create', domain_name=domain.name) }}">{% trans %}Add manager{% endtrans %}</a>
|
||||||
{% endblock %}
|
{%- endblock %}
|
||||||
|
|
||||||
{% block content %}
|
{%- block content %}
|
||||||
{% call macros.table() %}
|
{%- call macros.table() %}
|
||||||
|
<thead>
|
||||||
<tr>
|
<tr>
|
||||||
<th>{% trans %}Actions{% endtrans %}</th>
|
<th>{% trans %}Actions{% endtrans %}</th>
|
||||||
<th>{% trans %}Email{% endtrans %}</th>
|
<th>{% trans %}Email{% endtrans %}</th>
|
||||||
</tr>
|
</tr>
|
||||||
{% for manager in domain.managers %}
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
{%- for manager in domain.managers %}
|
||||||
<tr>
|
<tr>
|
||||||
<td>
|
<td>
|
||||||
<a href="{{ url_for('.manager_delete', domain_name=domain.name, user_email=manager.email) }}" title="{% trans %}Delete{% endtrans %}"><i class="fa fa-trash"></i></a>
|
<a href="{{ url_for('.manager_delete', domain_name=domain.name, user_email=manager.email) }}" title="{% trans %}Delete{% endtrans %}"><i class="fa fa-trash"></i></a>
|
||||||
</td>
|
</td>
|
||||||
<td>{{ manager }}</td>
|
<td>{{ manager }}</td>
|
||||||
</tr>
|
</tr>
|
||||||
{% endfor %}
|
{%- endfor %}
|
||||||
{% endcall %}
|
</tbody>
|
||||||
{% endblock %}
|
{%- endcall %}
|
||||||
|
{%- endblock %}
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
{% extends "form.html" %}
|
{%- extends "form.html" %}
|
||||||
|
|
||||||
{% block title %}
|
{%- block title %}
|
||||||
{% trans %}New relay domain{% endtrans %}
|
{% trans %}New relay domain{% endtrans %}
|
||||||
{% endblock %}
|
{%- endblock %}
|
||||||
|
@ -1,9 +1,9 @@
|
|||||||
{% extends "form.html" %}
|
{%- extends "form.html" %}
|
||||||
|
|
||||||
{% block title %}
|
{%- block title %}
|
||||||
{% trans %}Edit relayd domain{% endtrans %}
|
{% trans %}Edit relayd domain{% endtrans %}
|
||||||
{% endblock %}
|
{%- endblock %}
|
||||||
|
|
||||||
{% block subtitle %}
|
{%- block subtitle %}
|
||||||
{{ relay }}
|
{{ relay }}
|
||||||
{% endblock %}
|
{%- endblock %}
|
||||||
|
@ -1,120 +1,156 @@
|
|||||||
<section class="sidebar">
|
<div class="sidebar text-sm">
|
||||||
{% if current_user.is_authenticated %}
|
{%- if current_user.is_authenticated %}
|
||||||
<h4 class="text-center text-primary">{{ current_user }}</h4>
|
<div class="user-panel mt-3 pb-3 mb-3 d-flex">
|
||||||
{% endif %}
|
<div class="image">
|
||||||
|
<div class="div-circle elevation-2"><i class="fa fa-user text-lg text-dark"></i></div>
|
||||||
|
</div>
|
||||||
|
<div class="info">
|
||||||
|
<a href="{{ url_for('.user_settings') }}" class="d-block">{{ current_user }}</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{%- endif %}
|
||||||
|
<nav class="mt-2">
|
||||||
|
<ul class="nav nav-pills nav-sidebar flex-column" role="menu">
|
||||||
|
{%- if current_user.is_authenticated %}
|
||||||
|
<li class="nav-header text-uppercase text-primary" role="none">{% trans %}My account{% endtrans %}</li>
|
||||||
|
<li class="nav-item" role="none">
|
||||||
|
<a href="{{ url_for('.user_settings') }}" class="nav-link" role="menuitem">
|
||||||
|
<i class="nav-icon fa fa-wrench"></i>
|
||||||
|
<p>{% trans %}Settings{% endtrans %}</p>
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
<li class="nav-item" role="none">
|
||||||
|
<a href="{{ url_for('.user_password') }}" class="nav-link" role="menuitem">
|
||||||
|
<i class="nav-icon fa fa-lock"></i>
|
||||||
|
<p>{% trans %}Update password{% endtrans %}</p>
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
<li class="nav-item" role="none">
|
||||||
|
<a href="{{ url_for('.user_reply') }}" class="nav-link" role="menuitem">
|
||||||
|
<i class="nav-icon fa fa-plane"></i>
|
||||||
|
<p>{% trans %}Auto-reply{% endtrans %}</p>
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
<li class="nav-item" role="none">
|
||||||
|
<a href="{{ url_for('.fetch_list') }}" class="nav-link" role="menuitem">
|
||||||
|
<i class="nav-icon fas fa-download"></i>
|
||||||
|
<p>{% trans %}Fetched accounts{% endtrans %}</p>
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
<li class="nav-item" role="none">
|
||||||
|
<a href="{{ url_for('.token_list') }}" class="nav-link" role="menuitem">
|
||||||
|
<i class="nav-icon fas fa-ticket-alt"></i>
|
||||||
|
<p>{% trans %}Authentication tokens{% endtrans %}</p>
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
{%- if current_user.is_authenticated %}
|
||||||
|
<li class="nav-item" role="none">
|
||||||
|
<a href="{{ url_for('.client') }}" class="nav-link" role="menuitem">
|
||||||
|
<i class="nav-icon fa fa-laptop"></i>
|
||||||
|
<p>{% trans %}Client setup{% endtrans %}</p>
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
{%- endif %}
|
||||||
|
|
||||||
<ul class="sidebar-menu" data-widget="tree">
|
{%- if current_user.manager_of or current_user.global_admin %}
|
||||||
{% if current_user.is_authenticated %}
|
<li class="nav-header text-uppercase text-primary" role="none">{% trans %}Administration{% endtrans %}</li>
|
||||||
<li class="header">{% trans %}My account{% endtrans %}</li>
|
{%- endif %}
|
||||||
<li>
|
{%- if current_user.global_admin %}
|
||||||
<a href="{{ url_for('.user_settings') }}">
|
<li class="nav-item" role="none">
|
||||||
<i class="fa fa-wrench"></i> <span>{% trans %}Settings{% endtrans %}</span>
|
<a href="{{ url_for('.announcement') }}" class="nav-link" role="menuitem">
|
||||||
|
<i class="nav-icon fa fa-bullhorn"></i>
|
||||||
|
<p>{% trans %}Announcement{% endtrans %}</p>
|
||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li class="nav-item" role="none">
|
||||||
<a href="{{ url_for('.user_password') }}">
|
<a href="{{ url_for('.admin_list') }}" class="nav-link" role="menuitem">
|
||||||
<i class="fa fa-lock"></i> <span>{% trans %}Update password{% endtrans %}</span>
|
<i class="nav-icon fa fa-user"></i>
|
||||||
|
<p>{% trans %}Administrators{% endtrans %}</p>
|
||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li class="nav-item" role="none">
|
||||||
<a href="{{ url_for('.user_reply') }}">
|
<a href="{{ url_for('.relay_list') }}" class="nav-link" role="menuitem">
|
||||||
<i class="fa fa-plane"></i> <span>{% trans %}Auto-reply{% endtrans %}</span>
|
<i class="nav-icon fa fa-reply-all"></i>
|
||||||
|
<p>{% trans %}Relayed domains{% endtrans %}</p>
|
||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li class="nav-item" role="none">
|
||||||
<a href="{{ url_for('.fetch_list') }}">
|
<a href="{{ config["WEB_ADMIN"] }}/antispam/" data-clicked="{{ url_for('.antispam') }}" target="_blank" class="nav-link" role="menuitem">
|
||||||
<i class="fa fa-download"></i> <span>{% trans %}Fetched accounts{% endtrans %}</span>
|
<i class="nav-icon fas fa-trash-alt"></i>
|
||||||
|
<p>{% trans %}Antispam{% endtrans %}</p>
|
||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
<li>
|
{%- endif %}
|
||||||
<a href="{{ url_for('.token_list') }}">
|
{%- if current_user.manager_of or current_user.global_admin %}
|
||||||
<i class="fa fa-ticket"></i> <span>{% trans %}Authentication tokens{% endtrans %}</span>
|
<li class="nav-item" role="none">
|
||||||
|
<a href="{{ url_for('.domain_list') }}" class="nav-link" role="menuitem">
|
||||||
|
<i class="nav-icon fa fa-envelope"></i>
|
||||||
|
<p>{% trans %}Mail domains{% endtrans %}</p>
|
||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
|
{%- endif %}
|
||||||
|
{%- endif %}
|
||||||
|
|
||||||
{% if current_user.manager_of or current_user.global_admin %}
|
<li class="nav-header text-uppercase text-primary" role="none">{% trans %}Go to{% endtrans %}</li>
|
||||||
<li class="header">{% trans %}Administration{% endtrans %}</li>
|
{%- if config["WEBMAIL"] != "none" and current_user.is_authenticated %}
|
||||||
{% endif %}
|
<li class="nav-item" role="none">
|
||||||
{% if current_user.global_admin %}
|
<a href="{{ config["WEB_WEBMAIL"] }}" target="_blank" class="nav-link" role="menuitem">
|
||||||
<li>
|
<i class="nav-icon far fa-envelope"></i>
|
||||||
<a href="{{ url_for('.announcement') }}">
|
<p>{% trans %}Webmail{% endtrans %} <i class="fas fa-external-link-alt text-xs"></i></p>
|
||||||
<i class="fa fa-bullhorn"></i> <span>{% trans %}Announcement{% endtrans %}</span>
|
|
||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
<li>
|
{%- endif %}
|
||||||
<a href="{{ url_for('.admin_list') }}">
|
{%- if not current_user.is_authenticated %}
|
||||||
<i class="fa fa-user"></i> <span>{% trans %}Administrators{% endtrans %}</span>
|
<li class="nav-item" role="none">
|
||||||
|
<a href="{{ url_for('.client') }}" class="nav-link" role="menuitem">
|
||||||
|
<i class="nav-icon fa fa-laptop"></i>
|
||||||
|
<p>{% trans %}Client setup{% endtrans %}</p>
|
||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
<li>
|
{%- endif %}
|
||||||
<a href="{{ url_for('.relay_list') }}">
|
<li class="nav-item" role="none">
|
||||||
<i class="fa fa-reply-all"></i> <span>{% trans %}Relayed domains{% endtrans %}</span>
|
<a href="{{ config["WEBSITE"] }}" target="_blank" class="nav-link" role="menuitem" rel="noreferrer">
|
||||||
|
<i class="nav-icon fa fa-globe"></i>
|
||||||
|
<p>{% trans %}Website{% endtrans %} <i class="fas fa-external-link-alt text-xs"></i></p>
|
||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li class="nav-item" role="none">
|
||||||
<a href="{{ config["WEB_ADMIN"] }}/antispam/" target="_blank">
|
<a href="https://mailu.io" target="_blank" class="nav-link" role="menuitem" rel="noreferrer">
|
||||||
<i class="fa fa-trash-o"></i> <span>{% trans %}Antispam{% endtrans %}</span>
|
<i class="nav-icon fa fa-life-ring"></i>
|
||||||
|
<p>{% trans %}Help{% endtrans %} <i class="fas fa-external-link-alt text-xs"></i></p>
|
||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
{% endif %}
|
{%- if config['DOMAIN_REGISTRATION'] %}
|
||||||
{% if current_user.manager_of or current_user.global_admin %}
|
<li class="nav-item" role="none">
|
||||||
<li>
|
<a href="{{ url_for('.domain_signup') }}" class="nav-link" role="menuitem">
|
||||||
<a href="{{ url_for('.domain_list') }}">
|
<i class="nav-icon fa fa-plus-square"></i>
|
||||||
<i class="fa fa-envelope"></i> <span>{% trans %}Mail domains{% endtrans %}</span>
|
<p>{% trans %}Register a domain{% endtrans %}</p>
|
||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
{% endif %}
|
{%- endif %}
|
||||||
{% endif %}
|
{%- if current_user.is_authenticated %}
|
||||||
|
<li class="nav-item" role="none">
|
||||||
<li class="header">{% trans %}Go to{% endtrans %}</li>
|
<a href="{{ url_for('sso.logout') }}" class="nav-link" role="menuitem">
|
||||||
{% if config["WEBMAIL"] != "none" %}
|
<i class="nav-icon fas fa-sign-out-alt"></i>
|
||||||
<li>
|
<p>{% trans %}Sign out{% endtrans %}</p>
|
||||||
<a href="{{ config["WEB_WEBMAIL"] }}" target="_blank">
|
|
||||||
<i class="fa fa-envelope-o"></i> <span>{% trans %}Webmail{% endtrans %}</span>
|
|
||||||
</a>
|
|
||||||
</li>
|
|
||||||
{% endif %}
|
|
||||||
<li>
|
|
||||||
<a href="{{ url_for('.client') }}">
|
|
||||||
<i class="fa fa-laptop"></i> <span>{% trans %}Client setup{% endtrans %}</span>
|
|
||||||
</a>
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<a href="{{ config["WEBSITE"] }}" target="_blank">
|
|
||||||
<i class="fa fa-globe"></i> <span>{% trans %}Website{% endtrans %}</span>
|
|
||||||
</a>
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<a href="https://mailu.io" target="_blank">
|
|
||||||
<i class="fa fa-life-ring"></i> <span>{% trans %}Help{% endtrans %}</span>
|
|
||||||
</a>
|
|
||||||
</li>
|
|
||||||
{% if config['DOMAIN_REGISTRATION'] %}
|
|
||||||
<li>
|
|
||||||
<a href="{{ url_for('.domain_signup') }}">
|
|
||||||
<i class="fa fa-plus-square"></i> <span>{% trans %}Register a domain{% endtrans %}</span>
|
|
||||||
</a>
|
|
||||||
</li>
|
|
||||||
{% endif %}
|
|
||||||
{% if current_user.is_authenticated %}
|
|
||||||
<li>
|
|
||||||
<a href="{{ url_for('.logout') }}">
|
|
||||||
<i class="fa fa-sign-out"></i> <span>{% trans %}Sign out{% endtrans %}</span>
|
|
||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
{% else %}
|
{% else %}
|
||||||
<li>
|
<li class="nav-item" role="none">
|
||||||
<a href="{{ url_for('.login') }}">
|
<a href="{{ url_for('sso.login') }}" class="nav-link" role="menuitem">
|
||||||
<i class="fa fa-sign-in"></i> <span>{% trans %}Sign in{% endtrans %}</span>
|
<i class="nav-icon fas fa-sign-in-alt"></i>
|
||||||
|
<p>{% trans %}Sign in{% endtrans %}</p>
|
||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
{% if signup_domains %}
|
{%- if signup_domains %}
|
||||||
<li>
|
<li class="nav-item" role="none">
|
||||||
<a href="{{ url_for('.user_signup') }}">
|
<a href="{{ url_for('.user_signup') }}" class="nav-link" role="menuitem">
|
||||||
<i class="fa fa-user-plus"></i> <span>{% trans %}Sign up{% endtrans %}</span>
|
<i class="nav-icon fa fa-user-plus"></i>
|
||||||
|
<p>{% trans %}Sign up{% endtrans %}</p>
|
||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
{% endif %}
|
{%- endif %}
|
||||||
{% endif %}
|
{%- endif %}
|
||||||
</ul>
|
</ul>
|
||||||
</section>
|
</nav>
|
||||||
|
</div>
|
||||||
|
@ -1,9 +1,9 @@
|
|||||||
{% extends "form.html" %}
|
{%- extends "form.html" %}
|
||||||
|
|
||||||
{% block title %}
|
{%- block title %}
|
||||||
{% trans %}Create an authentication token{% endtrans %}
|
{% trans %}Create an authentication token{% endtrans %}
|
||||||
{% endblock %}
|
{%- endblock %}
|
||||||
|
|
||||||
{% block subtitle %}
|
{%- block subtitle %}
|
||||||
{{ user }}
|
{{ user }}
|
||||||
{% endblock %}
|
{%- endblock %}
|
||||||
|
@ -1,34 +1,40 @@
|
|||||||
{% extends "base.html" %}
|
{%- extends "base.html" %}
|
||||||
|
|
||||||
{% block title %}
|
{%- block title %}
|
||||||
{% trans %}Authentication tokens{% endtrans %}
|
{% trans %}Authentication tokens{% endtrans %}
|
||||||
{% endblock %}
|
{%- endblock %}
|
||||||
|
|
||||||
{% block subtitle %}
|
{%- block subtitle %}
|
||||||
{{ user }}
|
{{ user }}
|
||||||
{% endblock %}
|
{%- endblock %}
|
||||||
|
|
||||||
{% block main_action %}
|
{%- block main_action %}
|
||||||
<a class="btn btn-primary" href="{{ url_for('.token_create', user_email=user.email) }}">{% trans %}New token{% endtrans %}</a>
|
<a class="btn btn-primary float-right" href="{{ url_for('.token_create', user_email=user.email) }}">{% trans %}New token{% endtrans %}</a>
|
||||||
{% endblock %}
|
{%- endblock %}
|
||||||
|
|
||||||
{% block content %}
|
{%- block content %}
|
||||||
{% call macros.table() %}
|
{%- call macros.table() %}
|
||||||
|
<thead>
|
||||||
<tr>
|
<tr>
|
||||||
<th>{% trans %}Actions{% endtrans %}</th>
|
<th>{% trans %}Actions{% endtrans %}</th>
|
||||||
<th>{% trans %}Comment{% endtrans %}</th>
|
<th>{% trans %}Comment{% endtrans %}</th>
|
||||||
<th>{% trans %}Authorized IP{% endtrans %}</th>
|
<th>{% trans %}Authorized IP{% endtrans %}</th>
|
||||||
<th>{% trans %}Created{% endtrans %}</th>
|
<th>{% trans %}Created{% endtrans %}</th>
|
||||||
|
<th>{% trans %}Last edit{% endtrans %}</th>
|
||||||
</tr>
|
</tr>
|
||||||
{% for token in user.tokens %}
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
{%- for token in user.tokens %}
|
||||||
<tr>
|
<tr>
|
||||||
<td>
|
<td>
|
||||||
<a href="{{ url_for('.token_delete', token_id=token.id) }}" title="{% trans %}Delete{% endtrans %}"><i class="fa fa-trash"></i></a>
|
<a href="{{ url_for('.token_delete', token_id=token.id) }}" title="{% trans %}Delete{% endtrans %}"><i class="fa fa-trash"></i></a>
|
||||||
</td>
|
</td>
|
||||||
<td>{{ token.comment }}</td>
|
<td>{{ token.comment }}</td>
|
||||||
<td>{{ token.ip or "any" }}</td>
|
<td>{{ token.ip or "any" }}</td>
|
||||||
<td>{{ token.created_at }}</td>
|
<td>{{ token.created_at | format_date }}</td>
|
||||||
|
<td>{{ token.updated_at | format_date }}</td>
|
||||||
</tr>
|
</tr>
|
||||||
{% endfor %}
|
{%- endfor %}
|
||||||
{% endcall %}
|
</tbody>
|
||||||
{% endblock %}
|
{%- endcall %}
|
||||||
|
{%- endblock %}
|
||||||
|
@ -1,33 +1,32 @@
|
|||||||
{% extends "base.html" %}
|
{%- extends "base.html" %}
|
||||||
|
|
||||||
{% block title %}
|
{%- block title %}
|
||||||
{% trans %}New user{% endtrans %}
|
{% trans %}New user{% endtrans %}
|
||||||
{% endblock %}
|
{%- endblock %}
|
||||||
|
|
||||||
{% block subtitle %}
|
{%- block subtitle %}
|
||||||
{{ domain.name }}
|
{{ domain.name }}
|
||||||
{% endblock %}
|
{%- endblock %}
|
||||||
|
|
||||||
{% block content %}
|
{%- block content %}
|
||||||
<form class="form" method="post" role="form">
|
<form class="form" method="post" role="form">
|
||||||
{{ form.hidden_tag() }}
|
{{ form.hidden_tag() }}
|
||||||
|
|
||||||
{% call macros.box(_("General")) %}
|
{%- call macros.card(_("General")) %}
|
||||||
{{ macros.form_field(form.localpart, append='<span class="input-group-addon">@'+domain.name+'</span>') }}
|
{{ macros.form_field(form.localpart, append='<span class="input-group-text">@'+domain.name+'</span>') }}
|
||||||
{{ macros.form_fields((form.pw, form.pw2)) }}
|
{{ macros.form_fields((form.pw, form.pw2)) }}
|
||||||
{{ macros.form_field(form.displayed_name) }}
|
{{ macros.form_field(form.displayed_name) }}
|
||||||
{{ macros.form_field(form.comment) }}
|
{{ macros.form_field(form.comment) }}
|
||||||
{{ macros.form_field(form.enabled) }}
|
{{ macros.form_field(form.enabled) }}
|
||||||
{% endcall %}
|
{%- endcall %}
|
||||||
|
|
||||||
{% call macros.box(_("Features and quotas"), theme="success") %}
|
{%- call macros.card(_("Features and quotas"), theme="success") %}
|
||||||
{{ macros.form_field(form.quota_bytes, step=1000000000, max=(max_quota_bytes or domain.max_quota_bytes or 50000000000),
|
{{ macros.form_field(form.quota_bytes, step=1000000000, max=(max_quota_bytes or domain.max_quota_bytes or 50*10**9), data_infinity="true",
|
||||||
prepend='<span class="input-group-addon"><span id="quota">'+((form.quota_bytes.data//1000000000).__str__() if form.quota_bytes.data else '∞')+'</span> GiB</span>',
|
prepend='<span class="input-group-text"><span id="quota_bytes_value"></span> GB</span>') }}
|
||||||
oninput='$("#quota").text(this.value == 0 ? "∞" : this.value/1000000000);') }}
|
|
||||||
{{ macros.form_field(form.enable_imap) }}
|
{{ macros.form_field(form.enable_imap) }}
|
||||||
{{ macros.form_field(form.enable_pop) }}
|
{{ macros.form_field(form.enable_pop) }}
|
||||||
{% endcall %}
|
{%- endcall %}
|
||||||
|
|
||||||
{{ macros.form_field(form.submit) }}
|
{{ macros.form_field(form.submit) }}
|
||||||
</form>
|
</form>
|
||||||
{% endblock %}
|
{%- endblock %}
|
||||||
|
@ -1,9 +1,9 @@
|
|||||||
{% extends "user/create.html" %}
|
{%- extends "user/create.html" %}
|
||||||
|
|
||||||
{% block title %}
|
{%- block title %}
|
||||||
{% trans %}Edit user{% endtrans %}
|
{% trans %}Edit user{% endtrans %}
|
||||||
{% endblock %}
|
{%- endblock %}
|
||||||
|
|
||||||
{% block subtitle %}
|
{%- block subtitle %}
|
||||||
{{ user }}
|
{{ user }}
|
||||||
{% endblock %}
|
{%- endblock %}
|
||||||
|
@ -1,25 +0,0 @@
|
|||||||
{% extends "base.html" %}
|
|
||||||
|
|
||||||
{% block title %}
|
|
||||||
{% trans %}Forward emails{% endtrans %}
|
|
||||||
{% endblock %}
|
|
||||||
|
|
||||||
{% block subtitle %}
|
|
||||||
{{ user }}
|
|
||||||
{% endblock %}
|
|
||||||
|
|
||||||
{% block content %}
|
|
||||||
{% call macros.box() %}
|
|
||||||
<form class="form" method="post" role="form">
|
|
||||||
{{ form.hidden_tag() }}
|
|
||||||
{{ macros.form_field(form.forward_enabled,
|
|
||||||
onchange="if(this.checked){$('#forward_destination,#forward_keep').removeAttr('disabled')}
|
|
||||||
else{$('#forward_destination,#forward_keep').attr('disabled', '')}") }}
|
|
||||||
{{ macros.form_field(form.forward_keep,
|
|
||||||
**{("enabled" if user.forward_enabled else "disabled"): ""}) }}
|
|
||||||
{{ macros.form_field(form.forward_destination,
|
|
||||||
**{("enabled" if user.forward_enabled else "disabled"): ""}) }}
|
|
||||||
{{ macros.form_field(form.submit) }}
|
|
||||||
</form>
|
|
||||||
{% endcall %}
|
|
||||||
{% endblock %}
|
|
@ -1,9 +1,9 @@
|
|||||||
{% extends "form.html" %}
|
{%- extends "form.html" %}
|
||||||
|
|
||||||
{% block title %}
|
{%- block title %}
|
||||||
{% trans %}Password update{% endtrans %}
|
{% trans %}Password update{% endtrans %}
|
||||||
{% endblock %}
|
{%- endblock %}
|
||||||
|
|
||||||
{% block subtitle %}
|
{%- block subtitle %}
|
||||||
{{ user }}
|
{{ user }}
|
||||||
{% endblock %}
|
{%- endblock %}
|
||||||
|
@ -1,30 +1,23 @@
|
|||||||
{% extends "base.html" %}
|
{%- extends "base.html" %}
|
||||||
|
|
||||||
{% block title %}
|
{%- block title %}
|
||||||
{% trans %}Automatic reply{% endtrans %}
|
{% trans %}Automatic reply{% endtrans %}
|
||||||
{% endblock %}
|
{%- endblock %}
|
||||||
|
|
||||||
{% block subtitle %}
|
{%- block subtitle %}
|
||||||
{{ user }}
|
{{ user }}
|
||||||
{% endblock %}
|
{%- endblock %}
|
||||||
|
|
||||||
{% block content %}
|
{%- block content %}
|
||||||
{% call macros.box() %}
|
{%- call macros.card() %}
|
||||||
<form class="form" method="post" role="form">
|
<form class="form" method="post" role="form">
|
||||||
{{ form.hidden_tag() }}
|
{{ form.hidden_tag() }}
|
||||||
{{ macros.form_field(form.reply_enabled,
|
{%- call macros.fieldset(
|
||||||
onchange="if(this.checked){$('#reply_subject,#reply_body,#reply_enddate,#reply_startdate').removeAttr('readonly')}
|
field=form.reply_enabled,
|
||||||
else{$('#reply_subject,#reply_body,#reply_enddate').attr('readonly', '')}") }}
|
enabled=user.reply_enabled,
|
||||||
{{ macros.form_field(form.reply_subject,
|
fields=[form.reply_subject, form.reply_body, form.reply_enddate, form.reply_startdate]) %}
|
||||||
**{("rw" if user.reply_enabled else "readonly"): ""}) }}
|
{%- endcall %}
|
||||||
{{ macros.form_field(form.reply_body, rows=10,
|
|
||||||
**{("rw" if user.reply_enabled else "readonly"): ""}) }}
|
|
||||||
{{ macros.form_field(form.reply_enddate,
|
|
||||||
**{("rw" if user.reply_enabled else "readonly"): ""}) }}
|
|
||||||
{{ macros.form_field(form.reply_startdate,
|
|
||||||
**{("rw" if user.reply_enabled else "readonly"): ""}) }}
|
|
||||||
|
|
||||||
{{ macros.form_field(form.submit) }}
|
{{ macros.form_field(form.submit) }}
|
||||||
</form>
|
</form>
|
||||||
{% endcall %}
|
{%- endcall %}
|
||||||
{% endblock %}
|
{%- endblock %}
|
||||||
|
@ -1,38 +1,36 @@
|
|||||||
{% extends "base.html" %}
|
{%- extends "base.html" %}
|
||||||
|
|
||||||
{% block title %}
|
{%- block title %}
|
||||||
{% trans %}User settings{% endtrans %}
|
{% trans %}User settings{% endtrans %}
|
||||||
{% endblock %}
|
{%- endblock %}
|
||||||
|
|
||||||
{% block subtitle %}
|
{%- block subtitle %}
|
||||||
{{ user }}
|
{{ user }}
|
||||||
{% endblock %}
|
{%- endblock %}
|
||||||
|
|
||||||
{% block content %}
|
{%- block content %}
|
||||||
<form class="form" method="post" role="form">
|
<form class="form" method="post" role="form">
|
||||||
{{ form.hidden_tag() }}
|
{{ form.hidden_tag() }}
|
||||||
|
|
||||||
{% call macros.box(title=_("Displayed name")) %}
|
{%- call macros.card(title=_("Displayed name")) %}
|
||||||
{{ macros.form_field(form.displayed_name) }}
|
{{ macros.form_field(form.displayed_name) }}
|
||||||
{% endcall %}
|
{%- endcall %}
|
||||||
|
|
||||||
{% call macros.box(title=_("Antispam")) %}
|
{%- call macros.card(title=_("Antispam")) %}
|
||||||
{{ macros.form_field(form.spam_enabled) }}
|
{%- call macros.fieldset(field=form.spam_enabled, enabled=user.spam_enabled) %}
|
||||||
{{ macros.form_field(form.spam_threshold, step=1, max=100,
|
{{ macros.form_field(form.spam_threshold, step=1, max=100,
|
||||||
prepend='<span class="input-group-addon"><span id="threshold">'+form.spam_threshold.data.__str__()+'</span> / 100</span>',
|
prepend='<span class="input-group-text"><span id="spam_threshold_value"></span> / 100</span>') }}
|
||||||
oninput='$("#threshold").text(this.value);') }}
|
{%- endcall %}
|
||||||
{% endcall %}
|
{%- endcall %}
|
||||||
|
|
||||||
{% call macros.box(title=_("Auto-forward")) %}
|
{%- call macros.card(title=_("Auto-forward")) %}
|
||||||
{{ macros.form_field(form.forward_enabled,
|
{%- call macros.fieldset(
|
||||||
onchange="if(this.checked){$('#forward_destination,#forward_keep').removeAttr('disabled')}
|
field=form.forward_enabled,
|
||||||
else{$('#forward_destination,#forward_keep').attr('disabled', '')}") }}
|
enabled=user.forward_enabled,
|
||||||
{{ macros.form_field(form.forward_keep,
|
fields=[form.forward_keep, form.forward_destination]) %}
|
||||||
**{("enabled" if user.forward_enabled else "disabled"): ""}) }}
|
{%- endcall %}
|
||||||
{{ macros.form_field(form.forward_destination,
|
{%- endcall %}
|
||||||
**{("enabled" if user.forward_enabled else "disabled"): ""}) }}
|
|
||||||
{% endcall %}
|
|
||||||
|
|
||||||
{{ macros.form_field(form.submit) }}
|
{{ macros.form_field(form.submit) }}
|
||||||
</form>
|
</form>
|
||||||
{% endblock %}
|
{%- endblock %}
|
||||||
|
@ -1,23 +1,23 @@
|
|||||||
{% extends "base.html" %}
|
{%- extends "base.html" %}
|
||||||
|
|
||||||
{% block title %}
|
{%- block title %}
|
||||||
{% trans %}Sign up{% endtrans %}
|
{% trans %}Sign up{% endtrans %}
|
||||||
{% endblock %}
|
{%- endblock %}
|
||||||
|
|
||||||
{% block subtitle %}
|
{%- block subtitle %}
|
||||||
{{ domain }}
|
{{ domain }}
|
||||||
{% endblock %}
|
{%- endblock %}
|
||||||
|
|
||||||
{% block content %}
|
{%- block content %}
|
||||||
<form class="form" method="post" role="form">
|
<form class="form" method="post" role="form">
|
||||||
{{ form.hidden_tag() }}
|
{{ form.hidden_tag() }}
|
||||||
{% call macros.box() %}
|
{%- call macros.card() %}
|
||||||
{{ macros.form_field(form.localpart, append='<span class="input-group-addon">@'+domain.name+'</span>') }}
|
{{ macros.form_field(form.localpart, append='<span class="input-group-text">@'+domain.name+'</span>') }}
|
||||||
{{ macros.form_fields((form.pw, form.pw2)) }}
|
{{ macros.form_fields((form.pw, form.pw2)) }}
|
||||||
{% if form.captcha %}
|
{%- if form.captcha %}
|
||||||
{{ macros.form_field(form.captcha) }}
|
{{ macros.form_field(form.captcha) }}
|
||||||
{% endif %}
|
{%- endif %}
|
||||||
{{ macros.form_field(form.submit) }}
|
{{ macros.form_field(form.submit) }}
|
||||||
{% endcall %}
|
{%- endcall %}
|
||||||
</form>
|
</form>
|
||||||
{% endblock %}
|
{%- endblock %}
|
||||||
|
@ -1,26 +1,26 @@
|
|||||||
{% extends "base.html" %}
|
{%- extends "base.html" %}
|
||||||
|
|
||||||
{% block title %}
|
{%- block title %}
|
||||||
{% trans %}Sign up{% endtrans %}
|
{% trans %}Sign up{% endtrans %}
|
||||||
{% endblock %}
|
{%- endblock %}
|
||||||
|
|
||||||
{% block subtitle %}
|
{%- block subtitle %}
|
||||||
{% trans %}pick a domain for the new account{% endtrans %}
|
{% trans %}pick a domain for the new account{% endtrans %}
|
||||||
{% endblock %}
|
{%- endblock %}
|
||||||
|
|
||||||
{% block content %}
|
{%- block content %}
|
||||||
{% call macros.table() %}
|
{%- call macros.table() %}
|
||||||
<tr>
|
<tr>
|
||||||
<th>{% trans %}Domain{% endtrans %}</th>
|
<th>{% trans %}Domain{% endtrans %}</th>
|
||||||
<th>{% trans %}Available slots{% endtrans %}</th>
|
<th>{% trans %}Available slots{% endtrans %}</th>
|
||||||
<th>{% trans %}Quota{% endtrans %}</th>
|
<th>{% trans %}Quota{% endtrans %}</th>
|
||||||
</tr>
|
</tr>
|
||||||
{% for domain_name, domain in available_domains.items() %}
|
{%- for domain_name, domain in available_domains.items() %}
|
||||||
<tr>
|
<tr>
|
||||||
<td><a href="{{ url_for('.user_signup', domain_name=domain_name) }}">{{ domain_name }}</a></td>
|
<td><a href="{{ url_for('.user_signup', domain_name=domain_name) }}">{{ domain_name }}</a></td>
|
||||||
<td>{{ '∞' if domain.max_users == -1 else domain.max_users - (domain.users | count)}}</td>
|
<td>{{ '∞' if domain.max_users == -1 else domain.max_users - (domain.users | count)}}</td>
|
||||||
<td>{{ domain.max_quota_bytes or config['DEFAULT_QUOTA'] | filesizeformat }}</td>
|
<td>{{ domain.max_quota_bytes or config['DEFAULT_QUOTA'] | filesizeformat }}</td>
|
||||||
</tr>
|
</tr>
|
||||||
{% endfor %}
|
{%- endfor %}
|
||||||
{% endcall %}
|
{%- endcall %}
|
||||||
{% endblock %}
|
{%- endblock %}
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
{% extends "base.html" %}
|
{%- extends "base.html" %}
|
||||||
|
|
||||||
{% block content %}
|
{%- block content %}
|
||||||
<div class="alert alert-warning" role="alert">{% trans %}We are still working on this feature!{% endtrans %}</div>
|
<div class="alert alert-warning" role="alert">{% trans %}We are still working on this feature!{% endtrans %}</div>
|
||||||
{% endblock %}
|
{%- endblock %}
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
__all__ = [
|
__all__ = [
|
||||||
'admins', 'aliases', 'alternatives', 'base', 'domains', 'fetches',
|
'admins', 'aliases', 'alternatives', 'base', 'domains', 'fetches',
|
||||||
'managers', 'users', 'relays', 'tokens'
|
'managers', 'users', 'relays', 'tokens', 'languages'
|
||||||
]
|
]
|
||||||
|
@ -0,0 +1,9 @@
|
|||||||
|
from mailu.ui import ui, forms, access
|
||||||
|
|
||||||
|
import flask
|
||||||
|
|
||||||
|
@ui.route('/language/<language>', methods=['POST'])
|
||||||
|
def set_language(language=None):
|
||||||
|
flask.session['language'] = language
|
||||||
|
return flask.Response(status=200)
|
||||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue