Skip to content

Commit 5525b92

Browse files
cfat_ token support, suppress expected 403 log noise, add sending status badge and docs
1 parent 2a4d105 commit 5525b92

25 files changed

Lines changed: 287 additions & 33 deletions

dockflare/app/core/cloudflare_api.py

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@
3232

3333
dns_semaphore = threading.Semaphore(config.MAX_CONCURRENT_DNS_OPS)
3434

35-
def cf_api_request(method, endpoint, json_data=None, params=None):
35+
def cf_api_request(method, endpoint, json_data=None, params=None, log_errors=True):
3636

3737
url = f"{config.CF_API_BASE_URL}{endpoint}"
3838
error_msg = None
@@ -75,9 +75,10 @@ def cf_api_request(method, endpoint, json_data=None, params=None):
7575
error_code = cf_errors[0].get('code')
7676
else:
7777
error_msg = f"API reported failure but no error details provided. Response: {response_data}"
78-
logging.error(f"CF API Request Failed ({method} {url}): {error_msg} - Full Errors: {cf_errors}")
78+
if log_errors:
79+
logging.error(f"CF API Request Failed ({method} {url}): {error_msg} - Full Errors: {cf_errors}")
7980
api_exception = requests.exceptions.RequestException(error_msg, response=response)
80-
api_exception.cf_error_code = error_code
81+
api_exception.cf_error_code = error_code
8182
raise api_exception
8283
else:
8384
logging.warning(f"CF API response for {method} {url} was valid JSON but missing 'success' field. Status: {response.status_code}. Body: {str(response_data)[:200]}")
@@ -101,10 +102,12 @@ def cf_api_request(method, endpoint, json_data=None, params=None):
101102
log_error_msg += f" - API Details: {cf_errors[0].get('message', 'Unknown error')}"
102103
else:
103104
log_error_msg += f" - HTTP {e.response.status_code} - Response Text (first 100): {e.response.text[:100]}"
104-
logging.error(f"CF API Error Response Body: {error_data}")
105+
if log_errors:
106+
logging.error(f"CF API Error Response Body: {error_data}")
105107
except (ValueError, AttributeError, json.JSONDecodeError):
106108
log_error_msg += f" - HTTP {e.response.status_code} - Response Text (first 100): {e.response.text[:100]}"
107-
logging.error(log_error_msg)
109+
if log_errors:
110+
logging.error(log_error_msg)
108111
raise
109112

110113
def get_zone_id_from_name(zone_name):

dockflare/app/core/email_manager.py

Lines changed: 19 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -50,14 +50,16 @@ def check_token_permissions():
5050

5151
def enable_email_routing(zone_id):
5252
try:
53-
return cf_api_request('POST', f'/zones/{zone_id}/email/routing/enable')
53+
return cf_api_request('POST', f'/zones/{zone_id}/email/routing/enable', log_errors=False)
5454
except Exception as e:
55-
# 422/conflict means already enabled — safe to continue
5655
err_str = str(e)
5756
if '2004' in err_str or 'already enabled' in err_str.lower() or 'Unprocessable' in err_str:
5857
logging.info(f"Email routing already enabled on zone {zone_id}, continuing")
5958
return {}
60-
logging.error(f"Error enabling email routing: {e}")
59+
if '403' in err_str or 'Forbidden' in err_str or '10000' in err_str or 'Authentication' in err_str:
60+
logging.info(f"Email routing enable not permitted (zone {zone_id}); CF auto-activates via MX records")
61+
return {}
62+
logging.warning(f"Could not enable email routing on zone {zone_id}: {e}")
6163
raise
6264

6365
def enable_email_sending(zone_id, zone_name):
@@ -134,7 +136,7 @@ def _safe_create_dns(zone_id, type, name, content, priority=None):
134136

135137
def setup_email_dns_records(zone_id, zone_name):
136138
try:
137-
res = cf_api_request('GET', f'/zones/{zone_id}/email/routing/dns')
139+
res = cf_api_request('GET', f'/zones/{zone_id}/email/routing/dns', log_errors=False)
138140
required = res.get('result', [])
139141
for record in required:
140142
rtype = record.get('type')
@@ -144,13 +146,25 @@ def setup_email_dns_records(zone_id, zone_name):
144146
if rtype and rname and rcontent:
145147
_safe_create_dns(zone_id, rtype, rname, rcontent, priority=rpriority)
146148
except Exception as e:
147-
logging.warning(f"Could not fetch required email routing DNS records from CF API: {e}, falling back to defaults")
149+
logging.info(f"Could not fetch email routing DNS from CF API (falling back to defaults): {e}")
148150
_safe_create_dns(zone_id, 'MX', zone_name, 'route1.mx.cloudflare.net', priority=14)
149151
_safe_create_dns(zone_id, 'MX', zone_name, 'route2.mx.cloudflare.net', priority=36)
150152
_safe_create_dns(zone_id, 'MX', zone_name, 'route3.mx.cloudflare.net', priority=88)
151153
_safe_create_dns(zone_id, 'TXT', zone_name, 'v=spf1 include:_spf.mx.cloudflare.net ~all')
152154
_safe_create_dns(zone_id, 'TXT', f'_dmarc.{zone_name}', f'v=DMARC1; p=quarantine; rua=mailto:dmarc@{zone_name}')
153155

156+
def get_email_sending_status(zone_id, zone_name):
157+
try:
158+
res = cf_api_request('GET', f'/zones/{zone_id}/dns_records?type=TXT&search=_domainkey', log_errors=False)
159+
records = res.get('result', [])
160+
suffix = f'._domainkey.{zone_name}'
161+
for r in records:
162+
if r.get('name', '').endswith(suffix):
163+
return 'configured'
164+
return 'not_configured'
165+
except Exception:
166+
return 'unknown'
167+
154168
def verify_email_dns_records(zone_id, zone_name):
155169
res = cf_api_request('GET', f'/zones/{zone_id}/dns_records')
156170
records = res.get('result', [])

dockflare/app/main.py

Lines changed: 28 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -217,7 +217,34 @@ def start_core_services():
217217
if not config.USE_EXTERNAL_CLOUDFLARED and tunnel_state.get("id") and tunnel_state.get("token"):
218218
logging.info("Checking and reconciling managed cloudflared agent container...")
219219
start_cloudflared_container()
220-
220+
221+
if getattr(config, 'EMAIL_CONFIG', {}).get('enabled'):
222+
try:
223+
container = docker_client.containers.get('dockflare-mail-manager')
224+
if container.status == 'running':
225+
container.restart()
226+
logging.info("Email active: restarted dockflare-mail-manager to sync config.")
227+
except Exception as e:
228+
logging.debug(f"dockflare-mail-manager not found or could not restart: {e}")
229+
230+
try:
231+
from app.core.email_manager import get_email_sending_status
232+
from app.web.email_routes import save_email_config
233+
email_cfg = config.EMAIL_CONFIG
234+
updated = False
235+
for domain, domain_cfg in email_cfg.get('domains', {}).items():
236+
if domain_cfg.get('email_sending_status') in (None, 'unknown'):
237+
zone_id = domain_cfg.get('zone_id')
238+
if zone_id:
239+
status = get_email_sending_status(zone_id, domain)
240+
domain_cfg['email_sending_status'] = status
241+
updated = True
242+
logging.info(f"Email sending status for {domain}: {status}")
243+
if updated:
244+
save_email_config(email_cfg)
245+
except Exception as e:
246+
logging.debug(f"Could not refresh email sending status on startup: {e}")
247+
221248
run_all_background_tasks()
222249

223250
def perform_initial_setup_and_tasks():

dockflare/app/templates/docs/de/Email-Overview.md

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,22 @@ Das System besteht aus mehreren integrierten Komponenten:
1919
* **Ausgehend:** Webmail-UI → Mail Manager API → Outbound Worker → Cloudflare `send_email` → Internet.
2020
* **Datensouveränität:** Alle E-Mails werden geparst und in einer lokalen SQLite-Datenbank gespeichert; Anhänge werden im lokalen Dateisystem abgelegt.
2121

22+
## Ausgehende Nachrichten – Tarife & Einschränkungen
23+
24+
Cloudflare Email Sending (Beta) bietet je nach Cloudflare-Tarif zwei Stufen:
25+
26+
| Empfänger | Free-Tarif | Workers Paid Plan (5 $/Monat) |
27+
| :--- | :--- | :--- |
28+
| Verifizierte Cloudflare-Adressen (im CF-Konto bestätigte Adressen) | ✅ Erlaubt | ✅ Erlaubt |
29+
| Beliebige externe Adressen | ❌ Nicht erlaubt | ✅ Erlaubt |
30+
31+
DockFlare richtet die DKIM-Signierschlüssel und die Versandsubdomain (`mail.ihredomain.com`) automatisch während der Domain-Einrichtung ein. **Für den vollständigen externen Versand sind jedoch zwei zusätzliche manuelle Schritte erforderlich:**
32+
33+
1. **Upgrade auf den Cloudflare Workers Paid Plan** – verfügbar für 5 $/Monat in Ihrem Cloudflare-Dashboard.
34+
2. **CF Email Sending (Beta) aktivieren** – navigieren Sie in Ihrem [Cloudflare-Dashboard → E-Mail → E-Mail-Versand](https://dash.cloudflare.com/) und aktivieren Sie die Funktion für Ihr Konto.
35+
36+
Bis diese Schritte abgeschlossen sind, werden ausgehende E-Mails nur an E-Mail-Adressen zugestellt, die in Ihrem Cloudflare-Konto verifiziert sind. Das Domain-Status-Badge auf der DockFlare E-Mail-Verwaltungsseite zeigt an, ob DKIM konfiguriert ist (`Sending: Active`) oder noch nicht eingerichtet wurde (`Sending: Pending`).
37+
2238
## Hauptfunktionen
2339

2440
* **Multi-Domain-Unterstützung:** Hosten Sie E-Mails für beliebig viele Domains, die Sie in Cloudflare verwalten.

dockflare/app/templates/docs/de/Email-Prerequisites.md

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,12 @@ Bevor Sie die E-Mail-Suite aktivieren, stellen Sie sicher, dass Ihre Umgebung un
55
## Cloudflare-Anforderungen
66

77
1. **Domain-Verwaltung:** Ihre Domain muss in Cloudflare aktiv sein.
8-
2. **E-Mail-Routing:** Die Domain muss für Cloudflare E-Mail-Routing berechtigt sein (auf den meisten Tarifen verfügbar, einschließlich Free) und für Cloudflare E-Mail-Versand (Beta-Zugang für ausgehende Mails erforderlich).
9-
3. **R2-Speicher:** R2 muss in Ihrem Cloudflare-Dashboard aktiviert sein. R2 beinhaltet ein kostenloses Kontingent von 10 GB; zur Aktivierung kann jedoch eine Zahlungsmethode erforderlich sein.
8+
2. **E-Mail-Routing (Eingehend):** Cloudflare Email Routing ist auf allen Tarifen verfügbar, einschließlich Free. DockFlare konfiguriert die erforderlichen MX-, SPF- und DMARC-Einträge automatisch.
9+
3. **E-Mail-Versand (Ausgehend):** Cloudflare Email Sending befindet sich derzeit in der Beta-Phase. DockFlare konfiguriert die DKIM-Signierschlüssel und die Versandsubdomain automatisch. Für den Versand an externe Adressen ist jedoch Folgendes erforderlich:
10+
- Ein **Cloudflare Workers Paid Plan** (5 $/Monat).
11+
- Manuelle Aktivierung von **CF Email Sending (Beta)** im Cloudflare-Dashboard unter **E-Mail → E-Mail-Versand**.
12+
- Ohne diese Schritte ist der ausgehende Versand auf verifizierte Cloudflare-Adressen beschränkt.
13+
4. **R2-Speicher:** R2 muss in Ihrem Cloudflare-Dashboard aktiviert sein. R2 beinhaltet ein kostenloses Kontingent von 10 GB; zur Aktivierung kann jedoch eine Zahlungsmethode erforderlich sein.
1014

1115
## API-Token-Berechtigungen
1216

dockflare/app/templates/docs/en/Email-Overview.md

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,22 @@ The system consists of several integrated components:
1919
* **Outbound Flow:** Webmail UI → Mail Manager API → Outbound Worker → Cloudflare `send_email` → Internet.
2020
* **Data Sovereignty:** All emails are parsed and stored in a local SQLite database with attachments saved to your local filesystem.
2121

22+
## Outbound Sending — Plans & Limitations
23+
24+
Cloudflare Email Sending (Beta) has two tiers depending on your Cloudflare plan:
25+
26+
| Sending Target | Free Plan | Workers Paid Plan ($5/mo) |
27+
| :--- | :--- | :--- |
28+
| Verified Cloudflare addresses (addresses confirmed in your CF account) | ✅ Allowed | ✅ Allowed |
29+
| Any external address | ❌ Not allowed | ✅ Allowed |
30+
31+
DockFlare sets up the DKIM signing records and the sending subdomain (`mail.yourdomain.com`) automatically during domain setup. However, **full external sending requires two additional manual steps**:
32+
33+
1. **Upgrade to the Cloudflare Workers Paid Plan** — available at $5/month in your Cloudflare dashboard.
34+
2. **Activate CF Email Sending (Beta)** — navigate to your [Cloudflare Dashboard → Email → Email Sending](https://dash.cloudflare.com/) and enable the feature for your account.
35+
36+
Until these steps are completed, outbound mail from your webmail client will only be delivered to email addresses that have been verified in your Cloudflare account. The domain status badge in DockFlare's Email Management page reflects whether DKIM is configured (`Sending: Active`) or not yet set up (`Sending: Pending`).
37+
2238
## Key Features
2339

2440
* **Multi-Domain Support:** Host email for as many domains as you manage in Cloudflare.

dockflare/app/templates/docs/en/Email-Prerequisites.md

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,12 @@ Before enabling the Email Suite, ensure your environment and Cloudflare account
55
## Cloudflare Requirements
66

77
1. **Domain Management:** Your domain must be active on Cloudflare.
8-
2. **Email Routing:** The domain must be eligible for Cloudflare Email Routing (available on most plans, including Free) and Cloudflare Email Sending (Beta Access required for outbound mail).
9-
3. **R2 Storage:** You must have R2 enabled in your Cloudflare dashboard. R2 includes a free tier of 10 GB, but you may need to add a payment method to your account to activate it.
8+
2. **Email Routing (Inbound):** Cloudflare Email Routing is available on all plans, including Free. DockFlare configures the required MX, SPF, and DMARC records automatically.
9+
3. **Email Sending (Outbound):** Cloudflare Email Sending is currently in Beta. DockFlare automatically configures the DKIM signing records and sending subdomain. However, sending to external addresses requires:
10+
- A **Cloudflare Workers Paid Plan** ($5/month).
11+
- Manual activation of **CF Email Sending (Beta)** in the Cloudflare Dashboard under **Email → Email Sending**.
12+
- Without these steps, outbound mail is restricted to verified Cloudflare addresses only.
13+
4. **R2 Storage:** You must have R2 enabled in your Cloudflare dashboard. R2 includes a free tier of 10 GB, but you may need to add a payment method to your account to activate it.
1014

1115
## API Token Permissions
1216

dockflare/app/templates/docs/es/Email-Overview.md

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,22 @@ El sistema consta de varios componentes integrados:
1919
* **Flujo saliente:** Interfaz webmail → API Mail Manager → Outbound Worker → Cloudflare `send_email` → Internet.
2020
* **Soberanía de datos:** Todos los correos se analizan y almacenan en una base de datos SQLite local, con los archivos adjuntos guardados en su sistema de archivos local.
2121

22+
## Envío saliente – Planes y limitaciones
23+
24+
Cloudflare Email Sending (Beta) ofrece dos niveles según su plan de Cloudflare:
25+
26+
| Destinatario | Plan gratuito | Workers Paid Plan (5 $/mes) |
27+
| :--- | :--- | :--- |
28+
| Direcciones Cloudflare verificadas (confirmadas en su cuenta CF) | ✅ Permitido | ✅ Permitido |
29+
| Cualquier dirección externa | ❌ No permitido | ✅ Permitido |
30+
31+
DockFlare configura automáticamente los registros de firma DKIM y el subdominio de envío (`mail.sudominio.com`) durante la configuración del dominio. Sin embargo, **el envío externo completo requiere dos pasos manuales adicionales:**
32+
33+
1. **Actualizar al Cloudflare Workers Paid Plan** – disponible por 5 $/mes en su panel de Cloudflare.
34+
2. **Activar CF Email Sending (Beta)** – navegue a su [Panel de Cloudflare → Email → Email Sending](https://dash.cloudflare.com/) y habilite la función para su cuenta.
35+
36+
Hasta completar estos pasos, el correo saliente desde su cliente webmail solo se entregará a direcciones verificadas en su cuenta de Cloudflare. El badge de estado del dominio en la página de gestión de correo de DockFlare refleja si DKIM está configurado (`Sending: Active`) o aún no está listo (`Sending: Pending`).
37+
2238
## Características principales
2339

2440
* **Soporte multi-dominio:** Aloje correo electrónico para tantos dominios como gestione en Cloudflare.

dockflare/app/templates/docs/es/Email-Prerequisites.md

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,12 @@ Antes de activar la Suite de correo electrónico, asegúrese de que su entorno y
55
## Requisitos de Cloudflare
66

77
1. **Gestión de dominio:** Su dominio debe estar activo en Cloudflare.
8-
2. **Email Routing:** El dominio debe ser elegible para Cloudflare Email Routing (disponible en la mayoría de los planes, incluido el gratuito) y para Cloudflare Email Sending (se requiere acceso beta para el correo saliente).
9-
3. **Almacenamiento R2:** R2 debe estar habilitado en su panel de Cloudflare. R2 incluye un nivel gratuito de 10 GB, pero es posible que deba agregar un método de pago para activarlo.
8+
2. **Email Routing (Entrante):** Cloudflare Email Routing está disponible en todos los planes, incluido el gratuito. DockFlare configura automáticamente los registros MX, SPF y DMARC necesarios.
9+
3. **Email Sending (Saliente):** Cloudflare Email Sending se encuentra actualmente en Beta. DockFlare configura automáticamente los registros de firma DKIM y el subdominio de envío. Sin embargo, el envío a direcciones externas requiere:
10+
- Un **Cloudflare Workers Paid Plan** (5 $/mes).
11+
- La activación manual de **CF Email Sending (Beta)** en el Panel de Cloudflare bajo **Email → Email Sending**.
12+
- Sin estos pasos, el correo saliente queda restringido a direcciones Cloudflare verificadas.
13+
4. **Almacenamiento R2:** R2 debe estar habilitado en su panel de Cloudflare. R2 incluye un nivel gratuito de 10 GB, pero es posible que deba agregar un método de pago para activarlo.
1014

1115
## Permisos del token API
1216

dockflare/app/templates/docs/fr/Email-Overview.md

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,22 @@ Le système se compose de plusieurs composants intégrés :
1919
* **Flux sortant :** Interface Webmail → API Mail Manager → Outbound Worker → Cloudflare `send_email` → Internet.
2020
* **Souveraineté des données :** Tous les e-mails sont analysés et stockés dans une base de données SQLite locale, avec les pièces jointes sauvegardées sur votre système de fichiers local.
2121

22+
## Envoi sortant – Plans et limitations
23+
24+
Cloudflare Email Sending (Beta) propose deux niveaux selon votre plan Cloudflare :
25+
26+
| Destinataire | Plan gratuit | Workers Paid Plan (5 $/mois) |
27+
| :--- | :--- | :--- |
28+
| Adresses Cloudflare vérifiées (confirmées dans votre compte CF) | ✅ Autorisé | ✅ Autorisé |
29+
| Toute adresse externe | ❌ Non autorisé | ✅ Autorisé |
30+
31+
DockFlare configure automatiquement les enregistrements de signature DKIM et le sous-domaine d'envoi (`mail.votredomaine.com`) lors de la configuration du domaine. Cependant, **l'envoi externe complet nécessite deux étapes manuelles supplémentaires :**
32+
33+
1. **Passer au Cloudflare Workers Paid Plan** – disponible à 5 $/mois dans votre tableau de bord Cloudflare.
34+
2. **Activer CF Email Sending (Beta)** – accédez à votre [Tableau de bord Cloudflare → Email → Email Sending](https://dash.cloudflare.com/) et activez la fonctionnalité pour votre compte.
35+
36+
Tant que ces étapes ne sont pas effectuées, les e-mails sortants de votre client webmail ne seront délivrés qu'aux adresses vérifiées dans votre compte Cloudflare. Le badge de statut du domaine sur la page de gestion des e-mails de DockFlare indique si DKIM est configuré (`Sending: Active`) ou pas encore mis en place (`Sending: Pending`).
37+
2238
## Fonctionnalités principales
2339

2440
* **Support multi-domaine :** Hébergez la messagerie pour autant de domaines que vous en gérez dans Cloudflare.

0 commit comments

Comments
 (0)