Remove fetchmail dependency to the databse

master
kaiyou 6 years ago
parent 43b6547e1c
commit f9c6c98180

@ -6,6 +6,7 @@ import flask
import flask_login import flask_login
import base64 import base64
import urllib import urllib
import datetime
@internal.route("/auth/email") @internal.route("/auth/email")
@ -128,3 +129,30 @@ def dovecot_sieve_data(user_email):
user = models.User.query.get(user_email) or flask.abort(404) user = models.User.query.get(user_email) or flask.abort(404)
return flask.jsonify(flask.render_template("default.sieve", user=user)) return flask.jsonify(flask.render_template("default.sieve", user=user))
@internal.route("/fetch")
def fetch_list():
return flask.jsonify([
{
"id": fetch.id,
"tls": fetch.tls,
"keep": fetch.keep,
"user_email": fetch.user_email,
"protocol": fetch.protocol,
"host": fetch.host,
"port": fetch.port,
"username": fetch.username,
"password": fetch.password
} for fetch in models.Fetch.query.all()
])
@internal.route("/fetch/<fetch_id>", methods=["POST"])
def fetch_done(fetch_id):
fetch = models.Fetch.query.get(fetch_id) or flask.abort(404)
fetch.last_check = datetime.datetime.now()
fetch.error_message = str(flask.request.get_json())
db.session.add(fetch)
db.session.commit()
return ""

@ -102,5 +102,3 @@ services:
image: mailu/fetchmail:$VERSION image: mailu/fetchmail:$VERSION
restart: always restart: always
env_file: .env env_file: .env
volumes:
- "$ROOT/data:/data"

@ -1,7 +1,9 @@
FROM python:alpine FROM python:3-alpine
RUN apk add --no-cache fetchmail ca-certificates RUN apk add --no-cache fetchmail ca-certificates \
&& pip install requests
COPY fetchmail.py /fetchmail.py COPY fetchmail.py /fetchmail.py
USER fetchmail
CMD ["/fetchmail.py"] CMD ["/fetchmail.py"]

@ -1,12 +1,12 @@
#!/usr/bin/env python #!/usr/bin/env python
import sqlite3
import time import time
import os import os
import tempfile import tempfile
import shlex import shlex
import subprocess import subprocess
import re import re
import requests
FETCHMAIL = """ FETCHMAIL = """
@ -15,6 +15,7 @@ fetchmail -N \
-f {} -f {}
""" """
RC_LINE = """ RC_LINE = """
poll "{host}" proto {protocol} port {port} poll "{host}" proto {protocol} port {port}
user "{username}" password "{password}" user "{username}" password "{password}"
@ -24,10 +25,12 @@ poll "{host}" proto {protocol} port {port}
sslproto 'AUTO' sslproto 'AUTO'
""" """
def extract_host_port(host_and_port, default_port): def extract_host_port(host_and_port, default_port):
host, _, port = re.match('^(.*)(:([0-9]*))?$', host_and_port).groups() host, _, port = re.match('^(.*)(:([0-9]*))?$', host_and_port).groups()
return host, int(port) if port else default_port return host, int(port) if port else default_port
def escape_rc_string(arg): def escape_rc_string(arg):
return arg.replace("\\", "\\\\").replace('"', '\\"') return arg.replace("\\", "\\\\").replace('"', '\\"')
@ -41,30 +44,26 @@ def fetchmail(fetchmailrc):
return output return output
def run(connection, cursor, debug): def run(debug):
cursor.execute(""" fetches = requests.get("http://admin/internal/fetch").json()
SELECT user_email, protocol, host, port, tls, username, password, keep
FROM fetch
""")
smtphost, smtpport = extract_host_port(os.environ.get("HOST_SMTP", "smtp"), None) smtphost, smtpport = extract_host_port(os.environ.get("HOST_SMTP", "smtp"), None)
if smtpport is None: if smtpport is None:
smtphostport = smtphost smtphostport = smtphost
else: else:
smtphostport = "%s/%d" % (smtphost, smtpport) smtphostport = "%s/%d" % (smtphost, smtpport)
for line in cursor.fetchall(): for fetch in fetches:
fetchmailrc = "" fetchmailrc = ""
user_email, protocol, host, port, tls, username, password, keep = line
options = "options antispam 501, 504, 550, 553, 554" options = "options antispam 501, 504, 550, 553, 554"
options += " ssl" if tls else "" options += " ssl" if fetch["tls"] else ""
options += " keep" if keep else " fetchall" options += " keep" if fetch["keep"] else " fetchall"
fetchmailrc += RC_LINE.format( fetchmailrc += RC_LINE.format(
user_email=escape_rc_string(user_email), user_email=escape_rc_string(fetch["user_email"]),
protocol=protocol, protocol=fetch["protocol"],
host=escape_rc_string(host), host=escape_rc_string(fetch["host"]),
port=port, port=fetch["port"],
smtphost=smtphostport, smtphost=smtphostport,
username=escape_rc_string(username), username=escape_rc_string(fetch["username"]),
password=escape_rc_string(password), password=escape_rc_string(fetch["password"]),
options=options options=options
) )
if debug: if debug:
@ -77,26 +76,20 @@ def run(connection, cursor, debug):
# No mail is not an error # No mail is not an error
if not error_message.startswith("fetchmail: No mail"): if not error_message.startswith("fetchmail: No mail"):
print(error_message) print(error_message)
user_info = "for %s at %s" % (user_email, host) user_info = "for %s at %s" % (fetch["user_email"], fetch["host"])
# Number of messages seen is not a error as well # Number of messages seen is not a error as well
if ("messages" in error_message and if ("messages" in error_message and
"(seen " in error_message and "(seen " in error_message and
user_info in error_message): user_info in error_message):
print(error_message) print(error_message)
finally: finally:
cursor.execute(""" requests.post("http://admin/internal/fetch/{}".format(fetch["id"]),
UPDATE fetch SET error=?, last_check=datetime('now') json=error_message.split("\n")[0]
WHERE user_email=? )
""", (error_message.split("\n")[0], user_email))
connection.commit()
if __name__ == "__main__": if __name__ == "__main__":
debug = os.environ.get("DEBUG", None) == "True"
db_path = os.environ.get("DB_PATH", "/data/main.db")
connection = sqlite3.connect(db_path)
while True: while True:
cursor = connection.cursor()
run(connection, cursor, debug)
cursor.close()
time.sleep(int(os.environ.get("FETCHMAIL_DELAY", 60))) time.sleep(int(os.environ.get("FETCHMAIL_DELAY", 60)))
run(os.environ.get("DEBUG", None) == "True")

Loading…
Cancel
Save