Repository: Mailu/Mailu

Issue:
Using external smtp relay server for outgoing emails
Hi,

I need to use mailchannels.com to relay all outgoing emails from my Mailu install. In this doc is what I need to change in Postfix:

https://mailchannels.zendesk.com/hc/en-us/articles/200262640-Setting-up-for-Postfix

Is there any way to do this in Mailu ?

Thanks,



Discussion:
No, there is not currently, you have to add a couple of lines to postfix configuration. I've just made a script to do that. I can make a PR if it's gonna be welcomed. What do you think @kaiyou?
@OrkhanAlikhanov You can share the code of the script ?

Thanks,
Specify relay variables in .env file:
```
RELAYHOST=[smtp.mailgun.org]:587
RELAY_LOGIN=xxxx
RELAY_PASSWORD=xxxx
```

Create **relay_conf.sh**
```bash
#!/bin/sh

# Configuration for the script
POSTFIX_CONFIG=/etc/postfix/main.cf
POSTFIX_SASL=/etc/postfix/sasl_passwd

# Set a safe umask
umask 077

# Add the relay host params 
cat >> $POSTFIX_CONFIG << EOF
# Mailgun configuration
smtp_tls_security_level = encrypt
smtp_sasl_auth_enable = yes
smtp_sasl_password_maps = hash:$POSTFIX_SASL
smtp_sasl_security_options = noanonymous
EOF

# Remove old
rm -f $POSTFIX_SASL

# Create new
cat > $POSTFIX_SASL << EOF
$RELAYHOST $RELAY_LOGIN:$RELAY_PASSWORD
EOF

chmod 600 $POSTFIX_SASL
postmap $POSTFIX_SASL

# Reload Postfix
/etc/init.d/postfix restart
```
Then make the `relay_conf.sh` executable and copy it to the docker where postfix runs.
In my case it was docker named: `mailu_smtp_1`.
``` bash
sudo chmod +x relay_conf.sh 
sudo docker cp ./relay_conf.sh mailu_smtp_1:/relay_conf.sh 
sudo docker exec -e .env -it  mailu_smtp_1 /relay_conf.sh
```
It's done. You may need to adjust some other parameters in the script according to relay server's need. I configured it for MailGun.

***Note:**  you need to perform these steps each time you rebuild the dockers
The script is modified version of https://gist.github.com/jgeewax/2c63810a534197c8a6be
This is pretty nice, @OrkhanAlikhanov :) if you could insert this as optional parameters in the `.env` and use the Jinja template in the Postfix container, it definitely would deserve a merge!
@kaiyou Cool. I'll PR this weekend inshaAllah :)
Using the @OrkhanAlikhanov  solution as a starting point I was able to configure Mailu to send emails using the Mailchannels service (it works for Mailgun and others as well) as follows:

1) Create the **data/overrides/postfix-maichannels.map** file and put the authentication credentials for **smtp.mailchannels.net** in it:
```
smtp.mailchannels.net mailchannelsuser:mailchannelspassword
```
2) Create/edit the **data/overrides/postfix.cf** file with the settings to be used by Postfix:
```
smtp_sasl_auth_enable = yes
smtp_sasl_auth_enable = yes
smtp_sasl_password_maps = hash:/etc/postfix/postfix-maichannels.map
smtpd_sasl_authenticated_header = yes
smtp_sasl_security_options = noanonymous
smtp_sasl_mechanism_filter = AUTH LOGIN
smtp_tls_security_level = encrypt
smtp_sasl_tls_security_options = noanonymous
```

3) Edit the **.env** file and set the **RELAYHOST** variable:
```
RELAYHOST=smtp.mailchannels.net
```
4) Reload/restart mailu

**IMPORTANT**: Note that in the **data/overrides/postfix.cf** file the **smtp_sasl_auth_enable** entry appears 2 times:
```
smtp_sasl_auth_enable = yes
smtp_sasl_auth_enable = yes
smtp_sasl_password_maps = hash:/etc/postfix/postfix-maichannels.map
...
```
This is not a typo. The **postconf** command when setting a variable that does not exist in the original **/etc/postfix/main.cf** adds it to the end of the **/etc/postfix/main.cf** file without a *<newline>* before. That is, as the Mailu **/conf/main.cf** file used to create the original **/etc/postfix/main.cf**ends like this:
```
###############
# Extra Settings
###############
```
The first run of **postconf -e "smtp_sasl_auth_enable = yes"** from **start.py** will make **/etc/postfix/main.cf** look like this:
```
###############
# Extra Settings
###############smtp_sasl_auth_enable = yes
```
And after the second run we get the desired result:
```
###############
# Extra Settings
###############smtp_sasl_auth_enable = yes
smtp_sasl_auth_enable = yes
```
Of course this is an ugly and temporary solution.
One permanent solution would be to change the **start.py** to something like:
```
for postfix_file in glob.glob("/conf/*.cf"):
    convert(postfix_file, os.path.join("/etc/postfix", os.path.basename(postfix_file)))
    with open("/etc/postfix/{0}".format(os.path.basename(postfix_file)), 'a') as f:
        f.write("\n")
```
To make sure that all Postfix configuration files end with a blank line.


@OrkhanAlikhanov Thanks for your script! I made a few changes as I had some errors, one of them being: `sh: /etc/init.d/postfix: not found` (possibly because of the lightweight linux distro inside docker)

Aside from the changed script, there's not much else to do, so you can just follow the tutorial mentioned above (https://github.com/Mailu/Mailu/issues/387#issuecomment-370464619)
I changed the script to this (note that it's now using overrides and `postfix reload`):

```sh
#!/bin/sh

# Configuration for the script
POSTFIX_CONFIG=/overrides/postfix.cf
POSTFIX_SASL=/etc/postfix/sasl_passwd

# Set a safe umask
umask 077

# Add the relay host params  
cat >> $POSTFIX_CONFIG << EOF
smtp_tls_security_level = encrypt
smtp_sasl_auth_enable = yes
smtp_sasl_password_maps = hash:$POSTFIX_SASL
smtp_sasl_security_options = noanonymous
EOF

# Remove old
rm -f $POSTFIX_SASL

# Create new
cat > $POSTFIX_SASL << EOF
$RELAYHOST $RELAY_LOGIN:$RELAY_PASSWORD
EOF

chmod 600 $POSTFIX_SASL
postmap $POSTFIX_SASL

# Reload Postfix
postfix reload
```

**Reasons for these changes:**

- Even if you restart (read: not rebuild) Docker, the changes remain working
- Errors regarding `/etc/init.d/postfix`

Thanks! This helped me.

I'm using it with Sendgrid. For specific configs check [here](https://sendgrid.com/docs/for-developers/sending-email/postfix/). (But it seems I have to [remove SPF, DKIM and DMARC](https://sendgrid.com/blog/dmarc-domain-based-message-authentication-reporting-conformance/))

Resolving patch:
diff --git a/core/postfix/start.py b/core/postfix/start.py
--- a/core/postfix/start.py
+++ b/core/postfix/start.py
@@ -48,6 +48,11 @@ def start_podop():
     os.system("postmap {}".format(destination))
     os.remove(destination)
 
+if "RELAYUSER" in os.environ:
+    path = "/etc/postfix/sasl_passwd"
+    convert("/conf/sasl_passwd", path)
+    os.system("postmap {}".format(path))
+
 convert("/conf/rsyslog.conf", "/etc/rsyslog.conf")
 
 # Run Podop and Postfix


Test patch: