Browse Source

Merge pull request #135 from lcnetdev/feedback

Write feedback message to file if SMTP is not set.
Stefano Cossu 8 months ago
parent
commit
1fe75495f0
3 changed files with 59 additions and 20 deletions
  1. 9 2
      README.md
  2. 29 11
      scriptshifter/__init__.py
  3. 21 7
      scriptshifter/rest_api.py

+ 9 - 2
README.md

@@ -88,11 +88,18 @@ string in a production environment.
 
 `TXL_LOGLEVEL`: Logging level. Use Python notation. The default is `WARN`.
 
-`TXL_SMTP_HOST`: SMTP host to send feedback messages through. If not defined,
-the feedback form will not be shown in the UI.
+`TXL_SMTP_HOST`: SMTP host to send feedback messages through.
 
 `TXL_SMTP_PORT`: Port of the SMTP server. Defaults to `1025`.
 
+`TXL_FEEDBACK_PATH`: if a SMTP server is not available, the feedback message
+may be written to a file under this given path for further processing. The file
+will have a random name and a `.txt` suffix. This option is only available if
+`TXL_SMTP_HOST` is not defined. If neither `TXL_SMTP_HOST` nor
+`TXL_FEEDBACK_PATH` is defined, the feedback form will not be shown in the UI
+and a POST request to the `/feedback` REST endpoint will result in a `501 Not
+Implemented` error.
+
 
 ## Web UI
 

+ 29 - 11
scriptshifter/__init__.py

@@ -22,10 +22,21 @@ SMTP server for sending email. For a dummy server that just echoes the
 messages, run: `python -m smtpd -n -c DebuggingServer localhost:1025`
 and set SMTP_HOST to "localhost".
 
-The default is None in which causes the feedback form to be disabled.
+The default is None which causes the feedback form to be disabled.
 """
 SMTP_HOST = environ.get("TXL_SMTP_HOST")
 
+"""
+Folder path for the serialized feedback form.
+
+The feedback message shall be written to this folder as a text file for further
+processing in case a SMTP server is not available. The file name will have
+a unique random name.
+
+This only takes effect if SMTP_HOST is not set.
+"""
+FEEDBACK_PATH = environ.get("TXL_FEEDBACK_PATH")
+
 with open(path.join(path.dirname(APP_ROOT), "VERSION")) as fh:
     version_info = fh.readlines()
 GIT_TAG = version_info[0].strip()
@@ -39,13 +50,20 @@ logger = logging.getLogger(__name__)
 if not env:
     logger.warn("No .env file found. Assuming env was passed externally.")
 
-if SMTP_HOST:
-    try:
-        SMTP_PORT = int(environ.get("TXL_SMTP_PORT", "1025"))
-    except ValueError:
-        raise SystemError("TXL_SMTP_PORT env var is not an integer.")
-    EMAIL_FROM = environ["TXL_EMAIL_FROM"]
-    EMAIL_TO = environ["TXL_EMAIL_TO"]
-else:
-    logger.warn("No SMTP host defined. Feedback form won't be available.")
-    SMTP_PORT = EMAIL_FROM = EMAIL_TO = None
+EMAIL_FROM = environ["TXL_EMAIL_FROM"]
+EMAIL_TO = environ["TXL_EMAIL_TO"]
+try:
+    SMTP_PORT = int(environ.get("TXL_SMTP_PORT", "1025"))
+except ValueError:
+    raise SystemError("TXL_SMTP_PORT env var is not an integer.")
+
+if not SMTP_HOST:
+    if FEEDBACK_PATH:
+        logger.info(
+            "No SMTP host defined. Feedback messages will be written "
+            f"to files under {FEEDBACK_PATH}.")
+    else:
+        logger.warn(
+                "No SMTP host or feedback message folder defined. "
+                "Feedback form won't be available.")
+        SMTP_PORT = EMAIL_FROM = EMAIL_TO = None

+ 21 - 7
scriptshifter/rest_api.py

@@ -2,9 +2,11 @@ import logging
 
 from base64 import b64encode
 from email.message import EmailMessage
+from email.generator import Generator
 from json import dumps
 from os import environ, urandom
 from smtplib import SMTP
+from tempfile import NamedTemporaryFile
 
 from flask import Flask, jsonify, render_template, request
 from flask_cors import CORS
@@ -12,7 +14,8 @@ from flask_cors import CORS
 from scriptshifter import (
         EMAIL_FROM, EMAIL_TO,
         GIT_COMMIT, GIT_TAG,
-        SMTP_HOST, SMTP_PORT)
+        SMTP_HOST, SMTP_PORT,
+        FEEDBACK_PATH)
 from scriptshifter.exceptions import ApiError
 from scriptshifter.tables import list_tables, get_language
 from scriptshifter.trans import transliterate
@@ -72,7 +75,7 @@ def index():
             "index.html",
             languages=list_tables(),
             version_info=(GIT_TAG, GIT_COMMIT),
-            feedback_form=SMTP_HOST is not None)
+            feedback_form=SMTP_HOST is not None or FEEDBACK_PATH is not None)
 
 
 @app.route("/health", methods=["GET"])
@@ -132,6 +135,9 @@ def feedback():
     """
     Allows users to provide feedback to improve a specific result.
     """
+    if not SMTP_HOST and not FEEDBACK_PATH:
+        return {"message": "Feedback form is not configured."}, 501
+
     t_dir = request.json.get("t_dir", "s2r")
     options = request.json.get("options", {})
     contact = request.json.get("contact")
@@ -155,10 +161,18 @@ def feedback():
         *Notes:*\n
         {request.json['notes']}""")
 
-    # TODO This uses a test SMTP server:
-    # python -m smtpd -n -c DebuggingServer localhost:1025
-    smtp = SMTP(SMTP_HOST, SMTP_PORT)
-    smtp.send_message(msg)
-    smtp.quit()
+    if SMTP_HOST:
+        # TODO This uses a test SMTP server:
+        # python -m smtpd -n -c DebuggingServer localhost:1025
+        smtp = SMTP(SMTP_HOST, SMTP_PORT)
+        smtp.send_message(msg)
+        smtp.quit()
+
+    else:
+        with NamedTemporaryFile(
+                suffix=".txt", dir=FEEDBACK_PATH, delete=False) as fh:
+            gen = Generator(fh)
+            gen.write(msg.as_bytes())
+            logger.info(f"Feedback message generated at {fh.name}.")
 
     return {"message": "Feedback message sent."}