Est.
Enable Outbound E-mail on GCP
The first thing I wanted to do with my GCP VM was to install some blog software. I had the old-fashioned notion that if I wanted to offer a blog on the web, I had to join a blog site like Blogger.com or set up my own blog on my own server using WordPress or something similar.
At the time, that made sense to me. Today, I run Ergberg's Jotter using VitePress on Cloudflare Pages.
I don't remember which version of WordPress I tried at the time, but I do remember that the installer wanted to send e-mails about administrative events, all of which ended up in the dead letter queue.
Egress Traffic to Port 25 is Blocked
So I learned that by default Google blocks all TCP connections that leave the cloud platform and try to connect to port 25 in the outside world. The reason is simple to understand: Google doesn't want to be the turbo for spammers. Of course, there are also exceptions to this rule. As a selected customer, you can ask Google to exempt you from this restriction, but the blocking is set by default.
Sending E-mail from Within GCP
There are several solutions to get around the restriction. Basically, you need to find an e-mail service to forward your e-mails to. This can be Google Workspace or a trusted third-party mail provider. I chose SendGrid as the provider through which I route my e-mail traffic. Not only do they offer a free plan that is perfectly adequate for my needs. GCP also provides step-by-step instructions on how to set it up. In addition to SendGrid, GCP equally supports Mailjet and Mailgun. I chose purely based on the names, preferring the least militant.
Config: Sending via SendGrid
So I created an account with SendGrid and generated an API key. I installed mailutils (which includes postfix) on my GCP box. Google suggests to install postfix with the Local Only
config, remove default_transport = error
and relay_transport = error
in /etc/postfix/main.cf
and add the following lines there:
< default_transport = error
< relay_transport = error
---
> relayhost = [smtp.sendgrid.net]:2525
> smtp_tls_security_level = encrypt
> smtp_sasl_auth_enable = yes
> smtp_sasl_password_maps = hash:/etc/postfix/sasl_passwd
> header_size_limit = 4096000
> smtp_sasl_security_options = noanonymous
< default_transport = error
< relay_transport = error
---
> relayhost = [smtp.sendgrid.net]:2525
> smtp_tls_security_level = encrypt
> smtp_sasl_auth_enable = yes
> smtp_sasl_password_maps = hash:/etc/postfix/sasl_passwd
> header_size_limit = 4096000
> smtp_sasl_security_options = noanonymous
Here the API key is stored in /etc/postfix/sasl_passwd.db
as follows (assuming api_key
variable holds the key):
echo "[smtp.sendgrid.net]:2525 apikey:${api_key}" > \
/etc/postfix/sasl_passwd
postmap /etc/postfix/sasl_passwd
chmod 600 /etc/postfix/sasl_passwd.db
rm /etc/postfix/sasl_passwd
echo "[smtp.sendgrid.net]:2525 apikey:${api_key}" > \
/etc/postfix/sasl_passwd
postmap /etc/postfix/sasl_passwd
chmod 600 /etc/postfix/sasl_passwd.db
rm /etc/postfix/sasl_passwd
In addition to the suggestions from Google, I also made the following settings
> masquerade_domains = ergberg.tk
> sender_canonical_maps = regexp:/etc/postfix/sender_canonical_maps
> masquerade_domains = ergberg.tk
> sender_canonical_maps = regexp:/etc/postfix/sender_canonical_maps
masquerade_domains
maps subdomains to ergberg.tk
. The substitutions in /etc
map senders of my GCP domain xx
to xx
.
Receiving E-mail for a Domain
The Local Only
configuration is sufficient to send mails and fulfills my original requirement. But since I just set up Postfix on my GCP box: Why not go all the way and set up mail.ergberg.tk
as mailhost for ergberg.tk
?
That's a longer trip:
- I'll start with the
Send Only
configuration above. - I have an internet domain name, so that mail can be sent to
user@ergberg.tk
. - This domain needs an DNS MX record so others can find the mail host.
- To get rid of the snake oil in
main.cf
, I requested a TLS certificate formail.ergberg.tk
- Finally, I completed the
main.cf
configuration, see next section.
Config: Receiving Mail
The main additional change in /etc/postfix/main.cf
for receiving e-mail is listening on some/all network interfaces. Changing loopback-only
to all
is equivalent to deleting the inet_interfaces
line, since all
is the default. So instead of applying the diff, you can just delete the line.
< inet_interfaces = loopback-only
---
> inet_interfaces = all
< inet_interfaces = loopback-only
---
> inet_interfaces = all
I also replaced the Snakeoil with the Let's Encrypt certificate, which would also make sense for Send Only
variant.
< smtp_tls_security_level=may
< smtpd_tls_cert_file=/etc/ssl/certs/ssl-cert-snakeoil.pem
< smtpd_tls_key_file=/etc/ssl/private/ssl-cert-snakeoil.key
---
> smtp_tls_security_level=encrypt
> smtpd_tls_cert_file=/etc/letsencrypt/live/ergberg.tk/fullchain.pem
> smtpd_tls_key_file=/etc/letsencrypt/live/ergberg.tk/privkey.pem
< smtp_tls_security_level=may
< smtpd_tls_cert_file=/etc/ssl/certs/ssl-cert-snakeoil.pem
< smtpd_tls_key_file=/etc/ssl/private/ssl-cert-snakeoil.key
---
> smtp_tls_security_level=encrypt
> smtpd_tls_cert_file=/etc/letsencrypt/live/ergberg.tk/fullchain.pem
> smtpd_tls_key_file=/etc/letsencrypt/live/ergberg.tk/privkey.pem