diff --git a/Mail-Service-API.md b/Mail-Service-API.md new file mode 100644 index 0000000..46b519c --- /dev/null +++ b/Mail-Service-API.md @@ -0,0 +1,380 @@ +# Mail Service API + +**Multi-Tenant Mail-Weiterleitung für Kontaktformulare** + +## Endpoint + +``` +POST /v1/mail/send +``` + +**Zweck:** Leitet Kontaktformular-Daten als E-Mail an konfigurierte Empfänger weiter. Jeder API-Key erhält seine eigene Mail-Konfiguration. + +## Authentication + +```http +X-API-Key: your-tenant-api-key +``` + +**Warum Tenant-basiert:** Jeder API-Key definiert: +- Eigenen Mail-Empfänger +- Eigene SMTP-Konfiguration +- Eigene Subject-Präfixe +- Isolierte Mail-Logs + +Dadurch kann ein Furt-Gateway Kontaktformulare für mehrere Websites gleichzeitig verwalten. + +## Request Format + +### Required Fields + +```json +{ + "name": "string (required, non-empty)", + "email": "string (required, valid email)", + "message": "string (required, non-empty, max 5000 chars)" +} +``` + +### Optional Fields + +```json +{ + "subject": "string (optional, max 200 chars)" +} +``` + +### Complete Example + +```json +{ + "name": "John Doe", + "email": "john@example.com", + "subject": "Partnership Inquiry", + "message": "Hello, I'm interested in discussing a potential partnership. Could we schedule a call this week?" +} +``` + +## Validation Rules + +**Warum strenge Validation:** Verhindert Spam und gewährleistet brauchbare Mails. + +### Name Validation +- **Required:** Feld muss vorhanden sein +- **Non-empty:** Keine leeren Strings oder nur Whitespace +- **Type:** Muss String sein + +```json +// Invalid examples +{"name": ""} // Empty string +{"name": " "} // Only whitespace +{"name": null} // Null value +{"name": 123} // Wrong type +``` + +### Email Validation +- **Required:** Feld muss vorhanden sein +- **Format:** Basis-Regex-Validation `^[^@]+@[^@]+%.[^@]+$` +- **Type:** Muss String sein + +```json +// Invalid examples +{"email": "notanemail"} // Missing @ +{"email": "user@"} // Missing domain +{"email": "@domain.com"} // Missing user +{"email": "user@domain"} // Missing TLD +``` + +### Message Validation +- **Required:** Feld muss vorhanden sein +- **Non-empty:** Keine leeren Strings oder nur Whitespace +- **Length:** Maximum 5000 Zeichen +- **Type:** Muss String sein + +### Subject Validation (Optional) +- **Optional:** Feld kann fehlen +- **Length:** Maximum 200 Zeichen wenn vorhanden +- **Type:** Muss String sein wenn vorhanden +- **Default:** "Contact Form Message" wenn nicht angegeben + +## Response Format + +### Success Response (HTTP 200) + +```json +{ + "success": true, + "message": "Mail sent successfully", + "request_id": "1632150000-1234", + "tenant": { + "name": "your-website", + "recipient": "contact@your-website.com", + "smtp_server": "mail.your-provider.com" + } +} +``` + +**Tenant-Info:** Zeigt welche Konfiguration verwendet wurde. Nützlich für Debugging bei Multi-Tenant-Setups. + +### Error Responses + +#### Validation Error (HTTP 400) + +```json +{ + "success": false, + "error": "Name is required and cannot be empty", + "code": "VALIDATION_ERROR", + "request_id": "1632150000-1234" +} +``` + +**Mögliche Validation-Errors:** +- `"Name is required and cannot be empty"` +- `"Valid email address is required"` +- `"Message is required and cannot be empty"` +- `"Subject must be a string with max 200 characters"` +- `"Message too long (max 5000 characters)"` + +#### JSON Error (HTTP 400) + +```json +{ + "success": false, + "error": "Invalid JSON", + "code": "INVALID_JSON", + "body": "the-invalid-json-string" +} +``` + +#### Missing Body Error (HTTP 400) + +```json +{ + "success": false, + "error": "No request body", + "code": "MISSING_BODY" +} +``` + +#### Configuration Error (HTTP 500) + +```json +{ + "success": false, + "error": "Mail configuration error: No recipient configured for this API key", + "code": "CONFIG_ERROR", + "request_id": "1632150000-1234" +} +``` + +**Warum Config-Errors:** Wenn ein API-Key keine vollständige Mail-Konfiguration hat (fehlender Empfänger, SMTP-Server, etc.). + +#### SMTP Error (HTTP 500) + +```json +{ + "success": false, + "error": "Failed to send email: SMTP connection failed", + "code": "SMTP_ERROR", + "request_id": "1632150000-1234", + "tenant": "your-website" +} +``` + +## Multi-Tenant Configuration + +**Warum Multi-Tenant:** Ermöglicht einem Furt-Gateway, Mails für verschiedene Websites zu verwalten. + +### Tenant-spezifische Features + +#### Subject Prefix +Jeder Tenant kann ein Subject-Präfix konfigurieren: + +``` +Tenant-Config: subject_prefix = "[Website-A] " +User-Subject: "Partnership Inquiry" +Final-Subject: "[Website-A] Partnership Inquiry" +``` + +#### Mail Content +Die gesendete Mail enthält alle Kontext-Informationen: + +``` +Website: your-website (your-api-key) +From: John Doe +Subject: Partnership Inquiry + +Hello, I'm interested in discussing a potential partnership. +Could we schedule a call this week? + +--- +Sent via Furt Gateway +API Key: your-website +Request ID: 1632150000-1234 +``` + +**Warum detaillierte Mails:** Empfänger sehen sofort von welcher Website die Mail kommt und haben alle nötigen Infos für die Antwort. + +## Rate Limiting + +Mail-Requests unterliegen Rate-Limiting pro API-Key: + +- **Standard:** 60 Requests pro Minute +- **Konfigurierbar:** Per Tenant anpassbar +- **Headers:** Rate-Limit-Status in Response-Headers + +```http +X-RateLimit-Limit: 60 +X-RateLimit-Remaining: 45 +X-RateLimit-Reset: 1632150000 +``` + +**Rate-Limit-Exceeded Response (HTTP 429):** + +```json +{ + "success": false, + "error": "Rate limit exceeded", + "code": "RATE_LIMIT_EXCEEDED" +} +``` + +## Integration Examples + +### HTML Form (Basic) + +```html +
+ + + + + +
+``` + +### JavaScript Integration + +```javascript +document.getElementById('contact-form').addEventListener('submit', async (e) => { + e.preventDefault(); + + const formData = new FormData(e.target); + const data = Object.fromEntries(formData); + + try { + const response = await fetch('/v1/mail/send', { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + 'X-API-Key': 'your-api-key' + }, + body: JSON.stringify(data) + }); + + const result = await response.json(); + + if (result.success) { + alert('Message sent successfully!'); + e.target.reset(); + } else { + alert('Error: ' + result.error); + } + } catch (error) { + alert('Network error: ' + error.message); + } +}); +``` + +### Hugo Shortcode Integration + +```go +{{< furt-contact-form + api-endpoint="https://api.dragons-at-work.de/v1/mail/send" + api-key="your-api-key" + success-url="/contact/thanks/" + fields="name,email,subject,message" +>}} +``` + +### curl Testing + +```bash +# Valid request +curl -X POST https://api.dragons-at-work.de/v1/mail/send \ + -H "Content-Type: application/json" \ + -H "X-API-Key: your-api-key" \ + -d '{ + "name": "Test User", + "email": "test@example.com", + "subject": "Test Message", + "message": "This is a test message from the API." + }' + +# Test validation error +curl -X POST https://api.dragons-at-work.de/v1/mail/send \ + -H "Content-Type: application/json" \ + -H "X-API-Key: your-api-key" \ + -d '{ + "name": "", + "email": "invalid-email", + "message": "" + }' +``` + +## Security Considerations + +### Input Sanitization +- **HTML-Escaping:** User-Input wird in der Mail HTML-escaped +- **Length-Limits:** Verhindert Memory-Exhaustion-Attacks +- **Email-Validation:** Verhindert Mail-Header-Injection + +### SMTP Security +- **Per-Tenant-SMTP:** Jeder Tenant nutzt eigene SMTP-Credentials +- **Connection-Pooling:** Wiederverwendung von SMTP-Connections +- **Error-Isolation:** SMTP-Failures eines Tenants beeinflussen andere nicht + +### Rate Limiting +- **Spam-Protection:** Verhindert Missbrauch als Mail-Relay +- **Per-Key-Limits:** Isolierte Limits pro Tenant +- **Configurable:** Limits können per Tenant angepasst werden + +## Troubleshooting + +### Common Issues + +**"Mail configuration error":** +- API-Key hat keine vollständige Mail-Konfiguration +- Prüfe `/etc/furt/furt.conf` oder `/usr/local/etc/furt/furt.conf` +- Tenant muss `to_address`, `from_address`, SMTP-Details haben + +**"SMTP connection failed":** +- SMTP-Server nicht erreichbar +- Falsche SMTP-Credentials +- Firewall blockiert SMTP-Port (587/465) + +**"Validation errors":** +- Prüfe Request-Format gegen Validation-Rules +- Stelle sicher dass alle Required-Fields vorhanden sind +- Prüfe Field-Types (String vs. Number, etc.) + +### Debug Mode + +Für Debugging können detaillierte Logs aktiviert werden: + +```bash +# Server-Logs anzeigen +journalctl -fu furt # Linux +tail -f /var/log/daemon # OpenBSD +``` + +**Log-Format:** +``` +Mail endpoint called - Method: POST, Path: /v1/mail/send +Authenticated as: your-website (your-api-key) +Sending mail for tenant: your-website + To: contact@your-website.com + From: noreply@your-website.com + SMTP: mail.your-provider.com:587 +``` \ No newline at end of file