update documentation

This commit is contained in:
Jonas Heinrich 2025-08-18 14:57:49 +02:00
parent a1ea6e4609
commit e924bf1db6
4 changed files with 52 additions and 28 deletions

View file

@ -1,6 +1,7 @@
# eintopf-radar-sync
Small script to sync events of an radar.quad.net group to a specific Eintopf
instance.
# mail-quota-warning
Small script to check a configured list of IMAP accounts for mailbox quota and send
a warning mail in case a specific threashold is exceeded.
## Installation
@ -11,7 +12,7 @@ Add the module to your `flake.nix`:
```nix
{
inputs = {
eintopf-radar-sync.url = "git+https://git.project-insanity.org/onny/eintopf-radar-sync.git";
mail-quota-warning.url = "git+https://git.project-insanity.org/onny/mail-quota-warning.git";
[...]
};
@ -21,12 +22,12 @@ Add the module to your `flake.nix`:
system = "x86_64-linux";
specialArgs.inputs = inputs;
modules = [
inputs.eintopf-radar-sync.nixosModule
inputs.mail-quota-warning.nixosModule
({ pkgs, ... }:{
nixpkgs.overlays = [
inputs.eintopf-radar-sync.overlay
inputs.mail-quota-warning.overlay
];
})
@ -42,30 +43,26 @@ Add the module to your `flake.nix`:
Add this to your `configuration.nix` file
```nix
environment.etc."eintopf-radar-sync-secrets".text = ''
environment.etc."eintopf-radar-sync-secrets.yml".text = ''
EINTOPF_AUTHORIZATION_TOKEN=foobar23
'';
services.eintopf-radar-sync = {
services.mail-quota-warning = {
enable = true;
settings = {
EINTOPF_URL = "https://karlsunruh.eintopf.info";
RADAR_GROUP_ID = "436012";
};
secrets = [ /etc/eintopf-radar-sync-secrets ];
secrets = [ /etc/mail-quota-warning-secrets.yml ];
};
```
Replace setting variables according to your setup.
Get the authorization token through login request in the Eintopf
Swagger api interface, for example
https://karlsunruh.project-insanity.org/api/v1/swagger#/auth/login
### From source
```
cd eintopf-radar-sync
cd mail-quota-warning
nix develop
export EINTOPF_URL = "https://karlsunruh.eintopf.info"
export EINTOPF_AUTHORIZATION_TOKEN = "secret key"

View file

@ -1,5 +1,6 @@
check_interval_days: 7 # Minimum days between warnings for same account
quota_warning_threshold_percent: 80
working_dir: /var/lib/mail-quota-warning
accounts:
- name: Sales

View file

@ -5,30 +5,55 @@ import yaml
import json
import os
import threading
import argparse
from email.mime.text import MIMEText
from datetime import datetime, timedelta
CONFIG_FILE = "config.yml"
STATE_FILE = "quota_state.json"
# TODO:
# - make working dir configurable for state file
# - optional read config.yml from command line argument
# - note in warning mail that it exceeded XX% quota threashold
# - fix list summary mark all accounts which are critical
# TODO
# - load config from file
# - override with env vars
def load_config():
with open(CONFIG_FILE, "r") as f:
def get_config_value(config, env_var, config_key, default_value, value_type=int):
"""Get configuration value from environment variable or config file, with fallback to default"""
env_value = os.environ.get(env_var)
if env_value is not None:
try:
return value_type(env_value)
except ValueError:
log(f"Invalid value for {env_var}: {env_value}, using config/default")
return config.get(config_key, default_value)
def parse_args():
parser = argparse.ArgumentParser(description="Email quota monitoring script")
parser.add_argument(
"--config",
default="config.yml",
help="Path to config.yml file (default: config.yml in current directory)"
)
return parser.parse_args()
def load_config(config_file):
if not os.path.exists(config_file):
log(f"Config file not found: {config_file}")
raise FileNotFoundError(f"Config file not found: {config_file}")
with open(config_file, "r") as f:
return yaml.safe_load(f)
def load_state():
if os.path.exists(STATE_FILE):
with open(STATE_FILE, "r") as f:
state_file = "quota_state.json"
if os.path.exists(state_file):
with open(state_file, "r") as f:
return json.load(f)
return {}
def save_state(state):
with open(STATE_FILE, "w") as f:
state_file = "quota_state.json"
with open(state_file, "w") as f:
json.dump(state, f, indent=2)
def log(msg):
@ -235,7 +260,8 @@ def check_account_quota(account, config, state, threshold, interval_days):
return None, quota_info
def main():
config = load_config()
args = parse_args()
config = load_config(args.config)
state = load_state()
interval_days = config.get("check_interval_days", 7)
threshold = config.get("quota_warning_threshold_percent", 80)

View file

@ -21,14 +21,14 @@ in
type = lib.types.submodule {
freeformType = with lib.types; attrsOf types.str;
options = {
EINTOPF_URL = lib.mkOption {
CHECK_INTERVAL_DAYS = lib.mkOption {
default = "";
type = lib.types.str;
description = ''
Base URL of the target Eintopf host.
'';
};
RADAR_GROUP_ID = lib.mkOption {
QUOTA_WARNING_THRESHOLD_PERCENT = lib.mkOption {
default = "";
type = lib.types.str;
description = ''
@ -49,7 +49,7 @@ in
'';
};
secrets = lib.mkOption {
secretFile = lib.mkOption {
type = with lib.types; listOf path;
description = ''
A list of files containing the various secrets. Should be in the