The following explores the configuration of an OpenBSD base install to send emails from the CLI (mail(1), sendmail(8), etc.), relaying them to an existing Gmail account. We’re not touching upon reading emails here; we’ll present some tools to help with attachments.
Essential bits of smtpd(8) configuration to achieve email relaying are actually the first example setup from smtpd.conf(5):
EXAMPLES
The default smtpd.conf file which ships with OpenBSD listens on the
loopback network interface (lo0) and allows for mail from users and
daemons on the local machine, as well as permitting email to remote
servers. Some more complex configurations are given below.
This first example is similar to the default configuration, but all
outgoing mail is forwarded to a remote SMTP server. A secrets file is
needed to specify a username and password:
# touch /etc/mail/secrets
# chmod 640 /etc/mail/secrets
# chown root:_smtpd /etc/mail/secrets
# echo "bob username:password" > /etc/mail/secrets
smtpd.conf would look like this:
table aliases file:/etc/mail/aliases
table secrets file:/etc/mail/secrets
listen on lo0
action "local_mail" mbox alias <aliases>
action "outbound" relay host smtp+tls://bob@smtp.example.com \
auth <secrets>
match from local for local action "local_mail"
match from local for any action "outbound"
Gmail account setup
In order,
- you first need to make sure that the 2-Step Verification is enabled for your account (this should be enabled by default);
- you’ll then be able to create app passwords for your account by going on your personal App passwords page.
The previous links should be clear enough on the exact procedure; bear in mind that the application name only has a self-documentation use. In the end, this should yield a 16 ASCII lowercase letters password; we’ll assume from now on:
- the gmail address to be:
foobar@gmail.com
; - and the associated secret to be:
jbvypwimgctkcgaz
.
smtpd(8), smtpd.conf(5)
We can then configure smtpd(8); the default
/etc/mail/smtpd.conf
looks something like:
# $OpenBSD: smtpd.conf,v 1.14 2019/11/26 20:14:38 gilles Exp $
# This is the smtpd server system-wide configuration file.
# See smtpd.conf(5) for more information.
table aliases file:/etc/mail/aliases
listen on socket
# To accept external mail, replace with: listen on all
#
listen on lo0
action "local_mail" mbox alias <aliases>
action "outbound" relay
# Uncomment the following to accept external mail for domain "example.org"
#
# match from any for domain "example.org" action "local_mail"
match from local for local action "local_mail"
match from local for any action "outbound"
Relevant bits from smtpd.conf(5):
DESCRIPTION
...
action name method [options]
When the queue runner processes an envelope from the mail queue,
it carries out the action name, selected by the match ... action
directive when the message was received. The action directive
provides configuration data for delivery attempts. Required
lookups are performed at the time of each delivery attempt.
Consequently, changing an action directive or the files it
references and restarting the smtpd(8) daemon causes the changes
to take effect for subsequent delivery attempts for the
respective dispatcher name, even for messages that were already
stuck in the queue prior to the configuration changes.
The delivery method parameter may be one of the following:
...
relay Relay the message to another SMTP server.
The local delivery methods support additional options:
...
host relay-url
Do not perform MX lookups but relay messages to the relay
host described by relay-url. The format for relay-url is
[proto://[label@]]host[:port]. The following protocols
are available:
smtp Normal SMTP session with opportunistic
STARTTLS (the default).
smtp+tls Normal SMTP session with mandatory STARTTLS.
smtp+notls Plain text SMTP session without TLS.
lmtp LMTP session. port is required.
smtps SMTP session with forced TLS on connection.
The default port is 465.
Unless noted, port defaults to 25.
The label corresponds to an entry in a credentials table,
as documented in table(5). It is used with the
"smtp+tls" and "smtps" protocols for authentication.
Server certificates for those protocols are verified by
default.
...
auth <table>
Use the mapping table for connecting to relay-url using
credentials. This option is usable only with host
option. The credential table format is described in
table(5).
...
match options action name
If at least one mail envelope matches the options of one match
action directive, receive the incoming message, put a copy into
each matching envelope, and atomically save the envelopes to the
mail spool for later processing by the respective dispatcher
name.
[!] for any
Specify that session may address any destination.
...
[!] from local
Specify that session may only originate from a local IP
address, or from the local enqueuer. This is the
default, and may be omitted.
...
table name [type:]pathname
Tables provide additional configuration information for smtpd(8)
in the form of lists or key-value mappings. The format of the
entries depends on what the table is used for. Refer to table(5)
for the exhaustive documentation.
Each table is identified by an arbitrary, unique name.
If the type is db, information is stored in a file created with
makemap(8); if it is file or omitted, information is stored in a
plain text file using the format described in table(5). The
pathname to the file must be absolute.
As suggested by smtpd.conf(5), we’ll want to add to
/etc/mail/smtpd.conf
a new table containing our secret:
table secrets file:/etc/mail/secrets
The /etc/mail/secrets
itself can be created as such:
(server); echo 'entryname foobar@gmail.com:jbvypwimgctkcgaz' > /etc/mail/secrets
(server); chown root:_smtpd /etc/mail/secrets
(server); chmod 640 /etc/mail/secrets
Going back to /etc/mail/smtpd.conf
, we now need to inform
smtpd(8) that it needs to relay all outbound mails
through this gmail account, which will be implemented with such
two lines:
action "relay" relay host smtp+tls://entryname@smtp.gmail.com:587 auth <secrets>
match from local for any action "relay"
Which in the end gives us for /etc/mail/smtpd.conf
something like:
# This is the smtpd server system-wide configuration file.
# See smtpd.conf(5) for more information.
table aliases file:/etc/mail/aliases
table secrets file:/etc/mail/secrets
listen on socket
# To accept external mail, replace with: listen on all
#
listen on lo0
action "local_mail" mbox alias <aliases>
action "relay" relay host smtp+tls://entryname@smtp.gmail.com:587 auth <secrets>
# Uncomment the following to accept external mail for domain "example.org"
#
# match from any for domain "example.org" action "local"
match from local for local action "local_mail"
match from local for any action "relay"
You may now check the configuration file, restart smtpd(8), and try sending an email, while inspecting relevant logs:
# Checking smtpd.conf...
(server); smtpd -n
# Restarting smtpd...
(server); rcctl restart smtpd
# Display smtpd logs on console
(server); tail -f -n 0 /var/log/maillog &
# Send test mail
(server); echo foo | mail -s bar foobar@gmail.com
# Logs displayed by the tail(1)
2022-07-25T23:06:42.400Z main smtpd[36237]: fa7d3d2223174777 smtp message msgid=d9680942 size=377 nrcpt=1 proto=ESMTP
2022-07-25T23:06:42.400Z main smtpd[36237]: fa7d3d2223174777 smtp envelope evpid=d968094237ae067f from=<root@main.openstacklocal> to=<foobar@gmail.com>
2022-07-25T23:06:42.400Z main smtpd[36237]: fa7d3d2223174777 smtp disconnected reason=quit
2022-07-25T23:06:42.406Z main smtpd[36237]: fa7d3d2672071d9e mta connecting address=smtp+tls://108.177.127.109:587 host=el-in-f109.1e100.net
2022-07-25T23:06:42.419Z main smtpd[36237]: fa7d3d2672071d9e mta connected
2022-07-25T23:06:42.503Z main smtpd[36237]: fa7d3d2672071d9e mta tls ciphers=TLSv1.3:TLS_AES_256_GCM_SHA384:256
2022-07-25T23:06:42.503Z main smtpd[36237]: fa7d3d2672071d9e mta cert-check result="valid" fingerprint="SHA256:3858f62230ac3c915f300c664312c63f3858f62230ac3c915f300c664312c63f"
2022-07-25T23:06:43.406Z main smtpd[36237]: fa7d3d2672071d9e mta delivery evpid=d968094237ae067f from=<root@main.openstacklocal> to=<foobar@gmail.com> rcpt=<-> source="1.1.1.1" relay="108.177.127.109 (el-in-f109.1e100.net)" delay=1s result="Ok" stat="250 2.0.0 OK 1658790403 f23-20020a17090631d700b0072b55713daesm5693643ejf.56 - gsmtp"
2022-07-25T23:06:53.517Z main smtpd[36237]: fa7d3d2672071d9e mta disconnected reason=quit messages=1
MIME mails
By default, OpenBSD only comes with uuencode(1) to help sending emails with attachments, based on an essentially deprecated 1980s software, and which are poorly displayed by Gmail. It is typically used as such:
(
echo Subject: [name] backup -- $date
echo "\r\n"
uuencode /path/to/backup.tgz name-$date.tgz
) | sendmail -f $from $to
An alternative is to use the MIME (Multipurpose Internet Mail Extensions)
format: in particular, this daemonforums.org post by Adriaan
van Roosmalen (J65nko) presents the format, and provides a
small sh(1) tool, matts
, to actually send MIME emails.
Note: I’ve actually used matts
as a base to wrote a similar
wrapper mmail, which as a main difference, allows to set arbitrary
headers.
Forwarding cronjobs mail
By default, cronjobs’s output is sent to the local mail box of
the crontab(1) owner. The behavior can be overidden by setting
the MAILTO
environment variable in the crontab(5):
ENVIRONMENT
...
MAILTO If MAILTO is defined and non-empty, mail is sent to the user
so named. If MAILTO is defined but empty (MAILTO = ""), no
mail will be sent. Otherwise mail is sent to the owner of
the crontab. This is useful for pseudo-users that lack an
alias that would otherwise redirect the mail to a real
person.
By setting a non-local address, smtpd(8) will automatically relay the email, so the following crontab will send cronjobs output by email to our gmail address:
#
SHELL=/bin/sh
HOME=/var/log
SUGARD=/var/sugard
PATH=/bin:/sbin:/usr/bin:/usr/sbin:/var/sugard/bin
MAILTO=foobar@gmail.com
#
#minute hour mday month wday [flags] command
#
# rotate log files every hour, if necessary
0 * * * * /usr/bin/newsyslog
...
00 00 * * * /bin/sh $SUGARD/bin/renew-certs >/dev/null
30 00 * * * /bin/sh $SUGARD/bin/backup-certs >/dev/null
00 00 * * * /bin/sh $SUGARD/bin/get-ip2location >/dev/null
sugar(1)
For the record, the setup (smtpd, mmail) can be simply automated with sugar(1): see the dedicated OpenBSD repository.
% sugar -s box setup-gmail
hook-pre-setup-gmail : Preparing mail/secrets for sync...
setup-gmail : Installing mail/secrets and smtpd.conf...
setup-gmail : Checking smtpd.conf...
setup-gmail : Restarting smtpd...
OK
% sugar -s main setup-mmail
hook-pre-setup-mmail : Asserting mmail is locally installed...
hook-pre-setup-mmail : Preparing mmail for sync...
setup-mmail : Installing mmail...
setup-mmail : Updating mandoc.db...
OK
For more about sugar, see:
- On sugar, a sweeter Salt/Chef/Ansible/Puppet (1/5)
- On sugar, a sweeter Salt: documentation (2/5)
- On sugar, a sweeter Salt: one OpenBSD box (3/5)
- On sugar, a sweeter Salt: multiple systems (4/5)
- On sugar, a sweeter Salt: Annexes (5/5)
Comments
By email, at mathieu.bivert chez: