Rename project to Mail-Graveyard

This commit is contained in:
DonVoo 2026-07-05 22:30:32 +02:00
parent ba53f8bb19
commit bb2bcb0576
20 changed files with 55 additions and 55 deletions

4
.gitignore vendored
View file

@ -6,8 +6,8 @@ config.json
# Lokales Cold Backup (mbox) nicht versionieren # Lokales Cold Backup (mbox) nicht versionieren
backup/ backup/
/emailforwarder /mail-graveyard
/emailforwarder.exe /mail-graveyard.exe
# Bun / Frontend # Bun / Frontend
frontend-js/node_modules/ frontend-js/node_modules/

View file

@ -1,4 +1,4 @@
# Codex-Briefing — Email-Forwarder # Codex-Briefing — Mail-Graveyard
Du baust ein Go-Single-Binary im Hausstil (wie WatchDove): `main.go` als Du baust ein Go-Single-Binary im Hausstil (wie WatchDove): `main.go` als
Orchestrator, nummerierte `backend/NN-*.go`, Server-gerendertes HTML + HTMX, Orchestrator, nummerierte `backend/NN-*.go`, Server-gerendertes HTML + HTMX,

View file

@ -5,7 +5,7 @@ lesen, dann NUR den Durchstich bauen (nicht mehr).
--- ---
Baue den **Durchstich** des Email-Forwarder (Go-Single-Binary, Hausstil steht als Baue den **Durchstich** des Mail-Graveyard (Go-Single-Binary, Hausstil steht als
Stub-Gerüst). Ziel: **ein Konto, nur den Posteingang, sauber und wiederholbar Stub-Gerüst). Ziel: **ein Konto, nur den Posteingang, sauber und wiederholbar
umziehen.** Lies zuerst `Codex-Briefing.md` und `Projektbeschreibung.md`; die 6 umziehen.** Lies zuerst `Codex-Briefing.md` und `Projektbeschreibung.md`; die 6
harten Regeln sind bindend. harten Regeln sind bindend.
@ -29,6 +29,6 @@ Bewusst NOCH NICHT: Web-CRUD, Viewer, Weiterleiten, alle Ordner rekursiv,
Rollen-Mapping (11-folders.go), `--watch`, POP3. Nur INBOX, nur CLI. Rollen-Mapping (11-folders.go), `--watch`, POP3. Nur INBOX, nur CLI.
**Abnahme:** Konto per SQL/Seed eintragen (Klartext-IMAP-Quelle testen!), **Abnahme:** Konto per SQL/Seed eintragen (Klartext-IMAP-Quelle testen!),
`./emailforwarder --run test` zweimal laufen lassen → beim zweiten Mal werden `./mail-graveyard --run test` zweimal laufen lassen → beim zweiten Mal werden
0 Mails kopiert (Idempotenz), Ziel-INBOX und lokale mbox enthalten dieselben 0 Mails kopiert (Idempotenz), Ziel-INBOX und lokale mbox enthalten dieselben
Mails mit erhaltenen Flags und Original-Datum. Mails mit erhaltenen Flags und Original-Datum.

View file

@ -1,4 +1,4 @@
# Email-Forwarder — bauen & benutzen # Mail-Graveyard — bauen & benutzen
## 1. Bauen ## 1. Bauen
@ -7,7 +7,7 @@
``` ```
Holt htmx ins `frontend-js/dist`, macht `go mod tidy` und baut ein statisches Holt htmx ins `frontend-js/dist`, macht `go mod tidy` und baut ein statisches
Binary für Linux **und** Windows (`emailforwarder` / `emailforwarder.exe`). Binary für Linux **und** Windows (`mail-graveyard` / `mail-graveyard.exe`).
## 2. Konfig ## 2. Konfig
@ -23,7 +23,7 @@ an, nicht hier.
## 3. Starten (Web) ## 3. Starten (Web)
```sh ```sh
./emailforwarder # lauscht auf 127.0.0.1:8087 ./mail-graveyard # lauscht auf 127.0.0.1:8087
``` ```
Browser auf `http://127.0.0.1:8087`, mit Admin-Login aus `config.json`. Browser auf `http://127.0.0.1:8087`, mit Admin-Login aus `config.json`.
@ -37,8 +37,8 @@ Logins), Reiter **Umzug** (starten + Fortschritt), Reiter **Betrachten**
Ohne Web, z. B. als Cronjob oder Dauerlauf im Umzugsfenster: Ohne Web, z. B. als Cronjob oder Dauerlauf im Umzugsfenster:
```sh ```sh
./emailforwarder --run all # einmalig alle Konten (Delta) ./mail-graveyard --run all # einmalig alle Konten (Delta)
./emailforwarder --run dr-gold --watch # ein Konto, Delta-Schleife bis Stop ./mail-graveyard --run dr-gold --watch # ein Konto, Delta-Schleife bis Stop
``` ```
Dank Message-ID-Cache kopiert jeder Lauf nur Neues — beliebig oft wiederholbar Dank Message-ID-Cache kopiert jeder Lauf nur Neues — beliebig oft wiederholbar

View file

@ -1,4 +1,4 @@
# Email-Forwarder # Mail-Graveyard
Kleines Go-Single-Binary für **Postfach-Umzüge zwischen Hosts**. Holt Mails aus Kleines Go-Single-Binary für **Postfach-Umzüge zwischen Hosts**. Holt Mails aus
Quell-Konten (IMAP, POP3 nur als Notnagel) und spielt sie **1:1 in Ziel-Konten Quell-Konten (IMAP, POP3 nur als Notnagel) und spielt sie **1:1 in Ziel-Konten
@ -42,6 +42,6 @@ das zum Umzugszeitpunkt gilt.
## Bedienung ## Bedienung
- **Web (Default):** `./emailforwarder` → Browser auf `127.0.0.1:8087`. - **Web (Default):** `./mail-graveyard` → Browser auf `127.0.0.1:8087`.
- **CLI (Cronjob/Cutover):** `./emailforwarder --run all` (einmalig) oder - **CLI (Cronjob/Cutover):** `./mail-graveyard --run all` (einmalig) oder
`./emailforwarder --run dr-gold --watch` (Delta-Schleife). `./mail-graveyard --run dr-gold --watch` (Delta-Schleife).

View file

@ -38,12 +38,12 @@ func renderShell(w http.ResponseWriter, active, readingPane string) {
w.Header().Set("Content-Type", "text/html; charset=utf-8") w.Header().Set("Content-Type", "text/html; charset=utf-8")
fmt.Fprintf(w, `<!doctype html><html lang="de"><head><meta charset="utf-8"> fmt.Fprintf(w, `<!doctype html><html lang="de"><head><meta charset="utf-8">
<meta name="viewport" content="width=device-width,initial-scale=1"> <meta name="viewport" content="width=device-width,initial-scale=1">
<title>Email-Forwarder</title> <title>Mail-Graveyard</title>
<link rel="stylesheet" href="/static/style.css"> <link rel="stylesheet" href="/static/style.css">
<script src="/static/htmx.min.js"></script></head> <script src="/static/htmx.min.js"></script></head>
<body class="ol2013"> <body class="ol2013">
<header class="ribbon"> <header class="ribbon">
<div class="ribbon-title">Email-Forwarder</div> <div class="ribbon-title">Mail-Graveyard</div>
<nav class="ribbon-tabs"> <nav class="ribbon-tabs">
<a class="tab %s" href="/">Umzug</a> <a class="tab %s" href="/">Umzug</a>
<a class="tab" href="/accounts">Postf&auml;cher</a> <a class="tab" href="/accounts">Postf&auml;cher</a>

View file

@ -53,7 +53,7 @@ type Account struct {
// total, done, errors, state) im Browser. // total, done, errors, state) im Browser.
func ConnectDB() error { func ConnectDB() error {
if Cfg.DBPath == "" { if Cfg.DBPath == "" {
Cfg.DBPath = "emailforwarder.db" Cfg.DBPath = "mail-graveyard.db"
} }
db, err := sql.Open("sqlite", Cfg.DBPath) db, err := sql.Open("sqlite", Cfg.DBPath)
if err != nil { if err != nil {

View file

@ -12,6 +12,6 @@ go mod tidy
# Statisches Binary. Der Umzug laeuft dort, wo Netz zu beiden Providern besteht # Statisches Binary. Der Umzug laeuft dort, wo Netz zu beiden Providern besteht
# (Workstation oder DietPi-NB) -> Linux + Windows bauen. # (Workstation oder DietPi-NB) -> Linux + Windows bauen.
CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -trimpath -ldflags "-s -w" -o emailforwarder . CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -trimpath -ldflags "-s -w" -o mail-graveyard .
CGO_ENABLED=0 GOOS=windows GOARCH=amd64 go build -trimpath -ldflags "-s -w" -o emailforwarder.exe . CGO_ENABLED=0 GOOS=windows GOARCH=amd64 go build -trimpath -ldflags "-s -w" -o mail-graveyard.exe .
echo "built ./emailforwarder und ./emailforwarder.exe" echo "built ./mail-graveyard und ./mail-graveyard.exe"

View file

@ -3,7 +3,7 @@
"port": "8087", "port": "8087",
"admin_user": "vAdmin@golddata.eu", "admin_user": "vAdmin@golddata.eu",
"admin_pass": "CHANGE-ME-lokal", "admin_pass": "CHANGE-ME-lokal",
"db_path": "emailforwarder.db", "db_path": "mail-graveyard.db",
"mbox_root": "./backup", "mbox_root": "./backup",
"forward_smtp": { "forward_smtp": {
"host": "", "host": "",

View file

@ -1,13 +0,0 @@
SERVICE_NAME=Email-Forwarder
POD_NAME=email-forwarder-pod
CONTAINER_NAME=email-forwarder
WATCH_CONTAINER_NAME=email-forwarder-watch
IMAGE_NAME=localhost/email-forwarder:test
NETWORK=base-net
HOST_BIND=127.0.0.1
APP_PORT=8087
WATCH_ACCOUNT=codex-to-vdevop03
WATCH_INTERVAL=60s
BUILD_SRC=/mnt/DATA/Build/Email-Forwarder
DEVOP_CONTAINER=DevOp-Pod-build
APP_DIR=/mnt/DATA/Containers/Test-Container/Email-Forwarder-Pod

View file

@ -12,17 +12,17 @@ if [ ! -d "$BUILD_SRC" ]; then
exit 2 exit 2
fi fi
podman exec -w /work/Email-Forwarder "$DEVOP_CONTAINER" bash -lc ' podman exec -w /work/Mail-Graveyard "$DEVOP_CONTAINER" bash -lc '
set -euo pipefail set -euo pipefail
mkdir -p frontend-js/dist mkdir -p frontend-js/dist
if [ ! -f frontend-js/dist/htmx.min.js ]; then if [ ! -f frontend-js/dist/htmx.min.js ]; then
curl -fsSL https://unpkg.com/htmx.org@1.9.12/dist/htmx.min.js -o frontend-js/dist/htmx.min.js curl -fsSL https://unpkg.com/htmx.org@1.9.12/dist/htmx.min.js -o frontend-js/dist/htmx.min.js
fi fi
go mod tidy go mod tidy
CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -trimpath -ldflags "-s -w" -o emailforwarder . CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -trimpath -ldflags "-s -w" -o mail-graveyard .
' '
install -m0755 "$BUILD_SRC/emailforwarder" "$APP_DIR/build/emailforwarder" install -m0755 "$BUILD_SRC/mail-graveyard" "$APP_DIR/build/mail-graveyard"
if [ ! -f "$APP_DIR/config.json" ]; then if [ ! -f "$APP_DIR/config.json" ]; then
install -m0644 "$APP_DIR/config.json.example" "$APP_DIR/config.json" install -m0644 "$APP_DIR/config.json.example" "$APP_DIR/config.json"
fi fi
@ -31,7 +31,7 @@ install -m0644 "$APP_DIR/Containerfile" "$APP_DIR/build/Containerfile"
podman build -t "$IMAGE_NAME" -f "$APP_DIR/build/Containerfile" "$APP_DIR/build" podman build -t "$IMAGE_NAME" -f "$APP_DIR/build/Containerfile" "$APP_DIR/build"
podman rm -f "${WATCH_CONTAINER_NAME:-email-forwarder-watch}" >/dev/null 2>&1 || true podman rm -f "${WATCH_CONTAINER_NAME:-mail-graveyard-watch}" >/dev/null 2>&1 || true
podman rm -f "$CONTAINER_NAME" >/dev/null 2>&1 || true podman rm -f "$CONTAINER_NAME" >/dev/null 2>&1 || true
podman pod rm -f "$POD_NAME" >/dev/null 2>&1 || true podman pod rm -f "$POD_NAME" >/dev/null 2>&1 || true
podman pod create --name "$POD_NAME" --network "$NETWORK" -p "$HOST_BIND:$APP_PORT:$APP_PORT" >/dev/null podman pod create --name "$POD_NAME" --network "$NETWORK" -p "$HOST_BIND:$APP_PORT:$APP_PORT" >/dev/null
@ -42,7 +42,7 @@ podman run -d --name "$CONTAINER_NAME" --pod "$POD_NAME" \
"$IMAGE_NAME" >/dev/null "$IMAGE_NAME" >/dev/null
if [ -n "${WATCH_ACCOUNT:-}" ]; then if [ -n "${WATCH_ACCOUNT:-}" ]; then
podman run -d --name "${WATCH_CONTAINER_NAME:-email-forwarder-watch}" --pod "$POD_NAME" \ podman run -d --name "${WATCH_CONTAINER_NAME:-mail-graveyard-watch}" --pod "$POD_NAME" \
--restart=unless-stopped \ --restart=unless-stopped \
-v "$APP_DIR/data:/app/data:Z" \ -v "$APP_DIR/data:/app/data:Z" \
-v "$APP_DIR/backup:/app/backup:Z" \ -v "$APP_DIR/backup:/app/backup:Z" \
@ -51,7 +51,7 @@ fi
for _ in {1..20}; do for _ in {1..20}; do
if curl -fsS "http://$HOST_BIND:$APP_PORT/" >/dev/null 2>&1; then if curl -fsS "http://$HOST_BIND:$APP_PORT/" >/dev/null 2>&1; then
echo "Email-Forwarder reachable at http://$HOST_BIND:$APP_PORT/" echo "Mail-Graveyard reachable at http://$HOST_BIND:$APP_PORT/"
exit 0 exit 0
fi fi
sleep 1 sleep 1

View file

@ -1,4 +1,4 @@
#!/usr/bin/env bash #!/usr/bin/env bash
set -euo pipefail set -euo pipefail
cd "$(dirname "$0")" cd "$(dirname "$0")"
./01-install-Email-Forwarder-Pod.sh ./01-install-Mail-Graveyard-Pod.sh

View file

@ -7,17 +7,17 @@ set +a
mkdir -p "$APP_DIR/export" mkdir -p "$APP_DIR/export"
TS="$(date +%Y%m%d-%H%M%S)" TS="$(date +%Y%m%d-%H%M%S)"
OUT="$APP_DIR/export/email-forwarder-pod-$TS.tar.gz" OUT="$APP_DIR/export/mail-graveyard-pod-$TS.tar.gz"
tar -czf "$OUT" \ tar -czf "$OUT" \
config.env \ config.env \
config.json \ config.json \
Containerfile \ Containerfile \
01-install-Email-Forwarder-Pod.sh \ 01-install-Mail-Graveyard-Pod.sh \
02-reconf-Email-Forwarder-Pod.sh \ 02-reconf-Mail-Graveyard-Pod.sh \
03-import-Email-Forwarder-Pod.sh \ 03-import-Mail-Graveyard-Pod.sh \
04-export-Email-Forwarder-Pod.sh \ 04-export-Mail-Graveyard-Pod.sh \
05-uninstall-Email-Forwarder-Pod.sh \ 05-uninstall-Mail-Graveyard-Pod.sh \
data \ data \
backup backup

View file

@ -5,7 +5,7 @@ set -a
source ./config.env source ./config.env
set +a set +a
podman rm -f "${WATCH_CONTAINER_NAME:-email-forwarder-watch}" >/dev/null 2>&1 || true podman rm -f "${WATCH_CONTAINER_NAME:-mail-graveyard-watch}" >/dev/null 2>&1 || true
podman rm -f "$CONTAINER_NAME" >/dev/null 2>&1 || true podman rm -f "$CONTAINER_NAME" >/dev/null 2>&1 || true
podman pod rm -f "$POD_NAME" >/dev/null 2>&1 || true podman pod rm -f "$POD_NAME" >/dev/null 2>&1 || true
echo "Runtime removed. Persistent data kept at $APP_DIR/data and $APP_DIR/backup" echo "Runtime removed. Persistent data kept at $APP_DIR/data and $APP_DIR/backup"

View file

@ -3,10 +3,10 @@ RUN apt-get update \
&& apt-get install -y --no-install-recommends ca-certificates \ && apt-get install -y --no-install-recommends ca-certificates \
&& rm -rf /var/lib/apt/lists/* && rm -rf /var/lib/apt/lists/*
WORKDIR /app WORKDIR /app
COPY emailforwarder /app/emailforwarder COPY mail-graveyard /app/mail-graveyard
COPY config.json /app/config.json COPY config.json /app/config.json
RUN chmod 0755 /app/emailforwarder \ RUN chmod 0755 /app/mail-graveyard \
&& mkdir -p /app/data /app/backup && mkdir -p /app/data /app/backup
EXPOSE 8087 EXPOSE 8087
VOLUME ["/app/data", "/app/backup"] VOLUME ["/app/data", "/app/backup"]
ENTRYPOINT ["/app/emailforwarder"] ENTRYPOINT ["/app/mail-graveyard"]

View file

@ -0,0 +1,13 @@
SERVICE_NAME=Mail-Graveyard
POD_NAME=mail-graveyard-pod
CONTAINER_NAME=mail-graveyard
WATCH_CONTAINER_NAME=mail-graveyard-watch
IMAGE_NAME=localhost/mail-graveyard:test
NETWORK=base-net
HOST_BIND=127.0.0.1
APP_PORT=8087
WATCH_ACCOUNT=codex-to-vdevop03
WATCH_INTERVAL=60s
BUILD_SRC=/mnt/DATA/Build/Mail-Graveyard
DEVOP_CONTAINER=DevOp-Pod-build
APP_DIR=/mnt/DATA/Containers/Test-Container/Mail-Graveyard-Pod

View file

@ -3,7 +3,7 @@
"port": "8087", "port": "8087",
"admin_user": "vAdmin@golddata.eu", "admin_user": "vAdmin@golddata.eu",
"admin_pass": "CHANGE-ME-lokal", "admin_pass": "CHANGE-ME-lokal",
"db_path": "/app/data/emailforwarder.db", "db_path": "/app/data/mail-graveyard.db",
"mbox_root": "/app/backup", "mbox_root": "/app/backup",
"forward_smtp": { "forward_smtp": {
"host": "", "host": "",

2
go.mod
View file

@ -1,4 +1,4 @@
module emailforwarder module mail-graveyard
go 1.25 go 1.25

View file

@ -9,7 +9,7 @@ import (
"os" "os"
"time" "time"
"emailforwarder/backend" "mail-graveyard/backend"
) )
//go:embed frontend-js/dist/* //go:embed frontend-js/dist/*
@ -58,7 +58,7 @@ func main() {
backend.RegisterRoutes(mux) backend.RegisterRoutes(mux)
addr := backend.Cfg.Bind + ":" + backend.Cfg.Port addr := backend.Cfg.Bind + ":" + backend.Cfg.Port
log.Printf("Email-Forwarder listening on %s", addr) log.Printf("Mail-Graveyard listening on %s", addr)
log.Fatal(http.ListenAndServe(addr, backend.AuthMiddleware(mux))) log.Fatal(http.ListenAndServe(addr, backend.AuthMiddleware(mux)))
} }