# archivmail REST API v1

> **Lese-API** – alle Endpunkte sind read-only (`GET`). Schreiboperationen sind nicht verfügbar.

## Authentifizierung

Jede Anfrage muss einen gültigen API-Key im HTTP-Header mitschicken:

```
Authorization: Bearer <api-key>
```

API-Keys werden vom Admin im Admin-Bereich generiert und verwaltet. Ein API-Key hat eine zugewiesene Rolle (`user` oder `auditor`), die den Zugriffsumfang bestimmt.

| Rolle | Zugriff |
|-------|---------|
| `user` | Nur E-Mails aus zugewiesenen Postfächern |
| `auditor` | Alle E-Mails (postfachübergreifend) |

---

## Fehlercodes

| Code | Bedeutung |
|------|-----------|
| `200 OK` | Erfolg |
| `400 Bad Request` | Ungültige Parameter |
| `401 Unauthorized` | API-Key fehlt, ungültig oder deaktiviert |
| `403 Forbidden` | API-Key hat keine Berechtigung für diese Ressource |
| `404 Not Found` | E-Mail nicht gefunden |
| `405 Method Not Allowed` | Schreibmethode (POST, PUT, DELETE etc.) nicht erlaubt |
| `429 Too Many Requests` | Rate-Limit überschritten (Standard: 60 Anfragen/Minute) |
| `500 Internal Server Error` | Serverfehler |

---

## Endpunkte

---

### E-Mails suchen / filtern

```
GET /api/v1/mails
```

**Query-Parameter (alle optional, kombinierbar):**

| Parameter | Typ | Beschreibung | Beispiel |
|-----------|-----|-------------|---------|
| `q` | string | Volltext-Suche (Manticore QueryParser) | `q=Rechnung+2024` |
| `from` | string | Absender (exakt oder Partial-Match) | `from=alice@firma.de` |
| `to` | string | Empfänger | `to=bob@firma.de` |
| `cc` | string | CC-Empfänger | `cc=team@firma.de` |
| `contact` | string | From **oder** To **oder** CC enthält diese Adresse | `contact=kunde@example.com` |
| `subject` | string | Betreff enthält diesen Text | `subject=Angebot` |
| `date_from` | string (ISO 8601) | Mails ab diesem Datum | `date_from=2024-01-01` |
| `date_to` | string (ISO 8601) | Mails bis zu diesem Datum | `date_to=2024-12-31` |
| `has_attachments` | boolean | Nur Mails mit/ohne Anhänge | `has_attachments=true` |
| `page` | integer | Seite (Standard: 1) | `page=2` |
| `limit` | integer | Ergebnisse pro Seite (Standard: 25, max: 100) | `limit=50` |
| `sort` | string | Sortierung: `date_asc`, `date_desc` (Standard), `relevance` | `sort=date_asc` |

**Beispiel-Request:**
```
GET /api/v1/mails?contact=kunde@example.com&date_from=2024-01-01&limit=25
Authorization: Bearer am_abc123...
```

**Antwort:**
```json
{
  "total": 142,
  "page": 1,
  "limit": 25,
  "pages": 6,
  "mails": [
    {
      "message_id": "<abc123@mailserver.firma.de>",
      "from": "alice@firma.de",
      "to": ["kunde@example.com"],
      "cc": [],
      "subject": "Angebot vom 15.03.2024",
      "date": "2024-03-15T10:23:00Z",
      "size": 24680,
      "has_attachments": true,
      "attachments": [
        {
          "filename": "Angebot_2024.pdf",
          "mime_type": "application/pdf",
          "size": 18432
        }
      ]
    }
  ]
}
```

---

### Einzelne E-Mail abrufen (Metadaten + Body)

```
GET /api/v1/mails/{message_id}
```

**Pfad-Parameter:**

| Parameter | Beschreibung |
|-----------|-------------|
| `message_id` | RFC-2822 Message-ID (URL-encoded) |

**Beispiel-Request:**
```
GET /api/v1/mails/%3Cabc123%40mailserver.firma.de%3E
Authorization: Bearer am_abc123...
```

**Antwort:**
```json
{
  "message_id": "<abc123@mailserver.firma.de>",
  "from": "alice@firma.de",
  "to": ["kunde@example.com"],
  "cc": [],
  "subject": "Angebot vom 15.03.2024",
  "date": "2024-03-15T10:23:00Z",
  "size": 24680,
  "body_plain": "Sehr geehrte Damen und Herren,\n\nim Anhang finden Sie...",
  "body_html": "<html>...</html>",
  "has_attachments": true,
  "attachments": [
    {
      "filename": "Angebot_2024.pdf",
      "mime_type": "application/pdf",
      "size": 18432,
      "download_url": "/api/v1/mails/%3Cabc123%40mailserver.firma.de%3E/attachments/0"
    }
  ]
}
```

---

### Original-E-Mail als EML herunterladen

```
GET /api/v1/mails/{message_id}/raw
```

Gibt die originale, unveränderte E-Mail im RFC-2822-Format zurück.

**Antwort-Header:**
```
Content-Type: message/rfc822
Content-Disposition: attachment; filename="<message_id>.eml"
```

---

### Einzelnen Anhang herunterladen

```
GET /api/v1/mails/{message_id}/attachments/{index}
```

**Pfad-Parameter:**

| Parameter | Beschreibung |
|-----------|-------------|
| `message_id` | RFC-2822 Message-ID (URL-encoded) |
| `index` | Position des Anhangs (0-basiert, aus der Attachment-Liste) |

**Antwort-Header:**
```
Content-Type: application/pdf        (je nach MIME-Type des Anhangs)
Content-Disposition: attachment; filename="Angebot_2024.pdf"
```

---

### Server-Info

```
GET /api/v1/info
```

Gibt Version und Status des Servers zurück. Nützlich zum Testen der Verbindung.

**Antwort:**
```json
{
  "version": "1.0.0",
  "status": "ok",
  "mail_count": 142857
}
```

---

## Volltext-Suche Syntax (`q`-Parameter)

Der `q`-Parameter unterstützt Manticore QueryParser-Syntax:

| Syntax | Beispiel | Bedeutung |
|--------|---------|-----------|
| Einfacher Begriff | `Rechnung` | Enthält "Rechnung" |
| Mehrere Begriffe | `Rechnung Mahnung` | Enthält beide Begriffe (AND) |
| Phrasensuche | `"offene Rechnung"` | Exakter Ausdruck |
| OR-Verknüpfung | `Rechnung OR Angebot` | Eines von beiden |
| Ausschließen | `Rechnung NOT Storno` | Rechnung aber nicht Storno |
| Wildcard | `Rechnun*` | Beginnt mit "Rechnun" |
| Feldspezifisch | `subject:Angebot` | Nur im Betreff suchen |
| Feldspezifisch | `from:alice@firma.de` | Nur von diesem Absender |

---

## Paginierung

Alle Listen-Endpunkte sind paginiert:

```
GET /api/v1/mails?page=2&limit=50
```

Die Antwort enthält immer:
- `total` – Gesamtanzahl der Treffer
- `page` – aktuelle Seite
- `limit` – Einträge pro Seite
- `pages` – Gesamtanzahl der Seiten

Maximum: 100 Einträge pro Anfrage. Für größere Abfragen mehrere Seiten iterieren.

---

## Rate Limiting

Standard: **60 Anfragen pro Minute** pro API-Key (konfigurierbar durch Admin).

Bei Überschreitung:
```
HTTP 429 Too Many Requests
Retry-After: 30
```

---

## Changelog

| Version | Datum | Änderungen |
|---------|-------|-----------|
| v1.0 | 2026-03-13 | Initiale Version |
