Compare commits
26 commits
feature/st
...
main
| Author | SHA1 | Date | |
|---|---|---|---|
| 83e267a608 | |||
| f684ea1b4c | |||
| caeb5662d4 | |||
| f20915ff33 | |||
| 4af068e15c | |||
| 7a921dc791 | |||
| ec7086259e | |||
| 304b010a56 | |||
| 9cd8f4bce0 | |||
| f5d9f359de | |||
| 166325b133 | |||
| 8b7806670c | |||
| 6c60d88f62 | |||
| 54c594e656 | |||
| 08b49d3d75 | |||
| baa2490bbe | |||
| 32c51e326e | |||
| 24bd94dec4 | |||
| 77b9685231 | |||
| b4bc104750 | |||
| 683d6e5e5d | |||
| df1edf3dc5 | |||
| bbbbeef072 | |||
| 59f372f2b0 | |||
| 7ee990b052 | |||
| 25a709ebbe |
25 changed files with 281 additions and 576 deletions
1
.gitignore
vendored
1
.gitignore
vendored
|
|
@ -68,3 +68,4 @@ config.production.lua
|
||||||
|
|
||||||
config/furt.conf
|
config/furt.conf
|
||||||
|
|
||||||
|
scripts/production_test_sequence.sh
|
||||||
|
|
|
||||||
|
|
@ -20,3 +20,14 @@
|
||||||
795f8867,78e8ded,fix/json-library-compatibility,2025-09-05T15:44:42Z,michael,git,lua-api
|
795f8867,78e8ded,fix/json-library-compatibility,2025-09-05T15:44:42Z,michael,git,lua-api
|
||||||
795f8867,d4fa6e3,fix/ssl-dependency-check,2025-09-05T16:20:08Z,michael,git,lua-api
|
795f8867,d4fa6e3,fix/ssl-dependency-check,2025-09-05T16:20:08Z,michael,git,lua-api
|
||||||
a670de0f,d271b84,refactor/extract-health-routes-and-server-core,2025-09-05T17:25:09Z,michael,git,lua-api
|
a670de0f,d271b84,refactor/extract-health-routes-and-server-core,2025-09-05T17:25:09Z,michael,git,lua-api
|
||||||
|
a670de0f,25a709e,feature/pid-file-service-management,2025-09-05T20:30:13Z,michael,git,lua-api
|
||||||
|
a670de0f,59f372f,feature/pid-file-service-management,2025-09-07T14:58:01Z,michael,git,lua-api
|
||||||
|
a670de0f,683d6e5,fix/validate-config-posix-regex,2025-09-07T16:00:48Z,michael,git,lua-api
|
||||||
|
a670de0f,24bd94d,feature/systemd-hardening,2025-09-07T16:40:47Z,michael,git,lua-api
|
||||||
|
4ee95dbc,08b49d3,security/sanitize-test-scripts,2025-09-07T19:25:38Z,michael,git,lua-api
|
||||||
|
59c85431,8b78066,main,2025-09-10T10:20:50Z,michael,git,lua-api
|
||||||
|
a71dd794,f5d9f35,main,2025-09-10T12:27:54Z,michael,git,lua-api
|
||||||
|
de5318f2,304b010,main,2025-09-10T14:45:12Z,michael,git,lua-api
|
||||||
|
980d67cd,7a921dc,main,2025-09-10T14:46:13Z,michael,git,lua-api
|
||||||
|
efbcbbd8,f20915f,main,2025-09-10T18:01:18Z,michael,git,lua-api
|
||||||
|
f777e765,f684ea1,main,2025-09-10T18:04:19Z,michael,git,lua-api
|
||||||
|
|
|
||||||
159
README.md
159
README.md
|
|
@ -1,160 +1,83 @@
|
||||||
# Furt API Gateway
|
# Furt API Gateway
|
||||||
|
|
||||||
**HTTP-Server in Lua für Service-Integration**
|
**Pure Lua HTTP-Server für digitale Souveränität**
|
||||||
|
|
||||||
## Überblick
|
## Überblick
|
||||||
|
|
||||||
Furt ist ein HTTP-Server der verschiedene Services unter einer API vereint. Aktuell unterstützt es Mail-Versendung über SMTP und bietet eine einfache JSON-API für Web-Integration.
|
Furt ist ein minimalistisches HTTP-Server in Lua 5.1 für Mail-Versendung über SMTP. Es bietet eine einfache JSON-API für Web-Integration und Multi-Tenant-Unterstützung über API-Keys.
|
||||||
|
|
||||||
## Features
|
## Features
|
||||||
|
|
||||||
- HTTP-Server mit JSON-APIs
|
- HTTP-Server mit JSON-APIs
|
||||||
- Mail-Versendung über SMTP
|
- Multi-Tenant Mail-Routing über SMTP
|
||||||
- Request-Routing und Authentication
|
- API-Key-basierte Authentifizierung
|
||||||
- Health-Check-Endpoints
|
- Health-Check-Endpoints
|
||||||
- Konfigurierbare Rate-Limiting
|
- Rate-Limiting pro API-Key
|
||||||
- Hugo/Website-Integration
|
- CORS-Support für Frontend-Integration
|
||||||
|
|
||||||
## Dependencies
|
## Quick Start
|
||||||
|
|
||||||
**Erforderlich:**
|
**Dependencies installieren:**
|
||||||
- `lua` 5.4+
|
```bash
|
||||||
- `lua-socket` (HTTP-Server)
|
# OpenBSD
|
||||||
- `lua-cjson` (JSON-Verarbeitung)
|
doas pkg_add lua lua-socket lua-cjson luasec
|
||||||
|
|
||||||
|
# Debian/Ubuntu
|
||||||
|
sudo apt install lua5.1 lua-socket lua-cjson lua-sec
|
||||||
|
|
||||||
|
# Arch Linux
|
||||||
|
sudo pacman -S lua51 lua51-socket lua51-dkjson lua51-sec
|
||||||
|
```
|
||||||
|
|
||||||
**Installation:**
|
**Installation:**
|
||||||
```bash
|
```bash
|
||||||
# Arch Linux
|
git clone https://smida.dragons-at-work.de/DAW/furt.git
|
||||||
pacman -S lua lua-socket lua-cjson
|
|
||||||
|
|
||||||
# Ubuntu/Debian
|
|
||||||
apt install lua5.4 lua-socket lua-cjson
|
|
||||||
```
|
|
||||||
|
|
||||||
## Installation
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# Repository klonen
|
|
||||||
git clone <repository-url>
|
|
||||||
cd furt
|
cd furt
|
||||||
|
sudo ./install.sh
|
||||||
# Scripts ausführbar machen
|
|
||||||
chmod +x scripts/*.sh
|
|
||||||
|
|
||||||
# Server starten
|
|
||||||
./scripts/start.sh
|
|
||||||
```
|
```
|
||||||
|
|
||||||
**Server läuft auf:** http://127.0.0.1:8080
|
**Server läuft auf:** http://127.0.0.1:7811
|
||||||
|
|
||||||
## API-Endpoints
|
## API-Endpoints
|
||||||
|
|
||||||
### Health Check
|
**Health Check:**
|
||||||
```bash
|
```bash
|
||||||
GET /health
|
curl http://127.0.0.1:7811/health
|
||||||
→ {"status":"healthy","service":"furt","version":"1.0.0"}
|
|
||||||
```
|
```
|
||||||
|
|
||||||
### Mail senden
|
**Mail senden:**
|
||||||
```bash
|
```bash
|
||||||
POST /v1/mail/send
|
curl -X POST http://127.0.0.1:7811/v1/mail/send \
|
||||||
Content-Type: application/json
|
-H "X-API-Key: your-api-key" \
|
||||||
|
|
||||||
{
|
|
||||||
"name": "Name",
|
|
||||||
"email": "sender@example.com",
|
|
||||||
"message": "Nachricht"
|
|
||||||
}
|
|
||||||
|
|
||||||
→ {"success":true,"message":"Mail sent"}
|
|
||||||
```
|
|
||||||
|
|
||||||
## Konfiguration
|
|
||||||
|
|
||||||
**Environment Variables (.env):**
|
|
||||||
```bash
|
|
||||||
FURT_MAIL_HOST=mail.example.com
|
|
||||||
FURT_MAIL_PORT=587
|
|
||||||
FURT_MAIL_USERNAME=user@example.com
|
|
||||||
FURT_MAIL_PASSWORD=password
|
|
||||||
FURT_MAIL_TO=empfaenger@example.com
|
|
||||||
```
|
|
||||||
|
|
||||||
**Server-Config (config/server.lua):**
|
|
||||||
- Port und Host-Einstellungen
|
|
||||||
- API-Key-Konfiguration
|
|
||||||
- Rate-Limiting-Parameter
|
|
||||||
|
|
||||||
## Testing
|
|
||||||
|
|
||||||
**Automatische Tests:**
|
|
||||||
```bash
|
|
||||||
lua tests/test_http.lua
|
|
||||||
```
|
|
||||||
|
|
||||||
**Manuelle Tests:**
|
|
||||||
```bash
|
|
||||||
./scripts/test_curl.sh
|
|
||||||
|
|
||||||
# Oder direkt:
|
|
||||||
curl -X POST http://127.0.0.1:8080/v1/mail/send \
|
|
||||||
-H "Content-Type: application/json" \
|
-H "Content-Type: application/json" \
|
||||||
-d '{"name":"Test","email":"test@example.com","message":"Test"}'
|
-d '{"name":"Test","email":"test@example.com","subject":"Test","message":"Test-Nachricht"}'
|
||||||
```
|
```
|
||||||
|
|
||||||
## Deployment
|
## Dokumentation
|
||||||
|
|
||||||
**OpenBSD:**
|
**Installation & Konfiguration:** [Furt Wiki](https://smida.dragons-at-work.de/DAW/furt/wiki)
|
||||||
- rc.d-Script in `deployment/openbsd/`
|
|
||||||
- Systemd-Integration über Scripts
|
|
||||||
|
|
||||||
**Production-Setup:**
|
|
||||||
```bash
|
|
||||||
# Environment-Config kopieren
|
|
||||||
cp .env.example .env.production
|
|
||||||
# → SMTP-Credentials anpassen
|
|
||||||
|
|
||||||
# Production-Mode starten
|
|
||||||
export FURT_ENV=production
|
|
||||||
./scripts/start.sh
|
|
||||||
```
|
|
||||||
|
|
||||||
## Projektstruktur
|
## Projektstruktur
|
||||||
|
|
||||||
```
|
```
|
||||||
furt/
|
furt/
|
||||||
├── src/ # Lua-Source-Code
|
├── src/ # Lua-Source-Code
|
||||||
│ ├── main.lua # HTTP-Server
|
├── config/ # Konfiguration
|
||||||
│ ├── routes/ # API-Endpoints
|
├── scripts/ # Installation & Management
|
||||||
│ └── smtp.lua # Mail-Integration
|
└── deployment/ # System-Integration
|
||||||
├── config/ # Konfiguration
|
|
||||||
├── scripts/ # Start/Test-Scripts
|
|
||||||
├── tests/ # Test-Suite
|
|
||||||
└── deployment/ # System-Integration
|
|
||||||
```
|
```
|
||||||
|
|
||||||
## Hugo-Integration
|
## Integration
|
||||||
|
|
||||||
**Shortcode-Beispiel:**
|
**merkwerk:** Versionierte Furt-Deployment über [merkwerk](https://smida.dragons-at-work.de/DAW/merkwerk)
|
||||||
```html
|
|
||||||
<form action="http://your-server:8080/v1/mail/send" method="POST">
|
|
||||||
<input name="name" type="text" required>
|
|
||||||
<input name="email" type="email" required>
|
|
||||||
<textarea name="message" required></textarea>
|
|
||||||
<button type="submit">Senden</button>
|
|
||||||
</form>
|
|
||||||
```
|
|
||||||
|
|
||||||
## Development
|
## License
|
||||||
|
|
||||||
**Code-Struktur:**
|
ISC - Siehe [LICENSE](LICENSE) für Details.
|
||||||
- Module unter 200 Zeilen
|
|
||||||
- Funktionen unter 50 Zeilen
|
|
||||||
- Klare Fehlerbehandlung
|
|
||||||
- Testbare Komponenten
|
|
||||||
|
|
||||||
**Dependencies minimal halten:**
|
## Links
|
||||||
- Nur lua-socket und lua-cjson
|
|
||||||
- Keine externen HTTP-Libraries
|
- **Repository:** [Forgejo](https://smida.dragons-at-work.de/DAW/furt)
|
||||||
- Standard-Lua-Funktionen bevorzugen
|
- **Dokumentation:** [Wiki](https://smida.dragons-at-work.de/DAW/furt/wiki)
|
||||||
|
- **Projekt:** [Dragons@Work](https://dragons-at-work.de)
|
||||||
|
|
||||||
|
|
|
||||||
2
VERSION
2
VERSION
|
|
@ -1 +1 @@
|
||||||
0.1.1
|
0.1.4
|
||||||
|
|
|
||||||
|
|
@ -1,18 +1,33 @@
|
||||||
[Unit]
|
[Unit]
|
||||||
Description=furt Multi-Tenant API Gateway
|
Description=furt Multi-Tenant API Gateway (Security-Hardened)
|
||||||
After=network.target
|
After=network.target
|
||||||
|
|
||||||
[Service]
|
[Service]
|
||||||
Type=forking
|
Type=forking
|
||||||
User=furt
|
User=furt
|
||||||
Group=furt
|
Group=furt
|
||||||
ExecStart=/usr/local/share/furt/scripts/start.sh start
|
ExecStart=/usr/local/share/furt/scripts/start.sh
|
||||||
|
PIDFile=/var/run/furt/furt.pid
|
||||||
WorkingDirectory=/usr/local/share/furt
|
WorkingDirectory=/usr/local/share/furt
|
||||||
Restart=always
|
Restart=always
|
||||||
RestartSec=5
|
RestartSec=5
|
||||||
StandardOutput=journal
|
StandardOutput=journal
|
||||||
StandardError=journal
|
StandardError=journal
|
||||||
|
|
||||||
|
# === SECURITY HARDENING ===
|
||||||
|
|
||||||
|
# Filesystem Protection
|
||||||
|
ProtectSystem=strict
|
||||||
|
ReadWritePaths=/var/run/furt /var/log/furt
|
||||||
|
ProtectHome=yes
|
||||||
|
|
||||||
|
# Process Hardening
|
||||||
|
NoNewPrivileges=yes
|
||||||
|
PrivateTmp=yes
|
||||||
|
|
||||||
|
# Network Restriction
|
||||||
|
RestrictAddressFamilies=AF_INET
|
||||||
|
|
||||||
[Install]
|
[Install]
|
||||||
WantedBy=multi-user.target
|
WantedBy=multi-user.target
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -3,11 +3,52 @@
|
||||||
daemon="/usr/local/share/furt/scripts/start.sh"
|
daemon="/usr/local/share/furt/scripts/start.sh"
|
||||||
daemon_user="_furt"
|
daemon_user="_furt"
|
||||||
daemon_cwd="/usr/local/share/furt"
|
daemon_cwd="/usr/local/share/furt"
|
||||||
daemon_flags="start"
|
|
||||||
|
|
||||||
. /etc/rc.d/rc.subr
|
. /etc/rc.d/rc.subr
|
||||||
|
|
||||||
pexp="lua.*src/main.lua"
|
# PID-File location
|
||||||
|
pidfile="/var/run/furt/furt.pid"
|
||||||
|
|
||||||
|
# Custom rc_check function (PID-File based)
|
||||||
|
rc_check() {
|
||||||
|
[ -f "$pidfile" ] && kill -0 $(cat "$pidfile") 2>/dev/null
|
||||||
|
}
|
||||||
|
|
||||||
|
# Custom rc_stop function (PID-File based)
|
||||||
|
rc_stop() {
|
||||||
|
if [ -f "$pidfile" ]; then
|
||||||
|
local _pid=$(cat "$pidfile")
|
||||||
|
echo "Stopping furt (PID: $_pid)"
|
||||||
|
kill "$_pid" 2>/dev/null
|
||||||
|
# Wait for process to die
|
||||||
|
local _timeout=10
|
||||||
|
while [ $_timeout -gt 0 ] && kill -0 "$_pid" 2>/dev/null; do
|
||||||
|
sleep 1
|
||||||
|
_timeout=$((_timeout - 1))
|
||||||
|
done
|
||||||
|
# Force kill if still running
|
||||||
|
if kill -0 "$_pid" 2>/dev/null; then
|
||||||
|
echo "Force killing furt (PID: $_pid)"
|
||||||
|
kill -9 "$_pid" 2>/dev/null
|
||||||
|
fi
|
||||||
|
rm -f "$pidfile"
|
||||||
|
echo "furt stopped"
|
||||||
|
else
|
||||||
|
echo "furt not running (no PID-File)"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
# Custom rc_reload function (signal-based)
|
||||||
|
rc_reload() {
|
||||||
|
if rc_check; then
|
||||||
|
local _pid=$(cat "$pidfile")
|
||||||
|
echo "Reloading furt configuration (PID: $_pid)"
|
||||||
|
kill -HUP "$_pid"
|
||||||
|
else
|
||||||
|
echo "furt not running"
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
rc_cmd $1
|
rc_cmd $1
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,176 +0,0 @@
|
||||||
# Multi-Tenant furt Setup-Anleitung
|
|
||||||
|
|
||||||
## Installation
|
|
||||||
|
|
||||||
### 1. Dateien platzieren
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# OpenBSD/FreeBSD
|
|
||||||
mkdir -p /usr/local/etc/furt
|
|
||||||
mkdir -p /usr/local/share/furt
|
|
||||||
|
|
||||||
# Oder Linux
|
|
||||||
mkdir -p /etc/furt
|
|
||||||
mkdir -p /usr/local/share/furt
|
|
||||||
|
|
||||||
# Source code
|
|
||||||
cp -r src/ /usr/local/share/furt/
|
|
||||||
cp -r config/ /usr/local/share/furt/
|
|
||||||
```
|
|
||||||
|
|
||||||
### 2. Konfiguration erstellen
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# Beispiel-Config kopieren und anpassen
|
|
||||||
# OpenBSD/FreeBSD:
|
|
||||||
cp furt.conf.example /usr/local/etc/furt/furt.conf
|
|
||||||
|
|
||||||
# Linux:
|
|
||||||
cp furt.conf.example /etc/furt/furt.conf
|
|
||||||
|
|
||||||
# Config editieren
|
|
||||||
vi /usr/local/etc/furt/furt.conf # oder /etc/furt/furt.conf
|
|
||||||
```
|
|
||||||
|
|
||||||
### 3. Start-Script
|
|
||||||
|
|
||||||
```bash
|
|
||||||
#!/bin/sh
|
|
||||||
# /usr/local/bin/furt
|
|
||||||
|
|
||||||
cd /usr/local/share/furt
|
|
||||||
lua src/main.lua
|
|
||||||
```
|
|
||||||
|
|
||||||
## Multi-Tenant Konfiguration
|
|
||||||
|
|
||||||
### Beispiel für 3 Websites
|
|
||||||
|
|
||||||
```ini
|
|
||||||
[server]
|
|
||||||
host = 127.0.0.1
|
|
||||||
port = 8080
|
|
||||||
|
|
||||||
[smtp_default]
|
|
||||||
host = mail.dragons-at-work.de
|
|
||||||
port = 465
|
|
||||||
user = noreply@dragons-at-work.de
|
|
||||||
password = your-smtp-password
|
|
||||||
|
|
||||||
# Website 1: Dragons@Work
|
|
||||||
[api_key "daw-key-abc123"]
|
|
||||||
name = "Dragons@Work Website"
|
|
||||||
permissions = mail:send
|
|
||||||
allowed_ips = 1.2.3.4/32, 10.0.0.0/8
|
|
||||||
mail_to = admin@dragons-at-work.de
|
|
||||||
mail_from = noreply@dragons-at-work.de
|
|
||||||
mail_subject_prefix = "[DAW] "
|
|
||||||
|
|
||||||
# Website 2: Biocodie (gleiche SMTP, andere Empfänger)
|
|
||||||
[api_key "bio-key-def456"]
|
|
||||||
name = "Biocodie Website"
|
|
||||||
permissions = mail:send
|
|
||||||
allowed_ips = 5.6.7.8/32
|
|
||||||
mail_to = contact@biocodie.de
|
|
||||||
mail_from = noreply@biocodie.de
|
|
||||||
mail_subject_prefix = "[Biocodie] "
|
|
||||||
|
|
||||||
# Website 3: Kunde mit eigenem SMTP
|
|
||||||
[api_key "kunde-key-ghi789"]
|
|
||||||
name = "Kunde X Website"
|
|
||||||
permissions = mail:send
|
|
||||||
allowed_ips = 9.10.11.12/32
|
|
||||||
mail_to = info@kunde-x.de
|
|
||||||
mail_from = noreply@kunde-x.de
|
|
||||||
mail_smtp_host = mail.kunde-x.de
|
|
||||||
mail_smtp_user = noreply@kunde-x.de
|
|
||||||
mail_smtp_pass = kunde-smtp-password
|
|
||||||
```
|
|
||||||
|
|
||||||
## Admin-Workflow
|
|
||||||
|
|
||||||
### Neue Website hinzufügen
|
|
||||||
|
|
||||||
1. **Config editieren:**
|
|
||||||
```bash
|
|
||||||
vi /usr/local/etc/furt/furt.conf
|
|
||||||
```
|
|
||||||
|
|
||||||
2. **Neuen API-Key-Block hinzufügen:**
|
|
||||||
```ini
|
|
||||||
[api_key "neue-website-key"]
|
|
||||||
name = "Neue Website"
|
|
||||||
permissions = mail:send
|
|
||||||
allowed_ips = 12.34.56.78/32
|
|
||||||
mail_to = contact@neue-website.de
|
|
||||||
mail_from = noreply@neue-website.de
|
|
||||||
```
|
|
||||||
|
|
||||||
3. **furt neu starten:**
|
|
||||||
```bash
|
|
||||||
systemctl restart furt
|
|
||||||
# oder
|
|
||||||
pkill -f "lua.*main.lua" && /usr/local/bin/furt &
|
|
||||||
```
|
|
||||||
|
|
||||||
### Website testen
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# Test mit curl
|
|
||||||
curl -X POST http://localhost:8080/v1/mail/send \
|
|
||||||
-H "X-API-Key: neue-website-key" \
|
|
||||||
-H "Content-Type: application/json" \
|
|
||||||
-d '{
|
|
||||||
"name": "Test User",
|
|
||||||
"email": "test@example.com",
|
|
||||||
"subject": "Test Message",
|
|
||||||
"message": "This is a test message"
|
|
||||||
}'
|
|
||||||
```
|
|
||||||
|
|
||||||
## Vorteile des Multi-Tenant-Systems
|
|
||||||
|
|
||||||
### ✅ Ein Server, viele Websites
|
|
||||||
- Alle Websites nutzen eine furt-Instanz
|
|
||||||
- Jede Website hat eigenen API-Key
|
|
||||||
- Verschiedene Empfänger-Adressen
|
|
||||||
- Verschiedene SMTP-Server möglich
|
|
||||||
|
|
||||||
### ✅ Admin-freundlich
|
|
||||||
- Nginx-style Config-Format
|
|
||||||
- Einfach neue Websites hinzufügen
|
|
||||||
- Klare Struktur pro Website
|
|
||||||
- Kommentare möglich
|
|
||||||
|
|
||||||
### ✅ Sicher
|
|
||||||
- IP-Restrictions pro Website
|
|
||||||
- Permissions pro API-Key
|
|
||||||
- Separate SMTP-Credentials möglich
|
|
||||||
- Rate-Limiting bleibt erhalten
|
|
||||||
|
|
||||||
### ✅ Flexibel
|
|
||||||
- Default SMTP + website-spezifische SMTP
|
|
||||||
- Subject-Prefix pro Website
|
|
||||||
- Verschiedene Mail-Adressen
|
|
||||||
- Beliebig viele Websites
|
|
||||||
|
|
||||||
## Backward Compatibility
|
|
||||||
|
|
||||||
Das neue System ist **vollständig kompatibel** mit der alten config/server.lua API. Bestehende Module (auth.lua, main.lua, etc.) funktionieren ohne Änderungen.
|
|
||||||
|
|
||||||
## Troubleshooting
|
|
||||||
|
|
||||||
### Config-Parsing-Fehler
|
|
||||||
```bash
|
|
||||||
# Config-Syntax prüfen
|
|
||||||
lua -e "require('src.config_parser').parse_file('/usr/local/etc/furt/furt.conf')"
|
|
||||||
```
|
|
||||||
|
|
||||||
### Mail-Routing testen
|
|
||||||
```bash
|
|
||||||
# Logs anschauen
|
|
||||||
tail -f /var/log/furt.log
|
|
||||||
|
|
||||||
# Debug-Mode
|
|
||||||
FURT_DEBUG=true lua src/main.lua
|
|
||||||
```
|
|
||||||
|
|
@ -102,7 +102,7 @@ else
|
||||||
echo ""
|
echo ""
|
||||||
echo "Next steps:"
|
echo "Next steps:"
|
||||||
echo "1. Edit configuration file:"
|
echo "1. Edit configuration file:"
|
||||||
if [ "$(uname)" = "OpenBSD" ] || [ "$(uname)" = "FreeBSD" ]; then
|
if [ "$(uname)" = "OpenBSD" ]; then
|
||||||
echo " /usr/local/etc/furt/furt.conf"
|
echo " /usr/local/etc/furt/furt.conf"
|
||||||
else
|
else
|
||||||
echo " /etc/furt/furt.conf"
|
echo " /etc/furt/furt.conf"
|
||||||
|
|
|
||||||
0
scripts/cleanup_debug.sh
Normal file → Executable file
0
scripts/cleanup_debug.sh
Normal file → Executable file
4
scripts/manual_mail_test.sh
Normal file → Executable file
4
scripts/manual_mail_test.sh
Normal file → Executable file
|
|
@ -4,11 +4,11 @@
|
||||||
echo "Testing SMTP with corrected JSON..."
|
echo "Testing SMTP with corrected JSON..."
|
||||||
|
|
||||||
# Simple test without timestamp embedding
|
# Simple test without timestamp embedding
|
||||||
curl -X POST http://127.0.0.1:8080/v1/mail/send \
|
curl -X POST http://127.0.0.1:7811/v1/mail/send \
|
||||||
-H "Content-Type: application/json" \
|
-H "Content-Type: application/json" \
|
||||||
-d '{
|
-d '{
|
||||||
"name": "Furt Test User",
|
"name": "Furt Test User",
|
||||||
"email": "michael@dragons-at-work.de",
|
"email": "admin@example.com",
|
||||||
"subject": "Furt SMTP Test Success!",
|
"subject": "Furt SMTP Test Success!",
|
||||||
"message": "This is a test email from Furt Lua HTTP-Server. SMTP Integration working!"
|
"message": "This is a test email from Furt Lua HTTP-Server. SMTP Integration working!"
|
||||||
}'
|
}'
|
||||||
|
|
|
||||||
|
|
@ -1,80 +0,0 @@
|
||||||
#!/bin/bash
|
|
||||||
# Production Test für api.dragons-at-work.de
|
|
||||||
|
|
||||||
echo "Testing Production API via Apache Proxy"
|
|
||||||
echo "======================================="
|
|
||||||
|
|
||||||
# Test 1: HTTPS Health Check
|
|
||||||
echo ""
|
|
||||||
echo "[1] Testing HTTPS Health Check..."
|
|
||||||
https_health=$(curl -s https://api.dragons-at-work.de/health)
|
|
||||||
echo "HTTPS Response: $https_health"
|
|
||||||
|
|
||||||
if echo "$https_health" | grep -q "healthy"; then
|
|
||||||
echo "[OK] HTTPS Proxy working"
|
|
||||||
else
|
|
||||||
echo "[ERROR] HTTPS Proxy failed"
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Test 2: SMTP Status via HTTPS
|
|
||||||
echo ""
|
|
||||||
echo "[2] Testing SMTP Configuration via HTTPS..."
|
|
||||||
if echo "$https_health" | grep -q '"smtp_configured":true'; then
|
|
||||||
echo "[OK] SMTP configured and accessible via HTTPS"
|
|
||||||
else
|
|
||||||
echo "[ERROR] SMTP not configured or not accessible"
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Test 3: CORS Headers
|
|
||||||
echo ""
|
|
||||||
echo "[3] Testing CORS Headers..."
|
|
||||||
cors_test=$(curl -s -I https://api.dragons-at-work.de/health | grep -i "access-control")
|
|
||||||
if [ -n "$cors_test" ]; then
|
|
||||||
echo "[OK] CORS headers present: $cors_test"
|
|
||||||
else
|
|
||||||
echo "[WARN] CORS headers missing - add to Apache config"
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Test 4: Production Mail Test
|
|
||||||
echo ""
|
|
||||||
echo "[4] Testing Production Mail via HTTPS..."
|
|
||||||
echo "WARNING: This sends real email via production API"
|
|
||||||
read -p "Continue with production mail test? (y/N): " -n 1 -r
|
|
||||||
echo
|
|
||||||
|
|
||||||
if [[ $REPLY =~ ^[Yy]$ ]]; then
|
|
||||||
echo "Sending production test email..."
|
|
||||||
|
|
||||||
prod_mail_response=$(curl -s -X POST https://api.dragons-at-work.de/v1/mail/send \
|
|
||||||
-H "Content-Type: application/json" \
|
|
||||||
-d '{
|
|
||||||
"name": "Production Test",
|
|
||||||
"email": "test@dragons-at-work.de",
|
|
||||||
"subject": "Production API Test - Apache Proxy Success!",
|
|
||||||
"message": "This email was sent via the production API at api.dragons-at-work.de through Apache proxy to Furt-Lua backend. HTTPS integration working!"
|
|
||||||
}')
|
|
||||||
|
|
||||||
echo "Production Response: $prod_mail_response"
|
|
||||||
|
|
||||||
if echo "$prod_mail_response" | grep -q '"success":true'; then
|
|
||||||
echo "[OK] PRODUCTION MAIL SENT VIA HTTPS!"
|
|
||||||
echo "Check admin@dragons-at-work.de for delivery confirmation"
|
|
||||||
else
|
|
||||||
echo "[ERROR] Production mail failed"
|
|
||||||
fi
|
|
||||||
else
|
|
||||||
echo "Skipping production mail test"
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Test 5: Security Headers
|
|
||||||
echo ""
|
|
||||||
echo "[5] Testing Security Headers..."
|
|
||||||
security_headers=$(curl -s -I https://api.dragons-at-work.de/health)
|
|
||||||
echo "Security Headers:"
|
|
||||||
echo "$security_headers" | grep -i "x-content-type-options\|x-frame-options\|strict-transport"
|
|
||||||
|
|
||||||
echo ""
|
|
||||||
echo "Production Test Complete!"
|
|
||||||
echo "========================"
|
|
||||||
echo "Next: Hugo integration with https://api.dragons-at-work.de/v1/mail/send"
|
|
||||||
|
|
@ -4,7 +4,7 @@
|
||||||
set -e
|
set -e
|
||||||
|
|
||||||
# Detect operating system for config directory
|
# Detect operating system for config directory
|
||||||
if [ "$(uname)" = "OpenBSD" ] || [ "$(uname)" = "FreeBSD" ]; then
|
if [ "$(uname)" = "OpenBSD" ]; then
|
||||||
CONFIG_DIR="/usr/local/etc/furt"
|
CONFIG_DIR="/usr/local/etc/furt"
|
||||||
USER="_furt"
|
USER="_furt"
|
||||||
GROUP="_furt"
|
GROUP="_furt"
|
||||||
|
|
@ -18,12 +18,15 @@ fi
|
||||||
mkdir -p "$CONFIG_DIR"
|
mkdir -p "$CONFIG_DIR"
|
||||||
mkdir -p /usr/local/share/furt
|
mkdir -p /usr/local/share/furt
|
||||||
mkdir -p /var/log/furt
|
mkdir -p /var/log/furt
|
||||||
|
mkdir -p /var/run/furt
|
||||||
|
|
||||||
# Set ownership for log directory (service user needs write access)
|
# Set ownership for log directory (service user needs write access)
|
||||||
chown "$USER:$GROUP" /var/log/furt
|
chown "$USER:$GROUP" /var/log/furt
|
||||||
|
chown "$USER:$GROUP" /var/run/furt
|
||||||
|
|
||||||
echo "Created directories:"
|
echo "Created directories:"
|
||||||
echo " Config: $CONFIG_DIR"
|
echo " Config: $CONFIG_DIR"
|
||||||
echo " Share: /usr/local/share/furt"
|
echo " Share: /usr/local/share/furt"
|
||||||
echo " Logs: /var/log/furt (owned by $USER)"
|
echo " Logs: /var/log/furt (owned by $USER)"
|
||||||
|
echo " PID: /var/run/furt (owned by $USER)"
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -4,7 +4,7 @@
|
||||||
set -e
|
set -e
|
||||||
|
|
||||||
# Detect operating system
|
# Detect operating system
|
||||||
if [ "$(uname)" = "OpenBSD" ] || [ "$(uname)" = "FreeBSD" ]; then
|
if [ "$(uname)" = "OpenBSD" ]; then
|
||||||
# BSD systems use _furt user convention
|
# BSD systems use _furt user convention
|
||||||
groupadd _furt 2>/dev/null || true
|
groupadd _furt 2>/dev/null || true
|
||||||
useradd -g _furt -s /bin/false -d /var/empty _furt 2>/dev/null || true
|
useradd -g _furt -s /bin/false -d /var/empty _furt 2>/dev/null || true
|
||||||
|
|
|
||||||
|
|
@ -1,101 +0,0 @@
|
||||||
#!/bin/bash
|
|
||||||
# furt-lua/scripts/setup_env.sh
|
|
||||||
# Add SMTP environment variables to existing .env (non-destructive)
|
|
||||||
|
|
||||||
set -e
|
|
||||||
|
|
||||||
# Colors for output
|
|
||||||
GREEN='\033[0;32m'
|
|
||||||
YELLOW='\033[1;33m'
|
|
||||||
RED='\033[0;31m'
|
|
||||||
NC='\033[0m' # No Color
|
|
||||||
|
|
||||||
echo -e "${GREEN}=== Furt SMTP Environment Setup ===${NC}"
|
|
||||||
|
|
||||||
# Navigate to furt project root
|
|
||||||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
||||||
PROJECT_ROOT="$(dirname "$(dirname "$SCRIPT_DIR")")"
|
|
||||||
ENV_FILE="$PROJECT_ROOT/.env"
|
|
||||||
|
|
||||||
echo -e "${YELLOW}Project root:${NC} $PROJECT_ROOT"
|
|
||||||
echo -e "${YELLOW}Environment file:${NC} $ENV_FILE"
|
|
||||||
|
|
||||||
# Check if .env exists
|
|
||||||
if [ ! -f "$ENV_FILE" ]; then
|
|
||||||
echo -e "${YELLOW}Creating new .env file...${NC}"
|
|
||||||
cat > "$ENV_FILE" << 'EOF'
|
|
||||||
# Dragons@Work Project Environment Variables
|
|
||||||
|
|
||||||
# Furt SMTP Configuration for mail.dragons-at-work.de
|
|
||||||
SMTP_HOST="mail.dragons-at-work.de"
|
|
||||||
SMTP_PORT="465"
|
|
||||||
SMTP_USERNAME="your_email@dragons-at-work.de"
|
|
||||||
SMTP_PASSWORD="your_smtp_password"
|
|
||||||
SMTP_FROM="noreply@dragons-at-work.de"
|
|
||||||
SMTP_TO="michael@dragons-at-work.de"
|
|
||||||
EOF
|
|
||||||
echo -e "${GREEN}[OK] Created new .env file${NC}"
|
|
||||||
echo -e "${YELLOW}[EDIT] Please edit:${NC} nano $ENV_FILE"
|
|
||||||
exit 0
|
|
||||||
fi
|
|
||||||
|
|
||||||
echo -e "${GREEN}[OK] Found existing .env file${NC}"
|
|
||||||
|
|
||||||
# Check if SMTP variables already exist
|
|
||||||
smtp_username_exists=$(grep -c "^SMTP_USERNAME=" "$ENV_FILE" 2>/dev/null || echo "0")
|
|
||||||
smtp_password_exists=$(grep -c "^SMTP_PASSWORD=" "$ENV_FILE" 2>/dev/null || echo "0")
|
|
||||||
|
|
||||||
if [ "$smtp_username_exists" -gt 0 ] && [ "$smtp_password_exists" -gt 0 ]; then
|
|
||||||
echo -e "${GREEN}[OK] SMTP variables already configured${NC}"
|
|
||||||
|
|
||||||
# Load and show current values
|
|
||||||
source "$ENV_FILE"
|
|
||||||
echo -e "${YELLOW}Current SMTP User:${NC} ${SMTP_USERNAME:-NOT_SET}"
|
|
||||||
echo -e "${YELLOW}Current SMTP Password:${NC} ${SMTP_PASSWORD:+[CONFIGURED]}${SMTP_PASSWORD:-NOT_SET}"
|
|
||||||
|
|
||||||
echo ""
|
|
||||||
echo -e "${YELLOW}To update SMTP settings:${NC} nano $ENV_FILE"
|
|
||||||
exit 0
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Add missing SMTP variables
|
|
||||||
echo -e "${YELLOW}Adding SMTP configuration to existing .env...${NC}"
|
|
||||||
|
|
||||||
# Add section header if not present
|
|
||||||
if ! grep -q "SMTP_" "$ENV_FILE" 2>/dev/null; then
|
|
||||||
echo "" >> "$ENV_FILE"
|
|
||||||
echo "# Furt SMTP Configuration for mail.dragons-at-work.de" >> "$ENV_FILE"
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Add username if missing
|
|
||||||
if [ "$smtp_username_exists" -eq 0 ]; then
|
|
||||||
echo "SMTP_HOST=\"mail.dragons-at-work.de\"" >> "$ENV_FILE"
|
|
||||||
echo "SMTP_PORT=\"465\"" >> "$ENV_FILE"
|
|
||||||
echo "SMTP_USERNAME=\"your_email@dragons-at-work.de\"" >> "$ENV_FILE"
|
|
||||||
echo -e "${GREEN}[OK] Added SMTP_HOST, SMTP_PORT, SMTP_USERNAME${NC}"
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Add password if missing
|
|
||||||
if [ "$smtp_password_exists" -eq 0 ]; then
|
|
||||||
echo "SMTP_PASSWORD=\"your_smtp_password\"" >> "$ENV_FILE"
|
|
||||||
echo "SMTP_FROM=\"noreply@dragons-at-work.de\"" >> "$ENV_FILE"
|
|
||||||
echo "SMTP_TO=\"michael@dragons-at-work.de\"" >> "$ENV_FILE"
|
|
||||||
echo -e "${GREEN}[OK] Added SMTP_PASSWORD, SMTP_FROM, SMTP_TO${NC}"
|
|
||||||
fi
|
|
||||||
|
|
||||||
echo -e "${GREEN}[OK] SMTP configuration added to .env${NC}"
|
|
||||||
echo ""
|
|
||||||
echo -e "${YELLOW}Next steps:${NC}"
|
|
||||||
echo "1. Edit SMTP credentials: nano $ENV_FILE"
|
|
||||||
echo "2. Set your actual email@dragons-at-work.de in SMTP_USERNAME"
|
|
||||||
echo "3. Set your actual SMTP password in SMTP_PASSWORD"
|
|
||||||
echo "4. Test with: ./scripts/start.sh"
|
|
||||||
|
|
||||||
echo ""
|
|
||||||
echo -e "${YELLOW}Current .env content:${NC}"
|
|
||||||
echo "==================="
|
|
||||||
cat "$ENV_FILE"
|
|
||||||
echo "==================="
|
|
||||||
echo ""
|
|
||||||
echo -e "${GREEN}Ready for SMTP testing!${NC}"
|
|
||||||
|
|
||||||
|
|
@ -17,10 +17,12 @@ echo -e "${GREEN}=== Furt Lua HTTP-Server Startup ===${NC}"
|
||||||
LUA_COMMAND=""
|
LUA_COMMAND=""
|
||||||
|
|
||||||
# Config check first
|
# Config check first
|
||||||
if [ "$(uname)" = "OpenBSD" ] || [ "$(uname)" = "FreeBSD" ]; then
|
if [ "$(uname)" = "OpenBSD" ]; then
|
||||||
CONFIG_FILE="/usr/local/etc/furt/furt.conf"
|
CONFIG_FILE="/usr/local/etc/furt/furt.conf"
|
||||||
|
PID_FILE="/var/run/furt/furt.pid"
|
||||||
else
|
else
|
||||||
CONFIG_FILE="/etc/furt/furt.conf"
|
CONFIG_FILE="/etc/furt/furt.conf"
|
||||||
|
PID_FILE="/var/run/furt/furt.pid"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if [ ! -f "$CONFIG_FILE" ] && [ ! -f "$PROJECT_DIR/config/furt.conf" ]; then
|
if [ ! -f "$CONFIG_FILE" ] && [ ! -f "$PROJECT_DIR/config/furt.conf" ]; then
|
||||||
|
|
@ -87,12 +89,38 @@ cd "$PROJECT_DIR"
|
||||||
|
|
||||||
echo -e "${GREEN}Starting Furt...${NC}"
|
echo -e "${GREEN}Starting Furt...${NC}"
|
||||||
|
|
||||||
|
# PID-File cleanup function
|
||||||
|
cleanup_pid() {
|
||||||
|
if [ -f "$PID_FILE" ]; then
|
||||||
|
rm -f "$PID_FILE"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
# Service vs Interactive Detection
|
# Service vs Interactive Detection
|
||||||
if [ ! -t 0 ] || [ ! -t 1 ]; then
|
if [ ! -t 0 ] || [ ! -t 1 ]; then
|
||||||
# Service mode - Background
|
# Service mode - Background + PID-File
|
||||||
|
echo -e "${GREEN}Service mode: Background + PID-File${NC}"
|
||||||
|
|
||||||
|
# Start process in background
|
||||||
"$LUA_COMMAND" src/main.lua &
|
"$LUA_COMMAND" src/main.lua &
|
||||||
|
PID=$!
|
||||||
|
|
||||||
|
# Write PID-File
|
||||||
|
echo "$PID" > "$PID_FILE"
|
||||||
|
echo -e "${GREEN}Furt started (PID: $PID, PID-File: $PID_FILE)${NC}"
|
||||||
|
|
||||||
|
# Verify process is still running after short delay
|
||||||
|
sleep 1
|
||||||
|
if ! kill -0 "$PID" 2>/dev/null; then
|
||||||
|
echo -e "${RED}Error: Process died immediately${NC}"
|
||||||
|
cleanup_pid
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo -e "${GREEN}Service startup successful${NC}"
|
||||||
else
|
else
|
||||||
# Interactive mode - Foreground
|
# Interactive mode - Foreground (no PID-File)
|
||||||
|
echo -e "${GREEN}Interactive mode: Foreground${NC}"
|
||||||
exec "$LUA_COMMAND" src/main.lua
|
exec "$LUA_COMMAND" src/main.lua
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -4,7 +4,7 @@
|
||||||
|
|
||||||
BASE_URL="http://127.0.0.1:8080"
|
BASE_URL="http://127.0.0.1:8080"
|
||||||
# Use correct API keys that match current .env
|
# Use correct API keys that match current .env
|
||||||
API_KEY="hugo-dev-key-change-in-production"
|
API_KEY="YOUR_API_KEY_HERE"
|
||||||
|
|
||||||
echo "⚡ Furt API Stress Test"
|
echo "⚡ Furt API Stress Test"
|
||||||
echo "======================"
|
echo "======================"
|
||||||
|
|
|
||||||
|
|
@ -24,8 +24,13 @@ cp -r integrations/ "$TARGET/"
|
||||||
[ -f "VERSION" ] && cp VERSION "$TARGET/"
|
[ -f "VERSION" ] && cp VERSION "$TARGET/"
|
||||||
[ -f ".version_history" ] && cp .version_history "$TARGET/"
|
[ -f ".version_history" ] && cp .version_history "$TARGET/"
|
||||||
|
|
||||||
# Set proper permissions
|
# Set proper permissions based on operating system
|
||||||
chown -R root:wheel "$TARGET" 2>/dev/null || chown -R root:root "$TARGET"
|
if [ "$(uname)" = "OpenBSD" ]; then
|
||||||
|
chown -R root:wheel "$TARGET"
|
||||||
|
else
|
||||||
|
chown -R root:root "$TARGET"
|
||||||
|
fi
|
||||||
|
|
||||||
chmod -R 644 "$TARGET"
|
chmod -R 644 "$TARGET"
|
||||||
find "$TARGET" -type d -exec chmod 755 {} \;
|
find "$TARGET" -type d -exec chmod 755 {} \;
|
||||||
chmod +x "$TARGET/scripts/start.sh"
|
chmod +x "$TARGET/scripts/start.sh"
|
||||||
|
|
|
||||||
|
|
@ -3,8 +3,8 @@
|
||||||
# Test API-Key-Authentifizierung (ohne jq parse errors)
|
# Test API-Key-Authentifizierung (ohne jq parse errors)
|
||||||
|
|
||||||
BASE_URL="http://127.0.0.1:8080"
|
BASE_URL="http://127.0.0.1:8080"
|
||||||
HUGO_API_KEY="hugo-dev-key-change-in-production"
|
HUGO_API_KEY="YOUR_API_KEY_HERE"
|
||||||
ADMIN_API_KEY="admin-dev-key-change-in-production"
|
ADMIN_API_KEY="YOUR_ADMIN_KEY_HERE"
|
||||||
INVALID_API_KEY="invalid-key-should-fail"
|
INVALID_API_KEY="invalid-key-should-fail"
|
||||||
|
|
||||||
echo "🔐 Testing Furt API-Key Authentication"
|
echo "🔐 Testing Furt API-Key Authentication"
|
||||||
|
|
|
||||||
2
scripts/test_modular.sh
Normal file → Executable file
2
scripts/test_modular.sh
Normal file → Executable file
|
|
@ -3,7 +3,7 @@
|
||||||
# Test der modularen Furt-Architektur
|
# Test der modularen Furt-Architektur
|
||||||
|
|
||||||
BASE_URL="http://127.0.0.1:8080"
|
BASE_URL="http://127.0.0.1:8080"
|
||||||
HUGO_API_KEY="hugo-dev-key-change-in-production"
|
HUGO_API_KEY="YOUR_API_KEY_HERE"
|
||||||
|
|
||||||
echo "🧩 Testing Modular Furt Architecture"
|
echo "🧩 Testing Modular Furt Architecture"
|
||||||
echo "===================================="
|
echo "===================================="
|
||||||
|
|
|
||||||
6
scripts/test_smtp.sh
Normal file → Executable file
6
scripts/test_smtp.sh
Normal file → Executable file
|
|
@ -54,7 +54,7 @@ fi
|
||||||
# Test 4: Valid Mail Request (REAL SMTP TEST)
|
# Test 4: Valid Mail Request (REAL SMTP TEST)
|
||||||
echo ""
|
echo ""
|
||||||
echo "[4] Testing REAL mail sending..."
|
echo "[4] Testing REAL mail sending..."
|
||||||
echo "WARNING: This will send a real email to michael@dragons-at-work.de"
|
echo "WARNING: This will send a real email to admin@example.com"
|
||||||
read -p "Continue with real mail test? (y/N): " -n 1 -r
|
read -p "Continue with real mail test? (y/N): " -n 1 -r
|
||||||
echo
|
echo
|
||||||
|
|
||||||
|
|
@ -65,7 +65,7 @@ if [[ $REPLY =~ ^[Yy]$ ]]; then
|
||||||
-H "Content-Type: application/json" \
|
-H "Content-Type: application/json" \
|
||||||
-d '{
|
-d '{
|
||||||
"name": "Furt Test User",
|
"name": "Furt Test User",
|
||||||
"email": "test@dragons-at-work.de",
|
"email": "test@example.com",
|
||||||
"subject": "Furt SMTP Test - Week 2 Success!",
|
"subject": "Furt SMTP Test - Week 2 Success!",
|
||||||
"message": "This is a test email from the Furt Lua HTTP-Server.\n\nSMTP Integration is working!\n\nTimestamp: '$(date)'\nServer: furt-lua v1.0"
|
"message": "This is a test email from the Furt Lua HTTP-Server.\n\nSMTP Integration is working!\n\nTimestamp: '$(date)'\nServer: furt-lua v1.0"
|
||||||
}')
|
}')
|
||||||
|
|
@ -75,7 +75,7 @@ if [[ $REPLY =~ ^[Yy]$ ]]; then
|
||||||
# Check for success
|
# Check for success
|
||||||
if echo "$mail_response" | grep -q '"success":true'; then
|
if echo "$mail_response" | grep -q '"success":true'; then
|
||||||
echo "[OK] MAIL SENT SUCCESSFULLY!"
|
echo "[OK] MAIL SENT SUCCESSFULLY!"
|
||||||
echo "Check michael@dragons-at-work.de inbox"
|
echo "Check admin@example.com inbox"
|
||||||
|
|
||||||
# Extract request ID
|
# Extract request ID
|
||||||
request_id=$(echo "$mail_response" | grep -o '"request_id":"[^"]*"' | cut -d'"' -f4)
|
request_id=$(echo "$mail_response" | grep -o '"request_id":"[^"]*"' | cut -d'"' -f4)
|
||||||
|
|
|
||||||
|
|
@ -4,7 +4,7 @@
|
||||||
set -e
|
set -e
|
||||||
|
|
||||||
# Detect config file location
|
# Detect config file location
|
||||||
if [ "$(uname)" = "OpenBSD" ] || [ "$(uname)" = "FreeBSD" ]; then
|
if [ "$(uname)" = "OpenBSD" ]; then
|
||||||
CONFIG_FILE="/usr/local/etc/furt/furt.conf"
|
CONFIG_FILE="/usr/local/etc/furt/furt.conf"
|
||||||
else
|
else
|
||||||
CONFIG_FILE="/etc/furt/furt.conf"
|
CONFIG_FILE="/etc/furt/furt.conf"
|
||||||
|
|
@ -24,12 +24,13 @@ if ! grep -q '^\[server\]' "$CONFIG_FILE"; then
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if ! grep -q '^port\s*=' "$CONFIG_FILE"; then
|
# Fix: Use POSIX-compatible regex patterns
|
||||||
|
if ! grep -q '^[ \t]*port[ \t]*=' "$CONFIG_FILE"; then
|
||||||
echo "Error: server port not configured"
|
echo "Error: server port not configured"
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if ! grep -q '^host\s*=' "$CONFIG_FILE"; then
|
if ! grep -q '^[ \t]*host[ \t]*=' "$CONFIG_FILE"; then
|
||||||
echo "Error: server host not configured"
|
echo "Error: server host not configured"
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
|
|
|
||||||
|
|
@ -215,7 +215,7 @@ end
|
||||||
function ConfigParser.load_config()
|
function ConfigParser.load_config()
|
||||||
-- Try different locations based on OS
|
-- Try different locations based on OS
|
||||||
local config_paths = {
|
local config_paths = {
|
||||||
"/usr/local/etc/furt/furt.conf", -- OpenBSD/FreeBSD
|
"/usr/local/etc/furt/furt.conf", -- OpenBSD
|
||||||
"/etc/furt/furt.conf", -- Linux
|
"/etc/furt/furt.conf", -- Linux
|
||||||
"config/furt.conf", -- Development
|
"config/furt.conf", -- Development
|
||||||
"furt.conf" -- Current directory
|
"furt.conf" -- Current directory
|
||||||
|
|
|
||||||
|
|
@ -91,9 +91,7 @@ end
|
||||||
function FurtServer:add_cors_headers(request)
|
function FurtServer:add_cors_headers(request)
|
||||||
local allowed_origins = config.cors and config.cors.allowed_origins or {
|
local allowed_origins = config.cors and config.cors.allowed_origins or {
|
||||||
"http://localhost:1313",
|
"http://localhost:1313",
|
||||||
"http://127.0.0.1:1313",
|
"http://127.0.0.1:1313"
|
||||||
"https://dragons-at-work.de",
|
|
||||||
"https://www.dragons-at-work.de"
|
|
||||||
}
|
}
|
||||||
|
|
||||||
-- Check if request has Origin header
|
-- Check if request has Origin header
|
||||||
|
|
|
||||||
46
src/smtp.lua
46
src/smtp.lua
|
|
@ -1,6 +1,6 @@
|
||||||
-- furt-lua/src/smtp.lua
|
-- src/smtp.lua
|
||||||
-- Universal SMTP implementation with SSL compatibility
|
-- Universal SMTP implementation with SSL compatibility
|
||||||
-- Supports both luaossl (Arch/karl) and luasec (OpenBSD/walter)
|
-- Supports both luaossl (Arch) and luasec (OpenBSD)
|
||||||
-- Dragons@Work Digital Sovereignty Project
|
-- Dragons@Work Digital Sovereignty Project
|
||||||
|
|
||||||
local socket = require("socket")
|
local socket = require("socket")
|
||||||
|
|
@ -95,11 +95,11 @@ end
|
||||||
-- Create SMTP instance
|
-- Create SMTP instance
|
||||||
function SMTP:new(config)
|
function SMTP:new(config)
|
||||||
local instance = {
|
local instance = {
|
||||||
server = config.smtp_server or "mail.dragons-at-work.de",
|
server = config.smtp_server,
|
||||||
port = config.smtp_port or 465,
|
port = config.smtp_port,
|
||||||
username = config.username,
|
username = config.username,
|
||||||
password = config.password,
|
password = config.password,
|
||||||
from_address = config.from_address or "noreply@dragons-at-work.de",
|
from_address = config.from_address,
|
||||||
use_ssl = config.use_ssl or true,
|
use_ssl = config.use_ssl or true,
|
||||||
debug = config.debug or false,
|
debug = config.debug or false,
|
||||||
ssl_compat = SSLCompat
|
ssl_compat = SSLCompat
|
||||||
|
|
@ -237,6 +237,33 @@ function SMTP:send_email(to_address, subject, message, from_name)
|
||||||
return cleanup_and_fail("EHLO failed: " .. response)
|
return cleanup_and_fail("EHLO failed: " .. response)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
-- STARTTLS hinzufügen für Port 587
|
||||||
|
if self.port == 587 and self.use_ssl then
|
||||||
|
-- STARTTLS command
|
||||||
|
local success, response = self:send_command(sock, "STARTTLS", 220)
|
||||||
|
if not success then
|
||||||
|
return cleanup_and_fail("STARTTLS failed: " .. response)
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Upgrade connection to SSL
|
||||||
|
local ssl_sock, err = self.ssl_compat:wrap_socket(sock, {
|
||||||
|
mode = "client",
|
||||||
|
protocol = "tlsv1_2"
|
||||||
|
})
|
||||||
|
|
||||||
|
if not ssl_sock then
|
||||||
|
return cleanup_and_fail("SSL upgrade failed: " .. err)
|
||||||
|
end
|
||||||
|
|
||||||
|
sock = ssl_sock
|
||||||
|
|
||||||
|
-- EHLO again over encrypted connection
|
||||||
|
local success, response = self:send_command(sock, "EHLO furt-lua", 250)
|
||||||
|
if not success then
|
||||||
|
return cleanup_and_fail("EHLO after STARTTLS failed: " .. response)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
-- AUTH LOGIN
|
-- AUTH LOGIN
|
||||||
local success, response = self:send_command(sock, "AUTH LOGIN", 334)
|
local success, response = self:send_command(sock, "AUTH LOGIN", 334)
|
||||||
if not success then
|
if not success then
|
||||||
|
|
@ -277,6 +304,11 @@ function SMTP:send_email(to_address, subject, message, from_name)
|
||||||
return cleanup_and_fail("DATA command failed: " .. response)
|
return cleanup_and_fail("DATA command failed: " .. response)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
-- Generate unique Message-ID
|
||||||
|
-- Extract domain from configured from_address
|
||||||
|
local hostname = self.from_address:match("@(.+)") or self.server
|
||||||
|
local message_id = string.format("<%d.%d@%s>", os.time(), math.random(10000), hostname)
|
||||||
|
|
||||||
-- Build email message
|
-- Build email message
|
||||||
local display_name = from_name or "Furt Contact Form"
|
local display_name = from_name or "Furt Contact Form"
|
||||||
local email_content = string.format(
|
local email_content = string.format(
|
||||||
|
|
@ -284,7 +316,10 @@ function SMTP:send_email(to_address, subject, message, from_name)
|
||||||
"To: <%s>\r\n" ..
|
"To: <%s>\r\n" ..
|
||||||
"Subject: %s\r\n" ..
|
"Subject: %s\r\n" ..
|
||||||
"Date: %s\r\n" ..
|
"Date: %s\r\n" ..
|
||||||
|
"Message-ID: %s\r\n" ..
|
||||||
|
"MIME-Version: 1.0\r\n" ..
|
||||||
"Content-Type: text/plain; charset=UTF-8\r\n" ..
|
"Content-Type: text/plain; charset=UTF-8\r\n" ..
|
||||||
|
"Content-Transfer-Encoding: 8bit\r\n" ..
|
||||||
"\r\n" ..
|
"\r\n" ..
|
||||||
"%s\r\n" ..
|
"%s\r\n" ..
|
||||||
".",
|
".",
|
||||||
|
|
@ -293,6 +328,7 @@ function SMTP:send_email(to_address, subject, message, from_name)
|
||||||
to_address,
|
to_address,
|
||||||
subject,
|
subject,
|
||||||
os.date("%a, %d %b %Y %H:%M:%S %z"),
|
os.date("%a, %d %b %Y %H:%M:%S %z"),
|
||||||
|
message_id,
|
||||||
message
|
message
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue