Implement configurable STATE_DIR for state files
Move processed_message_ids.txt and last_run.txt to STATE_DIR, configurable via .env. Install script creates ./state by default. Changes: - Add STATE_DIR to .env.example and config loading - Update EmailForwarder to use os.path.join for file paths - Add os.makedirs for state dir creation - Update README with STATE_DIR option
This commit is contained in:
parent
4adce1079f
commit
a32f79980e
3 changed files with 13 additions and 10 deletions
|
|
@ -7,6 +7,7 @@ DEST_PORT=993
|
||||||
DEST_USER=your@mxroute.com
|
DEST_USER=your@mxroute.com
|
||||||
DEST_PASS=password
|
DEST_PASS=password
|
||||||
FOLDERS=INBOX,Sent
|
FOLDERS=INBOX,Sent
|
||||||
|
STATE_DIR=./state
|
||||||
DRY_RUN=false
|
DRY_RUN=false
|
||||||
UPTIME_SUCCESS_URL=https://your-uptime-instance.com/api/push/your-token?status=up&msg=OK&ping=
|
UPTIME_SUCCESS_URL=https://your-uptime-instance.com/api/push/your-token?status=up&msg=OK&ping=
|
||||||
UPTIME_FAIL_URL=https://your-uptime-instance.com/api/push/your-token?status=down&msg=Failed
|
UPTIME_FAIL_URL=https://your-uptime-instance.com/api/push/your-token?status=down&msg=Failed
|
||||||
|
|
@ -19,6 +19,7 @@ This will set up the virtual environment, systemd services, and provide post-ins
|
||||||
- `DEST_USER`: Destination email/username
|
- `DEST_USER`: Destination email/username
|
||||||
- `DEST_PASS`: Destination password
|
- `DEST_PASS`: Destination password
|
||||||
- `FOLDERS`: Folders to sync (default "INBOX,Sent"; use "all" for all folders or comma-separated list)
|
- `FOLDERS`: Folders to sync (default "INBOX,Sent"; use "all" for all folders or comma-separated list)
|
||||||
|
- `STATE_DIR`: Directory for state files (default "./state")
|
||||||
- `DRY_RUN`: Set to `true` for testing without forwarding (default false)
|
- `DRY_RUN`: Set to `true` for testing without forwarding (default false)
|
||||||
- `UPTIME_SUCCESS_URL`: URL for success ping
|
- `UPTIME_SUCCESS_URL`: URL for success ping
|
||||||
- `UPTIME_FAIL_URL`: URL for failure ping
|
- `UPTIME_FAIL_URL`: URL for failure ping
|
||||||
|
|
|
||||||
|
|
@ -126,6 +126,10 @@ class EmailForwarder:
|
||||||
|
|
||||||
def __init__(self, config: dict):
|
def __init__(self, config: dict):
|
||||||
self.config = config
|
self.config = config
|
||||||
|
self.state_dir = config["state_dir"]
|
||||||
|
os.makedirs(self.state_dir, exist_ok=True)
|
||||||
|
self.processed_file = os.path.join(self.state_dir, "processed_message_ids.txt")
|
||||||
|
self.last_run_file = os.path.join(self.state_dir, "last_run.txt")
|
||||||
self.source = SourceImap(
|
self.source = SourceImap(
|
||||||
config["source_host"],
|
config["source_host"],
|
||||||
config["source_port"],
|
config["source_port"],
|
||||||
|
|
@ -144,23 +148,21 @@ class EmailForwarder:
|
||||||
|
|
||||||
def load_state(self):
|
def load_state(self):
|
||||||
"""Load last run and processed IDs."""
|
"""Load last run and processed IDs."""
|
||||||
last_run_file = self.config["last_run_file"]
|
if os.path.exists(self.last_run_file):
|
||||||
if os.path.exists(last_run_file):
|
with open(self.last_run_file) as f:
|
||||||
with open(last_run_file) as f:
|
|
||||||
last_run_str = f.read().strip()
|
last_run_str = f.read().strip()
|
||||||
self.last_run = datetime.fromisoformat(last_run_str)
|
self.last_run = datetime.fromisoformat(last_run_str)
|
||||||
else:
|
else:
|
||||||
self.last_run = datetime.now(timezone.utc)
|
self.last_run = datetime.now(timezone.utc)
|
||||||
|
|
||||||
processed_file = self.config["processed_file"]
|
if os.path.exists(self.processed_file):
|
||||||
if os.path.exists(processed_file):
|
with open(self.processed_file, "r") as f:
|
||||||
with open(processed_file, "r") as f:
|
|
||||||
self.processed_ids = set(filter(None, (line.strip() for line in f)))
|
self.processed_ids = set(filter(None, (line.strip() for line in f)))
|
||||||
|
|
||||||
def save_state(self):
|
def save_state(self):
|
||||||
"""Save last run and processed IDs."""
|
"""Save last run and processed IDs."""
|
||||||
if not self.dry_run:
|
if not self.dry_run:
|
||||||
with open(self.config["last_run_file"], "w") as f:
|
with open(self.last_run_file, "w") as f:
|
||||||
f.write(datetime.now(timezone.utc).isoformat())
|
f.write(datetime.now(timezone.utc).isoformat())
|
||||||
|
|
||||||
def sync_all_folders(self):
|
def sync_all_folders(self):
|
||||||
|
|
@ -209,7 +211,7 @@ class EmailForwarder:
|
||||||
if not self.dry_run:
|
if not self.dry_run:
|
||||||
self.dest.append_email(folder, raw_msg)
|
self.dest.append_email(folder, raw_msg)
|
||||||
self.processed_ids.add(msg_id)
|
self.processed_ids.add(msg_id)
|
||||||
with open(self.config["processed_file"], "a") as f:
|
with open(self.processed_file, "a") as f:
|
||||||
f.write(msg_id + "\n")
|
f.write(msg_id + "\n")
|
||||||
forwarded += 1
|
forwarded += 1
|
||||||
logging.info(f"Forwarded {msg_id} from {folder}")
|
logging.info(f"Forwarded {msg_id} from {folder}")
|
||||||
|
|
@ -239,8 +241,7 @@ def load_config():
|
||||||
"dest_user": os.getenv("DEST_USER"),
|
"dest_user": os.getenv("DEST_USER"),
|
||||||
"dest_pass": os.getenv("DEST_PASS"),
|
"dest_pass": os.getenv("DEST_PASS"),
|
||||||
"folders": os.getenv("FOLDERS", "INBOX"),
|
"folders": os.getenv("FOLDERS", "INBOX"),
|
||||||
"processed_file": "processed_message_ids.txt",
|
"state_dir": os.getenv("STATE_DIR", "./state"),
|
||||||
"last_run_file": "last_run.txt",
|
|
||||||
"dry_run": os.getenv("DRY_RUN", "false").lower() == "true",
|
"dry_run": os.getenv("DRY_RUN", "false").lower() == "true",
|
||||||
}
|
}
|
||||||
# Validate required
|
# Validate required
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue