2 Mail Service API
michael edited this page 2025-09-10 14:12:26 +02:00

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

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

{
  "name": "string (required, non-empty)",
  "email": "string (required, valid email)",
  "message": "string (required, non-empty, max 5000 chars)"
}

Optional Fields

{
  "subject": "string (optional, max 200 chars)"
}

Complete Example

{
  "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
// 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
// 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)

{
  "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)

{
  "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)

{
  "success": false,
  "error": "Invalid JSON",
  "code": "INVALID_JSON",
  "body": "the-invalid-json-string"
}

Missing Body Error (HTTP 400)

{
  "success": false,
  "error": "No request body",
  "code": "MISSING_BODY"
}

Configuration Error (HTTP 500)

{
  "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)

{
  "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
X-RateLimit-Limit: 60
X-RateLimit-Remaining: 45
X-RateLimit-Reset: 1632150000

Rate-Limit-Exceeded Response (HTTP 429):

{
  "success": false,
  "error": "Rate limit exceeded",
  "code": "RATE_LIMIT_EXCEEDED"
}

Integration Examples

HTML Form (Basic)

<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

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

{{< furt-contact-form
    api-endpoint="https://api.example.com/v1/mail/send"
    api-key="your-api-key"
    success-url="/contact/thanks/"
    fields="name,email,subject,message"
>}}

curl Testing

# Valid request
curl -X POST https://api.example.com/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.example.com/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:

# 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