added lmtp: prefix and documentation

master
Alexander Graf 3 years ago
parent b55b53b781
commit a1fd44fced

@ -36,15 +36,23 @@ def postfix_alias_map(alias):
def postfix_transport(email): def postfix_transport(email):
if email == '*' or re.match("(^|.*@)\[.*\]$", email): if email == '*' or re.match("(^|.*@)\[.*\]$", email):
return flask.abort(404) return flask.abort(404)
localpart, domain_name = models.Email.resolve_domain(email) _, domain_name = models.Email.resolve_domain(email)
relay = models.Relay.query.get(domain_name) or flask.abort(404) relay = models.Relay.query.get(domain_name) or flask.abort(404)
target = relay.smtp.lower() target = relay.smtp.lower()
port = None port = None
if use_mx := target.startswith('mx:'): use_lmtp = False
use_mx = False
# strip prefixes mx: and lmtp:
if target.startswith('mx:'):
target = target[3:] target = target[3:]
use_mx = True
elif target.startswith('lmtp:'):
target = target[5:]
use_lmtp = True
# split host:port or [host]:port
if target.startswith('['): if target.startswith('['):
if use_mx or ']' not in target: if use_mx or ']' not in target:
# invalid target (mx: and []) # invalid target (mx: and [] or missing ])
flask.abort(400) flask.abort(400)
host, rest = target[1:].split(']', 1) host, rest = target[1:].split(']', 1)
if rest.startswith(':'): if rest.startswith(':'):
@ -57,29 +65,38 @@ def postfix_transport(email):
host, port = target.rsplit(':', 1) host, port = target.rsplit(':', 1)
else: else:
host = target host = target
# default for empty host part is mx:domain
if not host: if not host:
host = relay.name.lower() if not use_lmtp:
use_mx = True host = relay.name.lower()
use_mx = True
else:
# lmtp: needs a host part
flask.abort(400)
# detect ipv6 address or encode host
if ':' in host: if ':' in host:
host = f'ipv6:{host}' host = f'ipv6:{host}'
else: else:
try: try:
host = idna.encode(host).decode('ascii') host = idna.encode(host).decode('ascii')
except idna.IDNAError: except idna.IDNAError:
# invalid target (fqdn not encodable) # invalid host (fqdn not encodable)
flask.abort(400) flask.abort(400)
# validate port
if port is not None: if port is not None:
try: try:
port = int(port, 10) port = int(port, 10)
if port == 25:
port = None
except ValueError: except ValueError:
# invalid target (port should be numeric) # invalid port (should be numeric)
flask.abort(400) flask.abort(400)
if not use_mx: # create transport
transport = 'lmtp' if use_lmtp else 'smtp'
# use [] when not using MX lookups or host is an ipv6 address
if host.startswith('ipv6:') or (not use_lmtp and not use_mx):
host = f'[{host}]' host = f'[{host}]'
# create port suffix
port = '' if port is None else f':{port}' port = '' if port is None else f':{port}'
return flask.jsonify(f'smtp:{host}{port}') return flask.jsonify(f'{transport}:{host}{port}')
@internal.route("/postfix/recipient/map/<path:recipient>") @internal.route("/postfix/recipient/map/<path:recipient>")

@ -215,22 +215,29 @@ On the new relayed domain page the following options can be entered for a new re
* Relayed domain name. The domain name that is relayed. Email messages addressed to this domain (To: John@example.com), will be forwarded to this domain. * Relayed domain name. The domain name that is relayed. Email messages addressed to this domain (To: John@example.com), will be forwarded to this domain.
No authentication is required. No authentication is required.
* Remote host (optional). The SMPT server that will be used for relaying the email message. * Remote host (optional). The host that will be used for relaying the email message.
When this field is blank, the Mailu server will directly send the email message to the relayed domain. When this field is blank, the Mailu server will directly send the email message to the mail server of the relayed domain.
As value can be entered either a hostname or IP address of the SMPT server. When a remote host is specified it can be prefixed by ``mx:`` or ``lmtp:`` and followed by a port number: ``:port``).
By default port 25 is used. To use a different port append ":port number" to the Remote Host. For example:
123.45.67.90:2525. ================ ===================================== =========================
Remote host Description postfix transport:nexthop
================ ===================================== =========================
empty use MX of relay domain smtp:domain
:port use MX of relay domain and use port smtp:domain:port
target resolve A/AAAA of target smtp:[target]
target:port resolve A/AAAA of target and use port smtp:[target]:port
mx:target resolve MX of target smtp:target
mx:target:port resolve MX of target and use port smtp:target:port
lmtp:target resolve A/AAAA of target lmtp:target
lmtp:target:port resolve A/AAAA of target and use port lmtp:target:port
================ ===================================== =========================
`target` can also be an IPv4 or IPv6 address (an IPv6 address must be enclosed in []: ``[2001:DB8::]``).
* Comment. A text field where a comment can be entered to describe the entry. * Comment. A text field where a comment can be entered to describe the entry.
Changes are effective immediately after clicking the Save button. Changes are effective immediately after clicking the Save button.
NOTE: Due to bug `1588`_ email messages fail to be relayed if no Remote Host is configured.
As a workaround the HOSTNAME or IP Address of the SMPT server of the relayed domain can be entered as Remote Host.
Please note that no MX lookup is performed when entering a hostname as Remote Host. You can use the MX lookup on mxtoolbox.com to find the hostname and IP Address of the SMTP server.
.. _`1588`: https://github.com/Mailu/Mailu/issues/1588
Antispam Antispam
-------- --------

Loading…
Cancel
Save