Replace attachments with links in Mailcow: dockerized (Postfix)

Daniel Castellanos
4 min readJan 10, 2021
Photo by Sigmund on Unsplash

Have you ever wanted to run your own email server? Nowadays it’s pretty easy. Until it’s not.

Por cierto, este artículo está disponible en Español aquí: https://decacis.medium.com/reemplazar-adjuntos-por-links-en-mailcow-dockerized-postfix-6918ea06e0a9

Mailcow: dockerized is an email “bundle” that includes all the necessary parts to have your own email server in minutes. I’ve had previously used other similar services to accomplish this such as Mail-in-a-Box and one characteristic of most of these services is that it is effortless to “set and forget”, the documentation that these packages provide make anyone with basic Linux, DNS y and some server management knowledge able to install, configure and enjoy a self-hosted email server. That being something good or bad is another topic.

Everyone who has tried to create a self-hosted email server knows that even if the installation and configuration part is easy, sometimes it can be a hassle to actually deliver the emails because of previously black-listed IPs and such things, so from the beginning I decided to delegate the sending part to Amazon SES. This services basically ensures that the emails will be delivered because I won’t be delivering them, Amazon will.

This article won’t focus on how to connect AWS SES with Mailcow (it’s actually pretty easy), but if you are interested you can visit the following link:

https://matthias.guru/2017/10/18/amazon-ses-als-relay-in-mailcow/ (it’s in Russian? But it includes images and can be translated, so I would say it is not a problem)

Note: as far as I know Mailcow: dockerized doesn’t release “versions” so all the steps performed in this article were performed cloning the repo at https://github.com/mailcow/mailcow-dockerized on Jan 7th 2021.

My environment is a VPS running Ubuntu 20.04 on Vultr.

Once everything is configured following the official documentation, you need to install a package called: MIMEDefang

MIMEDefang is… old. The problem is not actually that is old but rather the lack of information about configuring and using it. Before going further I will leave some links with useful information about it:

http://www.mickeyhill.com/mimedefang-howto/ (one of the best guides I found)
https://serverfault.com/questions/542679/how-to-integrate-postfix-and-mimedefang (general info to install it)
https://lists.roaringpenguin.com/pipermail/mimedefang/2007-December/033683.html (the main script in this article)

Let’s begin:

Step #1: Install MIMEDefang

$ sudo apt install mimedefang

Step #2: Install dependencies
The filters (Milters) that MIMEDefang uses are written in Perl, so you need to install some dependencies before, the list of required dependencies can be found here: http://www.mickeyhill.com/mimedefang-howto/#s5 but in short just run:

$ cpan IO::Stringy MIME::Base64 Mail::Cap Mail::Util Mail::Send Mail::Field Mail::Mailer Mail::Filter Mail::Header Mail::Address Mail::Internet MIME::Tools Digest::SHA1 Bundle::libnet Mail::Audit Time::HiRes HTML::Tagset HTML::Parser Compress::Zlib Archive::Zip

Step #3: Configure MIMEDefang
By default, MIMEDefang listens to a unix socket. This in general shouldn’t be a problem but because of permissions it can very well be, the solution is to simply use inet instead.

To do it you must edit this file: /etc/default/mimedefang

$ sudo nano /etc/default/mimedefang

Here there’s a line beginning with “SOCKET” and if it’s commented, then just remove the “#” and leave it like this:

SOCKET=inet:10995

The port can be any available one, you can choose port 10999, 10996 or any valid one.

Step #4: Configure the filter
MIMEDefang uses a file named“mimedefang-filter”. Inside that file are instructions to filter the passing messages. The next file is my configuration file and I will (try to) explain it a bit.

The path of this file is (or should be in case it doesn’t exist): /etc/mail/mimedefang-filter

The file is a little long, but I explain the important parts:

Line #23 | Write a valid email to receive notifications about quarantined messages:
$AdminAddress = ‘defang-admin@YOUR.DOMAIN.com’;

Line #24 | Write the name of the contact:
$AdminName = “YOUR NAME”;

Line #32 | This is the address that will show as “From” in the email:
$DaemonAddress = ‘mimedefang@YOUR.DOMAIN.com’;

Line #68–84 | Configuration:
#68 | $DetachBigEnable = 1; #If 0, the script won't detach the attachments and if it’s 1 it will.
#69 | $DetachBigSizeMB = 2; #The size in MB of the attachments to detach (≥ 2 in this case)
#72 | $DetachBasePath = ‘/var/www/detach’; #The path where the files will be stored.
#73 | $DetachBaseURL = ‘https://some.server.com/detach'; #Format of the link that will be inserted into the message. An example would be: https://some.server.com/detach/2021–1/74c6f491aae090756ba3a46b53d1fe477c4a9850.pdf
#74–80 | Text that will be put instead of the attachment.
#81–84 | Text that will be inserted in the body of the message.

Step #5: Edit postfix-mailcow
After configuring MIMEDefang it’s necessary to configure Postfix. To do this, you have to edit the following file:

$ sudo nano /opt/mailcow-dockerized/data/conf/postfix/extra.cf

This is my configuration:

myhostname = mail.mydomain.com
smtpd_milters = inet:rspamd:9900, inet:
149.28.122.147:10995

The important part is: inet:149.28.122.147:10995

inet:THE IP OF YOUR VPS:THE PORT YOU CHOSE AT THE BEGINNING

Once you save the file go to /opt/mailcow-dockerized and run the following commands:

$ sudo service mimedefang stop
$ docker-compose stop postfix-mailcow
$ sudo service mimedefang start
$ docker-compose start postfix-mailcow

And now to test it send an email with an attachment and… That’s it! It should work.

Note: if for some reason the servers restarts MIMEDefang must start before Postfix does, to achieve this you should edit the service file of MIMEDefang and add: BEFORE=docker.service

--

--

Daniel Castellanos
0 Followers

Hi! I’m Daniel and I really like to experiment with all sorts of technologies. I mainly work with Node.js and Javascript in general but I’m open to try things!