# Acme Contact Form

Ein wiederverwendbares, spam-geschütztes Kontaktformular-Package für Laravel mit Livewire. Bietet Honeypot, zeitbasierte Prüfung, Inhaltsanalyse, Rate Limiting und mehr – ohne externe Dienste, DSGVO-konform.

## Features

- **Spam-Schutz**: Honeypot, Zeitprüfung, Inhaltsanalyse, Wegwerf-E-Mails, Rate Limiting, IP-Blacklist, Bot-User-Agent-Erkennung
- **Konfigurierbare Felder**: Presets (simple, full) oder eigene Felddefinitionen
- **Livewire**: Reaktives Formular ohne Page-Reload
- **Flexibel**: Einfache Formulare bis komplexe Multi-Feld-Formulare
- **DSGVO-konform**: Keine externen Services, alles in-house

## Voraussetzungen

- PHP 8.2+
- Laravel 10+ / 11+ / 12+
- Livewire 3+

## Installation

### 1. Package installieren

```bash
composer require acme/contact-form
```

Für lokale Entwicklung (Path-Repository):

```json
{
    "repositories": [
        {
            "type": "path",
            "url": "package/acme/contact-form"
        }
    ],
    "require": {
        "acme/contact-form": "@dev"
    }
}
```

```bash
composer update acme/contact-form
```

### 2. Konfiguration

```bash
php artisan vendor:publish --tag=contact-form-config
```

In `.env`:

```env
CONTACT_FORM_RECIPIENT=kontakt@ihre-domain.de
CONTACT_FORM_MAX_ATTEMPTS=3
CONTACT_FORM_DECAY_MINUTES=15
CONTACT_FORM_MIN_FILL_TIME=3
```

### 3. Übersetzungen (optional)

```bash
php artisan vendor:publish --tag=contact-form-lang
```

## Verwendung

### Einfaches Formular (Preset: simple)

Name, E-Mail, Nachricht, Datenschutz-Checkbox:

```blade
<livewire:contact-form />
```

Oder mit explizitem Preset:

```blade
<livewire:contact-form preset="simple" subject="Kontaktanfrage" />
```

### Vollständiges Formular (Preset: full)

Vorname, Nachname, E-Mail, Telefon, Unternehmen, Nachricht, Datenschutz:

```blade
<livewire:contact-form preset="full" subject="Neue Kontaktanfrage" />
```

### Eigenes Formular mit benutzerdefinierten Feldern

Sie können beliebige Felder definieren. Jedes Feld benötigt:

- `type`: `text`, `email`, `tel`, `textarea`, `select`, `checkbox`, `honeypot`
- `rules`: Laravel-Validierungsregeln (Array)
- `label`: Anzeigename (optional)
- `placeholder`: Platzhalter (optional)
- `required`: true/false (optional, wird aus rules abgeleitet)
- `name`: Formularfeld-Name (optional, Standard: Array-Key)
- `options`: Für `select` – Array [value => label] (optional)

**Beispiel: Minimales Formular (nur E-Mail + Nachricht)**

```blade
<livewire:contact-form
    :fields="[
        'email' => [
            'type' => 'email',
            'rules' => ['required', 'email:rfc,dns', 'max:150'],
            'label' => 'Ihre E-Mail',
            'placeholder' => 'name@beispiel.de',
        ],
        'message' => [
            'type' => 'textarea',
            'rules' => ['required', 'string', 'max:2000'],
            'label' => 'Nachricht',
        ],
        'privacy' => [
            'type' => 'checkbox',
            'rules' => ['accepted'],
            'label' => 'Ich stimme der Datenschutzerklärung zu.',
        ],
        'honeypot' => [
            'type' => 'honeypot',
            'name' => 'website',
            'rules' => ['nullable', 'string', 'max:0'],
        ],
    ]"
    subject="Feedback"
/>
```

**Beispiel: Formular mit Select-Feld**

```blade
<livewire:contact-form
    :fields="[
        'name' => [
            'type' => 'text',
            'rules' => ['required', 'string', 'max:120'],
            'label' => 'Name',
        ],
        'email' => [
            'type' => 'email',
            'rules' => ['required', 'email:rfc,dns'],
            'label' => 'E-Mail',
        ],
        'topic' => [
            'type' => 'select',
            'rules' => ['required', 'string', 'in:general,support,sales'],
            'label' => 'Betreff',
            'placeholder' => 'Bitte wählen...',
            'options' => [
                'general' => 'Allgemeine Anfrage',
                'support' => 'Technischer Support',
                'sales' => 'Verkauf',
            ],
        ],
        'message' => [
            'type' => 'textarea',
            'rules' => ['required', 'string', 'max:2000'],
            'label' => 'Nachricht',
        ],
        'privacy' => [
            'type' => 'checkbox',
            'rules' => ['accepted'],
            'label' => 'Datenschutz akzeptiert',
        ],
        'honeypot' => [
            'type' => 'honeypot',
            'name' => 'company_check',
            'rules' => ['nullable', 'string', 'max:0'],
        ],
    ]"
    subject="Anfrage über Kontaktformular"
/>
```

**Wichtig**: Jedes Formular sollte ein Honeypot-Feld enthalten. Das Feld wird für Nutzer unsichtbar dargestellt; Bots füllen es oft aus und werden so erkannt.

### Eigene Presets in der Config

In `config/contact-form.php` können Sie eigene Presets definieren:

```php
'presets' => [
    'mein-formular' => [
        'name' => [
            'type' => 'text',
            'rules' => ['required', 'string', 'max:120'],
            'label' => 'Name',
        ],
        'email' => [
            'type' => 'email',
            'rules' => ['required', 'email:rfc,dns'],
            'label' => 'E-Mail',
        ],
        'message' => [
            'type' => 'textarea',
            'rules' => ['required', 'string', 'max:2000'],
            'label' => 'Nachricht',
        ],
        'privacy' => [
            'type' => 'checkbox',
            'rules' => ['accepted'],
            'label' => 'Datenschutz',
        ],
        'honeypot' => [
            'type' => 'honeypot',
            'name' => 'website',
            'rules' => ['nullable', 'string', 'max:0'],
        ],
    ],
],
```

Verwendung:

```blade
<livewire:contact-form preset="mein-formular" />
```

## Spam-Schutz im Detail

| Maßnahme | Beschreibung |
|----------|--------------|
| **Honeypot** | Verstecktes Feld – wenn ausgefüllt → Spam |
| **Zeitprüfung** | Formular < 3 Sek. ausgefüllt → Spam |
| **Inhaltsanalyse** | Spam-Keywords, URLs, XSS-Muster → Spam |
| **Wegwerf-E-Mails** | tempmail.com, mailinator.com etc. → Spam |
| **Rate Limiting** | Max. 3 Anfragen/IP in 15 Min. (konfigurierbar) |
| **IP-Blacklist** | Blockierte IPs in Config |
| **Bot-User-Agent** | curl, wget, python-requests etc. → Spam |

Bei Spam wird **immer** eine Erfolgsmeldung angezeigt (Täuschung von Bots), aber **keine E-Mail** versendet. Alle Anfragen werden geloggt.

## Service und SpamDetector direkt nutzen

Falls Sie einen eigenen Controller oder eine eigene Livewire-Komponente verwenden möchten:

```php
use Acme\ContactForm\ContactFormService;
use Acme\ContactForm\SpamDetector;

// Spam prüfen
$spamDetector = SpamDetector::fromConfig();
$isSpam = $spamDetector->detect($validatedData, $formLoadedAt);

// Anfrage verarbeiten
$service = app(ContactFormService::class);
$service->handle([
    'name' => $request->input('name'),
    'email' => $request->input('email'),
    'message' => $request->input('message'),
    'ip' => $request->ip(),
    'user_agent' => $request->userAgent(),
    'is_spam' => $isSpam,
], 'Betreff der E-Mail', 'Log-Kontext');
```

## Konfiguration

| Option | Beschreibung | Standard |
|--------|--------------|----------|
| `recipient` | E-Mail-Empfänger | aus .env |
| `rate_limit.max_attempts` | Max. Anfragen pro IP | 3 |
| `rate_limit.decay_minutes` | Zeitfenster in Minuten | 15 |
| `blacklisted_ips` | IP-Adressen blockieren | [] |
| `honeypot_fields` | Namen der Honeypot-Felder | company_check, website, url |
| `spam.min_fill_time_seconds` | Min. Zeit zum Ausfüllen | 3 |
| `spam.suspicious_patterns` | Regex für Spam-Erkennung | siehe Config |
| `spam.disposable_email_domains` | Wegwerf-Domains | siehe Config |

## Styling anpassen

Die Standard-Views nutzen generische Klassen (`border-gray-300`, `focus:ring-primary`). Passen Sie sie an Ihr Design an:

```bash
php artisan vendor:publish --tag=contact-form-views
```

Die Views liegen dann unter `resources/views/vendor/contact-form/`.

## Event nach Absenden

Nach erfolgreichem Absenden wird das Event `contact-form-submitted` dispatched. Sie können darauf reagieren:

```blade
<div x-data="{ submitted: false }"
     x-on:contact-form-submitted.window="submitted = true">
    <livewire:contact-form />

    <template x-if="submitted">
        <p>Vielen Dank für Ihre Nachricht!</p>
    </template>
</div>
```

## Lizenz

MIT License
