My Docker Mail - MailMoto

Info
If you are a native tagalog speaker then you will get why i named it “mailmoto” - mail mo ito.
 1                            ███  ████                            █████            
 2                           ░░░  ░░███                           ░░███             
 3 █████████████    ██████   ████  ░███  █████████████    ██████  ███████    ██████ 
 4░░███░░███░░███  ░░░░░███ ░░███  ░███ ░░███░░███░░███  ███░░███░░░███░    ███░░███
 5 ░███ ░███ ░███   ███████  ░███  ░███  ░███ ░███ ░███ ░███ ░███  ░███    ░███ ░███
 6 ░███ ░███ ░███  ███░░███  ░███  ░███  ░███ ░███ ░███ ░███ ░███  ░███ ███░███ ░███
 7 █████░███ █████░░████████ █████ █████ █████░███ █████░░██████   ░░█████ ░░██████ 
 8░░░░░ ░░░ ░░░░░  ░░░░░░░░ ░░░░░ ░░░░░ ░░░░░ ░░░ ░░░░░  ░░░░░░     ░░░░░   ░░░░░░  
 9
10Author: Mark Taguiad <marktaguiad@marktaguaid.dev>
11Site: https://marktaguiad.dev

This is not a replacement to your production email server solution, this was created as a solution for my low spec edge server (VPS with 1 core and 1gb ram). This sit comforably consumming 30mb RAM and low CPU utilization - on low volume of mails.

Repo: mcbtaguiad/mailmoto

Table of Contents

Quick Start

Use this compose.yml. Edit environment, put your domain. Make sure you have a valid TLS Certificate mounted.

 1services:
 2  mailmoto:
 3    container_name: mailmoto
 4    image: ghcr.io/mcbtaguiad/mailmoto:main
 5    build:
 6        context: .
 7        dockerfile: Dockerfile
 8    environment:
 9      MAIL_HOSTNAME: mail.marktaguiad.dev
10      MAIL_DOMAIN: marktaguiad.dev
11      RSPAMD_ENABLE: true
12    volumes:
13      - ./tls/fullchain.pem:/data/tls/fullchain.pem
14      - ./tls/privkey.pem:/data/tls/privkey.pem
15      - ./data:/data
16      # - ./log/mail.log:/var/log/mail.log
17    ports:
18      - "25:25"
19      - "587:587"
20      - "465:465"
21      - "143:143"
22      - "993:993" 
23
24    restart: always
25    healthcheck:
26      test:
27        - CMD
28        - nc
29        - -z
30        - localhost
31        - "25"
32      interval: 30s
33      timeout: 5s
34      retries: 3
35    logging:
36      driver: json-file
37      options:
38        max-size: 10m
39        max-file: "3"

Deploy.

1docker compose up -d

DNS

Add mail record to you DNS Record.

1mail    IN    A     <your_ip>
2mx1     IN    A     <your_ip> 
3<yourdomain>    IN      MX      mail.<yourdomain> 
4<yourdomain>    IN      TXT     "v=spf1 mx ~all"

Rspamd or Spamassassin

If you enable RSPAMD_ENABLE: true, this will disable Spamassassin, Opendkim, Opendmarc and Postgrey. Rspamd by default has module for dkim and dmarc. I also recommend Rspamd as it is a more modern solution to spams.

DKIM

Dkim is created after you run the compose file, make sure to mount /data.

Navigate to /data/dkim/<yourdomain>/, you’ll find mail.txt and mail.private.

Example.

1mail._domainkey	IN	TXT	( "v=DKIM1; h=sha256; k=rsa; "
2	 "p=MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCz85kQp9hUUn4ybRoJ/7Fg7YT6Z6mj57LY/t5b/VEvWav6Y0oWahx/GM0UOJUJJa/4YGA4KGo+z8x14S3Mkz3YzUmqIBRAD02cizHh2U3F2IzsADyRkjc/XYpsxQtK1pgdvIQiiofkPCaT2mey2CyFWXCQfZm8FmGcRLJyBAPKbwIDAQAB" )  ; ----- DKIM key mail for marktaguiad.dev

Add the content of mail.txt to your DNS Record.

DMARC

Check this post for more explanation and setup.

Example.

1_dmarc IN	TXT	( "v=DMARC1; p=quarantine; ruf=mailto:dmarc-report@marktaguiad.dev; rua=mailto:dmarc-report@marktaguiad.dev" )

User Create/ModifyDelete

Exec to the the container and run mailmoto to create, modify or delete email user.

1docker exec -it mailmoto bash
2./mailmoto
3MailMoTo Usage:
4./mailmoto create email password
5./mailmoto passwd email password
6./mailmoto delete email

Or.

1docker exec -it mailmoto ./mailmoto
2MailMoTo Usage:
3./mailmoto create email password
4./mailmoto passwd email password
5./mailmoto delete email

Example.

1docker exec -it mailmoto ./mailmoto create user@marktaguiad.dev AstrongPassword123!
2Creating mailbox user@marktaguiad.dev
3User created: user@marktaguiad.dev

Logging

You can mount /var/log/mail.log if you plan to use fail2ban.

To make fail2ban work, change the logpath in /etc/fail2ban/filter.d/, or just create a config file in /etc/fail2ban/jail.d.

mailmoto.conf

 1[postfix]
 2enabled = true
 3logpath = /srv/volume/mailmoto/mail.log # dir path where i mount logs
 4maxretry = 3
 5bantime = 3600
 6action = nftables[name=POSTFIX, port=smtp, protocol=tcp]
 7
 8[dovecot]
 9enabled = true
10logpath = /srv/volume/mailmoto/mail.log
11maxretry = 3
12bantime = 3600
13action = nftables[name=DOVECOT, port=imap, protocol=tcp]

If the container fails to start, make sure mail.log exist on the host - if mounted.

Testing

Send email to gmail, if your email server or IP is reputable it would be received by gmail. Click on your message and click on show original. SPF, DKIM and DMARC should show ‘PASS’. Reply and send, if spamassassin or rspamd is working then you would received the email from gmail.

Or use this external site/tool to test.