Compare commits

...

4 Commits

Author SHA1 Message Date
Aiirondev_dev 8673c0f05c secrets processibg chanbged 2026-09-16 15:02:00 +02:00
Aiirondev_dev 7ab2899e92 changes to the Secret changes 2026-09-16 14:36:04 +02:00
Aiirondev_dev eba20b7e2e Fixes for the Secret deployment 2026-09-16 14:16:13 +02:00
Aiirondev_dev 92c86334e9 Refactor email configuration handling and improve logging for email delivery
Release Inventarsystem / release-docker (push) Successful in 2m25s
2026-09-15 22:48:26 +02:00
3 changed files with 127 additions and 98 deletions
+100 -91
View File
@@ -230,97 +230,106 @@ jobs:
tags: | tags: |
${{ steps.meta.outputs.image }} ${{ steps.meta.outputs.image }}
- name: Create release-only docker bundle - name: Create release-only docker bundle
run: | run: |
mkdir -p release-bundle mkdir -p release-bundle
cat > release-bundle/docker-compose.yml <<EOF
services: # 1. .env Datei aus Gitea Secrets erzeugen
app: cat > release-bundle/.env <<EOF
image: \${INVENTAR_APP_IMAGE:-${{ steps.meta.outputs.image }}} INVENTAR_SECRET_KEY=${{ secrets.INVENTAR_SECRET_KEY }}
container_name: inventarsystem-app INVENTAR_DATA_ENCRYPTION_KEY=${{ secrets.INVENTAR_DATA_ENCRYPTION_KEY }}
restart: unless-stopped INVENTAR_MONGODB_PASSWORD=${{ secrets.INVENTAR_MONGODB_PASSWORD }}
ports: EMAIL_ENABLED=${{ secrets.EMAIL_ENABLED }}
- "\${INVENTAR_HTTP_PORT:-10000}:8000" EMAIL_SMTP_HOST=${{ secrets.EMAIL_SMTP_HOST }}
depends_on: EMAIL_SMTP_PORT=${{ secrets.EMAIL_SMTP_PORT }}
- mongodb EMAIL_USERNAME=${{ secrets.EMAIL_USERNAME }}
- redis EMAIL_PASSWORD=${{ secrets.EMAIL_PASSWORD }}
environment: EMAIL_FROM_ADDRESS=${{ secrets.EMAIL_FROM_ADDRESS }}
INVENTAR_MONGODB_HOST: mongodb EOF
INVENTAR_MONGODB_PORT: "27017"
INVENTAR_MONGODB_DB: Inventarsystem # 2. docker-compose.yml nutzt env_file
INVENTAR_BACKUP_FOLDER: /data/backups cat > release-bundle/docker-compose.yml <<EOF
INVENTAR_LOGS_FOLDER: /data/logs services:
INVENTAR_SECRET_KEY: ${{secrets.INVENTAR_SECRET_KEY}} app:
INVENTAR_DATA_ENCRYPTION_KEY: ${{secrets.INVENTAR_DATA_ENCRYPTION_KEY}} image: \${INVENTAR_APP_IMAGE:-${{ steps.meta.outputs.image }}}
INVENTAR_MONGODB_PASSWORD: ${{secrets.INVENTAR_MONGODB_PASSWORD}} container_name: inventarsystem-app
EMAIL_ENABLED: ${{secrets.EMAIL_ENABLED}} restart: unless-stopped
EMAIL_SMTP_HOST: ${{secrets.EMAIL_SMTP_HOST}} env_file:
EMAIL_SMTP_PORT: ${{secrets.EMAIL_SMTP_PORT}} - .env
EMAIL_USERNAME: ${{secrets.EMAIL_USERNAME}} ports:
EMAIL_PASSWORD: ${{secrets.EMAIL_PASSWORD}} - "\${INVENTAR_HTTP_PORT:-10000}:8000"
expose: depends_on:
- "8000" - mongodb
volumes: - redis
- ./config.json:/app/config.json:ro environment:
- app_uploads:/app/Web/uploads INVENTAR_MONGODB_HOST: mongodb
- app_thumbnails:/app/Web/thumbnails INVENTAR_MONGODB_PORT: "27017"
- app_previews:/app/Web/previews INVENTAR_MONGODB_DB: Inventarsystem
- app_qrcodes:/app/Web/QRCodes INVENTAR_BACKUP_FOLDER: /data/backups
- app_backups:/data/backups INVENTAR_LOGS_FOLDER: /data/logs
- app_logs:/data/logs expose:
- "8000"
mongodb: volumes:
image: mongo:7.0 - ./config.json:/app/config.json:ro
container_name: inventarsystem-mongodb - app_uploads:/app/Web/uploads
restart: unless-stopped - app_thumbnails:/app/Web/thumbnails
volumes: - app_previews:/app/Web/previews
- mongodb_data:/data/db - app_qrcodes:/app/Web/QRCodes
healthcheck: - app_backups:/data/backups
test: ["CMD", "mongosh", "--quiet", "--eval", "db.adminCommand('ping').ok"] - app_logs:/data/logs
interval: 10s
timeout: 5s mongodb:
retries: 10 image: mongo:7.0
container_name: inventarsystem-mongodb
redis: restart: unless-stopped
image: redis:7-alpine volumes:
container_name: inventarsystem-redis - mongodb_data:/data/db
restart: unless-stopped healthcheck:
command: redis-server --appendonly yes --maxmemory 512mb --maxmemory-policy allkeys-lru test: ["CMD", "mongosh", "--quiet", "--eval", "db.adminCommand('ping').ok"]
ports: interval: 10s
- "6379:6379" timeout: 5s
volumes: retries: 10
- redis_data:/data
healthcheck: redis:
test: ["CMD", "redis-cli", "ping"] image: redis:7-alpine
interval: 10s container_name: inventarsystem-redis
timeout: 5s restart: unless-stopped
retries: 5 command: redis-server --appendonly yes --maxmemory 512mb --maxmemory-policy allkeys-lru
ports:
volumes: - "6379:6379"
mongodb_data: volumes:
app_uploads: - redis_data:/data
app_thumbnails: healthcheck:
app_previews: test: ["CMD", "redis-cli", "ping"]
app_qrcodes: interval: 10s
app_backups: timeout: 5s
app_logs: retries: 5
redis_data:
EOF volumes:
mongodb_data:
for f in start.sh stop.sh restart.sh backup.sh restore.sh config.json update.sh; do app_uploads:
if [ -f "$f" ]; then app_thumbnails:
cp "$f" "release-bundle/$(basename "$f")" app_previews:
fi app_qrcodes:
done app_backups:
app_logs:
for f in docker-compose-multitenant.yml manage-tenant.sh run-tenant-cmd.sh MULTITENANT_DEPLOYMENT.md MULTITENANT_PYTHON_API.md; do redis_data:
if [ -f "$f" ]; then EOF
cp "$f" "release-bundle/$(basename "$f")"
fi for f in start.sh stop.sh restart.sh backup.sh restore.sh config.json update.sh; do
done if [ -f "$f" ]; then
cp "$f" "release-bundle/$(basename "$f")"
find release-bundle -maxdepth 1 -type f -name '*.sh' -exec chmod +x {} \; || true fi
tar -czf inventarsystem-docker-bundle.tar.gz -C release-bundle . done
for f in docker-compose-multitenant.yml manage-tenant.sh run-tenant-cmd.sh MULTITENANT_DEPLOYMENT.md MULTITENANT_PYTHON_API.md; do
if [ -f "$f" ]; then
cp "$f" "release-bundle/$(basename "$f")"
fi
done
find release-bundle -maxdepth 1 -type f -name '*.sh' -exec chmod +x {} \; || true
tar -czf inventarsystem-docker-bundle.tar.gz -C release-bundle .
- name: Create or update Gitea Release - name: Create or update Gitea Release
uses: https://gitea.com/actions/gitea-release-action@v1 uses: https://gitea.com/actions/gitea-release-action@v1
+17 -5
View File
@@ -220,13 +220,25 @@ SSL_CERT = _get(_conf, ['ssl', 'cert'], DEFAULTS['ssl']['cert'])
SSL_KEY = _get(_conf, ['ssl', 'key'], DEFAULTS['ssl']['key']) SSL_KEY = _get(_conf, ['ssl', 'key'], DEFAULTS['ssl']['key'])
# Email settings # Email settings
EMAIL_ENABLED = bool(os.getenv('EMAIL_ENABLED', False)) def _get_email_env(name, default=''):
EMAIL_SMTP_HOST = str(os.getenv('EMAIL_SMTP_HOST', False)) value = os.getenv(name)
if value is None:
return default
value = value.strip()
return '' if value.lower() in {'', 'false', 'none', 'null'} else value
EMAIL_ENABLED = _get_email_env('EMAIL_ENABLED').lower() in {'1', 'true', 'yes', 'on'}
EMAIL_SMTP_HOST = _get_email_env('EMAIL_SMTP_HOST')
EMAIL_SMTP_PORT = int(os.getenv('EMAIL_SMTP_PORT', 587)) EMAIL_SMTP_PORT = int(os.getenv('EMAIL_SMTP_PORT', 587))
EMAIL_USE_TLS = True EMAIL_USE_TLS = True
EMAIL_USERNAME = str(os.getenv('EMAIL_USERNAME', False)) EMAIL_USERNAME = _get_email_env('EMAIL_USERNAME')
EMAIL_PASSWORD = str(os.getenv('EMAIL_PASSWORD', False)) EMAIL_PASSWORD = _get_email_env('EMAIL_PASSWORD')
EMAIL_FROM_ADDRESS = _get(_conf, ['email', 'from_address'], EMAIL_USERNAME) EMAIL_FROM_ADDRESS = (
_get_email_env('EMAIL_FROM_ADDRESS')
or _get(_conf, ['email', 'from_address'], '')
or EMAIL_USERNAME
)
EMAIL_DEFAULT_SENDER_NAME = "Invario Inventarsystem Sender" EMAIL_DEFAULT_SENDER_NAME = "Invario Inventarsystem Sender"
EMAIL_TIMEOUT_SECONDS = 20 EMAIL_TIMEOUT_SECONDS = 20
+10 -2
View File
@@ -3,11 +3,18 @@ from email.mime.text import MIMEText
from email.mime.application import MIMEApplication from email.mime.application import MIMEApplication
import smtplib import smtplib
import time import time
import logging
import Web.modules.database.settings as cfg import Web.modules.database.settings as cfg
logger = logging.getLogger(__name__)
def _build_smtp_client(): def _build_smtp_client():
if not cfg.EMAIL_SMTP_HOST:
raise RuntimeError('EMAIL_SMTP_HOST ist nicht konfiguriert')
smtp = smtplib.SMTP( smtp = smtplib.SMTP(
cfg.EMAIL_SMTP_HOST, cfg.EMAIL_SMTP_HOST,
cfg.EMAIL_SMTP_PORT, cfg.EMAIL_SMTP_PORT,
@@ -31,11 +38,12 @@ def _normalize_recipients(email: list | str) -> list[str]:
def _send_message(email: list | str, subject: str, note: str, sender: str, attachment=None) -> bool: def _send_message(email: list | str, subject: str, note: str, sender: str, attachment=None) -> bool:
"""Send a plain/HTML message, optionally with one PDF attachment.""" """Send a plain/HTML message, optionally with one PDF attachment."""
if not cfg.MODULES.is_enabled("mail"): if not cfg.MODULES.is_enabled("mail"):
print("Debug: Module not enabled") logger.info("Email delivery skipped because the mail module is disabled")
return False return False
recipients = _normalize_recipients(email) recipients = _normalize_recipients(email)
if not recipients: if not recipients:
logger.warning("Email delivery skipped because no recipients were provided")
return False return False
body_message = note body_message = note
@@ -104,7 +112,7 @@ def _send_message(email: list | str, subject: str, note: str, sender: str, attac
return True return True
except Exception as e: except Exception as e:
print(f"Debug: Fehler beim Senden der E-Mail: {e}") logger.exception("Email delivery failed: %s", e)
return False return False
finally: finally:
if smtp: if smtp: