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:
Jeena 2026-01-04 19:45:48 +09:00
parent 4adce1079f
commit a32f79980e
3 changed files with 13 additions and 10 deletions

View file

@ -126,6 +126,10 @@ class EmailForwarder:
def __init__(self, config: dict):
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(
config["source_host"],
config["source_port"],
@ -144,23 +148,21 @@ class EmailForwarder:
def load_state(self):
"""Load last run and processed IDs."""
last_run_file = self.config["last_run_file"]
if os.path.exists(last_run_file):
with open(last_run_file) as f:
if os.path.exists(self.last_run_file):
with open(self.last_run_file) as f:
last_run_str = f.read().strip()
self.last_run = datetime.fromisoformat(last_run_str)
else:
self.last_run = datetime.now(timezone.utc)
processed_file = self.config["processed_file"]
if os.path.exists(processed_file):
with open(processed_file, "r") as f:
if os.path.exists(self.processed_file):
with open(self.processed_file, "r") as f:
self.processed_ids = set(filter(None, (line.strip() for line in f)))
def save_state(self):
"""Save last run and processed IDs."""
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())
def sync_all_folders(self):
@ -209,7 +211,7 @@ class EmailForwarder:
if not self.dry_run:
self.dest.append_email(folder, raw_msg)
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")
forwarded += 1
logging.info(f"Forwarded {msg_id} from {folder}")
@ -239,8 +241,7 @@ def load_config():
"dest_user": os.getenv("DEST_USER"),
"dest_pass": os.getenv("DEST_PASS"),
"folders": os.getenv("FOLDERS", "INBOX"),
"processed_file": "processed_message_ids.txt",
"last_run_file": "last_run.txt",
"state_dir": os.getenv("STATE_DIR", "./state"),
"dry_run": os.getenv("DRY_RUN", "false").lower() == "true",
}
# Validate required