Hello,

I’m trying to make an email availability script which made me wonder is CLI reading/sending available without extensive modification of the containers?

Open to any CLI mail recommendations, even accessing the mailcow container stack from the docker host.

  • This is the solution i made:

    mail-test.sh resides in the dovecot container via a bind mount, and awaits to be called by mail-deliverability.sh

    Add the following line to your docker-compose.yml :

    ...snip...
    volumes:
       - ./helper-scripts/mail-test.sh:/root/mail-test.sh:ro
    ...snip...

    Add the following line to your crontab file (Runs every 3 hours):
    0 */3 * * * <MAILCOW DIR>/helper-scripts/mail-deliverability.sh

    Save the scripts to your helper-scripts dir in the mailcow folder.

    mail-deliverability.sh >

    #!/usr/bin/env bash
    
    mailcow_dir="<MAILCOW DIR>/helper-scripts"
    verify_uuid="/tmp/verify_uuid"
    mail_format="+%y/%m/%d_%H:%M:%S::"
    dovecot_c="<DOVECOT CONTAINER NAME>" # eg. mailcow_dovecot
    domain="<YOUR DOMAIN>"
    password="<TEST USER PASSWORD>"
    
    echo "[*] Generating verification uuid in $verify_uuid..."
    if cat /proc/sys/kernel/random/uuid | sed 's/[-]//g' | head -c 20 > $verify_uuid; then
    
        uuid=$(cat $verify_uuid)
        echo "[+] Verify uuid [1/2] - $uuid"
        if docker cp $verify_uuid $dovecot_c:/root/; then
    
            echo "[*] Sending test mail..."
            if curl -s --ssl-reqd --mail-from "test@$domain" \
                --mail-rcpt "test@$domain" -T - \
                --url "smtps://mail.$domain:465" \
                --user "test@$domain:$password" \
                <<< "$(date $mail_format) :: $uuid"; then
    
                echo "[*] Sleeping 15 seconds..."
                sleep 15
    
                echo "[*] Checking if mail has been delivered..."
                echo
                if ! docker exec $dovecot_c /root/mail-test.sh; then
                    echo "[-] Unable to check if mail was delivered!"
                fi
            else
                echo "[-] Test mail was not sent!"
                exit 1
            fi
    
            rm $verify_uuid
        else
            echo "[-] Unable to copy verification uuid to $dovecot_c!"
            exit 1
        fi
    
    else
        echo "[-] Couldn't generate verification string at $verify_uuid!"
        exit 1
    fi

    mail-test.sh >

    #!/usr/bin/env bash
    
    domain=<YOUR DOMAIN>
    maildir="/var/vmail/$domain/test/Maildir/new"
    latestMail=$(ls -Art $maildir | tail -n 1)
    testfile="/root/test"
    verify_uuid="/root/verify_uuid"
    delete_older_than="8w"
    
    if [ -s "$maildir"/"$latestMail" ]; then
        cp "$maildir"/"$latestMail" $testfile
    
        if [[ $(head -c7 "$testfile") == "CRYPTED" ]]; then
            echo "[+] Expunging mail older than $delete_older_than..."
            echo
            if ! doveadm expunge -u test@$domain mailbox '*' before $delete_older_than; then
                echo "[-] Unable to expunge old mail!"
            fi
    
            echo "[+] Found latest message, decrypting..."
            echo
            if doveadm fs get compress lz4:1:crypt:private_key_path=/mail_crypt/ecprivkey.pem:public_key_path=/mail_crypt/ecpubkey.pem:posix:prefix=/ "$testfile" > "$testfile".dec; then
                echo "========== BEGIN MESSAGE =========="
                cat "$testfile.dec"
                echo "========== END MESSAGE =========="
                echo
            else
                echo "[-] Unable to decrypt latest message!"
                exit 1
            fi
        fi
    
        uuid=$(cat $verify_uuid)
        echo "[+] Verify uuid [2/2] - $uuid"
        echo
        if grep -q "$uuid" "$testfile".dec; then
            echo "[+] E-mail is up and running."
            ret=0
        else
            echo "[-] Message uuid verification failed!"
            ret=1
        fi
    
        rm "$verify_uuid"
        rm "$testfile"
        rm "$testfile".dec
        exit $ret
    
    else
        echo "[-] Latest mail not found!"
        exit 1
    fi
5 days later

This is the solution i made:

mail-test.sh resides in the dovecot container via a bind mount, and awaits to be called by mail-deliverability.sh

Add the following line to your docker-compose.yml :

...snip...
volumes:
   - ./helper-scripts/mail-test.sh:/root/mail-test.sh:ro
...snip...

Add the following line to your crontab file (Runs every 3 hours):
0 */3 * * * <MAILCOW DIR>/helper-scripts/mail-deliverability.sh

Save the scripts to your helper-scripts dir in the mailcow folder.

mail-deliverability.sh >

#!/usr/bin/env bash

mailcow_dir="<MAILCOW DIR>/helper-scripts"
verify_uuid="/tmp/verify_uuid"
mail_format="+%y/%m/%d_%H:%M:%S::"
dovecot_c="<DOVECOT CONTAINER NAME>" # eg. mailcow_dovecot
domain="<YOUR DOMAIN>"
password="<TEST USER PASSWORD>"

echo "[*] Generating verification uuid in $verify_uuid..."
if cat /proc/sys/kernel/random/uuid | sed 's/[-]//g' | head -c 20 > $verify_uuid; then

    uuid=$(cat $verify_uuid)
    echo "[+] Verify uuid [1/2] - $uuid"
    if docker cp $verify_uuid $dovecot_c:/root/; then

        echo "[*] Sending test mail..."
        if curl -s --ssl-reqd --mail-from "test@$domain" \
            --mail-rcpt "test@$domain" -T - \
            --url "smtps://mail.$domain:465" \
            --user "test@$domain:$password" \
            <<< "$(date $mail_format) :: $uuid"; then

            echo "[*] Sleeping 15 seconds..."
            sleep 15

            echo "[*] Checking if mail has been delivered..."
            echo
            if ! docker exec $dovecot_c /root/mail-test.sh; then
                echo "[-] Unable to check if mail was delivered!"
            fi
        else
            echo "[-] Test mail was not sent!"
            exit 1
        fi

        rm $verify_uuid
    else
        echo "[-] Unable to copy verification uuid to $dovecot_c!"
        exit 1
    fi

else
    echo "[-] Couldn't generate verification string at $verify_uuid!"
    exit 1
fi

mail-test.sh >

#!/usr/bin/env bash

domain=<YOUR DOMAIN>
maildir="/var/vmail/$domain/test/Maildir/new"
latestMail=$(ls -Art $maildir | tail -n 1)
testfile="/root/test"
verify_uuid="/root/verify_uuid"
delete_older_than="8w"

if [ -s "$maildir"/"$latestMail" ]; then
    cp "$maildir"/"$latestMail" $testfile

    if [[ $(head -c7 "$testfile") == "CRYPTED" ]]; then
        echo "[+] Expunging mail older than $delete_older_than..."
        echo
        if ! doveadm expunge -u test@$domain mailbox '*' before $delete_older_than; then
            echo "[-] Unable to expunge old mail!"
        fi

        echo "[+] Found latest message, decrypting..."
        echo
        if doveadm fs get compress lz4:1:crypt:private_key_path=/mail_crypt/ecprivkey.pem:public_key_path=/mail_crypt/ecpubkey.pem:posix:prefix=/ "$testfile" > "$testfile".dec; then
            echo "========== BEGIN MESSAGE =========="
            cat "$testfile.dec"
            echo "========== END MESSAGE =========="
            echo
        else
            echo "[-] Unable to decrypt latest message!"
            exit 1
        fi
    fi

    uuid=$(cat $verify_uuid)
    echo "[+] Verify uuid [2/2] - $uuid"
    echo
    if grep -q "$uuid" "$testfile".dec; then
        echo "[+] E-mail is up and running."
        ret=0
    else
        echo "[-] Message uuid verification failed!"
        ret=1
    fi

    rm "$verify_uuid"
    rm "$testfile"
    rm "$testfile".dec
    exit $ret

else
    echo "[-] Latest mail not found!"
    exit 1
fi

Have something to say?

Join the community by quickly registering to participate in this discussion. We'd like to see you joining our great moo-community!

If your mail server is resolvable by your dns, which it probably will be, this will only send the mail internally, but my reasoning is that if I can receive mail internally, I should be able to receive it from external sources, unless my internet is down, which I’m pretty sure I’d notice.

No one is typing