Mail Service API hinzugefügt
parent
ece6b49254
commit
317669d24c
1 changed files with 380 additions and 0 deletions
380
Mail-Service-API.md
Normal file
380
Mail-Service-API.md
Normal file
|
|
@ -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 <john@example.com>
|
||||
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
|
||||
<form id="contact-form">
|
||||
<input type="text" name="name" required>
|
||||
<input type="email" name="email" required>
|
||||
<input type="text" name="subject">
|
||||
<textarea name="message" required maxlength="5000"></textarea>
|
||||
<button type="submit">Send Message</button>
|
||||
</form>
|
||||
```
|
||||
|
||||
### 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
|
||||
```
|
||||
Loading…
Add table
Add a link
Reference in a new issue