data/conf/borgmatic/etc/config.yaml location: source_directories: - /mnt/source repositories: - user@rsync.net:mailcow remote_path: borg1 retention: keep_hourly: 24 keep_daily: 7 keep_weekly: 4 keep_monthly: 6 hooks: mysql_databases: - name: ${DBNAME} username: ${DBUSER} password: ${DBPASS} options: --default-character-set=utf8mb4 EOF Creating the file in this way ensures the correct MySQL credentials are pulled in from mailcow.conf . This file is a minimal example for using borgmatic with an account user on the cloud storage provider rsync.net for a repository called mailcow (see repositories setting). It will backup both the maildir and MySQL database, which is all you should need to restore your mailcow setup after an incident. The retention settings will keep one archive for each hour of the past 24 hours, one per day of the week, one per week of the month and one per month of the past half year. Check the borgmatic documentation on how to use other types of repositories or configuration options. If you choose to use a local filesystem as a backup destination make sure to mount it into the container. The container defines a volume called /mnt/borg-repository for this purpose. Note If you do not use rsync.net you can most likely drop the remote_path element from your config.","title":"Create data/conf/borgmatic/etc/config.yaml"},{"location":"third_party-borgmatic/#create-a-crontab","text":"Create a new text file in data/conf/borgmatic/etc/crontab.txt with the following content: 14 * * * * PATH=$PATH:/usr/bin /usr/bin/borgmatic --stats -v 0 2>&1 This file expects crontab syntax. The example shown here will trigger the backup to run every hour at 14 minutes past the hour and log some nice stats at the end.","title":"Create a crontab"},{"location":"third_party-borgmatic/#place-ssh-keys-in-folder","text":"Place the SSH keys you intend to use for remote repository connections in data/conf/borgmatic/ssh . OpenSSH expects the usual id_rsa , id_ed25519 or similar to be in this directory. Ensure the file is chmod 600 and not world readable or OpenSSH will refuse to use the SSH key.","title":"Place SSH keys in folder"},{"location":"third_party-borgmatic/#bring-up-the-container","text":"For the next step we need the container to be up and running in a configured state. To do that run: docker-compose up -d","title":"Bring up the container"},{"location":"third_party-borgmatic/#initialize-the-repository","text":"By now your borgmatic container is up and running, but the backups will currently fail due to the repository not being initialized. To initialize the repository run: docker-compose exec borgmatic-mailcow borgmatic init --encryption repokey-blake2 You will be asked you to authenticate the SSH host key of your remote repository server. See if it matches and confirm the prompt by entering yes . The repository will be initialized with the passphrase you set in the BORG_PASSPHRASE environment variable earlier. When using any of the repokey encryption methods the encryption key will be stored in the repository itself and not on the client, so there is no further action required in this regard. If you decide to use a keyfile instead of a repokey make sure you export the key and back it up separately. Check the Exporting Keys section for how to retrieve the key.","title":"Initialize the repository"},{"location":"third_party-borgmatic/#restart-container","text":"Now that we finished configuring and initializing the repository restart the container to ensure it is in a defined state: docker-compose restart borgmatic-mailcow","title":"Restart container"},{"location":"third_party-borgmatic/#restoring-from-a-backup","text":"Restoring a backup assumes you are starting off with a fresh installation of mailcow, and you currently do not have any custom data in your maildir or your mailcow database.","title":"Restoring from a backup"},{"location":"third_party-borgmatic/#restore-maildir","text":"Warning Doing this will overwrite files in your maildir! Do not run this unless you actually intend to recover mail files from a backup. If you use SELinux in Enforcing mode If you are using mailcow on a host with SELinux in Enforcing mode you will have to temporarily disable it during extraction of the archive as the mailcow setup labels the vmail volume as private, belonging to the dovecot container exclusively. SELinux will (rightfully) prevent any other container, such as the borgmatic container, from writing to this volume. Before running a restore you must make the vmail volume writeable in docker-compose.override.yml by removing the ro flag from the volume. Then you can use the following command to restore the maildir from a backup: docker-compose exec borgmatic-mailcow borgmatic extract --path mnt/source --archive latest Alternatively you can specify any archive name from the list of archives (see Listing all available archives )","title":"Restore maildir"},{"location":"third_party-borgmatic/#restore-mysql","text":"Warning Running this command will delete and recreate the mailcow database! Do not run this unless you actually intend to recover the mailcow database from a backup. To restore the MySQL database from the latest archive use this command: docker-compose exec borgmatic-mailcow borgmatic restore --archive latest Alternatively you can specify any archive name from the list of archives (see Listing all available archives )","title":"Restore MySQL"},{"location":"third_party-borgmatic/#after-restoring","text":"After restoring you need to restart mailcow. If you disabled SELinux enforcing mode now would be a good time to re-enable it. To restart mailcow use the follwing command: docker-compose down && docker-compose up -d If you use SELinux this will also trigger the re-labeling of all files in your vmail volume. Be patient, as this may take a while if you have lots of files.","title":"After restoring"},{"location":"third_party-borgmatic/#useful-commands","text":"","title":"Useful commands"},{"location":"third_party-borgmatic/#manual-archiving-run-with-debugging-output","text":"docker-compose exec borgmatic-mailcow borgmatic -v 2","title":"Manual archiving run (with debugging output)"},{"location":"third_party-borgmatic/#listing-all-available-archives","text":"docker-compose exec borgmatic-mailcow borgmatic list","title":"Listing all available archives"},{"location":"third_party-borgmatic/#break-lock","text":"When borg is interrupted during an archiving run it will leave behind a stale lock that needs to be cleared before any new operations can be performed: docker-compose exec borgmatic-mailcow borg break-lock user@rsync.net:mailcow Where user@rsync.net:mailcow is the URI to your repository. Now would be a good time to do a manual archiving run to ensure it can be successfully performed.","title":"Break lock"},{"location":"third_party-borgmatic/#exporting-keys","text":"When using any of the keyfile methods for encryption you MUST take care of backing up the key files yourself. The key files are generated when you initialize the repository. The repokey methods store the key file within the repository, so a manual backup isn't as essential. Note that in either case you also must have the passphrase to decrypt any archives. To fetch the keyfile run: docker-compose exec borgmatic-mailcow borg key export --paper user@rsync.net:mailcow Where user@rsync.net:mailcow is the URI to your repository.","title":"Exporting keys"},{"location":"third_party-exchange_onprem/","text":"Using Microsoft Exchange in a hybrid setup is possible with mailcow. With this setup you can add mailboxes on your mailcow and still use Exchange Online Protection . All mailboxes setup in Exchange will receive their mails as usual , while with the hybrid approach additional Mailboxes can be setup in mailcow without any further configuration. This setup becomes very handy if you have enabled the Office 365 security defaults and third party applications can no longer login into your mailboxes by any of the supported methods . Requirements \u00b6 The mx Record of your domain needs to point at the Exchange mail service. Log into your Admin center and look out for the dns settings of your domain to find your personalized gateway domain. It should look like this contoso-com.mail.protection.outlook.com . Contact your domain registrant to get further information on how to change mx record. The domain you want to have additional mailboxes for must be setup as internal relay domain in Exchange. Log in to your Exchange Admin Center Select the mail flow pane and click on accepted domains Select the domain and switch it from authorative to internal relay Set up the mailcow \u00b6 Your mailcow needs to relay all mails to your personalized Exchange Host. It is the same host address we already looked up for the mx Record. Add the domain to your mailcow Add your personalized Exchange Host address as relayhost Add your personalized Exchange Host address as forwarding host to unconditionally accepted all relayed mails from Exchange. (Admin > Configuration & Details > Configuration Dropdown > Forwarding Hosts) Go to the domain settings and select the newly added host on the Sender-dependent transports dropdown. Enable relaying by ticking the Relay this domain , Relay all recipients and the Relay non-existing mailboxes only. checkboxes Info From now on your mailcow will accept all mails relayed from Exchange. The inbound filtering and so the neural learning of your cow will no longer work . Because all mails are routed through Exchange the filtering process is handled there . Set up Connectors in Exchange \u00b6 All mail traffic now goes through Exchange. At this point the Exchange Online Protection already filters all incoming and outgoing mails. Now we need to set up two connectors to relay incoming mails from our Exchange Service to the mailcow and another one to allow mails relayed from the mailcow to our exchange service. You can follow the official guide from Microsoft . Warning For the connector that handles mails from your mailcow to Exchange Microsoft offers two ways of authenticating it. The recommended way is to use a tls certificate configured with a subject name that matches an accepted domain in Exchange. Otherwise you need to choose authentication with the static ip address of your mailcow. Validating \u00b6 The easiest way to validate the hybrid setup is by sending a mail from the internet to a mailbox that only exists on the mailcow and vice versa. Common Issues \u00b6 The connector validation from Exchange to your mailcow failed with 550 5.1.10 RESOLVER.ADR.RecipientNotFound; Recipient test@contoso.com not found by SMTP address lookup Possible Solution: Your domain is not set up as internal relay . Exchange therefore cannot find the recipient Mails sent from the mailcow to a mailbox in the internet cannot be sent. Non Delivery Report with error 550 5.7.64 TenantAttribution; Relay Access Denied Possible Solution: The authentication method failed. Make sure the certificate subject matches an accepted domain in Exchange. Try authenticating by static ip instead. Microsoft Guide for the connector setup and additional requirements: https://docs.microsoft.com/exchange/mail-flow-best-practices/use-connectors-to-configure-mail-flow/set-up-connectors-to-route-mail#prerequisites-for-your-on-premises-email-environment","title":"Exchange Hybrid Setup"},{"location":"third_party-exchange_onprem/#requirements","text":"The mx Record of your domain needs to point at the Exchange mail service. Log into your Admin center and look out for the dns settings of your domain to find your personalized gateway domain. It should look like this contoso-com.mail.protection.outlook.com . Contact your domain registrant to get further information on how to change mx record. The domain you want to have additional mailboxes for must be setup as internal relay domain in Exchange. Log in to your Exchange Admin Center Select the mail flow pane and click on accepted domains Select the domain and switch it from authorative to internal relay","title":"Requirements"},{"location":"third_party-exchange_onprem/#set-up-the-mailcow","text":"Your mailcow needs to relay all mails to your personalized Exchange Host. It is the same host address we already looked up for the mx Record. Add the domain to your mailcow Add your personalized Exchange Host address as relayhost Add your personalized Exchange Host address as forwarding host to unconditionally accepted all relayed mails from Exchange. (Admin > Configuration & Details > Configuration Dropdown > Forwarding Hosts) Go to the domain settings and select the newly added host on the Sender-dependent transports dropdown. Enable relaying by ticking the Relay this domain , Relay all recipients and the Relay non-existing mailboxes only. checkboxes Info From now on your mailcow will accept all mails relayed from Exchange. The inbound filtering and so the neural learning of your cow will no longer work . Because all mails are routed through Exchange the filtering process is handled there .","title":"Set up the mailcow"},{"location":"third_party-exchange_onprem/#set-up-connectors-in-exchange","text":"All mail traffic now goes through Exchange. At this point the Exchange Online Protection already filters all incoming and outgoing mails. Now we need to set up two connectors to relay incoming mails from our Exchange Service to the mailcow and another one to allow mails relayed from the mailcow to our exchange service. You can follow the official guide from Microsoft . Warning For the connector that handles mails from your mailcow to Exchange Microsoft offers two ways of authenticating it. The recommended way is to use a tls certificate configured with a subject name that matches an accepted domain in Exchange. Otherwise you need to choose authentication with the static ip address of your mailcow.","title":"Set up Connectors in Exchange"},{"location":"third_party-exchange_onprem/#validating","text":"The easiest way to validate the hybrid setup is by sending a mail from the internet to a mailbox that only exists on the mailcow and vice versa.","title":"Validating"},{"location":"third_party-exchange_onprem/#common-issues","text":"The connector validation from Exchange to your mailcow failed with 550 5.1.10 RESOLVER.ADR.RecipientNotFound; Recipient test@contoso.com not found by SMTP address lookup Possible Solution: Your domain is not set up as internal relay . Exchange therefore cannot find the recipient Mails sent from the mailcow to a mailbox in the internet cannot be sent. Non Delivery Report with error 550 5.7.64 TenantAttribution; Relay Access Denied Possible Solution: The authentication method failed. Make sure the certificate subject matches an accepted domain in Exchange. Try authenticating by static ip instead. Microsoft Guide for the connector setup and additional requirements: https://docs.microsoft.com/exchange/mail-flow-best-practices/use-connectors-to-configure-mail-flow/set-up-connectors-to-route-mail#prerequisites-for-your-on-premises-email-environment","title":"Common Issues"},{"location":"third_party-gitea/","text":"With Gitea' ability to authenticate over SMTP it is trivial to integrate it with mailcow. Few changes are needed: 1. Open docker-compose.override.yml and add gitea: version: '2.1' services: gitea-mailcow: image: gitea/gitea:1 volumes: - ./data/gitea:/data networks: mailcow-network: aliases: - gitea ports: - \"${GITEA_SSH_PORT:-127.0.0.1:4000}:22\" 2. Create data/conf/nginx/site.gitea.custom , add: location /gitea/ { proxy_pass http://gitea:3000/; } 3. Open mailcow.conf and define the binding you want gitea to use for SSH. Example: GITEA_SSH_PORT=127.0.0.1:4000 5. Run docker-compose up -d to bring up the gitea container and run docker-compose restart nginx-mailcow afterwards. 6. If you forced mailcow to https, execute step 9 and restart gitea with docker-compose restart gitea-mailcow . Go head with step 7 (Remember to use https instead of http, https://mx.example.org/gitea/ 7. Open http://${MAILCOW_HOSTNAME}/gitea/ , for example http://mx.example.org/gitea/ . For database details set mysql as database host. Use the value of DBNAME found in mailcow.conf as database name, DBUSER as database user and DBPASS as database password. 8. Once the installation is complete, login as admin and set \"settings\" -> \"authorization\" -> \"enable SMTP\". SMTP Host should be postfix with port 587 , set Skip TLS Verify as we are using an unlisted SAN (\"postfix\" is most likely not part of your certificate). 9. Create data/gitea/gitea/conf/app.ini and set following values. You can consult gitea cheat sheet for their meaning and other possible values. [server] SSH_LISTEN_PORT = 22 # For GITEA_SSH_PORT=127.0.0.1:4000 in mailcow.conf, set: SSH_DOMAIN = 127.0.0.1 SSH_PORT = 4000 # For MAILCOW_HOSTNAME=mx.example.org in mailcow.conf (and default ports for HTTPS), set: ROOT_URL = https://mx.example.org/gitea/ 10. Restart gitea with docker-compose restart gitea-mailcow . Your users should be able to login with mailcow managed accounts.","title":"Gitea"},{"location":"third_party-gogs/","text":"With Gogs' ability to authenticate over SMTP it is trivial to integrate it with mailcow. Few changes are needed: 1. Open docker-compose.override.yml and add Gogs: version: '2.1' services: gogs-mailcow: image: gogs/gogs volumes: - ./data/gogs:/data networks: mailcow-network: aliases: - gogs ports: - \"${GOGS_SSH_PORT:-127.0.0.1:4000}:22\" 2. Create data/conf/nginx/site.gogs.custom , add: location /gogs/ { proxy_pass http://gogs:3000/; } 3. Open mailcow.conf and define the binding you want Gogs to use for SSH. Example: GOGS_SSH_PORT=127.0.0.1:4000 5. Run docker-compose up -d to bring up the Gogs container and run docker-compose restart nginx-mailcow afterwards. 6. Open http://${MAILCOW_HOSTNAME}/gogs/ , for example http://mx.example.org/gogs/ . For database details set mysql as database host. Use the value of DBNAME found in mailcow.conf as database name, DBUSER as database user and DBPASS as database password. 7. Once the installation is complete, login as admin and set \"settings\" -> \"authorization\" -> \"enable SMTP\". SMTP Host should be postfix with port 587 , set Skip TLS Verify as we are using an unlisted SAN (\"postfix\" is most likely not part of your certificate). 8. Create data/gogs/gogs/conf/app.ini and set following values. You can consult Gogs cheat sheet for their meaning and other possible values. [server] SSH_LISTEN_PORT = 22 # For GOGS_SSH_PORT=127.0.0.1:4000 in mailcow.conf, set: SSH_DOMAIN = 127.0.0.1 SSH_PORT = 4000 # For MAILCOW_HOSTNAME=mx.example.org in mailcow.conf (and default ports for HTTPS), set: ROOT_URL = https://mx.example.org/gogs/ 9. Restart Gogs with docker-compose restart gogs-mailcow . Your users should be able to login with mailcow managed accounts.","title":"Gogs"},{"location":"third_party-mailpiler_integration/","text":"This is a simple integration of mailcow aliases and the mailbox name into mailpiler when using IMAP authentication. Disclaimer : This is not officially maintained nor supported by the mailcow project nor its contributors. No warranty or support is being provided, however you're free to open issues on GitHub for filing a bug or provide further ideas. GitHub repo can be found here . Info Support for domain wildcards were implemented in Piler 1.3.10 which was released on 03.01.2021. Prior versions basically do work, but after logging in you won't see emails sent from or to the domain alias. (e.g. when @example.com is an alias for admin@example.com ) The problem to solve \u00b6 mailpiler offers the authentication based on IMAP, for example: $config['ENABLE_IMAP_AUTH'] = 1; $config['IMAP_HOST'] = 'mail.example.com'; $config['IMAP_PORT'] = 993; $config['IMAP_SSL'] = true; So when you log in using patrik@example.com , you will only see delivered emails sent from or to this specific email address. When additional aliases are defined in mailcow, like team@example.com , you won't see emails sent to or from this email address even the fact you're a recipient of mails sent to this alias address. By hooking into the authentication process of mailpiler, we are able to get required data via the mailcow API during login. This fires API requests to the mailcow API (requiring read-only API access) to read out the aliases your email address participates and also the \"Name\" of the mailbox specified to display it on the top-right of mailpiler after login. Permitted email addresses can be seen in the mailpiler settings top-right after logging in. Info This is only pulled once during the authentication process. The authorized aliases and the realname are valid for the whole duration of the user session as mailpiler sets them in the session data. If user is removed from specific alias, this will only take effect after next login. The solution \u00b6 Note: File paths might vary depending on your setup. Requirements \u00b6 A working mailcow instance A working mailpiler instance ( You can find an installation guide here , check supported versions here ) An mailcow API key (read-only works just fine): Configuration & Details - Access - Read-Only Access . Don't forget to allow API access from your mailpiler IP. Warning As mailpiler authenticates against mailcow, our IMAP server, failed logins of users or bots might trigger a block for your mailpiler instance. Therefore you might want to consider whitelisting the IP address of the mailpiler instance within mailcow: Configuration & Details - Configuration - Fail2ban parameters - Whitelisted networks/hosts . Setup \u00b6 Set the custom query function of mailpiler and append this to /usr/local/etc/piler/config-site.php : $config['MAILCOW_API_KEY'] = 'YOUR_READONLY_API_KEY'; $config['MAILCOW_SET_REALNAME'] = true; // when not specified, then default is false $config['CUSTOM_EMAIL_QUERY_FUNCTION'] = 'query_mailcow_for_email_access'; include('auth-mailcow.php'); You can also change the mailcow hostname, if required: $config['MAILCOW_HOST'] = 'mail.domain.tld'; // defaults to $config['IMAP_HOST'] Download the PHP file with the functions from the GitHub repo : curl -o /usr/local/etc/piler/auth-mailcow.php https://raw.githubusercontent.com/patschi/mailpiler-mailcow-integration/master/auth-mailcow.php Done! Make sure to re-login with your IMAP credentials for changes to take effect. If it doesn't work, most likely something's wrong with the API query itself. Consider debugging by sending manual API requests to the API. (Tip: Open https://mail.domain.tld/api on your instance)","title":"Mailpiler Integration"},{"location":"third_party-mailpiler_integration/#the-problem-to-solve","text":"mailpiler offers the authentication based on IMAP, for example: $config['ENABLE_IMAP_AUTH'] = 1; $config['IMAP_HOST'] = 'mail.example.com'; $config['IMAP_PORT'] = 993; $config['IMAP_SSL'] = true; So when you log in using patrik@example.com , you will only see delivered emails sent from or to this specific email address. When additional aliases are defined in mailcow, like team@example.com , you won't see emails sent to or from this email address even the fact you're a recipient of mails sent to this alias address. By hooking into the authentication process of mailpiler, we are able to get required data via the mailcow API during login. This fires API requests to the mailcow API (requiring read-only API access) to read out the aliases your email address participates and also the \"Name\" of the mailbox specified to display it on the top-right of mailpiler after login. Permitted email addresses can be seen in the mailpiler settings top-right after logging in. Info This is only pulled once during the authentication process. The authorized aliases and the realname are valid for the whole duration of the user session as mailpiler sets them in the session data. If user is removed from specific alias, this will only take effect after next login.","title":"The problem to solve"},{"location":"third_party-mailpiler_integration/#the-solution","text":"Note: File paths might vary depending on your setup.","title":"The solution"},{"location":"third_party-mailpiler_integration/#requirements","text":"A working mailcow instance A working mailpiler instance ( You can find an installation guide here , check supported versions here ) An mailcow API key (read-only works just fine): Configuration & Details - Access - Read-Only Access . Don't forget to allow API access from your mailpiler IP. Warning As mailpiler authenticates against mailcow, our IMAP server, failed logins of users or bots might trigger a block for your mailpiler instance. Therefore you might want to consider whitelisting the IP address of the mailpiler instance within mailcow: Configuration & Details - Configuration - Fail2ban parameters - Whitelisted networks/hosts .","title":"Requirements"},{"location":"third_party-mailpiler_integration/#setup","text":"Set the custom query function of mailpiler and append this to /usr/local/etc/piler/config-site.php : $config['MAILCOW_API_KEY'] = 'YOUR_READONLY_API_KEY'; $config['MAILCOW_SET_REALNAME'] = true; // when not specified, then default is false $config['CUSTOM_EMAIL_QUERY_FUNCTION'] = 'query_mailcow_for_email_access'; include('auth-mailcow.php'); You can also change the mailcow hostname, if required: $config['MAILCOW_HOST'] = 'mail.domain.tld'; // defaults to $config['IMAP_HOST'] Download the PHP file with the functions from the GitHub repo : curl -o /usr/local/etc/piler/auth-mailcow.php https://raw.githubusercontent.com/patschi/mailpiler-mailcow-integration/master/auth-mailcow.php Done! Make sure to re-login with your IMAP credentials for changes to take effect. If it doesn't work, most likely something's wrong with the API query itself. Consider debugging by sending manual API requests to the API. (Tip: Open https://mail.domain.tld/api on your instance)","title":"Setup"},{"location":"third_party-nextcloud/","text":"Manage Nextcloud using the helper script \u00b6 Nextcloud can be set up (parameter -i ) and removed (parameter -p ) with the helper script included with mailcow. In order to install Nextcloud simply navigate to your mailcow-dockerized root folder and run the helper script as follows: ./helper-scripts/nextcloud.sh -i In case you have forgotten the password (e.g. for admin) and can't request a new one via the password reset link on the login screen calling the helper script with -r as parameter allows you to set a new password. Only use this option if your Nextcloud isn't configured to use mailcow for authentication as described in the next section. Configure Nextcloud to use mailcow for authentication \u00b6 The following describes how set up authentication via mailcow using the OAuth2 protocol. We will only assume that you have already set up Nextcloud at cloud.example.com and that your mailcow is running at mail.example.com . It does not matter if your Nextcloud is running on a different server, you can still use mailcow for authentication. 1. Log into mailcow as administrator. 2. Scroll down to OAuth2 Apps and click the Add button. Specify the redirect URI as https://cloud.example.com/index.php/apps/sociallogin/custom_oauth2/Mailcow and click Add . Save the client ID and secret for later. Info Some installations, including those setup using the helper script of mailcow, need to remove index.php/ from the URL to get a successful redirect: https://cloud.example.com/apps/sociallogin/custom_oauth2/Mailcow 3. Log into Nextcloud as administrator. 4. Click the button in the top right corner and select Apps . Click the search button in the toolbar, search for the Social Login plugin and click Download and enable next to it. 5. Click the button in the top right corner and select Settings . Scroll down to the Administration section on the left and click Social login . 6. Uncheck the following items: \"Disable auto create new users\" \"Allow users to connect social logins with their accounts\" \"Do not prune not available user groups on login\" \"Automatically create groups if they do not exists\" \"Restrict login for users without mapped groups\" 7. Check the following items: \"Prevent creating an account if the email address exists in another account\" \"Update user profile every login\" \"Disable notify admins about new users\" Click the Save button. 8. Scroll down to Custom OAuth2 and click the + button. 9. Configure the parameters as follows: Internal name: Mailcow Title: Mailcow API Base URL: https://mail.example.com Authorize URL: https://mail.example.com/oauth/authorize Token URL: https://mail.example.com/oauth/token Profile URL: https://mail.example.com/oauth/profile Logout URL: (leave blank) Client ID: (what you obtained in step 1) Client Secret: (what you obtained in step 1) Scope: profile Click the Save button at the very bottom of the page. If you have previously used Nextcloud with mailcow authentication via user_external/IMAP, you need to perform some additional steps to link your existing user accounts with OAuth2. 1. Click the button in the top right corner and select Apps . Scroll down to the External user authentication app and click Remove next to it. 2. Run the following queries in your Nextcloud database (if you set up Nextcloud using mailcow's script, you can run source mailcow.conf && docker-compose exec mysql-mailcow mysql -u$DBUSER -p$DBPASS $DBNAME ): INSERT INTO nc_users (uid, uid_lower) SELECT DISTINCT uid, LOWER(uid) FROM nc_users_external; INSERT INTO nc_sociallogin_connect (uid, identifier) SELECT DISTINCT uid, CONCAT(\"Mailcow-\", uid) FROM nc_users_external; If you have previously used Nextcloud without mailcow authentication, but with the same usernames as mailcow, you can also link your existing user accounts with OAuth2. 1. Run the following queries in your Nextcloud database (if you set up Nextcloud using mailcow's script, you can run source mailcow.conf && docker-compose exec mysql-mailcow mysql -u$DBUSER -p$DBPASS $DBNAME ): INSERT INTO nc_sociallogin_connect (uid, identifier) SELECT DISTINCT uid, CONCAT(\"Mailcow-\", uid) FROM nc_users; Update \u00b6 The Nextcloud instance can be updated easily with the web update mechanism. In the case of larger updates, there may be further changes to be made after the update. After the Nextcloud instance has been checked, problems are shown. This can be e.g. missing indices in the DB or similar. It shows which commands have to be executed, these have to be placed in the php-fpm-mailcow container. As an an example run the following command to add the missing indices. docker exec -it -u www-data $(docker ps -f name=php-fpm-mailcow -q) bash -c \"php /web/nextcloud/occ db:add-missing-indices\" Debugging & Troubleshooting \u00b6 It may happen that you cannot reach the Nextcloud instance from your network. This may be due to the fact that the entry of your subnet in the array 'trusted_proxies' is missing. You can make changes in the Nextcloud config.php in data/web/nextcloud/config/* . 'trusted_proxies' => array ( 0 => 'fd4d:6169:6c63:6f77::/64', 1 => '172.22.1.0/24', 2 => 'NewSubnet/24', ), After the changes have been made, the nginx container must be restarted. docker-compose restart nginx-mailcow","title":"Nextcloud"},{"location":"third_party-nextcloud/#manage-nextcloud-using-the-helper-script","text":"Nextcloud can be set up (parameter -i ) and removed (parameter -p ) with the helper script included with mailcow. In order to install Nextcloud simply navigate to your mailcow-dockerized root folder and run the helper script as follows: ./helper-scripts/nextcloud.sh -i In case you have forgotten the password (e.g. for admin) and can't request a new one via the password reset link on the login screen calling the helper script with -r as parameter allows you to set a new password. Only use this option if your Nextcloud isn't configured to use mailcow for authentication as described in the next section.","title":"Manage Nextcloud using the helper script"},{"location":"third_party-nextcloud/#configure-nextcloud-to-use-mailcow-for-authentication","text":"The following describes how set up authentication via mailcow using the OAuth2 protocol. We will only assume that you have already set up Nextcloud at cloud.example.com and that your mailcow is running at mail.example.com . It does not matter if your Nextcloud is running on a different server, you can still use mailcow for authentication. 1. Log into mailcow as administrator. 2. Scroll down to OAuth2 Apps and click the Add button. Specify the redirect URI as https://cloud.example.com/index.php/apps/sociallogin/custom_oauth2/Mailcow and click Add . Save the client ID and secret for later. Info Some installations, including those setup using the helper script of mailcow, need to remove index.php/ from the URL to get a successful redirect: https://cloud.example.com/apps/sociallogin/custom_oauth2/Mailcow 3. Log into Nextcloud as administrator. 4. Click the button in the top right corner and select Apps . Click the search button in the toolbar, search for the Social Login plugin and click Download and enable next to it. 5. Click the button in the top right corner and select Settings . Scroll down to the Administration section on the left and click Social login . 6. Uncheck the following items: \"Disable auto create new users\" \"Allow users to connect social logins with their accounts\" \"Do not prune not available user groups on login\" \"Automatically create groups if they do not exists\" \"Restrict login for users without mapped groups\" 7. Check the following items: \"Prevent creating an account if the email address exists in another account\" \"Update user profile every login\" \"Disable notify admins about new users\" Click the Save button. 8. Scroll down to Custom OAuth2 and click the + button. 9. Configure the parameters as follows: Internal name: Mailcow Title: Mailcow API Base URL: https://mail.example.com Authorize URL: https://mail.example.com/oauth/authorize Token URL: https://mail.example.com/oauth/token Profile URL: https://mail.example.com/oauth/profile Logout URL: (leave blank) Client ID: (what you obtained in step 1) Client Secret: (what you obtained in step 1) Scope: profile Click the Save button at the very bottom of the page. If you have previously used Nextcloud with mailcow authentication via user_external/IMAP, you need to perform some additional steps to link your existing user accounts with OAuth2. 1. Click the button in the top right corner and select Apps . Scroll down to the External user authentication app and click Remove next to it. 2. Run the following queries in your Nextcloud database (if you set up Nextcloud using mailcow's script, you can run source mailcow.conf && docker-compose exec mysql-mailcow mysql -u$DBUSER -p$DBPASS $DBNAME ): INSERT INTO nc_users (uid, uid_lower) SELECT DISTINCT uid, LOWER(uid) FROM nc_users_external; INSERT INTO nc_sociallogin_connect (uid, identifier) SELECT DISTINCT uid, CONCAT(\"Mailcow-\", uid) FROM nc_users_external; If you have previously used Nextcloud without mailcow authentication, but with the same usernames as mailcow, you can also link your existing user accounts with OAuth2. 1. Run the following queries in your Nextcloud database (if you set up Nextcloud using mailcow's script, you can run source mailcow.conf && docker-compose exec mysql-mailcow mysql -u$DBUSER -p$DBPASS $DBNAME ): INSERT INTO nc_sociallogin_connect (uid, identifier) SELECT DISTINCT uid, CONCAT(\"Mailcow-\", uid) FROM nc_users;","title":"Configure Nextcloud to use mailcow for authentication"},{"location":"third_party-nextcloud/#update","text":"The Nextcloud instance can be updated easily with the web update mechanism. In the case of larger updates, there may be further changes to be made after the update. After the Nextcloud instance has been checked, problems are shown. This can be e.g. missing indices in the DB or similar. It shows which commands have to be executed, these have to be placed in the php-fpm-mailcow container. As an an example run the following command to add the missing indices. docker exec -it -u www-data $(docker ps -f name=php-fpm-mailcow -q) bash -c \"php /web/nextcloud/occ db:add-missing-indices\"","title":"Update"},{"location":"third_party-nextcloud/#debugging-troubleshooting","text":"It may happen that you cannot reach the Nextcloud instance from your network. This may be due to the fact that the entry of your subnet in the array 'trusted_proxies' is missing. You can make changes in the Nextcloud config.php in data/web/nextcloud/config/* . 'trusted_proxies' => array ( 0 => 'fd4d:6169:6c63:6f77::/64', 1 => '172.22.1.0/24', 2 => 'NewSubnet/24', ), After the changes have been made, the nginx container must be restarted. docker-compose restart nginx-mailcow","title":"Debugging & Troubleshooting"},{"location":"third_party-portainer/","text":"In order to enable Portainer, the docker-compose.yml and site.conf for Nginx must be modified. 1. Create a new file docker-compose.override.yml in the mailcow-dockerized root folder and insert the following configuration version: '2.1' services: portainer-mailcow: image: portainer/portainer-ce volumes: - /var/run/docker.sock:/var/run/docker.sock - ./data/conf/portainer:/data restart: always dns: - 172.22.1.254 dns_search: mailcow-network networks: mailcow-network: aliases: - portainer 2a. Create data/conf/nginx/portainer.conf : upstream portainer { server portainer-mailcow:9000; } map $http_upgrade $connection_upgrade { default upgrade; '' close; } 2b. Insert a new location to the default mailcow site by creating the file data/conf/nginx/site.portainer.custom : location /portainer/ { proxy_http_version 1.1; proxy_set_header Host $http_host; # required for docker client's sake proxy_set_header X-Real-IP $remote_addr; # pass on real client's IP proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Proto $scheme; proxy_read_timeout 900; proxy_set_header Connection \"\"; proxy_buffers 32 4k; proxy_pass http://portainer/; } location /portainer/api/websocket/ { proxy_http_version 1.1; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection $connection_upgrade; proxy_pass http://portainer/api/websocket/; } 3. Apply your changes: docker-compose up -d && docker-compose restart nginx-mailcow Now you can simply navigate to https://${MAILCOW_HOSTNAME}/portainer/ to view your Portainer container monitoring page. You\u2019ll then be prompted to specify a new password for the admin account. After specifying your password, you\u2019ll then be able to connect to the Portainer UI.","title":"Portainer"},{"location":"third_party-roundcube/","text":"Download Roundcube 1.4.x to the web htdocs directory and extract it (here rc/ ): # Check for a newer release! cd data/web wget -O - https://github.com/roundcube/roundcubemail/releases/download/1.4.11/roundcubemail-1.4.11-complete.tar.gz | tar xfvz - # Change folder name mv roundcubemail-1.4.11 rc # Change permissions chown -R root: rc/ Create a file data/web/rc/config/config.inc.php with the following content. Change the des_key parameter to a random value. It is used to temporarily store your IMAP password. The \"db_prefix\" is optional but recommended. array('verify_peer' => false, 'verify_peer_name' => false, 'allow_self_signed' => true) ); $config['enable_installer'] = true; $config['smtp_conn_options'] = array( 'ssl' => array('verify_peer' => false, 'verify_peer_name' => false, 'allow_self_signed' => true) ); $config['db_prefix'] = 'mailcow_rc1'; Point your browser to https://myserver/rc/installer and follow the instructions. Initialize the database and leave the installer. Delete the directory data/web/rc/installer after a successful installation! Configure ManageSieve filtering \u00b6 Open data/web/rc/plugins/managesieve/config.inc.php and change the following parameters (or add them at the bottom of that file): $config['managesieve_port'] = 4190; $config['managesieve_host'] = 'tls://dovecot'; $config['managesieve_conn_options'] = array( 'ssl' => array('verify_peer' => false, 'verify_peer_name' => false, 'allow_self_signed' => true) ); // Enables separate management interface for vacation responses (out-of-office) // 0 - no separate section (default), // 1 - add Vacation section, // 2 - add Vacation section, but hide Filters section $config['managesieve_vacation'] = 1; Enable change password function in Roundcube \u00b6 Open data/web/rc/config/config.inc.php and enable the password plugin: ... $config['plugins'] = array( 'archive', 'password', ); ... Open data/web/rc/plugins/password/password.php , search for case 'ssha': and add above: case 'ssha256': $salt = rcube_utils::random_bytes(8); $crypted = base64_encode( hash('sha256', $password . $salt, TRUE ) . $salt ); $prefix = '{SSHA256}'; break; Open data/web/rc/plugins/password/config.inc.php and change the following parameters (or add them at the bottom of that file): $config['password_driver'] = 'sql'; $config['password_algorithm'] = 'ssha256'; $config['password_algorithm_prefix'] = '{SSHA256}'; $config['password_query'] = \"UPDATE mailbox SET password = %P WHERE username = %u\"; Integrate CardDAV addressbooks in Roundcube \u00b6 Download the latest release of RCMCardDAV to the Roundcube plugin directory and extract it (here rc/plugins ): cd data/web/rc/plugins wget -O - https://github.com/blind-coder/rcmcarddav/releases/download/v3.0.3/carddav-3.0.3.tar.bz2 | tar xfvj - chown -R root: carddav/ Copy the file config.inc.php.dist to config.inc.php (here in rc/plugins/carddav ) and append the following preset to the end of the file - don't forget to replace mx.example.org with your own hostname: $prefs['SOGo'] = array( 'name' => 'SOGo', 'username' => '%u', 'password' => '%p', 'url' => 'https://mx.example.org/SOGo/dav/%u/', 'carddav_name_only' => true, 'use_categories' => true, 'active' => true, 'readonly' => false, 'refresh_time' => '02:00:00', 'fixed' => array( 'active', 'name', 'username', 'password', 'refresh_time' ), 'hide' => false, ); Please note, that this preset only integrates the default addressbook (the one that's named \"Personal Address Book\" and can't be deleted). Additional addressbooks are currently not automatically detected but can be manually added within the roundecube settings. Enable the plugin by adding carddav to $config['plugins'] in rc/config/config.inc.php . If you want to remove the default addressbooks (stored in the Roundcube database), so that only the CardDAV addressbooks are accessible, append $config['address_book_type'] = ''; to the config file data/web/rc/config/config.inc.php . Optionally, you can add Roundcube's link to the mailcow Apps list. To do this, open or create data/web/inc/vars.local.inc.php and add the following code-block: NOTE: Don't forget to add the 'SOGo', 'link' => '/SOGo/' ), array( 'name' => 'Roundcube', 'link' => '/rc/' ) ); ...","title":"Roundcube"},{"location":"third_party-roundcube/#configure-managesieve-filtering","text":"Open data/web/rc/plugins/managesieve/config.inc.php and change the following parameters (or add them at the bottom of that file): $config['managesieve_port'] = 4190; $config['managesieve_host'] = 'tls://dovecot'; $config['managesieve_conn_options'] = array( 'ssl' => array('verify_peer' => false, 'verify_peer_name' => false, 'allow_self_signed' => true) ); // Enables separate management interface for vacation responses (out-of-office) // 0 - no separate section (default), // 1 - add Vacation section, // 2 - add Vacation section, but hide Filters section $config['managesieve_vacation'] = 1;","title":"Configure ManageSieve filtering"},{"location":"third_party-roundcube/#enable-change-password-function-in-roundcube","text":"Open data/web/rc/config/config.inc.php and enable the password plugin: ... $config['plugins'] = array( 'archive', 'password', ); ... Open data/web/rc/plugins/password/password.php , search for case 'ssha': and add above: case 'ssha256': $salt = rcube_utils::random_bytes(8); $crypted = base64_encode( hash('sha256', $password . $salt, TRUE ) . $salt ); $prefix = '{SSHA256}'; break; Open data/web/rc/plugins/password/config.inc.php and change the following parameters (or add them at the bottom of that file): $config['password_driver'] = 'sql'; $config['password_algorithm'] = 'ssha256'; $config['password_algorithm_prefix'] = '{SSHA256}'; $config['password_query'] = \"UPDATE mailbox SET password = %P WHERE username = %u\";","title":"Enable change password function in Roundcube"},{"location":"third_party-roundcube/#integrate-carddav-addressbooks-in-roundcube","text":"Download the latest release of RCMCardDAV to the Roundcube plugin directory and extract it (here rc/plugins ): cd data/web/rc/plugins wget -O - https://github.com/blind-coder/rcmcarddav/releases/download/v3.0.3/carddav-3.0.3.tar.bz2 | tar xfvj - chown -R root: carddav/ Copy the file config.inc.php.dist to config.inc.php (here in rc/plugins/carddav ) and append the following preset to the end of the file - don't forget to replace mx.example.org with your own hostname: $prefs['SOGo'] = array( 'name' => 'SOGo', 'username' => '%u', 'password' => '%p', 'url' => 'https://mx.example.org/SOGo/dav/%u/', 'carddav_name_only' => true, 'use_categories' => true, 'active' => true, 'readonly' => false, 'refresh_time' => '02:00:00', 'fixed' => array( 'active', 'name', 'username', 'password', 'refresh_time' ), 'hide' => false, ); Please note, that this preset only integrates the default addressbook (the one that's named \"Personal Address Book\" and can't be deleted). Additional addressbooks are currently not automatically detected but can be manually added within the roundecube settings. Enable the plugin by adding carddav to $config['plugins'] in rc/config/config.inc.php . If you want to remove the default addressbooks (stored in the Roundcube database), so that only the CardDAV addressbooks are accessible, append $config['address_book_type'] = ''; to the config file data/web/rc/config/config.inc.php . Optionally, you can add Roundcube's link to the mailcow Apps list. To do this, open or create data/web/inc/vars.local.inc.php and add the following code-block: NOTE: Don't forget to add the 'SOGo', 'link' => '/SOGo/' ), array( 'name' => 'Roundcube', 'link' => '/rc/' ) ); ...","title":"Integrate CardDAV addressbooks in Roundcube"},{"location":"third_party-thunderbird/","text":"Build the SOGo Connector plugin \u00b6 Install GNU Make, tar, and ZIP if you don't already have them installed. On Debian/Ubuntu, this can be done using apt-get install make tar zip Next, go to data/web inside mailcow-dockerized. Place the file thunderbird-plugins.php into that directory. Create a new directory thunderbird-plugins and place the script build-plugins.sh into it. Finally, execute the script with your hostname as an argument and piping it the names of all domains that mailcow handles. All of this can be done using the following commands: cd data/web curl -LO https://github.com/mailcow/mailcow-dockerized-docs/raw/master/docs/download/thunderbird-plugins.php mkdir thunderbird-plugins cd thunderbird-plugins curl -Lo build-plugins.sh https://github.com/mailcow/mailcow-dockerized-docs/raw/master/docs/download/build-thunderbird-plugins.sh chmod +x build-plugins.sh echo example.com example.org | ./build-plugins.sh mailcow.example.com Install it in Thunderbird \u00b6 After you have set up your mailcow IMAP account in Thunderbird, download the SOGo Connector plugin for your domain, e.g. https://mailcow.example.com/thunderbird-plugins/sogo-connector-68.0.1-example.com.xpi (see data/web/thunderbird-plugins ), and install it into Thunderbird. All your address books and calendars will be configured automatically.","title":"SOGo Connector for Thunderbird"},{"location":"third_party-thunderbird/#build-the-sogo-connector-plugin","text":"Install GNU Make, tar, and ZIP if you don't already have them installed. On Debian/Ubuntu, this can be done using apt-get install make tar zip Next, go to data/web inside mailcow-dockerized. Place the file thunderbird-plugins.php into that directory. Create a new directory thunderbird-plugins and place the script build-plugins.sh into it. Finally, execute the script with your hostname as an argument and piping it the names of all domains that mailcow handles. All of this can be done using the following commands: cd data/web curl -LO https://github.com/mailcow/mailcow-dockerized-docs/raw/master/docs/download/thunderbird-plugins.php mkdir thunderbird-plugins cd thunderbird-plugins curl -Lo build-plugins.sh https://github.com/mailcow/mailcow-dockerized-docs/raw/master/docs/download/build-thunderbird-plugins.sh chmod +x build-plugins.sh echo example.com example.org | ./build-plugins.sh mailcow.example.com","title":"Build the SOGo Connector plugin"},{"location":"third_party-thunderbird/#install-it-in-thunderbird","text":"After you have set up your mailcow IMAP account in Thunderbird, download the SOGo Connector plugin for your domain, e.g. https://mailcow.example.com/thunderbird-plugins/sogo-connector-68.0.1-example.com.xpi (see data/web/thunderbird-plugins ), and install it into Thunderbird. All your address books and calendars will be configured automatically.","title":"Install it in Thunderbird"},{"location":"u_e-80_to_443/","text":"Since February the 28th 2017 mailcow does come with port 80 and 443 enabled. Do not use the config below for reverse proxy setups , please see our reverse proxy guide for this, which includes a redirect from HTTP to HTTPS. Open mailcow.conf and set HTTP_BIND= - if not already set. Create a new file data/conf/nginx/redirect.conf and add the following server config to the file: server { root /web; listen 80 default_server; listen [::]:80 default_server; include /etc/nginx/conf.d/server_name.active; if ( $request_uri ~* \"%0A|%0D\" ) { return 403; } location ^~ /.well-known/acme-challenge/ { allow all; default_type \"text/plain\"; } location / { return 301 https://$host$uri$is_args$args; } } In case you changed the HTTP_BIND parameter, recreate the container: docker-compose up -d Otherwise restart Nginx: docker-compose restart nginx-mailcow","title":"Redirect HTTP to HTTPS"},{"location":"u_e-autodiscover_config/","text":"You do not need to change or create this file, autodiscover works out of the box . This guide is only meant for customizations to the autodiscover or autoconfig process. Newer Outlook clients (especially those delivered with O365) will not autodiscover mail profiles. Keep in mind, that ActiveSync should NOT be used with a desktop client . Open/create data/web/inc/vars.local.inc.php and add your changes to the configuration array. Changes will be merged with \"$autodiscover_config\" in data/web/inc/vars.inc.php ): 'activesync', // If autodiscoverType => activesync, also use ActiveSync (EAS) for Outlook desktop clients (>= Outlook 2013 on Windows) // Outlook for Mac does not support ActiveSync 'useEASforOutlook' => 'yes', // Please don't use STARTTLS-enabled service ports in the \"port\" variable. // The autodiscover service will always point to SMTPS and IMAPS (TLS-wrapped services). // The autoconfig service will additionally announce the STARTTLS-enabled ports, specified in the \"tlsport\" variable. 'imap' => array( 'server' => $mailcow_hostname, 'port' => array_pop(explode(':', getenv('IMAPS_PORT'))), 'tlsport' => array_pop(explode(':', getenv('IMAP_PORT'))), ), 'pop3' => array( 'server' => $mailcow_hostname, 'port' => array_pop(explode(':', getenv('POPS_PORT'))), 'tlsport' => array_pop(explode(':', getenv('POP_PORT'))), ), 'smtp' => array( 'server' => $mailcow_hostname, 'port' => array_pop(explode(':', getenv('SMTPS_PORT'))), 'tlsport' => array_pop(explode(':', getenv('SUBMISSION_PORT'))), ), 'activesync' => array( 'url' => 'https://'.$mailcow_hostname.($https_port == 443 ? '' : ':'.$https_port).'/Microsoft-Server-ActiveSync', ), 'caldav' => array( 'server' => $mailcow_hostname, 'port' => $https_port, ), 'carddav' => array( 'server' => $mailcow_hostname, 'port' => $https_port, ), ); To always use IMAP and SMTP instead of EAS, set 'autodiscoverType' => 'imap' . Disable ActiveSync for Outlook desktop clients by setting \"useEASforOutlook\" to \"no\".","title":"Autodiscover / Autoconfig"},{"location":"u_e-backup_restore-maildir/","text":"Backup \u00b6 This line backups the vmail directory to a file backup_vmail.tar.gz in the mailcow root directory: cd /path/to/mailcow-dockerized docker run --rm -i -v $(docker inspect --format '{{ range .Mounts }}{{ if eq .Destination \"/var/vmail\" }}{{ .Name }}{{ end }}{{ end }}' $(docker-compose ps -q dovecot-mailcow)):/vmail -v ${PWD}:/backup debian:stretch-slim tar cvfz /backup/backup_vmail.tar.gz /vmail You can change the path by adjusting ${PWD} (which equals to the current directory) to any path you have write-access to. Set the filename backup_vmail.tar.gz to any custom name, but leave the path as it is. Example: [...] tar cvfz /backup/my_own_filename_.tar.gz Restore \u00b6 cd /path/to/mailcow-dockerized docker run --rm -it -v $(docker inspect --format '{{ range .Mounts }}{{ if eq .Destination \"/var/vmail\" }}{{ .Name }}{{ end }}{{ end }}' $(docker-compose ps -q dovecot-mailcow)):/vmail -v ${PWD}:/backup debian:stretch-slim tar xvfz /backup/backup_vmail.tar.gz","title":"Maildir"},{"location":"u_e-backup_restore-maildir/#backup","text":"This line backups the vmail directory to a file backup_vmail.tar.gz in the mailcow root directory: cd /path/to/mailcow-dockerized docker run --rm -i -v $(docker inspect --format '{{ range .Mounts }}{{ if eq .Destination \"/var/vmail\" }}{{ .Name }}{{ end }}{{ end }}' $(docker-compose ps -q dovecot-mailcow)):/vmail -v ${PWD}:/backup debian:stretch-slim tar cvfz /backup/backup_vmail.tar.gz /vmail You can change the path by adjusting ${PWD} (which equals to the current directory) to any path you have write-access to. Set the filename backup_vmail.tar.gz to any custom name, but leave the path as it is. Example: [...] tar cvfz /backup/my_own_filename_.tar.gz","title":"Backup"},{"location":"u_e-backup_restore-maildir/#restore","text":"cd /path/to/mailcow-dockerized docker run --rm -it -v $(docker inspect --format '{{ range .Mounts }}{{ if eq .Destination \"/var/vmail\" }}{{ .Name }}{{ end }}{{ end }}' $(docker-compose ps -q dovecot-mailcow)):/vmail -v ${PWD}:/backup debian:stretch-slim tar xvfz /backup/backup_vmail.tar.gz","title":"Restore"},{"location":"u_e-backup_restore-mysql/","text":"Backup \u00b6 cd /path/to/mailcow-dockerized source mailcow.conf DATE=$(date +\"%Y%m%d_%H%M%S\") docker-compose exec -T mysql-mailcow mysqldump --default-character-set=utf8mb4 -u${DBUSER} -p${DBPASS} ${DBNAME} > backup_${DBNAME}_${DATE}.sql Restore \u00b6 Warning You should redirect the SQL dump without docker-compose to prevent parsing errors. cd /path/to/mailcow-dockerized source mailcow.conf docker exec -i $(docker-compose ps -q mysql-mailcow) mysql -u${DBUSER} -p${DBPASS} ${DBNAME} < backup_file.sql","title":"MySQL"},{"location":"u_e-backup_restore-mysql/#backup","text":"cd /path/to/mailcow-dockerized source mailcow.conf DATE=$(date +\"%Y%m%d_%H%M%S\") docker-compose exec -T mysql-mailcow mysqldump --default-character-set=utf8mb4 -u${DBUSER} -p${DBPASS} ${DBNAME} > backup_${DBNAME}_${DATE}.sql","title":"Backup"},{"location":"u_e-backup_restore-mysql/#restore","text":"Warning You should redirect the SQL dump without docker-compose to prevent parsing errors. cd /path/to/mailcow-dockerized source mailcow.conf docker exec -i $(docker-compose ps -q mysql-mailcow) mysql -u${DBUSER} -p${DBPASS} ${DBNAME} < backup_file.sql","title":"Restore"},{"location":"u_e-docker-cust_dockerfiles/","text":"You need to copy the override file with corresponding build tags to the mailcow: dockerized root folder (i.e. /opt/mailcow-dockerized ): cp helper-scripts/docker-compose.override.yml.d/BUILD_FLAGS/docker-compose.override.yml docker-compose.override.yml Make your changes in data/Dockerfiles/$service and build the image locally: docker build data/Dockerfiles/service -t mailcow/$service Now auto-recreate modified containers: docker-compose up -d","title":"Customize Dockerfiles"},{"location":"u_e-docker-dc_bash_compl/","text":"To get some sexy bash completion inside your containers simply execute the following: curl -L https://raw.githubusercontent.com/docker/compose/$(docker-compose version --short)/contrib/completion/bash/docker-compose -o /etc/bash_completion.d/docker-compose","title":"Docker Compose Bash Completion"},{"location":"u_e-dovecot-any_acl/","text":"On August the 17th, we disabled the possibility to share with \"any\" or \"all authenticated users\" by default. This function can be re-enabled by setting ACL_ANYONE to allow in mailcow.conf: ACL_ANYONE=allow Apply the changes by running docker-compose up -d .","title":"Enable \"any\" ACL settings"},{"location":"u_e-dovecot-expunge/","text":"If you want to delete old mails out of the .Junk or .Trash folders or maybe delete all read mails that are older than a certain amount of time you may use dovecot's tool doveadm man doveadm-expunge . The manual way \u00b6 That said, let's dive in: Delete a user's mails inside the junk folder that are read and older than 4 hours docker-compose exec dovecot-mailcow doveadm expunge -u 'mailbox@example.com' mailbox 'Junk' SEEN not SINCE 4h Delete all user's mails in the junk folder that are older than 7 days docker-compose exec dovecot-mailcow doveadm expunge -A mailbox 'Junk' savedbefore 7d Delete all mails (of all users) in all folders that are older than 52 weeks (internal date of the mail, not the date it was saved on the system => before instead of savedbefore ). Useful for deleting very old mails on all users and folders (thus especially useful for GDPR-compliance). docker-compose exec dovecot-mailcow doveadm expunge -A mailbox % before 52w Delete mails inside a custom folder inside a user's inbox that are not flagged and older than 2 weeks docker-compose exec dovecot-mailcow doveadm expunge -u 'mailbox@example.com' mailbox 'INBOX/custom-folder' not FLAGGED not SINCE 2w Info For possible time spans or search keys have a look at man doveadm-search-query Job scheduler \u00b6 via the host system cron \u00b6 If you want to automate such a task you can create a cron job on your host that calls a script like the one below: #!/bin/bash # Path to mailcow-dockerized, e.g. /opt/mailcow-dockerized cd /path/to/your/mailcow-dockerized /usr/local/bin/docker-compose exec -T dovecot-mailcow doveadm expunge -A mailbox 'Junk' savedbefore 2w /usr/local/bin/docker-compose exec -T dovecot-mailcow doveadm expunge -A mailbox 'Junk' SEEN not SINCE 12h [...] To create a cron job you may execute crontab -e and insert something like the following to execute a script: # Execute everyday at 04:00 A.M. 0 4 * * * /path/to/your/expunge_mailboxes.sh via Docker job scheduler \u00b6 To archive this with a docker job scheduler use this docker-compose.override.yml with your mailcow: version: '2.1' services: ofelia: image: mcuadros/ofelia:latest restart: always command: daemon --docker volumes: - /var/run/docker.sock:/var/run/docker.sock:ro network_mode: none dovecot-mailcow: labels: - \"ofelia.enabled=true\" - \"ofelia.job-exec.dovecot-expunge-trash.schedule=0 4 * * *\" - \"ofelia.job-exec.dovecot-expunge-trash.command=doveadm expunge -A mailbox 'Junk' savedbefore 2w\" - \"ofelia.job-exec.dovecot-expunge-trash.tty=false\" The job controller just need access to the docker control socket to be able to emulate the behavior of \"exec\". Then we add a few label to our dovecot-container to activate the job scheduler and tell him in a cron compatible scheduling format when to run. If you struggle with that schedule string you can use crontab guru . This docker-compose.override.yml deletes all mails older then 2 weeks from the \"Junk\" folder every day at 4 am. To see if things ran proper, you can not only see in your mailbox but also check Ofelia's docker log if it looks something like this: common.go:124 \u25b6 NOTICE [Job \"dovecot-expunge-trash\" (8759567efa66)] Started - doveadm expunge -A mailbox 'Junk' savedbefore 2w, common.go:124 \u25b6 NOTICE [Job \"dovecot-expunge-trash\" (8759567efa66)] Finished in \"285.032291ms\", failed: false, skipped: false, error: none, If it failed it will say so and give you the output of the doveadm in the log to make it easy on you to debug. In case you want to add more jobs, ensure you change the \"dovecot-expunge-trash\" part after \"ofelia.job-exec.\" to something else, it defines the name of the job. Syntax of the labels you find at mcuadros/ofelia .","title":"Expunge a Users mails"},{"location":"u_e-dovecot-expunge/#the-manual-way","text":"That said, let's dive in: Delete a user's mails inside the junk folder that are read and older than 4 hours docker-compose exec dovecot-mailcow doveadm expunge -u 'mailbox@example.com' mailbox 'Junk' SEEN not SINCE 4h Delete all user's mails in the junk folder that are older than 7 days docker-compose exec dovecot-mailcow doveadm expunge -A mailbox 'Junk' savedbefore 7d Delete all mails (of all users) in all folders that are older than 52 weeks (internal date of the mail, not the date it was saved on the system => before instead of savedbefore ). Useful for deleting very old mails on all users and folders (thus especially useful for GDPR-compliance). docker-compose exec dovecot-mailcow doveadm expunge -A mailbox % before 52w Delete mails inside a custom folder inside a user's inbox that are not flagged and older than 2 weeks docker-compose exec dovecot-mailcow doveadm expunge -u 'mailbox@example.com' mailbox 'INBOX/custom-folder' not FLAGGED not SINCE 2w Info For possible time spans or search keys have a look at man doveadm-search-query","title":"The manual way"},{"location":"u_e-dovecot-expunge/#job-scheduler","text":"","title":"Job scheduler"},{"location":"u_e-dovecot-expunge/#via-the-host-system-cron","text":"If you want to automate such a task you can create a cron job on your host that calls a script like the one below: #!/bin/bash # Path to mailcow-dockerized, e.g. /opt/mailcow-dockerized cd /path/to/your/mailcow-dockerized /usr/local/bin/docker-compose exec -T dovecot-mailcow doveadm expunge -A mailbox 'Junk' savedbefore 2w /usr/local/bin/docker-compose exec -T dovecot-mailcow doveadm expunge -A mailbox 'Junk' SEEN not SINCE 12h [...] To create a cron job you may execute crontab -e and insert something like the following to execute a script: # Execute everyday at 04:00 A.M. 0 4 * * * /path/to/your/expunge_mailboxes.sh","title":"via the host system cron"},{"location":"u_e-dovecot-expunge/#via-docker-job-scheduler","text":"To archive this with a docker job scheduler use this docker-compose.override.yml with your mailcow: version: '2.1' services: ofelia: image: mcuadros/ofelia:latest restart: always command: daemon --docker volumes: - /var/run/docker.sock:/var/run/docker.sock:ro network_mode: none dovecot-mailcow: labels: - \"ofelia.enabled=true\" - \"ofelia.job-exec.dovecot-expunge-trash.schedule=0 4 * * *\" - \"ofelia.job-exec.dovecot-expunge-trash.command=doveadm expunge -A mailbox 'Junk' savedbefore 2w\" - \"ofelia.job-exec.dovecot-expunge-trash.tty=false\" The job controller just need access to the docker control socket to be able to emulate the behavior of \"exec\". Then we add a few label to our dovecot-container to activate the job scheduler and tell him in a cron compatible scheduling format when to run. If you struggle with that schedule string you can use crontab guru . This docker-compose.override.yml deletes all mails older then 2 weeks from the \"Junk\" folder every day at 4 am. To see if things ran proper, you can not only see in your mailbox but also check Ofelia's docker log if it looks something like this: common.go:124 \u25b6 NOTICE [Job \"dovecot-expunge-trash\" (8759567efa66)] Started - doveadm expunge -A mailbox 'Junk' savedbefore 2w, common.go:124 \u25b6 NOTICE [Job \"dovecot-expunge-trash\" (8759567efa66)] Finished in \"285.032291ms\", failed: false, skipped: false, error: none, If it failed it will say so and give you the output of the doveadm in the log to make it easy on you to debug. In case you want to add more jobs, ensure you change the \"dovecot-expunge-trash\" part after \"ofelia.job-exec.\" to something else, it defines the name of the job. Syntax of the labels you find at mcuadros/ofelia .","title":"via Docker job scheduler"},{"location":"u_e-dovecot-extra_conf/","text":"Create a file data/conf/dovecot/extra.conf - if missing - and add your additional content here. Restart dovecot-mailcow to apply your changes: docker-compose restart dovecot-mailcow","title":"Customize/Expand dovecot.conf"},{"location":"u_e-dovecot-fts/","text":"Solr is used for setups with memory >= 3.5 GiB to provide full-text search in Dovecot. Please be aware that applications like Solr may need maintenance from time to time. Besides that, Solr will eat a lot of RAM, depending on the usage of your server. Please avoid it on machines with less than 3 GB RAM. The default heap size (1024 M) is defined in mailcow.conf. Since we run in Docker and create our containers with the \"restart: always\" flag, a oom situation will at least only trigger a restart of the container. FTS related Dovecot commands \u00b6 # single user docker-compose exec dovecot-mailcow doveadm fts rescan -u user@domain # all users docker-compose exec dovecot-mailcow doveadm fts rescan -A Dovecot Wiki: \"Scan what mails exist in the full text search index and compare those to what actually exist in mailboxes. This removes mails from the index that have already been expunged and makes sure that the next doveadm index will index all the missing mails (if any).\" This does not re-index a mailbox. It basically repairs a given index. If you want to re-index data immediately, you can run the followig command, where '*' can also be a mailbox mask like 'Sent'. You do not need to run these commands, but it will speed things up a bit: # single user docker-compose exec dovecot-mailcow doveadm index -u user@domain '*' # all users, but obviously slower and more dangerous docker-compose exec dovecot-mailcow doveadm index -A '*' This will take some time depending on your machine and Solr can run oom, monitor it! Because re-indexing is very sensible, we did not include it to mailcow UI. You will need to take care of any errors while re-indexing a mailbox. Delete mailbox data \u00b6 mailcow will purge index data of a user when deleting a mailbox.","title":"FTS (Solr)"},{"location":"u_e-dovecot-fts/#fts-related-dovecot-commands","text":"# single user docker-compose exec dovecot-mailcow doveadm fts rescan -u user@domain # all users docker-compose exec dovecot-mailcow doveadm fts rescan -A Dovecot Wiki: \"Scan what mails exist in the full text search index and compare those to what actually exist in mailboxes. This removes mails from the index that have already been expunged and makes sure that the next doveadm index will index all the missing mails (if any).\" This does not re-index a mailbox. It basically repairs a given index. If you want to re-index data immediately, you can run the followig command, where '*' can also be a mailbox mask like 'Sent'. You do not need to run these commands, but it will speed things up a bit: # single user docker-compose exec dovecot-mailcow doveadm index -u user@domain '*' # all users, but obviously slower and more dangerous docker-compose exec dovecot-mailcow doveadm index -A '*' This will take some time depending on your machine and Solr can run oom, monitor it! Because re-indexing is very sensible, we did not include it to mailcow UI. You will need to take care of any errors while re-indexing a mailbox.","title":"FTS related Dovecot commands"},{"location":"u_e-dovecot-fts/#delete-mailbox-data","text":"mailcow will purge index data of a user when deleting a mailbox.","title":"Delete mailbox data"},{"location":"u_e-dovecot-idle_interval/","text":"Changing the IMAP IDLE interval \u00b6 What is the IDLE interval? \u00b6 Per default, Dovecot sends a \"I'm still here\" notification to every client that has an open connection with Dovecot to get mails as quickly as possible without manually polling it (IMAP PUSH). This notification is controlled by the setting imap_idle_notify_interval , which defaults to 2 minutes. A short interval results in the client getting a lot of messages for this connection, which is bad for mobile devices, because every time the device receives this message, the mailing app has to wake up. This can result in unnecessary battery drain. Edit the value \u00b6 Change configuration \u00b6 Create a new file data/conf/dovecot/extra.conf (or edit it if it already exists). Insert the setting followed by the new value. For example, to set the interval to 5 minutes you could type: imap_idle_notify_interval = 5 mins 29 minutes is the maximum value allowed by the corresponding RFC . Warning This isn't a default setting in mailcow because we don't know how this setting changes the behavior of other clients. Be careful if you change this and monitor different behavior. Reload Dovecot \u00b6 Now reload Dovecot: docker-compose exec dovecot-mailcow dovecot reload Info You can check the value of this setting with docker-compose exec dovecot-mailcow dovecot -a | grep \"imap_idle_notify_interval\" If you didn't change it, it should be at 2m. If you did change it, you should see your new value.","title":"IMAP IDLE interval"},{"location":"u_e-dovecot-idle_interval/#changing-the-imap-idle-interval","text":"","title":"Changing the IMAP IDLE interval"},{"location":"u_e-dovecot-idle_interval/#what-is-the-idle-interval","text":"Per default, Dovecot sends a \"I'm still here\" notification to every client that has an open connection with Dovecot to get mails as quickly as possible without manually polling it (IMAP PUSH). This notification is controlled by the setting imap_idle_notify_interval , which defaults to 2 minutes. A short interval results in the client getting a lot of messages for this connection, which is bad for mobile devices, because every time the device receives this message, the mailing app has to wake up. This can result in unnecessary battery drain.","title":"What is the IDLE interval?"},{"location":"u_e-dovecot-idle_interval/#edit-the-value","text":"","title":"Edit the value"},{"location":"u_e-dovecot-idle_interval/#change-configuration","text":"Create a new file data/conf/dovecot/extra.conf (or edit it if it already exists). Insert the setting followed by the new value. For example, to set the interval to 5 minutes you could type: imap_idle_notify_interval = 5 mins 29 minutes is the maximum value allowed by the corresponding RFC . Warning This isn't a default setting in mailcow because we don't know how this setting changes the behavior of other clients. Be careful if you change this and monitor different behavior.","title":"Change configuration"},{"location":"u_e-dovecot-idle_interval/#reload-dovecot","text":"Now reload Dovecot: docker-compose exec dovecot-mailcow dovecot reload Info You can check the value of this setting with docker-compose exec dovecot-mailcow dovecot -a | grep \"imap_idle_notify_interval\" If you didn't change it, it should be at 2m. If you did change it, you should see your new value.","title":"Reload Dovecot"},{"location":"u_e-dovecot-mail-crypt/","text":"Mails are stored compressed (lz4) and encrypted. The key pair can be found in crypt-vol-1. If you want to decode/encode existing maildir files, you can use the following script at your own risk: Enter Dovecot by running docker-compose exec dovecot-mailcow /bin/bash in the mailcow-dockerized location. # Decrypt /var/vmail find /var/vmail/ -type f -regextype egrep -regex '.*S=.*W=.*' | while read -r file; do if [[ $(head -c7 \"$file\") == \"CRYPTED\" ]]; then doveadm fs get compress lz4:0:crypt:private_key_path=/mail_crypt/ecprivkey.pem:public_key_path=/mail_crypt/ecpubkey.pem:posix:prefix=/ \\ \"$file\" > \"/tmp/$(basename \"$file\")\" if [[ -s \"/tmp/$(basename \"$file\")\" ]]; then chmod 600 \"/tmp/$(basename \"$file\")\" chown 5000:5000 \"/tmp/$(basename \"$file\")\" mv \"/tmp/$(basename \"$file\")\" \"$file\" else rm \"/tmp/$(basename \"$file\")\" fi fi done # Encrypt /var/vmail find /var/vmail/ -type f -regextype egrep -regex '.*S=.*W=.*' | while read -r file; do if [[ $(head -c7 \"$file\") != \"CRYPTED\" ]]; then doveadm fs put crypt private_key_path=/mail_crypt/ecprivkey.pem:public_key_path=/mail_crypt/ecpubkey.pem:posix:prefix=/ \\ \"$file\" \"$file\" chmod 600 \"$file\" chown 5000:5000 \"$file\" fi done","title":"Mail crypt"},{"location":"u_e-dovecot-more/","text":"Here is just an unsorted list of useful doveadm commands that could be useful. doveadm quota \u00b6 The quota get and quota recalc 1 commands are used to display or recalculate the current user's quota usage. The reported values are in kilobytes . To list the current quota status for a user / mailbox, do: doveadm quota get -u 'mailbox@example.org' To list the quota storage value for all users, do: doveadm quota get -A |grep \"STORAGE\" Recalculate a single user's quota usage: doveadm quota recalc -u 'mailbox@example.org' doveadm search \u00b6 The doveadm search 2 command is used to find messages matching your query. It can return the username, mailbox-GUID / -UID and message-GUIDs / -UIDs. To view the number of messages, by user, in their .Trash folder: doveadm search -A mailbox 'Trash' | awk '{print $1}' | sort | uniq -c Show all messages in a user's inbox older then 90 days: doveadm search -u 'mailbox@example.org' mailbox 'INBOX' savedbefore 90d Show all messages in any folder that are older then 30 days for mailbox@example.org : doveadm search -u 'mailbox@example.org' mailbox \"*\" savedbefore 30d https://wiki.dovecot.org/Tools/Doveadm/Quota \u21a9 https://wiki.dovecot.org/Tools/Doveadm/Search \u21a9","title":"More Examples with DOVEADM"},{"location":"u_e-dovecot-more/#doveadm-quota","text":"The quota get and quota recalc 1 commands are used to display or recalculate the current user's quota usage. The reported values are in kilobytes . To list the current quota status for a user / mailbox, do: doveadm quota get -u 'mailbox@example.org' To list the quota storage value for all users, do: doveadm quota get -A |grep \"STORAGE\" Recalculate a single user's quota usage: doveadm quota recalc -u 'mailbox@example.org'","title":"doveadm quota"},{"location":"u_e-dovecot-more/#doveadm-search","text":"The doveadm search 2 command is used to find messages matching your query. It can return the username, mailbox-GUID / -UID and message-GUIDs / -UIDs. To view the number of messages, by user, in their .Trash folder: doveadm search -A mailbox 'Trash' | awk '{print $1}' | sort | uniq -c Show all messages in a user's inbox older then 90 days: doveadm search -u 'mailbox@example.org' mailbox 'INBOX' savedbefore 90d Show all messages in any folder that are older then 30 days for mailbox@example.org : doveadm search -u 'mailbox@example.org' mailbox \"*\" savedbefore 30d https://wiki.dovecot.org/Tools/Doveadm/Quota \u21a9 https://wiki.dovecot.org/Tools/Doveadm/Search \u21a9","title":"doveadm search"},{"location":"u_e-dovecot-public_folder/","text":"Create a new public namespace \"Public\" and a mailbox \"Develcow\" inside that namespace: Edit or create data/conf/dovecot/extra.conf , add: namespace { type = public separator = / prefix = Public/ location = maildir:/var/vmail/public:INDEXPVT=~/public subscriptions = yes mailbox \"Develcow\" { auto = subscribe } } :INDEXPVT=~/public can be omitted if per-user seen flags are not wanted. The new mailbox in the public namespace will be auto-subscribed by users. To allow all authenticated users access full to that new mailbox (not the whole namespace), run: docker-compose exec dovecot-mailcow doveadm acl set -A \"Public/Develcow\" \"authenticated\" lookup read write write-seen write-deleted insert post delete expunge create Adjust the command to your needs if you like to assign more granular rights per user (use -u user@domain instead of -A for example). Allow authenticated users access to the whole public namespace \u00b6 To allow all authenticated users access full access to the whole public namespace and its subfolders, create a new dovecot-acl file in the namespace root directory: Open/edit/create /var/lib/docker/volumes/mailcowdockerized_vmail-vol-1/_data/public/dovecot-acl (adjust the path accordingly) to create the global ACL file with the following content: authenticated kxeilprwts kxeilprwts equals to lookup read write write-seen write-deleted insert post delete expunge create . You can use doveadm acl set -u user@domain \"Public/Develcow\" user=user@domain lookup read to limit access for a single user. You may also turn it around to limit access for all users to \"lr\" and grant only some users full access. See Dovecot ACL for further information about ACL.","title":"Public folders"},{"location":"u_e-dovecot-public_folder/#allow-authenticated-users-access-to-the-whole-public-namespace","text":"To allow all authenticated users access full access to the whole public namespace and its subfolders, create a new dovecot-acl file in the namespace root directory: Open/edit/create /var/lib/docker/volumes/mailcowdockerized_vmail-vol-1/_data/public/dovecot-acl (adjust the path accordingly) to create the global ACL file with the following content: authenticated kxeilprwts kxeilprwts equals to lookup read write write-seen write-deleted insert post delete expunge create . You can use doveadm acl set -u user@domain \"Public/Develcow\" user=user@domain lookup read to limit access for a single user. You may also turn it around to limit access for all users to \"lr\" and grant only some users full access. See Dovecot ACL for further information about ACL.","title":"Allow authenticated users access to the whole public namespace"},{"location":"u_e-dovecot-static_master/","text":"Random master usernames and passwords are automatically created on every restart of dovecot-mailcow. That's recommended and should not be changed. If you need the user to be static anyway, please specify two variables in mailcow.conf . Both parameters must not be empty! DOVECOT_MASTER_USER=mymasteruser DOVECOT_MASTER_PASS=mysecretpass Run docker-compose up -d to apply your changes. The static master username will be expanded to DOVECOT_MASTER_USER@mailcow.local . To login as test@example.org this would equal to test@example.org*mymasteruser@mailcow.local with the specified password above. A login to SOGo is not possible with this username. A click-to-login function for SOGo is available for admins as described here No master user is required.","title":"Static master user"},{"location":"u_e-dovecot-vmail-volume/","text":"The \"new\" way \u00b6 WARNING : Newer Docker versions seem to complain about existing volumes. You can fix this temporarily by removing the existing volume and start mailcow with the override file. But it seems to be problematic after a reboot (needs to be confirmed). An easy, dirty, yet stable workaround is to stop mailcow ( docker-compose down ), remove /var/lib/docker/volumes/mailcowdockerized_vmail-vol-1/_data and create a new link to your remote filesystem location, for example: mv /var/lib/docker/volumes/mailcowdockerized_vmail-vol-1/_data /var/lib/docker/volumes/mailcowdockerized_vmail-vol-1/_data_backup ln -s /mnt/volume-xy/vmail_data /var/lib/docker/volumes/mailcowdockerized_vmail-vol-1/_data Start mailcow afterwards. The \"old\" way \u00b6 If you want to use another folder for the vmail-volume, you can create a docker-compose.override.yml file and add the following content: version: '2.1' volumes: vmail-vol-1: driver_opts: type: none device: /data/mailcow/vmail o: bind Moving an existing vmail folder: \u00b6 Locate the current vmail folder by its \"Mountpoint\" attribute: docker volume inspect mailcowdockerized_vmail-vol-1 [ { \"CreatedAt\": \"2019-06-16T22:08:34+02:00\", \"Driver\": \"local\", \"Labels\": { \"com.docker.compose.project\": \"mailcowdockerized\", \"com.docker.compose.version\": \"1.23.2\", \"com.docker.compose.volume\": \"vmail-vol-1\" }, \"Mountpoint\": \"/var/lib/docker/volumes/mailcowdockerized_vmail-vol-1/_data\", \"Name\": \"mailcowdockerized_vmail-vol-1\", \"Options\": null, \"Scope\": \"local\" } ] Copy the content of the Mountpoint folder to the new location (e.g. /data/mailcow/vmail ) using cp -a , rsync -a or a similar non strcuture breaking copy command Stop mailcow by executing docker-compose down from within your mailcow root folder (e.g. /opt/mailcow-dockerized ) Create the file docker-compose.override.yml , edit the device path accordingly Delete the current vmail folder: docker volume rm mailcowdockerized_vmail-vol-1 Start mailcow by executing docker-compose up -d from within your mailcow root folder (e.g. /opt/mailcow-dockerized )","title":"Move Maildir (vmail)"},{"location":"u_e-dovecot-vmail-volume/#the-new-way","text":"WARNING : Newer Docker versions seem to complain about existing volumes. You can fix this temporarily by removing the existing volume and start mailcow with the override file. But it seems to be problematic after a reboot (needs to be confirmed). An easy, dirty, yet stable workaround is to stop mailcow ( docker-compose down ), remove /var/lib/docker/volumes/mailcowdockerized_vmail-vol-1/_data and create a new link to your remote filesystem location, for example: mv /var/lib/docker/volumes/mailcowdockerized_vmail-vol-1/_data /var/lib/docker/volumes/mailcowdockerized_vmail-vol-1/_data_backup ln -s /mnt/volume-xy/vmail_data /var/lib/docker/volumes/mailcowdockerized_vmail-vol-1/_data Start mailcow afterwards.","title":"The \"new\" way"},{"location":"u_e-dovecot-vmail-volume/#the-old-way","text":"If you want to use another folder for the vmail-volume, you can create a docker-compose.override.yml file and add the following content: version: '2.1' volumes: vmail-vol-1: driver_opts: type: none device: /data/mailcow/vmail o: bind","title":"The \"old\" way"},{"location":"u_e-dovecot-vmail-volume/#moving-an-existing-vmail-folder","text":"Locate the current vmail folder by its \"Mountpoint\" attribute: docker volume inspect mailcowdockerized_vmail-vol-1 [ { \"CreatedAt\": \"2019-06-16T22:08:34+02:00\", \"Driver\": \"local\", \"Labels\": { \"com.docker.compose.project\": \"mailcowdockerized\", \"com.docker.compose.version\": \"1.23.2\", \"com.docker.compose.volume\": \"vmail-vol-1\" }, \"Mountpoint\": \"/var/lib/docker/volumes/mailcowdockerized_vmail-vol-1/_data\", \"Name\": \"mailcowdockerized_vmail-vol-1\", \"Options\": null, \"Scope\": \"local\" } ] Copy the content of the Mountpoint folder to the new location (e.g. /data/mailcow/vmail ) using cp -a , rsync -a or a similar non strcuture breaking copy command Stop mailcow by executing docker-compose down from within your mailcow root folder (e.g. /opt/mailcow-dockerized ) Create the file docker-compose.override.yml , edit the device path accordingly Delete the current vmail folder: docker volume rm mailcowdockerized_vmail-vol-1 Start mailcow by executing docker-compose up -d from within your mailcow root folder (e.g. /opt/mailcow-dockerized )","title":"Moving an existing vmail folder:"},{"location":"u_e-fido2/","text":"How is UV handled in mailcow? \u00b6 The UV flag (as in \"user verification\") enforces WebAuthn to verify the user before it allows access to the key (think of a PIN). We don't enforce UV to allow logins via iOS and NFC (YubiKey). Login and key processing \u00b6 mailcow uses client-side key processing . We ask the authenticator (i.e. YubiKey) to save the registration in its memory. A user does not need to enter a username. The available credentials - if any - will be shown to the user when selecting the \"key login\" via mailcow UI login. When calling the login process, the authenticator is not given any credential IDs. This will force it to lookup credentials in its own memory. Who can use WebAuthn to login to mailcow? \u00b6 As of today, only administrators and domain administrators are able to setup WebAuthn/FIDO2.","title":"WebAuthn / FIDO2"},{"location":"u_e-fido2/#how-is-uv-handled-in-mailcow","text":"The UV flag (as in \"user verification\") enforces WebAuthn to verify the user before it allows access to the key (think of a PIN). We don't enforce UV to allow logins via iOS and NFC (YubiKey).","title":"How is UV handled in mailcow?"},{"location":"u_e-fido2/#login-and-key-processing","text":"mailcow uses client-side key processing . We ask the authenticator (i.e. YubiKey) to save the registration in its memory. A user does not need to enter a username. The available credentials - if any - will be shown to the user when selecting the \"key login\" via mailcow UI login. When calling the login process, the authenticator is not given any credential IDs. This will force it to lookup credentials in its own memory.","title":"Login and key processing"},{"location":"u_e-fido2/#who-can-use-webauthn-to-login-to-mailcow","text":"As of today, only administrators and domain administrators are able to setup WebAuthn/FIDO2.","title":"Who can use WebAuthn to login to mailcow?"},{"location":"u_e-mailcow_ui-bl_wl/","text":"To add or edit an entry to your domain wide filter table, login to your mailcow UI as (domain) administrator. Info Be aware that a user may override this setting by setting his own black- and whitelist! There is also a global filter table in /admin to configure a server-wide filter for multiple Regex maps (Todo: Screenshots).","title":"Blacklist / Whitelist"},{"location":"u_e-mailcow_ui-config/","text":"Several configuration parameters of the mailcow UI can be changed by creating a file data/web/inc/vars.local.inc.php which overrides defaults settings found in data/web/inc/vars.inc.php . The local configuration file is persistent over updates of mailcow. Try not to change values inside data/web/inc/vars.inc.php , but use them as template for the local override. mailcow UI configuration parameters can be used to... ...change the default language 1 ...change the default bootstrap theme ...set a password complexity regex ...enable DKIM private key visibility ...set a pagination trigger size ...set default mailbox attributes ...change session lifetimes ...create fixed app menus (which cannot be changed in mailcow UI) ...set a default \"To\" field for relayhost tests ...set a timeout for Docker API requests ...toggle IP anonymization To change SOGos default language, you will need to edit data/conf/sogo/sogo.conf and replace \"English\" by your preferred language. \u21a9","title":"Configuration"},{"location":"u_e-mailcow_ui-css/","text":"For custom overrides of specific elements via CSS, use data/web/css/build/0081-custom-mailcow.css . The file is excluded from tracking and persists over updates.","title":"CSS overrides"},{"location":"u_e-mailcow_ui-pushover/","text":"Info Pushover makes it easy to get real-time notifications on your Android, iPhone, iPad, and Desktop You can use Pushover to get a push notification on every mail you receive for each mailbox where you enabled this feature. 1. As admin open your mailbox' settings and scroll down to the Pushover settings 2. Register yourself on Pushover 3. Put your 'User Key' in the 'User/Group Key' field in your mailbox settings 4. Create an Applications to get the API Token/Key which you also need to put in your mailbox settings 5. Optional you can edit the notification title/text and define certain sender email addresses where a push notification is triggered 6. Save everything and then you can verify your credentials If everything is done you can test sending a mail and you will receive a push message on your phone","title":"Pushover"},{"location":"u_e-mailcow_ui-spamalias/","text":"These temporary email aliases are mostly used for places where we need to provide an email address but don't want future correspondence with. They are also called spam alias. To create, delete or extend a temporary email aliases you need to login to mailcow's UI as a mailbox user and navigate to the tab Temporary email aliases :","title":"Temporary email aliases"},{"location":"u_e-mailcow_ui-spamfilter/","text":"A mailbox user may adjust the spam filter and black- / whitelist settings for his mailbox individually by navigating to the Spam filter tab in the users mailcow UI. Info For global adjustments on your spam filter please check our section on Rspamd . For a domain wide black- and whitelist please check our guide on Black / Whitelist","title":"Spamfilter"},{"location":"u_e-mailcow_ui-tagging/","text":"Mailbox users can tag their mail address like in me+facebook@example.org . They can control the tag handling in the users mailcow UI panel. Available Actions \u00b6 1. Move this message to a sub folder \"facebook\" (will be created lower case if not existing) 2. Prepend the tag to the subject: \"[facebook] Subject\" Please note: Uppercase tags are converted to lowercase except for the first letter. If you want to keep the tag as it is, please apply the following diff and restart mailcow: diff --git a/data/conf/dovecot/global_sieve_after b/data/conf/dovecot/global_sieve_after index e047136e..933c4137 100644 --- a/data/conf/dovecot/global_sieve_after +++ b/data/conf/dovecot/global_sieve_after @@ -15,7 +15,7 @@ if allof ( envelope :detail :matches \"to\" \"*\", header :contains \"X-Moo-Tag\" \"YES\" ) { - set :lower :upperfirst \"tag\" \"${1}\"; + set \"tag\" \"${1}\"; if mailboxexists \"INBOX/${1}\" { fileinto \"INBOX/${1}\"; } else {","title":"Tagging"},{"location":"u_e-mailcow_ui-tagging/#available-actions","text":"1. Move this message to a sub folder \"facebook\" (will be created lower case if not existing) 2. Prepend the tag to the subject: \"[facebook] Subject\" Please note: Uppercase tags are converted to lowercase except for the first letter. If you want to keep the tag as it is, please apply the following diff and restart mailcow: diff --git a/data/conf/dovecot/global_sieve_after b/data/conf/dovecot/global_sieve_after index e047136e..933c4137 100644 --- a/data/conf/dovecot/global_sieve_after +++ b/data/conf/dovecot/global_sieve_after @@ -15,7 +15,7 @@ if allof ( envelope :detail :matches \"to\" \"*\", header :contains \"X-Moo-Tag\" \"YES\" ) { - set :lower :upperfirst \"tag\" \"${1}\"; + set \"tag\" \"${1}\"; if mailboxexists \"INBOX/${1}\" { fileinto \"INBOX/${1}\"; } else {","title":"Available Actions"},{"location":"u_e-mailcow_ui-tfa/","text":"So far three methods for Two-Factor Authentication are implemented: U2F, Yubi OTP, and TOTP For U2F to work, you need an encrypted connection to the server (HTTPS) as well as a FIDO security key. Both U2F and Yubi OTP work well with the fantastic Yubikey . While Yubi OTP needs an active internet connection and an API ID + key, U2F will work with any FIDO U2F USB key out of the box, but can only be used when mailcow is accessed over HTTPS. U2F and Yubi OTP support multiple keys per user. As the third TFA method mailcow uses TOTP: time-based one-time passwords. Those passwords can be generated with apps like \"Google Authenticator\" after initially scanning a QR code or entering the given secret manually. As administrator you are able to temporary disable a domain administrators TFA login until they successfully logged in. The key used to login will be displayed in green, while other keys remain grey. Information on how to remove 2FA can be found here . Yubi OTP \u00b6 The Yubi API ID and Key will be checked against the Yubico Cloud API. When setting up TFA you will be asked for your personal API account for this key. The API ID, API key and the first 12 characters (your YubiKeys ID in modhex) are stored in the MySQL table as secret. U2F \u00b6 To use U2F, the browser must support this standard. The following desktop browsers support this authentication type: Edge (>=79) Firefox (>=47, enabled by default since version 67) Chrome (>=41) Safari (>=13) Opera (40, >=42, not 41) The following mobile browsers support this authentication type: Safari on iOS (>=13.3) Firefox on Android (>=68) Sources: caniuse.com , blog.mozilla.org U2F works without an internet connection. TOTP \u00b6 The best known TFA method mostly used with a smartphone.","title":"Two-Factor Authentication"},{"location":"u_e-mailcow_ui-tfa/#yubi-otp","text":"The Yubi API ID and Key will be checked against the Yubico Cloud API. When setting up TFA you will be asked for your personal API account for this key. The API ID, API key and the first 12 characters (your YubiKeys ID in modhex) are stored in the MySQL table as secret.","title":"Yubi OTP"},{"location":"u_e-mailcow_ui-tfa/#u2f","text":"To use U2F, the browser must support this standard. The following desktop browsers support this authentication type: Edge (>=79) Firefox (>=47, enabled by default since version 67) Chrome (>=41) Safari (>=13) Opera (40, >=42, not 41) The following mobile browsers support this authentication type: Safari on iOS (>=13.3) Firefox on Android (>=68) Sources: caniuse.com , blog.mozilla.org U2F works without an internet connection.","title":"U2F"},{"location":"u_e-mailcow_ui-tfa/#totp","text":"The best known TFA method mostly used with a smartphone.","title":"TOTP"},{"location":"u_e-nginx/","text":"To create persistent (over updates) sites hosted by mailcow: dockerized, a new site configuration must be placed inside data/conf/nginx/ : nano data/conf/nginx/my_custom_site.conf A good template to begin with: server { ssl_certificate /etc/ssl/mail/cert.pem; ssl_certificate_key /etc/ssl/mail/key.pem; ssl_protocols TLSv1.2 TLSv1.3; ssl_prefer_server_ciphers on; ssl_ciphers ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305; ssl_ecdh_curve X25519:X448:secp384r1:secp256k1; ssl_session_cache shared:SSL:50m; ssl_session_timeout 1d; ssl_session_tickets off; index index.php index.html; client_max_body_size 0; root /web; include /etc/nginx/conf.d/listen_plain.active; include /etc/nginx/conf.d/listen_ssl.active; server_name mysite.example.org; server_tokens off; location ^~ /.well-known/acme-challenge/ { allow all; default_type \"text/plain\"; } if ($scheme = http) { return 301 https://$server_name$request_uri; } } Another example with a reverse proxy configuration: server { ssl_certificate /etc/ssl/mail/cert.pem; ssl_certificate_key /etc/ssl/mail/key.pem; ssl_protocols TLSv1.2 TLSv1.3; ssl_prefer_server_ciphers on; ssl_ciphers ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305; ssl_ecdh_curve X25519:X448:secp384r1:secp256k1; ssl_session_cache shared:SSL:50m; ssl_session_timeout 1d; ssl_session_tickets off; index index.php index.html; client_max_body_size 0; root /web; include /etc/nginx/conf.d/listen_plain.active; include /etc/nginx/conf.d/listen_ssl.active; server_name example.domain.tld; server_tokens off; location ^~ /.well-known/acme-challenge/ { allow all; default_type \"text/plain\"; } if ($scheme = http) { return 301 https://$host$request_uri; } location / { proxy_pass http://service:3000/; proxy_set_header Host $http_host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Proto $scheme; client_max_body_size 0; } } The filename is not important, as long as the filename carries a .conf extension. It is also possible to extend the configuration of the default file site.conf file: nano data/conf/nginx/site.my_content.custom This filename does not need to have a \".conf\" extension, but follows the pattern site.*.custom , where * is a custom name. If PHP is to be included in a custom site, please use the PHP-FPM listener on phpfpm:9002 or create a new listener in data/conf/phpfpm/php-fpm.d/pools.conf . Restart Nginx (and PHP-FPM, if a new listener was created): docker-compose restart nginx-mailcow docker-compose restart php-fpm-mailcow","title":"Custom sites"},{"location":"u_e-postfix-attachment_size/","text":"Open data/conf/postfix/main.cf and set the message_size_limit accordingly in bytes. Restart Postfix: docker-compose restart postfix-mailcow","title":"Max. message size (attachment size)"},{"location":"u_e-postfix-custom_transport/","text":"For transport maps other than those to be configured in mailcow UI, please use data/conf/postfix/custom_transport.pcre to prevent existing maps or settings from being overwritten by updates. In most cases using this file is not necessary. Please make sure mailcow UI is not able to route your desired traffic properly before using that file. The file needs valid PCRE content and can break Postfix, if configured incorrectly.","title":"Custom transport maps"},{"location":"u_e-postfix-disable_sender_verification/","text":"New guide \u00b6 Edit a mailbox and select \"Allow to send as *\". For historical reasons we kept the old and deprecated guide below: Deprecated guide (DO NOT USE ON NEWER MAILCOWS!) \u00b6 This option is not best-practice and should only be implemented when there is no other option available to achieve whatever you are trying to do. Simply create a file data/conf/postfix/check_sasl_access and enter the following content. This user must exist in your installation and needs to authenticate before sending mail. user-to-allow-everything@example.com OK Open data/conf/postfix/main.cf and find smtpd_sender_restrictions . Prepend check_sasl_access hash:/opt/postfix/conf/check_sasl_access like this: smtpd_sender_restrictions = check_sasl_access hash:/opt/postfix/conf/check_sasl_access reject_authenticated_sender_login_mismatch [...] Run postmap on check_sasl_access: docker-compose exec postfix-mailcow postmap /opt/postfix/conf/check_sasl_access Restart the Postfix container.","title":"Disable Sender Addresses Verification"},{"location":"u_e-postfix-disable_sender_verification/#new-guide","text":"Edit a mailbox and select \"Allow to send as *\". For historical reasons we kept the old and deprecated guide below:","title":"New guide"},{"location":"u_e-postfix-disable_sender_verification/#deprecated-guide-do-not-use-on-newer-mailcows","text":"This option is not best-practice and should only be implemented when there is no other option available to achieve whatever you are trying to do. Simply create a file data/conf/postfix/check_sasl_access and enter the following content. This user must exist in your installation and needs to authenticate before sending mail. user-to-allow-everything@example.com OK Open data/conf/postfix/main.cf and find smtpd_sender_restrictions . Prepend check_sasl_access hash:/opt/postfix/conf/check_sasl_access like this: smtpd_sender_restrictions = check_sasl_access hash:/opt/postfix/conf/check_sasl_access reject_authenticated_sender_login_mismatch [...] Run postmap on check_sasl_access: docker-compose exec postfix-mailcow postmap /opt/postfix/conf/check_sasl_access Restart the Postfix container.","title":"Deprecated guide (DO NOT USE ON NEWER MAILCOWS!)"},{"location":"u_e-postfix-extra_cf/","text":"Please create a new file data/conf/postfix/extra.cf for overrides or additional content to main.cf . Postfix will complain about duplicate values once after starting postfix-mailcow, this is intended. Syslog-ng was configured to hide those warnings while Postfix is running, to not spam the log files with unnecessary information every time a service is used. Restart postfix-mailcow to apply your changes: docker-compose restart postfix-mailcow","title":"Customize/Expand main.cf"},{"location":"u_e-postfix-pflogsumm/","text":"To use pflogsumm with the default logging driver, we need to query postfix-mailcow via docker logs and pipe the output to pflogsumm: docker logs --since 24h $(docker ps -qf name=postfix-mailcow) | pflogsumm The above log output is limited to the past 24 hours. It's also possible to create a daily pflogsumm report via cron. Create the file /etc/cron.d/pflogsumm with the following content: SHELL=/bin/bash 59 23 * * * root docker logs --since 24h $(docker ps -qf name=postfix-mailcow) | /usr/sbin/pflogsumm -d today | mail -s \"Postfix Report of $(date)\" postmaster@example.net Based on the last 24h postfix logs, this example sends every day at 23:59:00 a pflogsumm report to postmaster@example.net .","title":"Statistics with pflogsumm"},{"location":"u_e-postfix-postscreen_whitelist/","text":"IPs can be removed from Postscreen and therefore also from RBL checks in data/conf/postfix/custom_postscreen_whitelist.cidr . Postscreen does multiple checks to identify malicious senders. In most cases you want to whitelist an IP to exclude it from blacklist lookups. The format of the file is as follows: CIDR ACTION Where CIDR is a single IP address or IP range in CIDR notation, and action is either \"permit\" or \"reject\". Example: # Rules are evaluated in the order as specified. # Blacklist 192.168.* except 192.168.0.1. 192.168.0.1 permit 192.168.0.0/16 reject The file is reloaded on the fly, postfix restart is not required.","title":"Whitelist IP in Postscreen"},{"location":"u_e-redis/","text":"Redis is used as a key-value store for rspamd's and (some of) mailcow's settings and data. If you are unfamiliar with redis please read the introduction to redis and maybe visit this wonderful guide on how to use it. Client \u00b6 To connect to the redis cli execute: docker-compose exec redis-mailcow redis-cli Debugging \u00b6 Here are some useful commands for the redis-cli for debugging: MONITOR \u00b6 Listens for all requests received by the server in real time: # docker-compose exec redis-mailcow redis-cli 127.0.0.1:6379> monitor OK 1494077286.401963 [0 172.22.1.253:41228] \"SMEMBERS\" \"BAYES_SPAM_keys\" 1494077288.292970 [0 172.22.1.253:41229] \"SMEMBERS\" \"BAYES_SPAM_keys\" [...] KEYS \u00b6 Get all keys matching your pattern: KEYS * PING \u00b6 Test a connection: 127.0.0.1:6379> PING PONG If you want to know more, here is a cheat sheet .","title":"Redis"},{"location":"u_e-redis/#client","text":"To connect to the redis cli execute: docker-compose exec redis-mailcow redis-cli","title":"Client"},{"location":"u_e-redis/#debugging","text":"Here are some useful commands for the redis-cli for debugging:","title":"Debugging"},{"location":"u_e-redis/#monitor","text":"Listens for all requests received by the server in real time: # docker-compose exec redis-mailcow redis-cli 127.0.0.1:6379> monitor OK 1494077286.401963 [0 172.22.1.253:41228] \"SMEMBERS\" \"BAYES_SPAM_keys\" 1494077288.292970 [0 172.22.1.253:41229] \"SMEMBERS\" \"BAYES_SPAM_keys\" [...]","title":"MONITOR"},{"location":"u_e-redis/#keys","text":"Get all keys matching your pattern: KEYS *","title":"KEYS"},{"location":"u_e-redis/#ping","text":"Test a connection: 127.0.0.1:6379> PING PONG If you want to know more, here is a cheat sheet .","title":"PING"},{"location":"u_e-reeanble-weak-protocols/","text":"On February the 12th 2020 we disabled the deprecated protocols TLS 1.0 and 1.1 in Dovecot (POP3, POP3S, IMAP, IMAPS) and Postfix (SMTPS, SUBMISSION). Unauthenticated mail via SMTP on port 25/tcp does still accept >= TLS 1.0 . It is better to accept a weak encryption than none at all. How to re-enable weak protocols? Edit data/conf/postfix/extra.cf : submission_smtpd_tls_mandatory_protocols = !SSLv2, !SSLv3 smtps_smtpd_tls_mandatory_protocols = !SSLv2, !SSLv3 Edit data/conf/dovecot/extra.conf : ssl_min_protocol = TLSv1 Restart the affected services: docker-compose restart postfix-mailcow dovecot-mailcow Hint: You can enable TLS 1.2 in Windows 7.","title":"Re-enable TLS 1.0 and TLS 1.1"},{"location":"u_e-rspamd/","text":"Rspamd is used for AV handling, DKIM signing and SPAM handling. It's a powerful and fast filter system. For a more in-depth documentation on Rspamd please visit its own documentation . Learn Spam & Ham \u00b6 Rspamd learns mail as spam or ham when you move a message in or out of the junk folder to any mailbox besides trash. This is achieved by using the Sieve plugin \"sieve_imapsieve\" and parser scripts. Rspamd also auto-learns mail when a high or low score is detected (see https://rspamd.com/doc/configuration/statistic.html#autolearning ). We configured the plugin to keep a sane ratio between spam and ham learns. The bayes statistics are written to Redis as keys BAYES_HAM and BAYES_SPAM . Besides bayes, a local fuzzy storage is used to learn recurring patterns in text or images that indicate ham or spam. You can also use Rspamd's web UI to learn ham and / or spam or to adjust certain settings of Rspamd. Learn Spam or Ham from existing directory \u00b6 You can use a one-liner to learn mail in plain-text (uncompressed) format: # Ham for file in /my/folder/cur/* ; do docker exec -i $( docker-compose ps -q rspamd-mailcow ) rspamc learn_ham < $file ; done # Spam for file in /my/folder/.Junk/cur/* ; do docker exec -i $( docker-compose ps -q rspamd-mailcow ) rspamc learn_spam < $file ; done Consider attaching a local folder as new volume to rspamd-mailcow in docker-compose.yml and learn given files inside the container. This can be used as workaround to parse compressed data with zcat. Example: for file in /data/old_mail/.Junk/cur/* ; do rspamc learn_spam < zcat $file ; done Reset learned data (Bayes, Neural) \u00b6 You need to delete keys in Redis to reset learned data, so create a copy of your Redis database now: Backup database # It is better to stop Redis before you copy the file. cp /var/lib/docker/volumes/mailcowdockerized_redis-vol-1/_data/dump.rdb /root/ Reset Bayes data docker-compose exec redis-mailcow sh -c 'redis-cli --scan --pattern BAYES_* | xargs redis-cli del' docker-compose exec redis-mailcow sh -c 'redis-cli --scan --pattern RS* | xargs redis-cli del' Reset Neural data docker-compose exec redis-mailcow sh -c 'redis-cli --scan --pattern rn_* | xargs redis-cli del' Reset Fuzzy data # We need to enter the redis-cli first: docker-compose exec redis-mailcow redis-cli # In redis-cli: 127 .0.0.1:6379> EVAL \"for i, name in ipairs(redis.call('KEYS', ARGV[1])) do redis.call('DEL', name); end\" 0 fuzzy* Info If redis-cli complains about... (error) ERR wrong number of arguments for 'del' command ...the key pattern was not found and thus no data is available to delete - it is fine. CLI tools \u00b6 docker-compose exec rspamd-mailcow rspamc --help docker-compose exec rspamd-mailcow rspamadm --help Disable Greylisting \u00b6 Only messages with a higher score will be considered to be greylisted (soft rejected). It is bad practice to disable greylisting. You can disable greylisting server-wide by editing: {mailcow-dir}/data/conf/rspamd/local.d/greylist.conf Add the line: enabled = false ; Save the file and restart \"rspamd-mailcow\": docker-compose restart rspamd-mailcow Spam filter thresholds (global) \u00b6 Each user is able to change their spam rating individually . To define a new server-wide limit, edit data/conf/rspamd/local.d/actions.conf : reject = 15 ; add_header = 8 ; greylist = 7 ; Save the file and restart \"rspamd-mailcow\": docker-compose restart rspamd-mailcow Existing settings of users will not be overwritten! To reset custom defined thresholds, run: source mailcow.conf docker-compose exec mysql-mailcow mysql -umailcow -p$DBPASS mailcow -e \"delete from filterconf where option = 'highspamlevel' or option = 'lowspamlevel';\" # or: # docker-compose exec mysql-mailcow mysql -umailcow -p$DBPASS mailcow -e \"delete from filterconf where option = 'highspamlevel' or option = 'lowspamlevel' and object = 'only-this-mailbox@example.org';\" Custom reject messages \u00b6 The default spam reject message can be changed by adding a new file data/conf/rspamd/override.d/worker-proxy.custom.inc with the following content: reject_message = \"My custom reject message\"; Save the file and restart Rspamd: docker-compose restart rspamd-mailcow . While the above works for rejected mails with a high spam score, prefilter reject actions will ignore this setting. For these maps, the multimap module in Rspamd needs to be adjusted: Find prefilet reject symbol for which you want change message, to do it run: grep -R \"SYMBOL_YOU_WANT_TO_ADJUST\" /opt/mailcow-dockerized/data/conf/rspamd/ Add your custom message as new line: GLOBAL_RCPT_BL { type = \"rcpt\"; map = \"${LOCAL_CONFDIR}/custom/global_rcpt_blacklist.map\"; regexp = true; prefilter = true; action = \"reject\"; message = \"Sending mail to this recipient is prohibited by postmaster@your.domain\"; } Save the file and restart Rspamd: docker-compose restart rspamd-mailcow . Whitelist specific ClamAV signatures \u00b6 You may find that legitimate (clean) mail is being blocked by ClamAV (Rspamd will flag the mail with VIRUS_FOUND ). For instance, interactive PDF form attachments are blocked by default because the embedded Javascript code may be used for nefarious purposes. Confirm by looking at the clamd logs, e.g.: docker-compose logs clamd-mailcow | grep \"FOUND\" This line confirms that such was identified: clamd-mailcow_1 | Sat Sep 28 07:43:24 2019 -> instream(local): PUA.Pdf.Trojan.EmbeddedJavaScript-1(e887d2ac324ce90750768b86b63d0749:363325) FOUND To whitelist this particular signature (and enable sending this type of file attached), add it to the ClamAV signature whitelist file: echo 'PUA.Pdf.Trojan.EmbeddedJavaScript-1' >> data/conf/clamav/whitelist.ign2 Then restart the clamd-mailcow service container in the mailcow UI or using docker-compose: docker-compose restart clamd-mailcow Cleanup cached ClamAV results in Redis: # docker-compose exec redis-mailcow /bin/sh /data # redis-cli KEYS rs_cl* | xargs redis-cli DEL /data # exit Discard instead of reject \u00b6 If you want to silently drop a message, create or edit the file data/conf/rspamd/override.d/worker-proxy.custom.inc and add the following content: discard_on_reject = true; Restart Rspamd: docker-compose restart rspamd-mailcow Wipe all ratelimit keys \u00b6 If you don't want to use the UI and instead wipe all keys in the Redis database, you can use redis-cli for that task: docker-compose exec redis-mailcow sh # Unlink (available in Redis >=4.) will delete in the backgronud redis-cli --scan --pattern RL* | xargs redis-cli unlink Restart Rspamd: docker-compose exec redis-mailcow sh Trigger a resend of quarantine notifications \u00b6 Should be used for debugging only! docker-compose exec dovecot-mailcow bash mysql -umailcow -p$DBPASS mailcow -e \"update quarantine set notified = 0;\" redis-cli -h redis DEL Q_LAST_NOTIFIED quarantine_notify.py Increase history retention \u00b6 By default Rspamd keeps 1000 elements in the history. The history is stored compressed. It is recommended not to use a disproportionate high value here, try something along 5000 or 10000 and see how your server handles it: Edit data/conf/rspamd/local.d/history_redis.conf : nrows = 1000; # change this value Restart Rspamd afterwards: docker-compose restart rspamd-mailcow","title":"Rspamd"},{"location":"u_e-rspamd/#learn-spam-ham","text":"Rspamd learns mail as spam or ham when you move a message in or out of the junk folder to any mailbox besides trash. This is achieved by using the Sieve plugin \"sieve_imapsieve\" and parser scripts. Rspamd also auto-learns mail when a high or low score is detected (see https://rspamd.com/doc/configuration/statistic.html#autolearning ). We configured the plugin to keep a sane ratio between spam and ham learns. The bayes statistics are written to Redis as keys BAYES_HAM and BAYES_SPAM . Besides bayes, a local fuzzy storage is used to learn recurring patterns in text or images that indicate ham or spam. You can also use Rspamd's web UI to learn ham and / or spam or to adjust certain settings of Rspamd.","title":"Learn Spam & Ham"},{"location":"u_e-rspamd/#learn-spam-or-ham-from-existing-directory","text":"You can use a one-liner to learn mail in plain-text (uncompressed) format: # Ham for file in /my/folder/cur/* ; do docker exec -i $( docker-compose ps -q rspamd-mailcow ) rspamc learn_ham < $file ; done # Spam for file in /my/folder/.Junk/cur/* ; do docker exec -i $( docker-compose ps -q rspamd-mailcow ) rspamc learn_spam < $file ; done Consider attaching a local folder as new volume to rspamd-mailcow in docker-compose.yml and learn given files inside the container. This can be used as workaround to parse compressed data with zcat. Example: for file in /data/old_mail/.Junk/cur/* ; do rspamc learn_spam < zcat $file ; done","title":"Learn Spam or Ham from existing directory"},{"location":"u_e-rspamd/#reset-learned-data-bayes-neural","text":"You need to delete keys in Redis to reset learned data, so create a copy of your Redis database now: Backup database # It is better to stop Redis before you copy the file. cp /var/lib/docker/volumes/mailcowdockerized_redis-vol-1/_data/dump.rdb /root/ Reset Bayes data docker-compose exec redis-mailcow sh -c 'redis-cli --scan --pattern BAYES_* | xargs redis-cli del' docker-compose exec redis-mailcow sh -c 'redis-cli --scan --pattern RS* | xargs redis-cli del' Reset Neural data docker-compose exec redis-mailcow sh -c 'redis-cli --scan --pattern rn_* | xargs redis-cli del' Reset Fuzzy data # We need to enter the redis-cli first: docker-compose exec redis-mailcow redis-cli # In redis-cli: 127 .0.0.1:6379> EVAL \"for i, name in ipairs(redis.call('KEYS', ARGV[1])) do redis.call('DEL', name); end\" 0 fuzzy* Info If redis-cli complains about... (error) ERR wrong number of arguments for 'del' command ...the key pattern was not found and thus no data is available to delete - it is fine.","title":"Reset learned data (Bayes, Neural)"},{"location":"u_e-rspamd/#cli-tools","text":"docker-compose exec rspamd-mailcow rspamc --help docker-compose exec rspamd-mailcow rspamadm --help","title":"CLI tools"},{"location":"u_e-rspamd/#disable-greylisting","text":"Only messages with a higher score will be considered to be greylisted (soft rejected). It is bad practice to disable greylisting. You can disable greylisting server-wide by editing: {mailcow-dir}/data/conf/rspamd/local.d/greylist.conf Add the line: enabled = false ; Save the file and restart \"rspamd-mailcow\": docker-compose restart rspamd-mailcow","title":"Disable Greylisting"},{"location":"u_e-rspamd/#spam-filter-thresholds-global","text":"Each user is able to change their spam rating individually . To define a new server-wide limit, edit data/conf/rspamd/local.d/actions.conf : reject = 15 ; add_header = 8 ; greylist = 7 ; Save the file and restart \"rspamd-mailcow\": docker-compose restart rspamd-mailcow Existing settings of users will not be overwritten! To reset custom defined thresholds, run: source mailcow.conf docker-compose exec mysql-mailcow mysql -umailcow -p$DBPASS mailcow -e \"delete from filterconf where option = 'highspamlevel' or option = 'lowspamlevel';\" # or: # docker-compose exec mysql-mailcow mysql -umailcow -p$DBPASS mailcow -e \"delete from filterconf where option = 'highspamlevel' or option = 'lowspamlevel' and object = 'only-this-mailbox@example.org';\"","title":"Spam filter thresholds (global)"},{"location":"u_e-rspamd/#custom-reject-messages","text":"The default spam reject message can be changed by adding a new file data/conf/rspamd/override.d/worker-proxy.custom.inc with the following content: reject_message = \"My custom reject message\"; Save the file and restart Rspamd: docker-compose restart rspamd-mailcow . While the above works for rejected mails with a high spam score, prefilter reject actions will ignore this setting. For these maps, the multimap module in Rspamd needs to be adjusted: Find prefilet reject symbol for which you want change message, to do it run: grep -R \"SYMBOL_YOU_WANT_TO_ADJUST\" /opt/mailcow-dockerized/data/conf/rspamd/ Add your custom message as new line: GLOBAL_RCPT_BL { type = \"rcpt\"; map = \"${LOCAL_CONFDIR}/custom/global_rcpt_blacklist.map\"; regexp = true; prefilter = true; action = \"reject\"; message = \"Sending mail to this recipient is prohibited by postmaster@your.domain\"; } Save the file and restart Rspamd: docker-compose restart rspamd-mailcow .","title":"Custom reject messages"},{"location":"u_e-rspamd/#whitelist-specific-clamav-signatures","text":"You may find that legitimate (clean) mail is being blocked by ClamAV (Rspamd will flag the mail with VIRUS_FOUND ). For instance, interactive PDF form attachments are blocked by default because the embedded Javascript code may be used for nefarious purposes. Confirm by looking at the clamd logs, e.g.: docker-compose logs clamd-mailcow | grep \"FOUND\" This line confirms that such was identified: clamd-mailcow_1 | Sat Sep 28 07:43:24 2019 -> instream(local): PUA.Pdf.Trojan.EmbeddedJavaScript-1(e887d2ac324ce90750768b86b63d0749:363325) FOUND To whitelist this particular signature (and enable sending this type of file attached), add it to the ClamAV signature whitelist file: echo 'PUA.Pdf.Trojan.EmbeddedJavaScript-1' >> data/conf/clamav/whitelist.ign2 Then restart the clamd-mailcow service container in the mailcow UI or using docker-compose: docker-compose restart clamd-mailcow Cleanup cached ClamAV results in Redis: # docker-compose exec redis-mailcow /bin/sh /data # redis-cli KEYS rs_cl* | xargs redis-cli DEL /data # exit","title":"Whitelist specific ClamAV signatures"},{"location":"u_e-rspamd/#discard-instead-of-reject","text":"If you want to silently drop a message, create or edit the file data/conf/rspamd/override.d/worker-proxy.custom.inc and add the following content: discard_on_reject = true; Restart Rspamd: docker-compose restart rspamd-mailcow","title":"Discard instead of reject"},{"location":"u_e-rspamd/#wipe-all-ratelimit-keys","text":"If you don't want to use the UI and instead wipe all keys in the Redis database, you can use redis-cli for that task: docker-compose exec redis-mailcow sh # Unlink (available in Redis >=4.) will delete in the backgronud redis-cli --scan --pattern RL* | xargs redis-cli unlink Restart Rspamd: docker-compose exec redis-mailcow sh","title":"Wipe all ratelimit keys"},{"location":"u_e-rspamd/#trigger-a-resend-of-quarantine-notifications","text":"Should be used for debugging only! docker-compose exec dovecot-mailcow bash mysql -umailcow -p$DBPASS mailcow -e \"update quarantine set notified = 0;\" redis-cli -h redis DEL Q_LAST_NOTIFIED quarantine_notify.py","title":"Trigger a resend of quarantine notifications"},{"location":"u_e-rspamd/#increase-history-retention","text":"By default Rspamd keeps 1000 elements in the history. The history is stored compressed. It is recommended not to use a disproportionate high value here, try something along 5000 or 10000 and see how your server handles it: Edit data/conf/rspamd/local.d/history_redis.conf : nrows = 1000; # change this value Restart Rspamd afterwards: docker-compose restart rspamd-mailcow","title":"Increase history retention"},{"location":"u_e-sogo/","text":"SOGo is used for accessing your mails via a webbrowser, adding and sharing your contacts or calendars. For a more in-depth documentation on SOGo please visit its own documentation . Apply custom SOGo theme \u00b6 mailcow builds after 28 January 2021 can change SOGo's theme by editing data/conf/sogo/custom-theme.js . Please check the AngularJS Material intro and documentation as well as the material style guideline to learn how this works. You can use the provided custom-theme.js as an example starting point by removing the comments. After you modified data/conf/sogo/custom-theme.js and made changes to your new SOGo theme you need to edit data/conf/sogo/sogo.conf and append/set SOGoUIxDebugEnabled = YES; restart SOGo and Memcached containers by executing docker-compose restart memcached-mailcow sogo-mailcow . Reset to SOGo default theme \u00b6 Checkout data/conf/sogo/custom-theme.js by executing git fetch ; git checkout origin/master data/conf/sogo/custom-theme.js data/conf/sogo/custom-theme.js Find in data/conf/sogo/custom-theme.js : // Apply new palettes to the default theme, remap some of the hues $mdThemingProvider.theme('default') .primaryPalette('green-cow', { 'default': '400', // background color of top toolbars 'hue-1': '400', 'hue-2': '600', // background color of sidebar toolbar 'hue-3': 'A700' }) .accentPalette('green', { 'default': '600', // background color of fab buttons and login screen 'hue-1': '300', // background color of center list toolbar 'hue-2': '300', // highlight color for selected mail and current day calendar 'hue-3': 'A700' }) .backgroundPalette('frost-grey'); and replace with: $mdThemingProvider.theme('default'); Change favicon \u00b6 mailcow builds after 31 January 2021 can change SOGo's favicon by replacing data/conf/sogo/custom-favicon.ico for SOGo and data/web/favicon.png for mailcow UI. Note : You can use .png favicons for SOGo by renaming them to custom-favicon.ico . For both SOGo and mailcow UI favicons you need use one of the standard dimensions: 16x16, 32x32, 64x64, 128x128 and 256x256. After you replaced said file you need to restart SOGo and Memcached containers by executing docker-compose restart memcached-mailcow sogo-mailcow . Change logo \u00b6 mailcow builds after 21 December 2018 can change SOGo's logo by replacing or creating (if missing) data/conf/sogo/sogo-full.svg . After you replaced said file you need to restart SOGo and Memcached containers by executing docker-compose restart memcached-mailcow sogo-mailcow . Connect domains \u00b6 Domains are usually isolated from eachother. You can change that by modifying data/conf/sogo/sogo.conf : Search... // SOGoDomainsVisibility = ( // (domain1.tld, domain5.tld), // (domain3.tld, domain2.tld) // ); ...and replace it by - for example: SOGoDomainsVisibility = ( (example.org, example.com, example.net) ); Restart SOGo: docker-compose restart sogo-mailcow Disable password changing \u00b6 Edit data/conf/sogo/sogo.conf and change SOGoPasswordChangeEnabled to NO . Please do not add a new parameter. Run docker-compose restart memcached-mailcow sogo-mailcow to activate the changes.","title":"SOGo"},{"location":"u_e-sogo/#apply-custom-sogo-theme","text":"mailcow builds after 28 January 2021 can change SOGo's theme by editing data/conf/sogo/custom-theme.js . Please check the AngularJS Material intro and documentation as well as the material style guideline to learn how this works. You can use the provided custom-theme.js as an example starting point by removing the comments. After you modified data/conf/sogo/custom-theme.js and made changes to your new SOGo theme you need to edit data/conf/sogo/sogo.conf and append/set SOGoUIxDebugEnabled = YES; restart SOGo and Memcached containers by executing docker-compose restart memcached-mailcow sogo-mailcow .","title":"Apply custom SOGo theme"},{"location":"u_e-sogo/#reset-to-sogo-default-theme","text":"Checkout data/conf/sogo/custom-theme.js by executing git fetch ; git checkout origin/master data/conf/sogo/custom-theme.js data/conf/sogo/custom-theme.js Find in data/conf/sogo/custom-theme.js : // Apply new palettes to the default theme, remap some of the hues $mdThemingProvider.theme('default') .primaryPalette('green-cow', { 'default': '400', // background color of top toolbars 'hue-1': '400', 'hue-2': '600', // background color of sidebar toolbar 'hue-3': 'A700' }) .accentPalette('green', { 'default': '600', // background color of fab buttons and login screen 'hue-1': '300', // background color of center list toolbar 'hue-2': '300', // highlight color for selected mail and current day calendar 'hue-3': 'A700' }) .backgroundPalette('frost-grey'); and replace with: $mdThemingProvider.theme('default');","title":"Reset to SOGo default theme"},{"location":"u_e-sogo/#change-favicon","text":"mailcow builds after 31 January 2021 can change SOGo's favicon by replacing data/conf/sogo/custom-favicon.ico for SOGo and data/web/favicon.png for mailcow UI. Note : You can use .png favicons for SOGo by renaming them to custom-favicon.ico . For both SOGo and mailcow UI favicons you need use one of the standard dimensions: 16x16, 32x32, 64x64, 128x128 and 256x256. After you replaced said file you need to restart SOGo and Memcached containers by executing docker-compose restart memcached-mailcow sogo-mailcow .","title":"Change favicon"},{"location":"u_e-sogo/#change-logo","text":"mailcow builds after 21 December 2018 can change SOGo's logo by replacing or creating (if missing) data/conf/sogo/sogo-full.svg . After you replaced said file you need to restart SOGo and Memcached containers by executing docker-compose restart memcached-mailcow sogo-mailcow .","title":"Change logo"},{"location":"u_e-sogo/#connect-domains","text":"Domains are usually isolated from eachother. You can change that by modifying data/conf/sogo/sogo.conf : Search... // SOGoDomainsVisibility = ( // (domain1.tld, domain5.tld), // (domain3.tld, domain2.tld) // ); ...and replace it by - for example: SOGoDomainsVisibility = ( (example.org, example.com, example.net) ); Restart SOGo: docker-compose restart sogo-mailcow","title":"Connect domains"},{"location":"u_e-sogo/#disable-password-changing","text":"Edit data/conf/sogo/sogo.conf and change SOGoPasswordChangeEnabled to NO . Please do not add a new parameter. Run docker-compose restart memcached-mailcow sogo-mailcow to activate the changes.","title":"Disable password changing"},{"location":"u_e-unbound-fwd/","text":"If you want or have to use an external DNS service, you can either set a forwarder in Unbound or copy an override file to define external DNS servers: !!! warning Please do not use a public resolver like we did in the example above. Many - if not all - blacklist lookups will fail with public resolvers. Important : Only DNSSEC validating DNS services will work. Method A, Unbound \u00b6 Edit data/conf/unbound/unbound.conf and append the following parameters: forward-zone: name: \".\" forward-addr: 8.8.8.8 # DO NOT USE PUBLIC DNS SERVERS - JUST AN EXAMPLE forward-addr: 8.8.4.4 # DO NOT USE PUBLIC DNS SERVERS - JUST AN EXAMPLE Restart Unbound: docker-compose restart unbound-mailcow Method B, Override file \u00b6 cd /opt/mailcow-dockerized cp helper-scripts/docker-compose.override.yml.d/EXTERNAL_DNS/docker-compose.override.yml . Edit docker-compose.override.yml and adjust the IP. Run docker-compose down ; docker-compose up -d .","title":"Using an external DNS service"},{"location":"u_e-unbound-fwd/#method-a-unbound","text":"Edit data/conf/unbound/unbound.conf and append the following parameters: forward-zone: name: \".\" forward-addr: 8.8.8.8 # DO NOT USE PUBLIC DNS SERVERS - JUST AN EXAMPLE forward-addr: 8.8.4.4 # DO NOT USE PUBLIC DNS SERVERS - JUST AN EXAMPLE Restart Unbound: docker-compose restart unbound-mailcow","title":"Method A, Unbound"},{"location":"u_e-unbound-fwd/#method-b-override-file","text":"cd /opt/mailcow-dockerized cp helper-scripts/docker-compose.override.yml.d/EXTERNAL_DNS/docker-compose.override.yml . Edit docker-compose.override.yml and adjust the IP. Run docker-compose down ; docker-compose up -d .","title":"Method B, Override file"},{"location":"u_e-webmail-site/","text":"IMPORTANT : This guide only applies to non SNI enabled configurations. The certificate path needs to be adjusted if SNI is enabled. Something like ssl_certificate,key /etc/ssl/mail/webmail.example.org/cert.pem,key.pem; will do. But : The certificate should be acquired first and only after the certificate exists a site config should be created. Nginx will fail to start if it cannot find the certificate and key. To create a subdomain webmail.example.org and redirect it to SOGo, you need to create a new Nginx site. Take care of \"CHANGE_TO_MAILCOW_HOSTNAME\"! nano data/conf/nginx/webmail.conf server { ssl_certificate /etc/ssl/mail/cert.pem; ssl_certificate_key /etc/ssl/mail/key.pem; index index.php index.html; client_max_body_size 0; root /web; include /etc/nginx/conf.d/listen_plain.active; include /etc/nginx/conf.d/listen_ssl.active; server_name webmail.example.org; server_tokens off; location ^~ /.well-known/acme-challenge/ { allow all; default_type \"text/plain\"; } location / { return 301 https://CHANGE_TO_MAILCOW_HOSTNAME/SOGo; } } Save and restart Nginx: docker-compose restart nginx-mailcow . Now open mailcow.conf and find ADDITIONAL_SAN . Add webmail.example.org to this array, don't use quotes! ADDITIONAL_SAN=webmail.example.org Run docker-compose up -d . See \"acme-mailcow\" and \"nginx-mailcow\" logs if anything fails.","title":"Create subdomain webmail.example.org"},{"location":"u_e-why_unbound/","text":"For DNS blacklist lookups and DNSSEC. Most systems use either a public or a local caching DNS resolver. That's a very bad idea when it comes to filter spam using DNS-based black hole lists (DNSBL) or similar technics. Most if not all providers apply a rate limit based on the DNS resolver that is used to query their service. Using a public resolver like Googles 4x8, OpenDNS or any other shared DNS resolver like your ISPs will hit that limit very soon.","title":"Why unbound?"},{"location":"u_e-xmpp-enable/","text":"XMPP is provided by ejabberd, which describes itself as robust, scalable and extensible XMPP Server. So first of all, thanks to ejabberd and its contributers! Enable XMPP in mailcow \u00b6 To enable XMPP for a domain, you need to edit the given domain in mailcow UI: The chosen prefix will be used to derive your XMPP login. A prefix xmpp_prefix for the mailbox user cowboy@develcow.de would equal to the JID cowboy@xmpp_prefix.develcow.de . Info The login passwords for mail and XMPP are the same. XMPP users are authenticated against mailcow. Before enabling XMPP for a domain, you should create two CNAME records in DNS: # CNAMES # Name Type Value xmpp_prefix IN CNAME mail.example.org. (your ${MAILCOW_HOSTNAME}) *.xmpp_prefix IN CNAME mail.example.org. (your ${MAILCOW_HOSTNAME}) These two CNAMEs are essential for acquiring a certificate. Please do not add \"xmpp_prefix.domain.tld\" as name to ADDITIONAL_SAN . Make sure your CNAMEs are correct. Enable XMPP for your domain now. If you enabled XMPP first and then added your DNS records there is no need to worry. You will just need to wait for ejabberd to automatically acquire the certificates or simply restart ejabberd-mailcow to trigger the process immediately: docker-compose restart ejabberd-mailcow . Once ejabberd is enabled, you may want to re-run the DNS check in the mailcow UI where you will find two more SRV records: # SRV records # Name Type Value _xmpp-client._tcp.xmpp_prefix IN SRV 10 1 5222 mail.example.org. (your ${MAILCOW_HOSTNAME}) _xmpp-server._tcp.xmpp_prefix IN SRV 10 1 5269 mail.example.org. (your ${MAILCOW_HOSTNAME}) There is no need to restart ejabberd, add these SRV records whenever you like. These records are crucial for autoconfiguration of XMPP clients and server-to-server connections. ACL \u00b6 A domain administrator can be given the right to toggle XMPP access for domains and mailboxes, promoting users to XMPP administrators (WIP) and to change the prefix: Verify certificates \u00b6 Once everything is setup, make sure ejabberd was able to acquire certificates: If you see a message similar to... ejabberd-mailcow_1 | 2021-02-13 14:40:19.507956+01:00 [error] Failed to request certificate for im.example.org, pubsub.im.example.org and 3 more hosts: Challenge failed for domain conference.im.example.org: ACME server reported: DNS problem: NXDOMAIN looking up A for conference.im.example.org - check that a DNS record exists for this domain (error type: dns) ...you may need to recheck your DNS configuration or restart ejabberd-mailcow to restart the process in case of slow DNS propagation. Opening https://xmpp_prefix.domain.tld:5443/upload should point you to a 404 page with a valid certificate. Why can't we use no prefix? \u00b6 It does not matter which server name we point our SRV to, Jabber will always rely on the domain given in a JID. We would need to acquire a certificate for the SLD domain.tld , which hardly anyone wants to point to its mail system. We are sorry for this circumstance. As soon as we implemented Servercows DNS API, this may be reconsidered. My reverse proxy does not work anymore \u00b6 If your reverse proxy is configured to point to a site like webmail.domain.tld which mailcow is not aware of (as in MAILCOW_HOSTNAME does not match webmail.domain.tld ), you may now be redirected to the default ejabberd Nginx site. That's because mailcow does not know it should respond to webmail.domain.tld with mailcow UI. Method 1 \u00b6 A more simple approach is defining ADDITIONAL_SERVER_NAMES in mailcow.conf : ADDITIONAL_SERVER_NAMES=webmail.domain.tld Run docker-compose up -d to apply. Method 2 \u00b6 In your reverse proxy configuration, make sure you set a \"Host\" header that mailcow actually services, similar to this (Nginx example): proxy_set_header Host MAILCOW_HOSTNAME; # Instead of proxy_set_header Host $http_host; Now you can use whatever name you like, as long mailcow receives a known \"Host\" header.","title":"Enable XMPP"},{"location":"u_e-xmpp-enable/#enable-xmpp-in-mailcow","text":"To enable XMPP for a domain, you need to edit the given domain in mailcow UI: The chosen prefix will be used to derive your XMPP login. A prefix xmpp_prefix for the mailbox user cowboy@develcow.de would equal to the JID cowboy@xmpp_prefix.develcow.de . Info The login passwords for mail and XMPP are the same. XMPP users are authenticated against mailcow. Before enabling XMPP for a domain, you should create two CNAME records in DNS: # CNAMES # Name Type Value xmpp_prefix IN CNAME mail.example.org. (your ${MAILCOW_HOSTNAME}) *.xmpp_prefix IN CNAME mail.example.org. (your ${MAILCOW_HOSTNAME}) These two CNAMEs are essential for acquiring a certificate. Please do not add \"xmpp_prefix.domain.tld\" as name to ADDITIONAL_SAN . Make sure your CNAMEs are correct. Enable XMPP for your domain now. If you enabled XMPP first and then added your DNS records there is no need to worry. You will just need to wait for ejabberd to automatically acquire the certificates or simply restart ejabberd-mailcow to trigger the process immediately: docker-compose restart ejabberd-mailcow . Once ejabberd is enabled, you may want to re-run the DNS check in the mailcow UI where you will find two more SRV records: # SRV records # Name Type Value _xmpp-client._tcp.xmpp_prefix IN SRV 10 1 5222 mail.example.org. (your ${MAILCOW_HOSTNAME}) _xmpp-server._tcp.xmpp_prefix IN SRV 10 1 5269 mail.example.org. (your ${MAILCOW_HOSTNAME}) There is no need to restart ejabberd, add these SRV records whenever you like. These records are crucial for autoconfiguration of XMPP clients and server-to-server connections.","title":"Enable XMPP in mailcow"},{"location":"u_e-xmpp-enable/#acl","text":"A domain administrator can be given the right to toggle XMPP access for domains and mailboxes, promoting users to XMPP administrators (WIP) and to change the prefix:","title":"ACL"},{"location":"u_e-xmpp-enable/#verify-certificates","text":"Once everything is setup, make sure ejabberd was able to acquire certificates: If you see a message similar to... ejabberd-mailcow_1 | 2021-02-13 14:40:19.507956+01:00 [error] Failed to request certificate for im.example.org, pubsub.im.example.org and 3 more hosts: Challenge failed for domain conference.im.example.org: ACME server reported: DNS problem: NXDOMAIN looking up A for conference.im.example.org - check that a DNS record exists for this domain (error type: dns) ...you may need to recheck your DNS configuration or restart ejabberd-mailcow to restart the process in case of slow DNS propagation. Opening https://xmpp_prefix.domain.tld:5443/upload should point you to a 404 page with a valid certificate.","title":"Verify certificates"},{"location":"u_e-xmpp-enable/#why-cant-we-use-no-prefix","text":"It does not matter which server name we point our SRV to, Jabber will always rely on the domain given in a JID. We would need to acquire a certificate for the SLD domain.tld , which hardly anyone wants to point to its mail system. We are sorry for this circumstance. As soon as we implemented Servercows DNS API, this may be reconsidered.","title":"Why can't we use no prefix?"},{"location":"u_e-xmpp-enable/#my-reverse-proxy-does-not-work-anymore","text":"If your reverse proxy is configured to point to a site like webmail.domain.tld which mailcow is not aware of (as in MAILCOW_HOSTNAME does not match webmail.domain.tld ), you may now be redirected to the default ejabberd Nginx site. That's because mailcow does not know it should respond to webmail.domain.tld with mailcow UI.","title":"My reverse proxy does not work anymore"},{"location":"u_e-xmpp-enable/#method-1","text":"A more simple approach is defining ADDITIONAL_SERVER_NAMES in mailcow.conf : ADDITIONAL_SERVER_NAMES=webmail.domain.tld Run docker-compose up -d to apply.","title":"Method 1"},{"location":"u_e-xmpp-enable/#method-2","text":"In your reverse proxy configuration, make sure you set a \"Host\" header that mailcow actually services, similar to this (Nginx example): proxy_set_header Host MAILCOW_HOSTNAME; # Instead of proxy_set_header Host $http_host; Now you can use whatever name you like, as long mailcow receives a known \"Host\" header.","title":"Method 2"},{"location":"u_e-xmpp-faq/","text":"FAQ \u00b6 Please find the most frequently asked questions with their corresponding configuration in data/conf/ejabberd/ejabberd.yml (if any). I do not want to run ejabberd, is there a SKIP_XMPP variable? No, there is not. But you don't need one either. The xmppd behaves the same way as SOGo or Solr do when disabled. A shell will be idling and ejabberd will not be started (but open unconnected ports). As soon as a domain is enabled for XMPP, the container will be restarted and ejabberd bootstrapped. ejabberd is very light on resources, you may want to give it a try. Are messages stored on the server? Not by default. The default setting is to disable the message archive via mod_mam but allow users to enable the function if they want to: mod_mam: clear_archive_on_room_destroy: true default: never compress_xml: true request_activates_archiving: true Are uploaded files stored on the server? Yes, uploaded files are stored in the volume xmpp-uploads-vol-1 . The retention policy saves them for 30 days: mod_http_upload_quota: max_days: 30 Are messages stored when a JID is offline? Yes, up to 1000 messages are stored for \"normal\" users and administrators: shaper_rules: max_user_offline_messages: 1000: admin 1000: all Are messages written in group chats stored? No, messages are not stored: mod_muc: default_room_options: mam: false Are group chats persistent when the last participant leaves? No, they will vanish: mod_muc: default_room_options: persistent: false How many client sessions can be open at the same time? 10 sessions are allowed per user. shaper_rules: max_user_sessions: 10","title":"FAQ"},{"location":"u_e-xmpp-faq/#faq","text":"Please find the most frequently asked questions with their corresponding configuration in data/conf/ejabberd/ejabberd.yml (if any). I do not want to run ejabberd, is there a SKIP_XMPP variable? No, there is not. But you don't need one either. The xmppd behaves the same way as SOGo or Solr do when disabled. A shell will be idling and ejabberd will not be started (but open unconnected ports). As soon as a domain is enabled for XMPP, the container will be restarted and ejabberd bootstrapped. ejabberd is very light on resources, you may want to give it a try. Are messages stored on the server? Not by default. The default setting is to disable the message archive via mod_mam but allow users to enable the function if they want to: mod_mam: clear_archive_on_room_destroy: true default: never compress_xml: true request_activates_archiving: true Are uploaded files stored on the server? Yes, uploaded files are stored in the volume xmpp-uploads-vol-1 . The retention policy saves them for 30 days: mod_http_upload_quota: max_days: 30 Are messages stored when a JID is offline? Yes, up to 1000 messages are stored for \"normal\" users and administrators: shaper_rules: max_user_offline_messages: 1000: admin 1000: all Are messages written in group chats stored? No, messages are not stored: mod_muc: default_room_options: mam: false Are group chats persistent when the last participant leaves? No, they will vanish: mod_muc: default_room_options: persistent: false How many client sessions can be open at the same time? 10 sessions are allowed per user. shaper_rules: max_user_sessions: 10","title":"FAQ"},{"location":"client/client-android/","text":"Open the Email app. If this is your first email account, tap Add Account ; if not, tap More and Settings and then Add account . Select Microsoft Exchange ActiveSync . Enter your email address ( ) and password. Tap Sign in .","title":"Android"},{"location":"client/client-apple/","text":"Method 1 via Mobileconfig \u00b6 Email, contacts and calendars can be configured automatically on Apple devices by installing a profile. To download a profile you must login to the mailcow UI first. Method 1.1: IMAP, SMTP and Cal/CardDAV \u00b6 This method configures IMAP, CardDAV and CalDAV. Download and open the file from https://${MAILCOW_HOSTNAME}/mobileconfig.php mailcow.mobileconfig . Enter the unlock code (iPhone) or computer password (Mac). Enter your email password three times when prompted. Method 1.2: IMAP, SMTP (no DAV) \u00b6 This method configures IMAP and SMTP only. Download and open the file from https://${MAILCOW_HOSTNAME}/mobileconfig.php?only_email mailcow.mobileconfig . Enter the unlock code (iPhone) or computer password (Mac). Enter your email password when prompted. Method 2 (Exchange ActiveSync emulation) \u00b6 On iOS, Exchange ActiveSync is also supported as an alternative to the procedure above. It has the advantage of supporting push email (i.e. you are immediately notified of incoming messages), but has some limitations, e.g. it does not support more than three email addresses per contact in your address book. Follow the steps below if you decide to use Exchange instead. Open the Settings app, tap Mail , tap Accounts , tap Add Acccount , select Exchange . Enter your email address ( ) and tap Next . Enter your password, tap Next again. Finally, tap Save .","title":"Apple macOS / iOS"},{"location":"client/client-apple/#method-1-via-mobileconfig","text":"Email, contacts and calendars can be configured automatically on Apple devices by installing a profile. To download a profile you must login to the mailcow UI first.","title":"Method 1 via Mobileconfig"},{"location":"client/client-apple/#method-11-imap-smtp-and-calcarddav","text":"This method configures IMAP, CardDAV and CalDAV. Download and open the file from https://${MAILCOW_HOSTNAME}/mobileconfig.php mailcow.mobileconfig . Enter the unlock code (iPhone) or computer password (Mac). Enter your email password three times when prompted.","title":"Method 1.1: IMAP, SMTP and Cal/CardDAV"},{"location":"client/client-apple/#method-12-imap-smtp-no-dav","text":"This method configures IMAP and SMTP only. Download and open the file from https://${MAILCOW_HOSTNAME}/mobileconfig.php?only_email mailcow.mobileconfig . Enter the unlock code (iPhone) or computer password (Mac). Enter your email password when prompted.","title":"Method 1.2: IMAP, SMTP (no DAV)"},{"location":"client/client-apple/#method-2-exchange-activesync-emulation","text":"On iOS, Exchange ActiveSync is also supported as an alternative to the procedure above. It has the advantage of supporting push email (i.e. you are immediately notified of incoming messages), but has some limitations, e.g. it does not support more than three email addresses per contact in your address book. Follow the steps below if you decide to use Exchange instead. Open the Settings app, tap Mail , tap Accounts , tap Add Acccount , select Exchange . Enter your email address ( ) and tap Next . Enter your password, tap Next again. Finally, tap Save .","title":"Method 2 (Exchange ActiveSync emulation)"},{"location":"client/client-emclient/","text":"Launch eM Client. If this is the first time you launched eM Client, it asks you to set up your account. Proceed to step 4. Go to Menu at the top, select Tools and Accounts . Enter your email address ( ) and click Start Now . Enter your password and click Continue . Enter your name ( ) and click Next . Click Finish .","title":"eM Client"},{"location":"client/client-gajim_xmpp_client/","text":"WIP \u00b6","title":"Gajim XMPP client"},{"location":"client/client-gajim_xmpp_client/#wip","text":"","title":"WIP"},{"location":"client/client-kontact/","text":"Launch Kontact. If this is the first time you launched Kontact or KMail, it asks you to set up your account. Proceed to step 4. Go to Mail in the sidebar. Go to the Tools menu and select Account Wizard . Enter your name ( ) , email address ( ) and your password. Click Next . Click Create Account . If prompted, re-enter your password and click OK . Close the window by clicking Finish . Go to Calendar in the sidebar. Go to the Settings menu and select Configure KOrganizer . Go to the Calendars tab and click the Add button. Choose DAV groupware resource and click OK . Enter your email address ( ) and your password. Click Next . Select ScalableOGo from the dropdown menu and click Next . Enter your mailcow hostname into the Host field and click Next . Click Test Connection and then Finish . Finally, click OK twice. Once you have set up Kontact, you can also use KMail, KOrganizer and KAddressBook individually.","title":"KDE Kontact"},{"location":"client/client-manual/","text":"These instructions are valid for unchanged port bindings only! Email \u00b6 Service Encryption Host Port IMAP STARTTLS mailcow hostname 143 IMAPS SSL mailcow hostname 993 POP3 STARTTLS mailcow hostname 110 POP3S SSL mailcow hostname 995 SMTP STARTTLS mailcow hostname 587 SMTPS SSL mailcow hostname 465 Please use \"plain\" as authentication mechanisms. Contrary to the assumption no passwords will be transferred plain text, as no authentication is allowed to take place without TLS. Contacts and calendars \u00b6 SOGos default calendar (CalDAV) and contacts (CardDAV) URLs: CalDAV - https://mail.example.com/SOGo/dav/user@example.com/Calendar/personal/ CardDAV - https://mail.example.com/SOGo/dav/user@example.com/Contacts/personal/ Some applications may require you to use https://mail.example.com/SOGo/dav/ or the full path to your calendar, which can be found and copied from within SOGo.","title":"Manual configuration"},{"location":"client/client-manual/#email","text":"Service Encryption Host Port IMAP STARTTLS mailcow hostname 143 IMAPS SSL mailcow hostname 993 POP3 STARTTLS mailcow hostname 110 POP3S SSL mailcow hostname 995 SMTP STARTTLS mailcow hostname 587 SMTPS SSL mailcow hostname 465 Please use \"plain\" as authentication mechanisms. Contrary to the assumption no passwords will be transferred plain text, as no authentication is allowed to take place without TLS.","title":"Email"},{"location":"client/client-manual/#contacts-and-calendars","text":"SOGos default calendar (CalDAV) and contacts (CardDAV) URLs: CalDAV - https://mail.example.com/SOGo/dav/user@example.com/Calendar/personal/ CardDAV - https://mail.example.com/SOGo/dav/user@example.com/Contacts/personal/ Some applications may require you to use https://mail.example.com/SOGo/dav/ or the full path to your calendar, which can be found and copied from within SOGo.","title":"Contacts and calendars"},{"location":"client/client-outlook/","text":"Outlook 2016 or higher from Office 365 on Windows \u00b6 This is only applicable if your server administrator has not disabled EAS for Outlook. If it is disabled, please follow the guide for Outlook 2007 instead. Outlook 2016 has an issue with autodiscover . Only Outlook from Office 365 is affected. If you installed Outlook from another source, please follow the guide for Outlook 2013 or higher. For EAS you must use the old assistant by launching C:\\Program Files (x86)\\Microsoft Office\\root\\Office16\\OLCFG.EXE . If this application opens, you can go to step 4 of the guide for Outlook 2013 below. If it does not open, you can completely disable the new account creation wizard and follow the guide for Outlook 2013 below. Outlook 2013 or higher on Windows \u00b6 This is only applicable if your server administrator has not disabled EAS for Outlook. If it is disabled, please follow the guide for Outlook 2007 instead. Launch Outlook. If this is the first time you launched Outlook, it asks you to set up your account. Proceed to step 4. Go to the File menu and click Add Account . Enter your name ( ) , email address ( ) and your password. Click Next . When prompted, enter your password again, check Remember my credentials and click OK . Click the Allow button. Click Finish . Outlook 2007 or 2010 on Windows \u00b6 Outlook 2007 or higher on Windows \u00b6 Download and install Outlook CalDav Synchronizer . Launch Outlook. If this is the first time you launched Outlook, it asks you to set up your account. Proceed to step 5. Go to the File menu and click Add Account . Enter your name ( ) , email address ( ) and your password. Click Next . Click Finish . Go to the CalDav Synchronizer ribbon and click Synchronization Profiles . Click the second button at top ( Add multiple profiles ), select Sogo , click Ok . Click the Get IMAP/POP3 account settings button. Click Discover resources and assign to Outlook folders . In the Select Resource window that pops up, select your main calendar (usually Personal Calendar ), click the ... button, assign it to Calendar , and click OK . Go to the Address Books and Tasks tabs and repeat repeat the process accordingly. Do not assign multiple calendars, address books or task lists! Close all windows with the OK buttons. Outlook 2011 or higher on macOS \u00b6 The Mac version of Outlook does not synchronize calendars and contacts and therefore is not supported.","title":"Microsoft Outlook"},{"location":"client/client-outlook/#outlook-2016-or-higher-from-office-365-on-windows","text":"This is only applicable if your server administrator has not disabled EAS for Outlook. If it is disabled, please follow the guide for Outlook 2007 instead. Outlook 2016 has an issue with autodiscover . Only Outlook from Office 365 is affected. If you installed Outlook from another source, please follow the guide for Outlook 2013 or higher. For EAS you must use the old assistant by launching C:\\Program Files (x86)\\Microsoft Office\\root\\Office16\\OLCFG.EXE . If this application opens, you can go to step 4 of the guide for Outlook 2013 below. If it does not open, you can completely disable the new account creation wizard and follow the guide for Outlook 2013 below.","title":"Outlook 2016 or higher from Office 365 on Windows"},{"location":"client/client-outlook/#outlook-2013-or-higher-on-windows","text":"This is only applicable if your server administrator has not disabled EAS for Outlook. If it is disabled, please follow the guide for Outlook 2007 instead. Launch Outlook. If this is the first time you launched Outlook, it asks you to set up your account. Proceed to step 4. Go to the File menu and click Add Account . Enter your name ( ) , email address ( ) and your password. Click Next . When prompted, enter your password again, check Remember my credentials and click OK . Click the Allow button. Click Finish .","title":"Outlook 2013 or higher on Windows"},{"location":"client/client-outlook/#outlook-2007-or-2010-on-windows","text":"","title":"Outlook 2007 or 2010 on Windows"},{"location":"client/client-outlook/#outlook-2007-or-higher-on-windows","text":"Download and install Outlook CalDav Synchronizer . Launch Outlook. If this is the first time you launched Outlook, it asks you to set up your account. Proceed to step 5. Go to the File menu and click Add Account . Enter your name ( ) , email address ( ) and your password. Click Next . Click Finish . Go to the CalDav Synchronizer ribbon and click Synchronization Profiles . Click the second button at top ( Add multiple profiles ), select Sogo , click Ok . Click the Get IMAP/POP3 account settings button. Click Discover resources and assign to Outlook folders . In the Select Resource window that pops up, select your main calendar (usually Personal Calendar ), click the ... button, assign it to Calendar , and click OK . Go to the Address Books and Tasks tabs and repeat repeat the process accordingly. Do not assign multiple calendars, address books or task lists! Close all windows with the OK buttons.","title":"Outlook 2007 or higher on Windows"},{"location":"client/client-outlook/#outlook-2011-or-higher-on-macos","text":"The Mac version of Outlook does not synchronize calendars and contacts and therefore is not supported.","title":"Outlook 2011 or higher on macOS"},{"location":"client/client-thunderbird/","text":"Launch Thunderbird. If this is the first time you launched Thunderbird, it asks you whether you would like a new email address. Click Skip this and use my existing email and proceed to step 4. Go to the Tools menu and select Account Settings . Click the Account Actions dropdown menu at the bottom left and select Add Mail Account . Enter your name ( ) , email address ( ) and your password. Make sure the Remember password checkbox is selected and click Continue . Once the configuration has been automatically detected, click Done . If you already had other accounts configured in Thunderbird, select the new one ( ) on the left, click the Account Actions dropdown and select Set as Default . Close the account settings window with the OK button. In your web browser, download SOGo Connector SOGo Connector . Back in Thunderbird, go to the Tools menu and select Add-ons . Click Extensions on the left and ensure that the Lightning add-on is already installed. It is installed by default in the Windows and macOS versions of Thunderbird, but if you are running Linux and installed Thunderbird through your distribution's package manager, Lightning might be available as a separate package (e.g. xul-ext-lightning on Ubuntu). Click Extensions on the left, click the little gear icon at the top and select Install Add-on From File . Select the file you downloaded in step 9, click Open and, after waiting for a few seconds, Install Now . Click the Restart Now button at the top that appears. Thunderbird briefly shows a message that it is updating extensions, then restarts automatically once more. When you are prompted to authenticate for , enter your email address and password, check Use Password Manager and click OK . Automatic configuration of calendars and address books in Thunderbird is not currently supported. You can ask your server administrator to enable SOGo Connector if you need it. Automatic configuration of calendars and address books (from step 9 onward) in Thunderbird is only supported if your server administrator has enabled SOGo Connector . Different method of connecting Cal-/CardDAV in Thunderbird with automatic detection of address books and calendars \u00b6 Instead of using SOGo Connector you can use a combination of https://addons.thunderbird.net/de/thunderbird/addon/tbsync/ and https://addons.thunderbird.net/de/thunderbird/addon/dav-4-tbsync/ To add your Cal-/CardDAV accounts go to Tools and find TbSync You can add new accounts via the CalDAV & CardDAV provider: Choose \"Automatic Configuration\". Use your mail address as account and username. Use your mail password as DAV password. The server URL is your MAILCOW_HOSTNAME (specifying any protocol is not necessary, just enter the full domain). Now tick the checkbox for \"Enable and synchronize this account\" in the synchronization status tab: Several available resources should appear in the same window area now. Tick all checkboxes of the resources (address books and calendars) that you want to sync. Choose a synchronization period (in minutes) in the same window area before clicking on \"Synchronize now\". If you leave the sync at \"0\" it will only sync manually so choose at least 30 minutes for periodic synchronization. If you want to manually synchronize you can find this option under \"Account actions\" - the dropdown-menu where you added the Cal-/CardDAV account (step 2).","title":"Mozilla Thunderbird"},{"location":"client/client-thunderbird/#different-method-of-connecting-cal-carddav-in-thunderbird-with-automatic-detection-of-address-books-and-calendars","text":"Instead of using SOGo Connector you can use a combination of https://addons.thunderbird.net/de/thunderbird/addon/tbsync/ and https://addons.thunderbird.net/de/thunderbird/addon/dav-4-tbsync/ To add your Cal-/CardDAV accounts go to Tools and find TbSync You can add new accounts via the CalDAV & CardDAV provider: Choose \"Automatic Configuration\". Use your mail address as account and username. Use your mail password as DAV password. The server URL is your MAILCOW_HOSTNAME (specifying any protocol is not necessary, just enter the full domain). Now tick the checkbox for \"Enable and synchronize this account\" in the synchronization status tab: Several available resources should appear in the same window area now. Tick all checkboxes of the resources (address books and calendars) that you want to sync. Choose a synchronization period (in minutes) in the same window area before clicking on \"Synchronize now\". If you leave the sync at \"0\" it will only sync manually so choose at least 30 minutes for periodic synchronization. If you want to manually synchronize you can find this option under \"Account actions\" - the dropdown-menu where you added the Cal-/CardDAV account (step 2).","title":"Different method of connecting Cal-/CardDAV in Thunderbird with automatic detection of address books and calendars"},{"location":"client/client-windows/","text":"Windows 8 and higher support email, contacts and calendar via Exchange ActiveSync. Open the Mail app. If you have not previously used Mail, you can click Add Account in the main window. Proceed to step 4. Click Accounts in the sidebar on the left, then click Add Account on the far right. Select Exchange . Enter your email address ( ) and click Next . Enter your password and click Log in . Once you have set up the Mail app, you can also use the People and Calendar apps.","title":"Windows Mail"},{"location":"client/client-windowsphone/","text":"Open the Settings app. Select email + accounts and tap add an account . Tap Exchange . Enter your email address ( ) and your password. Tap Sign in . Tap done .","title":"Windows Phone"}]}
\ No newline at end of file
diff --git a/sitemap.xml.gz b/sitemap.xml.gz
index 0e8d279bf..6978ef07f 100644
Binary files a/sitemap.xml.gz and b/sitemap.xml.gz differ
diff --git a/u_e-mailcow_ui-tfa/index.html b/u_e-mailcow_ui-tfa/index.html
index 3ac149e68..2a875e8a2 100644
--- a/u_e-mailcow_ui-tfa/index.html
+++ b/u_e-mailcow_ui-tfa/index.html
@@ -1957,8 +1957,21 @@
The Yubi API ID and Key will be checked against the Yubico Cloud API. When setting up TFA you will be asked for your personal API account for this key.
The API ID, API key and the first 12 characters (your YubiKeys ID in modhex) are stored in the MySQL table as secret.
U2F
-Only Google Chrome (+derivatives) and Opera support U2F authentication to this day natively.
-Since version 67 Mozilla Firefox can handle U2F natively. (Source)
+To use U2F, the browser must support this standard.
+The following desktop browsers support this authentication type:
+
+- Edge (>=79)
+- Firefox (>=47, enabled by default since version 67)
+- Chrome (>=41)
+- Safari (>=13)
+- Opera (40, >=42, not 41)
+
+The following mobile browsers support this authentication type:
+
+- Safari on iOS (>=13.3)
+- Firefox on Android (>=68)
+
+Sources: caniuse.com, blog.mozilla.org
U2F works without an internet connection.
TOTP
The best known TFA method mostly used with a smartphone.