1
0
mirror of https://github.com/Mailu/Mailu.git synced 2025-01-14 02:34:22 +02:00
Mailu/services/fetchmail/fetchmail.py
Dario Ernst 5f4a6cf16b Update fetchmail to selfbuilt 7.0.0-alpha
Fetchmail in alpine is ~5 years old — and doesn’t support current SSL/TLS
variants anymore. This especially leads to our own fetchmail not being able to
pull mail from mailu itself. Since no new fetchmail release is on the horizon,
let’s build the lastest distribution artifact — which strangely is not
6.4.0-snapshot, but 7.0.0-alpha — ourselves.
2019-03-10 10:20:43 +00:00

95 lines
2.9 KiB
Python
Executable File

#!/usr/bin/python3
import time
import os
import tempfile
import shlex
import subprocess
import re
import requests
FETCHMAIL = """
fetchmail -N \
--sslcertck --sslcertpath /etc/ssl/certs \
-f {}
"""
RC_LINE = """
poll "{host}" proto {protocol} port {port}
user "{username}" password "{password}"
is "{user_email}"
smtphost "{smtphost}"
{options}
"""
def extract_host_port(host_and_port, default_port):
host, _, port = re.match('^(.*)(:([0-9]*))?$', host_and_port).groups()
return host, int(port) if port else default_port
def escape_rc_string(arg):
return arg.replace("\\", "\\\\").replace('"', '\\"')
def fetchmail(fetchmailrc):
with tempfile.NamedTemporaryFile() as handler:
handler.write(fetchmailrc.encode("utf8"))
handler.flush()
command = FETCHMAIL.format(shlex.quote(handler.name))
output = subprocess.check_output(command, shell=True)
return output
def run(debug):
fetches = requests.get("http://admin/internal/fetch").json()
smtphost, smtpport = extract_host_port(os.environ.get("HOST_SMTP", "smtp"), None)
if smtpport is None:
smtphostport = smtphost
else:
smtphostport = "%s/%d" % (smtphost, smtpport)
for fetch in fetches:
fetchmailrc = ""
options = "options antispam 501, 504, 550, 553, 554"
options += " sslmode wrapped" if fetch["tls"] else ""
options += " keep" if fetch["keep"] else " fetchall"
fetchmailrc += RC_LINE.format(
user_email=escape_rc_string(fetch["user_email"]),
protocol=fetch["protocol"],
host=escape_rc_string(fetch["host"]),
port=fetch["port"],
smtphost=smtphostport,
username=escape_rc_string(fetch["username"]),
password=escape_rc_string(fetch["password"]),
options=options
)
if debug:
print(fetchmailrc)
try:
print(fetchmail(fetchmailrc))
error_message = ""
except subprocess.CalledProcessError as error:
error_message = error.output.decode("utf8")
# No mail is not an error
if not error_message.startswith("fetchmail: No mail"):
print(error_message)
user_info = "for %s at %s" % (fetch["user_email"], fetch["host"])
# Number of messages seen is not a error as well
if ("messages" in error_message and
"(seen " in error_message and
user_info in error_message):
print(error_message)
finally:
requests.post("http://admin/internal/fetch/{}".format(fetch["id"]),
json=error_message.split("\n")[0]
)
if __name__ == "__main__":
while True:
time.sleep(int(os.environ.get("FETCHMAIL_DELAY", 60)))
run(os.environ.get("DEBUG", None) == "True")