Remove fetchmail dependency to the databse
This commit is contained in:
@@ -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")
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user