====== Intro ======
mailcow compress and encrypt mail stored inside the "mailcowdockerized_vmail-vol-1" docker volume.
[[https://docs.mailcow.email/manual-guides/Dovecot/u_e-dovecot-mail-crypt/|The documentation]] has a description on how you decrypt or re-encrypt the mail files inside the volume.
This requires that you enter the dovecot container and paste the logic. That is rather cumbersome, so here is a bash script which you can run from anywhere which takes care of that.
===== Script Which Takes It All =====
It take two flags "-d" for decryption and "-e" for encryption, which needs to be supplied when you run it.
#!/bin/bash
# Define the path inside the container
CONTAINER_PATH="/tmp/mail_crypt_tool.sh"
DOCKER_COMPOSE_FILE="/opt/mailcow-dockerized/docker-compose.yml"
# Function to decrypt files
decrypt_files() {
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:1: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
}
# Function to encrypt files
encrypt_files() {
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
}
# Function to print help
print_help() {
echo "Usage: $0 [OPTIONS]"
echo "Options:"
echo " -d Decrypt files in /var/vmail"
echo " -e Encrypt files in /var/vmail"
echo " -h Display this help message"
}
# Check if we're inside a Docker container
if [ -f /.dockerenv ]; then
# We are inside a container, proceed with the main logic
main() {
case "$1" in
-d)
decrypt_files
;;
-e)
encrypt_files
;;
*)
print_help
;;
esac
}
main "$@"
else
# We are outside a container, so let's copy and execute the script inside the container
docker compose -f $DOCKER_COMPOSE_FILE cp $0 dovecot-mailcow:$CONTAINER_PATH
docker compose -f $DOCKER_COMPOSE_FILE exec -T dovecot-mailcow chmod +x $CONTAINER_PATH
docker compose -f $DOCKER_COMPOSE_FILE exec -T dovecot-mailcow $CONTAINER_PATH "$@"
fi
===== Script Which Takes One Mailbox At a Time =====
#!/bin/bash
# Define the path inside the container
CONTAINER_PATH="/tmp/mail_crypt_tool.sh"
DOCKER_COMPOSE_FILE="/opt/mailcow-dockerized/docker-compose.yml"
decrypt_files() {
local mailbox_path="$1"
find "$mailbox_path" -type f -regextype egrep -regex '.*S=.*W=.*' | while read -r file; do
if [[ $(head -c7 "$file") == "CRYPTED" ]]; then
doveadm fs get compress lz4:1: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_files() {
local mailbox_path="$1"
find "$mailbox_path" -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
}
print_help() {
echo "Usage: $0 [OPTIONS] [MAILBOX_PATH]"
echo "Options:"
echo " -d Decrypt specified mailbox or all mailboxes if no path is provided"
echo " -e Encrypt specified mailbox or all mailboxes if no path is provided"
echo " -h Display this help message"
echo "MAILBOX_PATH: Path to the mailbox, format: /var/vmail/domain/user"
}
# Function to list and select user mailboxes
select_mailbox() {
local paths=($(find /var/vmail/ -mindepth 2 -maxdepth 2 -type d ! -name ".*"))
local mailboxes=()
# Convert paths to email format
for path in "${paths[@]}"; do
local user=$(basename "$path")
local domain=$(basename $(dirname "$path"))
mailboxes+=("$user@$domain")
done
select mailbox in "${mailboxes[@]}"; do
if [[ -n $mailbox ]]; then
# Convert back to path format and return
local user=$(echo "$mailbox" | cut -d'@' -f1)
local domain=$(echo "$mailbox" | cut -d'@' -f2)
echo "/var/vmail/$domain/$user"
return
else
echo "Invalid selection"
fi
done
}
# Check if we're inside a Docker container
if [ -f /.dockerenv ]; then
# We are inside a container, proceed with the main logic
main() {
local mailbox_path=""
if [[ -z "$2" ]]; then
echo "Select a mailbox:"
mailbox_path=$(select_mailbox)
else
mailbox_path="$2"
fi
case "$1" in
-d)
decrypt_files "$mailbox_path"
;;
-e)
encrypt_files "$mailbox_path"
;;
*)
print_help
;;
esac
}
main "$@"
else
# We are outside a container, so let's copy and execute the script inside the container
docker compose -f $DOCKER_COMPOSE_FILE cp $0 dovecot-mailcow:$CONTAINER_PATH
docker compose -f $DOCKER_COMPOSE_FILE exec -T dovecot-mailcow chmod +x $CONTAINER_PATH
docker compose -f $DOCKER_COMPOSE_FILE exec -T dovecot-mailcow $CONTAINER_PATH "$@"
fi