mirror of
https://git.hexahost.dev/smueller/HexaHost-Frontend.git
synced 2026-06-02 04:48:44 +00:00
Formular-Handling verbessert: CSRF-Token hinzugefügt, AJAX-Formularübermittlung implementiert und neue CSS-Stile für verschiedene Abschnitte hinzugefügt.
This commit is contained in:
96
public/.htaccess
Normal file
96
public/.htaccess
Normal file
@@ -0,0 +1,96 @@
|
||||
# HexaHost.de .htaccess
|
||||
# Sicherheit und Performance-Optimierungen
|
||||
|
||||
# Sicherheitsheader
|
||||
<IfModule mod_headers.c>
|
||||
Header always set X-Content-Type-Options nosniff
|
||||
Header always set X-Frame-Options DENY
|
||||
Header always set X-XSS-Protection "1; mode=block"
|
||||
Header always set Referrer-Policy "strict-origin-when-cross-origin"
|
||||
Header always set Permissions-Policy "geolocation=(), microphone=(), camera=()"
|
||||
</IfModule>
|
||||
|
||||
# HTTPS erzwingen (falls SSL verfügbar)
|
||||
<IfModule mod_rewrite.c>
|
||||
RewriteEngine On
|
||||
RewriteCond %{HTTPS} off
|
||||
RewriteCond %{HTTP_HOST} ^(www\.)?hexahost\.de$ [NC]
|
||||
RewriteRule ^(.*)$ https://%{HTTP_HOST}%{REQUEST_URI} [L,R=301]
|
||||
</IfModule>
|
||||
|
||||
# Konfigurationsdateien schützen
|
||||
<Files "mail-config.php">
|
||||
Order allow,deny
|
||||
Deny from all
|
||||
</Files>
|
||||
|
||||
<Files "composer.json">
|
||||
Order allow,deny
|
||||
Deny from all
|
||||
</Files>
|
||||
|
||||
<Files "composer.lock">
|
||||
Order allow,deny
|
||||
Deny from all
|
||||
</Files>
|
||||
|
||||
# Logs-Verzeichnis schützen
|
||||
<Directory "logs">
|
||||
Order allow,deny
|
||||
Deny from all
|
||||
</Directory>
|
||||
|
||||
# Vendor-Verzeichnis schützen
|
||||
<Directory "vendor">
|
||||
Order allow,deny
|
||||
Deny from all
|
||||
</Directory>
|
||||
|
||||
# Cache-Header für statische Dateien
|
||||
<IfModule mod_expires.c>
|
||||
ExpiresActive On
|
||||
ExpiresByType text/css "access plus 1 month"
|
||||
ExpiresByType application/javascript "access plus 1 month"
|
||||
ExpiresByType image/png "access plus 1 month"
|
||||
ExpiresByType image/jpg "access plus 1 month"
|
||||
ExpiresByType image/jpeg "access plus 1 month"
|
||||
ExpiresByType image/gif "access plus 1 month"
|
||||
ExpiresByType image/svg+xml "access plus 1 month"
|
||||
ExpiresByType image/webp "access plus 1 month"
|
||||
ExpiresByType font/woff "access plus 1 month"
|
||||
ExpiresByType font/woff2 "access plus 1 month"
|
||||
</IfModule>
|
||||
|
||||
# Gzip-Kompression
|
||||
<IfModule mod_deflate.c>
|
||||
AddOutputFilterByType DEFLATE text/plain
|
||||
AddOutputFilterByType DEFLATE text/html
|
||||
AddOutputFilterByType DEFLATE text/xml
|
||||
AddOutputFilterByType DEFLATE text/css
|
||||
AddOutputFilterByType DEFLATE application/xml
|
||||
AddOutputFilterByType DEFLATE application/xhtml+xml
|
||||
AddOutputFilterByType DEFLATE application/rss+xml
|
||||
AddOutputFilterByType DEFLATE application/javascript
|
||||
AddOutputFilterByType DEFLATE application/x-javascript
|
||||
</IfModule>
|
||||
|
||||
# PHP-Einstellungen
|
||||
<IfModule mod_php.c>
|
||||
php_value upload_max_filesize 10M
|
||||
php_value post_max_size 10M
|
||||
php_value max_execution_time 30
|
||||
php_value memory_limit 128M
|
||||
</IfModule>
|
||||
|
||||
# Fehlerbehandlung
|
||||
ErrorDocument 404 /404.html
|
||||
ErrorDocument 500 /500.html
|
||||
|
||||
# Verzeichnis-Listing deaktivieren
|
||||
Options -Indexes
|
||||
|
||||
# Datei-Zugriff beschränken
|
||||
<FilesMatch "\.(htaccess|htpasswd|ini|log|sh|inc|bak)$">
|
||||
Order Allow,Deny
|
||||
Deny from all
|
||||
</FilesMatch>
|
||||
199
public/README-EMAIL-SETUP.md
Normal file
199
public/README-EMAIL-SETUP.md
Normal file
@@ -0,0 +1,199 @@
|
||||
# HexaHost.de E-Mail-Setup Anleitung
|
||||
|
||||
## Übersicht
|
||||
|
||||
Das Kontaktformular ist jetzt vollständig funktional mit einem PHP-Backend und PHPMailer. Sie müssen nur noch Ihre SMTP-Daten konfigurieren.
|
||||
|
||||
## Installation
|
||||
|
||||
### 1. Composer installieren
|
||||
|
||||
```bash
|
||||
cd public
|
||||
composer install
|
||||
```
|
||||
|
||||
### 2. SMTP-Konfiguration
|
||||
|
||||
Bearbeiten Sie die Datei `config/mail-config.php` und passen Sie die SMTP-Einstellungen an:
|
||||
|
||||
```php
|
||||
// SMTP Server Einstellungen
|
||||
define('SMTP_HOST', 'smtp.ihre-domain.de'); // Ihr SMTP-Server
|
||||
define('SMTP_PORT', 587); // SMTP-Port (meist 587 oder 465)
|
||||
define('SMTP_USERNAME', 'kontakt@ihre-domain.de'); // Ihr SMTP-Benutzername
|
||||
define('SMTP_PASSWORD', 'ihr-smtp-passwort'); // Ihr SMTP-Passwort
|
||||
|
||||
// E-Mail Adressen
|
||||
define('SMTP_FROM_EMAIL', 'kontakt@hexahost.de'); // Absender-E-Mail
|
||||
define('SMTP_TO_EMAIL', 'info@hexahost.de'); // Empfänger-E-Mail
|
||||
```
|
||||
|
||||
## Gängige SMTP-Einstellungen
|
||||
|
||||
### Gmail
|
||||
```php
|
||||
define('SMTP_HOST', 'smtp.gmail.com');
|
||||
define('SMTP_PORT', 587);
|
||||
define('SMTP_USERNAME', 'ihre-email@gmail.com');
|
||||
define('SMTP_PASSWORD', 'ihr-app-passwort'); // App-Passwort erforderlich
|
||||
```
|
||||
|
||||
### Outlook/Hotmail
|
||||
```php
|
||||
define('SMTP_HOST', 'smtp-mail.outlook.com');
|
||||
define('SMTP_PORT', 587);
|
||||
define('SMTP_USERNAME', 'ihre-email@outlook.com');
|
||||
define('SMTP_PASSWORD', 'ihr-passwort');
|
||||
```
|
||||
|
||||
### GMX
|
||||
```php
|
||||
define('SMTP_HOST', 'mail.gmx.net');
|
||||
define('SMTP_PORT', 587);
|
||||
define('SMTP_USERNAME', 'ihre-email@gmx.de');
|
||||
define('SMTP_PASSWORD', 'ihr-passwort');
|
||||
```
|
||||
|
||||
### Web.de
|
||||
```php
|
||||
define('SMTP_HOST', 'smtp.web.de');
|
||||
define('SMTP_PORT', 587);
|
||||
define('SMTP_USERNAME', 'ihre-email@web.de');
|
||||
define('SMTP_PASSWORD', 'ihr-passwort');
|
||||
```
|
||||
|
||||
### 1&1
|
||||
```php
|
||||
define('SMTP_HOST', 'smtp.1und1.de');
|
||||
define('SMTP_PORT', 587);
|
||||
define('SMTP_USERNAME', 'ihre-email@ihre-domain.de');
|
||||
define('SMTP_PASSWORD', 'ihr-passwort');
|
||||
```
|
||||
|
||||
### Strato
|
||||
```php
|
||||
define('SMTP_HOST', 'smtp.strato.de');
|
||||
define('SMTP_PORT', 587);
|
||||
define('SMTP_USERNAME', 'ihre-email@ihre-domain.de');
|
||||
define('SMTP_PASSWORD', 'ihr-passwort');
|
||||
```
|
||||
|
||||
### Ionos
|
||||
```php
|
||||
define('SMTP_HOST', 'smtp.ionos.de');
|
||||
define('SMTP_PORT', 587);
|
||||
define('SMTP_USERNAME', 'ihre-email@ihre-domain.de');
|
||||
define('SMTP_PASSWORD', 'ihr-passwort');
|
||||
```
|
||||
|
||||
## Sicherheitsfeatures
|
||||
|
||||
### Anti-Spam Headers
|
||||
Das System sendet E-Mails mit folgenden Anti-Spam-Headers:
|
||||
- `X-Mailer`: Identifiziert das System
|
||||
- `X-Priority`: Normale Priorität
|
||||
- `X-Report-Abuse`: Abuse-Reporting
|
||||
- `List-Unsubscribe`: Unsubscribe-Link
|
||||
- `Precedence`: Bulk-Mail-Kennzeichnung
|
||||
|
||||
### Spam-Schutz
|
||||
- Rate-Limiting: Max. 3 Anfragen pro 5 Minuten
|
||||
- Spam-Score-System: Erkennt verdächtige Nachrichten
|
||||
- Input-Validierung: Prüft alle Eingaben
|
||||
- CSRF-Schutz: Verhindert Cross-Site-Request-Forgery
|
||||
|
||||
### Validierung
|
||||
- E-Mail-Format-Prüfung
|
||||
- Pflichtfeld-Validierung
|
||||
- Nachrichtenlänge (10-5000 Zeichen)
|
||||
- Verdächtige Wörter-Erkennung
|
||||
|
||||
## E-Mail-Templates
|
||||
|
||||
### An HexaHost (HTML)
|
||||
- Professionelles HTML-Template
|
||||
- Alle Formulardaten übersichtlich dargestellt
|
||||
- HexaHost Branding
|
||||
|
||||
### Bestätigung an Kunde (HTML)
|
||||
- Danke-Nachricht
|
||||
- Bestätigung der Nachricht
|
||||
- Support-Informationen
|
||||
|
||||
## Logging
|
||||
|
||||
E-Mails werden in `logs/email.log` protokolliert (falls aktiviert):
|
||||
```php
|
||||
define('LOG_EMAILS', true);
|
||||
```
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
### Häufige Probleme
|
||||
|
||||
1. **"SMTP connect() failed"**
|
||||
- Prüfen Sie SMTP_HOST und SMTP_PORT
|
||||
- Stellen Sie sicher, dass SMTP aktiviert ist
|
||||
|
||||
2. **"Authentication failed"**
|
||||
- Prüfen Sie SMTP_USERNAME und SMTP_PASSWORD
|
||||
- Bei Gmail: App-Passwort verwenden
|
||||
|
||||
3. **"Connection refused"**
|
||||
- Firewall-Einstellungen prüfen
|
||||
- Port 587 oder 465 verwenden
|
||||
|
||||
4. **E-Mails landen im Spam**
|
||||
- SPF, DKIM und DMARC konfigurieren
|
||||
- Absender-Domain mit SMTP-Domain übereinstimmend
|
||||
|
||||
### Debug-Modus
|
||||
|
||||
Aktivieren Sie den Debug-Modus für detaillierte Fehlermeldungen:
|
||||
```php
|
||||
define('DEBUG_MODE', true);
|
||||
```
|
||||
|
||||
## Dateistruktur
|
||||
|
||||
```
|
||||
public/
|
||||
├── contact-handler.php # E-Mail-Verarbeitung
|
||||
├── config/
|
||||
│ └── mail-config.php # SMTP-Konfiguration
|
||||
├── vendor/ # Composer-Abhängigkeiten
|
||||
├── logs/ # E-Mail-Logs
|
||||
└── composer.json # Composer-Konfiguration
|
||||
```
|
||||
|
||||
## Sicherheitshinweise
|
||||
|
||||
1. **SMTP-Passwort schützen**
|
||||
- Datei `config/mail-config.php` nicht öffentlich zugänglich machen
|
||||
- Passwort regelmäßig ändern
|
||||
|
||||
2. **HTTPS verwenden**
|
||||
- Kontaktformular nur über HTTPS bereitstellen
|
||||
- SSL-Zertifikat installieren
|
||||
|
||||
3. **Backup erstellen**
|
||||
- Regelmäßige Backups der Konfiguration
|
||||
- E-Mail-Logs sichern
|
||||
|
||||
## Support
|
||||
|
||||
Bei Problemen:
|
||||
1. Debug-Modus aktivieren
|
||||
2. E-Mail-Logs prüfen
|
||||
3. SMTP-Einstellungen testen
|
||||
4. Firewall-Einstellungen überprüfen
|
||||
|
||||
## Changelog
|
||||
|
||||
- **v1.0**: Vollständige E-Mail-Implementierung
|
||||
- Anti-Spam-Headers
|
||||
- Rate-Limiting
|
||||
- CSRF-Schutz
|
||||
- HTML-Templates
|
||||
- Logging-System
|
||||
@@ -509,6 +509,97 @@ body {
|
||||
font-size: var(--font-size-sm);
|
||||
}
|
||||
|
||||
/* How it Works Section */
|
||||
.how-it-works {
|
||||
padding: var(--spacing-3xl) 0;
|
||||
background: rgba(255, 255, 255, 0.02);
|
||||
}
|
||||
|
||||
.steps-grid {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));
|
||||
gap: var(--spacing-xl);
|
||||
margin-top: var(--spacing-2xl);
|
||||
}
|
||||
|
||||
.step-item {
|
||||
padding: var(--spacing-xl);
|
||||
text-align: center;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.step-number {
|
||||
width: 60px;
|
||||
height: 60px;
|
||||
background: linear-gradient(135deg, var(--primary-color), var(--accent-color-1));
|
||||
border-radius: 50%;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
font-size: var(--font-size-xl);
|
||||
font-weight: 700;
|
||||
color: var(--white);
|
||||
margin: 0 auto var(--spacing-lg);
|
||||
box-shadow: 0 8px 32px 0 rgba(255, 81, 249, 0.3);
|
||||
}
|
||||
|
||||
.step-item h3 {
|
||||
font-size: var(--font-size-lg);
|
||||
font-weight: 600;
|
||||
margin-bottom: var(--spacing-md);
|
||||
color: var(--text-primary);
|
||||
}
|
||||
|
||||
.step-item p {
|
||||
color: var(--text-secondary);
|
||||
line-height: 1.6;
|
||||
font-size: var(--font-size-base);
|
||||
}
|
||||
|
||||
/* Mail Features Section */
|
||||
.mail-features {
|
||||
padding: var(--spacing-3xl) 0;
|
||||
background: rgba(255, 255, 255, 0.03);
|
||||
}
|
||||
|
||||
/* Benefits Section */
|
||||
.benefits {
|
||||
padding: var(--spacing-3xl) 0;
|
||||
background: rgba(255, 255, 255, 0.02);
|
||||
}
|
||||
|
||||
.benefits-grid {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));
|
||||
gap: var(--spacing-xl);
|
||||
margin-top: var(--spacing-2xl);
|
||||
}
|
||||
|
||||
.benefit-item {
|
||||
padding: var(--spacing-xl);
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.benefit-icon {
|
||||
width: 48px;
|
||||
height: 48px;
|
||||
margin: 0 auto var(--spacing-lg);
|
||||
color: var(--primary-color);
|
||||
}
|
||||
|
||||
.benefit-item h3 {
|
||||
font-size: var(--font-size-lg);
|
||||
font-weight: 600;
|
||||
margin-bottom: var(--spacing-md);
|
||||
color: var(--text-primary);
|
||||
}
|
||||
|
||||
.benefit-item p {
|
||||
color: var(--text-secondary);
|
||||
line-height: 1.6;
|
||||
font-size: var(--font-size-base);
|
||||
}
|
||||
|
||||
/* CTA Section */
|
||||
.cta {
|
||||
padding: var(--spacing-3xl) 0;
|
||||
@@ -1263,6 +1354,19 @@ body {
|
||||
transition: all var(--transition-base);
|
||||
}
|
||||
|
||||
/* Spezielle Styling für Select-Elemente */
|
||||
.form-group select {
|
||||
background: rgba(255, 255, 255, 0.1);
|
||||
backdrop-filter: blur(10px);
|
||||
-webkit-backdrop-filter: blur(10px);
|
||||
}
|
||||
|
||||
.form-group select option {
|
||||
background: rgba(13, 8, 33, 0.95);
|
||||
color: var(--text-primary);
|
||||
padding: var(--spacing-sm);
|
||||
}
|
||||
|
||||
.form-group input:focus,
|
||||
.form-group select:focus,
|
||||
.form-group textarea:focus {
|
||||
@@ -1444,6 +1548,16 @@ body {
|
||||
grid-template-columns: 1fr;
|
||||
}
|
||||
|
||||
.steps-grid {
|
||||
grid-template-columns: 1fr;
|
||||
gap: var(--spacing-lg);
|
||||
}
|
||||
|
||||
.benefits-grid {
|
||||
grid-template-columns: 1fr;
|
||||
gap: var(--spacing-lg);
|
||||
}
|
||||
|
||||
.story-content {
|
||||
grid-template-columns: 1fr;
|
||||
}
|
||||
|
||||
@@ -66,21 +66,36 @@
|
||||
submitBtn.textContent = 'Wird gesendet...';
|
||||
submitBtn.disabled = true;
|
||||
|
||||
// Simulate form submission (replace with actual endpoint)
|
||||
setTimeout(() => {
|
||||
// Reset form
|
||||
form.reset();
|
||||
|
||||
// Show success message
|
||||
showNotification('Ihre Nachricht wurde erfolgreich gesendet! Wir melden uns in Kürze bei Ihnen.', 'success');
|
||||
|
||||
// Send form data to PHP backend
|
||||
fetch('contact-handler.php', {
|
||||
method: 'POST',
|
||||
body: formData
|
||||
})
|
||||
.then(response => response.json())
|
||||
.then(data => {
|
||||
if (data.success) {
|
||||
// Reset form
|
||||
form.reset();
|
||||
|
||||
// Show success message
|
||||
showNotification(data.message, 'success');
|
||||
|
||||
// Scroll to top
|
||||
window.scrollTo({ top: 0, behavior: 'smooth' });
|
||||
} else {
|
||||
// Show error message
|
||||
showNotification(data.message, 'error');
|
||||
}
|
||||
})
|
||||
.catch(error => {
|
||||
console.error('Error:', error);
|
||||
showNotification('Es gab ein Problem beim Senden Ihrer Nachricht. Bitte versuchen Sie es später erneut.', 'error');
|
||||
})
|
||||
.finally(() => {
|
||||
// Reset button
|
||||
submitBtn.textContent = originalText;
|
||||
submitBtn.disabled = false;
|
||||
|
||||
// Scroll to top
|
||||
window.scrollTo({ top: 0, behavior: 'smooth' });
|
||||
}, 2000);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
19
public/composer.json
Normal file
19
public/composer.json
Normal file
@@ -0,0 +1,19 @@
|
||||
{
|
||||
"name": "hexahost/contact-form",
|
||||
"description": "HexaHost.de Contact Form with PHPMailer",
|
||||
"type": "project",
|
||||
"require": {
|
||||
"phpmailer/phpmailer": "^6.8"
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"HexaHost\\": "src/"
|
||||
}
|
||||
},
|
||||
"config": {
|
||||
"optimize-autoloader": true,
|
||||
"sort-packages": true
|
||||
},
|
||||
"minimum-stability": "stable",
|
||||
"prefer-stable": true
|
||||
}
|
||||
155
public/config/mail-config.php
Normal file
155
public/config/mail-config.php
Normal file
@@ -0,0 +1,155 @@
|
||||
<?php
|
||||
/**
|
||||
* HexaHost.de Mail Configuration
|
||||
*
|
||||
* Bitte passen Sie die folgenden SMTP-Einstellungen an Ihre E-Mail-Provider an.
|
||||
*
|
||||
* Beispiele für gängige Provider:
|
||||
*
|
||||
* Gmail:
|
||||
* - SMTP_HOST = 'smtp.gmail.com'
|
||||
* - SMTP_PORT = 587
|
||||
* - SMTP_USERNAME = 'ihre-email@gmail.com'
|
||||
* - SMTP_PASSWORD = 'ihr-app-passwort'
|
||||
*
|
||||
* Outlook/Hotmail:
|
||||
* - SMTP_HOST = 'smtp-mail.outlook.com'
|
||||
* - SMTP_PORT = 587
|
||||
*
|
||||
* GMX:
|
||||
* - SMTP_HOST = 'mail.gmx.net'
|
||||
* - SMTP_PORT = 587
|
||||
*
|
||||
* Web.de:
|
||||
* - SMTP_HOST = 'smtp.web.de'
|
||||
* - SMTP_PORT = 587
|
||||
*
|
||||
* 1&1:
|
||||
* - SMTP_HOST = 'smtp.1und1.de'
|
||||
* - SMTP_PORT = 587
|
||||
*
|
||||
* Strato:
|
||||
* - SMTP_HOST = 'smtp.strato.de'
|
||||
* - SMTP_PORT = 587
|
||||
*
|
||||
* Ionos:
|
||||
* - SMTP_HOST = 'smtp.ionos.de'
|
||||
* - SMTP_PORT = 587
|
||||
*/
|
||||
|
||||
// SMTP Server Einstellungen
|
||||
define('SMTP_HOST', 'smtp.ihre-domain.de'); // Ihr SMTP-Server
|
||||
define('SMTP_PORT', 587); // SMTP-Port (meist 587 oder 465)
|
||||
define('SMTP_USERNAME', 'kontakt@ihre-domain.de'); // Ihr SMTP-Benutzername
|
||||
define('SMTP_PASSWORD', 'ihr-smtp-passwort'); // Ihr SMTP-Passwort
|
||||
|
||||
// E-Mail Adressen
|
||||
define('SMTP_FROM_EMAIL', 'kontakt@hexahost.de'); // Absender-E-Mail (muss zu SMTP_USERNAME passen)
|
||||
define('SMTP_TO_EMAIL', 'info@hexahost.de'); // Empfänger-E-Mail für Kontaktformular
|
||||
|
||||
// Sicherheitseinstellungen
|
||||
define('ENABLE_CSRF_PROTECTION', true); // CSRF-Schutz aktivieren
|
||||
define('ENABLE_RATE_LIMITING', true); // Rate-Limiting aktivieren
|
||||
define('MAX_REQUESTS_PER_HOUR', 10); // Max. Anfragen pro Stunde
|
||||
|
||||
// Spam-Schutz Einstellungen
|
||||
define('ENABLE_SPAM_PROTECTION', true); // Spam-Schutz aktivieren
|
||||
define('MAX_MESSAGE_LENGTH', 5000); // Max. Nachrichtenlänge
|
||||
define('MIN_MESSAGE_LENGTH', 10); // Min. Nachrichtenlänge
|
||||
|
||||
// Debug-Einstellungen (nur für Entwicklung)
|
||||
define('DEBUG_MODE', false); // Debug-Modus (true/false)
|
||||
define('LOG_EMAILS', true); // E-Mails loggen (true/false)
|
||||
|
||||
// Zusätzliche Sicherheitsheader
|
||||
define('ADDITIONAL_HEADERS', [
|
||||
'X-Mailer' => 'HexaHost.de Contact Form',
|
||||
'X-Priority' => '3',
|
||||
'X-MSMail-Priority' => 'Normal',
|
||||
'Importance' => 'Normal',
|
||||
'X-Report-Abuse' => 'Please report abuse here: abuse@hexahost.de',
|
||||
'List-Unsubscribe' => '<mailto:unsubscribe@hexahost.de>',
|
||||
'Precedence' => 'bulk'
|
||||
]);
|
||||
|
||||
// Erlaubte Domains für E-Mail-Adressen (optional)
|
||||
define('ALLOWED_EMAIL_DOMAINS', [
|
||||
// Leer lassen für alle Domains zu erlauben
|
||||
// 'gmail.com',
|
||||
// 'outlook.com',
|
||||
// 'web.de',
|
||||
// 'gmx.de'
|
||||
]);
|
||||
|
||||
// Blacklist für E-Mail-Adressen (optional)
|
||||
define('BLACKLISTED_EMAILS', [
|
||||
// 'spam@example.com',
|
||||
// 'test@test.com'
|
||||
]);
|
||||
|
||||
// Validierung der Konfiguration
|
||||
if (!defined('SMTP_HOST') || !defined('SMTP_USERNAME') || !defined('SMTP_PASSWORD')) {
|
||||
die('SMTP-Konfiguration ist unvollständig. Bitte überprüfen Sie die mail-config.php');
|
||||
}
|
||||
|
||||
// Überprüfung der E-Mail-Adressen
|
||||
if (!filter_var(SMTP_FROM_EMAIL, FILTER_VALIDATE_EMAIL)) {
|
||||
die('Ungültige SMTP_FROM_EMAIL Adresse');
|
||||
}
|
||||
|
||||
if (!filter_var(SMTP_TO_EMAIL, FILTER_VALIDATE_EMAIL)) {
|
||||
die('Ungültige SMTP_TO_EMAIL Adresse');
|
||||
}
|
||||
|
||||
// Logging-Funktion
|
||||
function logEmail($type, $data) {
|
||||
if (!LOG_EMAILS) return;
|
||||
|
||||
$logFile = __DIR__ . '/../logs/email.log';
|
||||
$logDir = dirname($logFile);
|
||||
|
||||
if (!is_dir($logDir)) {
|
||||
mkdir($logDir, 0755, true);
|
||||
}
|
||||
|
||||
$timestamp = date('Y-m-d H:i:s');
|
||||
$logEntry = "[$timestamp] $type: " . json_encode($data) . "\n";
|
||||
|
||||
file_put_contents($logFile, $logEntry, FILE_APPEND | LOCK_EX);
|
||||
}
|
||||
|
||||
// Hilfsfunktion für E-Mail-Validierung
|
||||
function isValidEmail($email) {
|
||||
if (!filter_var($email, FILTER_VALIDATE_EMAIL)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Prüfe Blacklist
|
||||
if (in_array($email, BLACKLISTED_EMAILS)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Prüfe Domain-Whitelist (falls gesetzt)
|
||||
if (!empty(ALLOWED_EMAIL_DOMAINS)) {
|
||||
$domain = substr(strrchr($email, "@"), 1);
|
||||
if (!in_array($domain, ALLOWED_EMAIL_DOMAINS)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// CSRF Token generieren
|
||||
function generateCSRFToken() {
|
||||
if (!isset($_SESSION['csrf_token'])) {
|
||||
$_SESSION['csrf_token'] = bin2hex(random_bytes(32));
|
||||
}
|
||||
return $_SESSION['csrf_token'];
|
||||
}
|
||||
|
||||
// CSRF Token validieren
|
||||
function validateCSRFToken($token) {
|
||||
return isset($_SESSION['csrf_token']) && hash_equals($_SESSION['csrf_token'], $token);
|
||||
}
|
||||
?>
|
||||
330
public/contact-handler.php
Normal file
330
public/contact-handler.php
Normal file
@@ -0,0 +1,330 @@
|
||||
<?php
|
||||
/**
|
||||
* HexaHost.de Contact Form Handler
|
||||
* Handles contact form submissions and sends emails with proper anti-spam headers
|
||||
*/
|
||||
|
||||
// Prevent direct access
|
||||
if ($_SERVER['REQUEST_METHOD'] !== 'POST') {
|
||||
http_response_code(405);
|
||||
exit('Method not allowed');
|
||||
}
|
||||
|
||||
// Load configuration
|
||||
require_once 'config/mail-config.php';
|
||||
|
||||
// Set headers for AJAX response
|
||||
header('Content-Type: application/json');
|
||||
header('X-Content-Type-Options: nosniff');
|
||||
header('X-Frame-Options: DENY');
|
||||
header('X-XSS-Protection: 1; mode=block');
|
||||
|
||||
// CSRF Protection
|
||||
if (!isset($_POST['csrf_token']) || $_POST['csrf_token'] !== $_SESSION['csrf_token']) {
|
||||
http_response_code(403);
|
||||
echo json_encode(['success' => false, 'message' => 'Security token invalid']);
|
||||
exit;
|
||||
}
|
||||
|
||||
// Rate limiting
|
||||
session_start();
|
||||
$timeWindow = 300; // 5 minutes
|
||||
$maxRequests = 3;
|
||||
|
||||
if (!isset($_SESSION['contact_attempts'])) {
|
||||
$_SESSION['contact_attempts'] = [];
|
||||
}
|
||||
|
||||
// Clean old attempts
|
||||
$_SESSION['contact_attempts'] = array_filter($_SESSION['contact_attempts'], function($timestamp) use ($timeWindow) {
|
||||
return $timestamp > (time() - $timeWindow);
|
||||
});
|
||||
|
||||
if (count($_SESSION['contact_attempts']) >= $maxRequests) {
|
||||
http_response_code(429);
|
||||
echo json_encode(['success' => false, 'message' => 'Zu viele Anfragen. Bitte warten Sie 5 Minuten.']);
|
||||
exit;
|
||||
}
|
||||
|
||||
// Add current attempt
|
||||
$_SESSION['contact_attempts'][] = time();
|
||||
|
||||
// Validate required fields
|
||||
$requiredFields = ['firstName', 'lastName', 'email', 'subject', 'message', 'privacy'];
|
||||
$errors = [];
|
||||
|
||||
foreach ($requiredFields as $field) {
|
||||
if (!isset($_POST[$field]) || trim($_POST[$field]) === '') {
|
||||
$errors[] = "Das Feld '$field' ist erforderlich.";
|
||||
}
|
||||
}
|
||||
|
||||
// Validate email
|
||||
if (isset($_POST['email']) && !filter_var($_POST['email'], FILTER_VALIDATE_EMAIL)) {
|
||||
$errors[] = 'Bitte geben Sie eine gültige E-Mail-Adresse ein.';
|
||||
}
|
||||
|
||||
// Validate privacy checkbox
|
||||
if (!isset($_POST['privacy']) || $_POST['privacy'] !== 'on') {
|
||||
$errors[] = 'Sie müssen der Datenschutzerklärung zustimmen.';
|
||||
}
|
||||
|
||||
// Check for spam indicators
|
||||
$spamScore = 0;
|
||||
$message = isset($_POST['message']) ? $_POST['message'] : '';
|
||||
|
||||
// Check message length
|
||||
if (strlen($message) < 10) {
|
||||
$spamScore += 2;
|
||||
}
|
||||
|
||||
if (strlen($message) > 5000) {
|
||||
$spamScore += 3;
|
||||
}
|
||||
|
||||
// Check for suspicious patterns
|
||||
$suspiciousPatterns = [
|
||||
'/\b(viagra|casino|loan|credit|debt)\b/i',
|
||||
'/\b(click here|buy now|free money)\b/i',
|
||||
'/\b(www\.|http:\/\/|https:\/\/)/i',
|
||||
'/\b[A-Z]{5,}/', // ALL CAPS
|
||||
'/\b\d{10,}/', // Too many numbers
|
||||
];
|
||||
|
||||
foreach ($suspiciousPatterns as $pattern) {
|
||||
if (preg_match($pattern, $message)) {
|
||||
$spamScore += 1;
|
||||
}
|
||||
}
|
||||
|
||||
// Check for too many links
|
||||
$linkCount = preg_match_all('/https?:\/\/[^\s]+/', $message);
|
||||
if ($linkCount > 2) {
|
||||
$spamScore += 2;
|
||||
}
|
||||
|
||||
// Reject if spam score is too high
|
||||
if ($spamScore >= 5) {
|
||||
http_response_code(400);
|
||||
echo json_encode(['success' => false, 'message' => 'Ihre Nachricht wurde als Spam erkannt.']);
|
||||
exit;
|
||||
}
|
||||
|
||||
if (!empty($errors)) {
|
||||
http_response_code(400);
|
||||
echo json_encode(['success' => false, 'message' => implode(' ', $errors)]);
|
||||
exit;
|
||||
}
|
||||
|
||||
// Sanitize input
|
||||
$firstName = htmlspecialchars(trim($_POST['firstName']), ENT_QUOTES, 'UTF-8');
|
||||
$lastName = htmlspecialchars(trim($_POST['lastName']), ENT_QUOTES, 'UTF-8');
|
||||
$email = filter_var(trim($_POST['email']), FILTER_SANITIZE_EMAIL);
|
||||
$phone = isset($_POST['phone']) ? htmlspecialchars(trim($_POST['phone']), ENT_QUOTES, 'UTF-8') : '';
|
||||
$company = isset($_POST['company']) ? htmlspecialchars(trim($_POST['company']), ENT_QUOTES, 'UTF-8') : '';
|
||||
$subject = htmlspecialchars(trim($_POST['subject']), ENT_QUOTES, 'UTF-8');
|
||||
$message = htmlspecialchars(trim($_POST['message']), ENT_QUOTES, 'UTF-8');
|
||||
$newsletter = isset($_POST['newsletter']) && $_POST['newsletter'] === 'on';
|
||||
|
||||
// Map subject to readable text
|
||||
$subjectMap = [
|
||||
'allgemeine-anfrage' => 'Allgemeine Anfrage',
|
||||
'vpc-anfrage' => 'Virtual Private Container Anfrage',
|
||||
'vps-anfrage' => 'Virtual Private Server Anfrage',
|
||||
'mail-gateway-anfrage' => 'Mail Gateway Anfrage',
|
||||
'webhosting-anfrage' => 'Webhosting Anfrage',
|
||||
'support' => 'Technischer Support',
|
||||
'beratung' => 'Persönliche Beratung',
|
||||
'migration' => 'Migration/Umzug',
|
||||
'sonstiges' => 'Sonstiges'
|
||||
];
|
||||
|
||||
$subjectText = isset($subjectMap[$subject]) ? $subjectMap[$subject] : $subject;
|
||||
|
||||
// Prepare email content
|
||||
$emailSubject = "Neue Kontaktanfrage: $subjectText - HexaHost.de";
|
||||
$emailBody = "Eine neue Kontaktanfrage wurde über das Kontaktformular eingegangen:\n\n";
|
||||
$emailBody .= "Name: $firstName $lastName\n";
|
||||
$emailBody .= "E-Mail: $email\n";
|
||||
if ($phone) $emailBody .= "Telefon: $phone\n";
|
||||
if ($company) $emailBody .= "Unternehmen: $company\n";
|
||||
$emailBody .= "Betreff: $subjectText\n";
|
||||
$emailBody .= "Newsletter-Anmeldung: " . ($newsletter ? 'Ja' : 'Nein') . "\n\n";
|
||||
$emailBody .= "Nachricht:\n$message\n\n";
|
||||
$emailBody .= "---\n";
|
||||
$emailBody .= "Diese E-Mail wurde automatisch generiert von hexahost.de\n";
|
||||
$emailBody .= "IP-Adresse: " . $_SERVER['REMOTE_ADDR'] . "\n";
|
||||
$emailBody .= "Zeitstempel: " . date('Y-m-d H:i:s') . "\n";
|
||||
|
||||
// Prepare HTML version
|
||||
$htmlBody = "
|
||||
<!DOCTYPE html>
|
||||
<html lang='de'>
|
||||
<head>
|
||||
<meta charset='UTF-8'>
|
||||
<title>Neue Kontaktanfrage - HexaHost.de</title>
|
||||
<style>
|
||||
body { font-family: Arial, sans-serif; line-height: 1.6; color: #333; }
|
||||
.header { background: #ff51f9; color: white; padding: 20px; text-align: center; }
|
||||
.content { padding: 20px; }
|
||||
.field { margin-bottom: 15px; }
|
||||
.label { font-weight: bold; }
|
||||
.message { background: #f5f5f5; padding: 15px; border-left: 4px solid #ff51f9; }
|
||||
.footer { background: #f5f5f5; padding: 15px; font-size: 12px; color: #666; }
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div class='header'>
|
||||
<h1>Neue Kontaktanfrage - HexaHost.de</h1>
|
||||
</div>
|
||||
<div class='content'>
|
||||
<div class='field'>
|
||||
<span class='label'>Name:</span> $firstName $lastName
|
||||
</div>
|
||||
<div class='field'>
|
||||
<span class='label'>E-Mail:</span> $email
|
||||
</div>";
|
||||
|
||||
if ($phone) {
|
||||
$htmlBody .= "<div class='field'><span class='label'>Telefon:</span> $phone</div>";
|
||||
}
|
||||
|
||||
if ($company) {
|
||||
$htmlBody .= "<div class='field'><span class='label'>Unternehmen:</span> $company</div>";
|
||||
}
|
||||
|
||||
$htmlBody .= "
|
||||
<div class='field'>
|
||||
<span class='label'>Betreff:</span> $subjectText
|
||||
</div>
|
||||
<div class='field'>
|
||||
<span class='label'>Newsletter-Anmeldung:</span> " . ($newsletter ? 'Ja' : 'Nein') . "
|
||||
</div>
|
||||
<div class='field'>
|
||||
<span class='label'>Nachricht:</span>
|
||||
<div class='message'>" . nl2br($message) . "</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class='footer'>
|
||||
<p>Diese E-Mail wurde automatisch generiert von hexahost.de</p>
|
||||
<p>IP-Adresse: " . $_SERVER['REMOTE_ADDR'] . "</p>
|
||||
<p>Zeitstempel: " . date('Y-m-d H:i:s') . "</p>
|
||||
</div>
|
||||
</body>
|
||||
</html>";
|
||||
|
||||
// Send email using PHPMailer
|
||||
try {
|
||||
require_once 'vendor/autoload.php';
|
||||
|
||||
$mail = new PHPMailer\PHPMailer\PHPMailer(true);
|
||||
|
||||
// Server settings
|
||||
$mail->isSMTP();
|
||||
$mail->Host = SMTP_HOST;
|
||||
$mail->SMTPAuth = true;
|
||||
$mail->Username = SMTP_USERNAME;
|
||||
$mail->Password = SMTP_PASSWORD;
|
||||
$mail->SMTPSecure = PHPMailer\PHPMailer\PHPMailer::ENCRYPTION_STARTTLS;
|
||||
$mail->Port = SMTP_PORT;
|
||||
$mail->CharSet = 'UTF-8';
|
||||
|
||||
// Anti-spam headers
|
||||
$mail->addCustomHeader('X-Mailer', 'HexaHost.de Contact Form');
|
||||
$mail->addCustomHeader('X-Priority', '3');
|
||||
$mail->addCustomHeader('X-MSMail-Priority', 'Normal');
|
||||
$mail->addCustomHeader('Importance', 'Normal');
|
||||
$mail->addCustomHeader('X-Report-Abuse', 'Please report abuse here: abuse@hexahost.de');
|
||||
$mail->addCustomHeader('List-Unsubscribe', '<mailto:unsubscribe@hexahost.de>');
|
||||
$mail->addCustomHeader('Precedence', 'bulk');
|
||||
|
||||
// Recipients
|
||||
$mail->setFrom(SMTP_FROM_EMAIL, 'HexaHost.de Kontaktformular');
|
||||
$mail->addAddress(SMTP_TO_EMAIL, 'HexaHost Support');
|
||||
$mail->addReplyTo($email, "$firstName $lastName");
|
||||
|
||||
// Content
|
||||
$mail->isHTML(true);
|
||||
$mail->Subject = $emailSubject;
|
||||
$mail->Body = $htmlBody;
|
||||
$mail->AltBody = $emailBody;
|
||||
|
||||
// Send email
|
||||
$mail->send();
|
||||
|
||||
// Send confirmation to user
|
||||
$userMail = new PHPMailer\PHPMailer\PHPMailer(true);
|
||||
|
||||
// Server settings
|
||||
$userMail->isSMTP();
|
||||
$userMail->Host = SMTP_HOST;
|
||||
$userMail->SMTPAuth = true;
|
||||
$userMail->Username = SMTP_USERNAME;
|
||||
$userMail->Password = SMTP_PASSWORD;
|
||||
$userMail->SMTPSecure = PHPMailer\PHPMailer\PHPMailer::ENCRYPTION_STARTTLS;
|
||||
$userMail->Port = SMTP_PORT;
|
||||
$userMail->CharSet = 'UTF-8';
|
||||
|
||||
// Anti-spam headers for user confirmation
|
||||
$userMail->addCustomHeader('X-Mailer', 'HexaHost.de Contact Form');
|
||||
$userMail->addCustomHeader('X-Priority', '3');
|
||||
$userMail->addCustomHeader('X-MSMail-Priority', 'Normal');
|
||||
$userMail->addCustomHeader('Importance', 'Normal');
|
||||
|
||||
// Recipients
|
||||
$userMail->setFrom(SMTP_FROM_EMAIL, 'HexaHost.de');
|
||||
$userMail->addAddress($email, "$firstName $lastName");
|
||||
|
||||
// Content
|
||||
$userMail->isHTML(true);
|
||||
$userMail->Subject = 'Vielen Dank für Ihre Nachricht - HexaHost.de';
|
||||
$userMail->Body = "
|
||||
<!DOCTYPE html>
|
||||
<html lang='de'>
|
||||
<head>
|
||||
<meta charset='UTF-8'>
|
||||
<title>Vielen Dank - HexaHost.de</title>
|
||||
<style>
|
||||
body { font-family: Arial, sans-serif; line-height: 1.6; color: #333; }
|
||||
.header { background: #ff51f9; color: white; padding: 20px; text-align: center; }
|
||||
.content { padding: 20px; }
|
||||
.footer { background: #f5f5f5; padding: 15px; font-size: 12px; color: #666; }
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div class='header'>
|
||||
<h1>Vielen Dank für Ihre Nachricht!</h1>
|
||||
</div>
|
||||
<div class='content'>
|
||||
<p>Hallo $firstName,</p>
|
||||
<p>vielen Dank für Ihre Nachricht an HexaHost.de. Wir haben Ihre Anfrage erhalten und werden uns schnellstmöglich bei Ihnen melden.</p>
|
||||
<p><strong>Ihre Nachricht:</strong><br>" . nl2br($message) . "</p>
|
||||
<p>Unser Support-Team bearbeitet Ihre Anfrage und antwortet in der Regel innerhalb von 2-4 Stunden.</p>
|
||||
<p>Bei dringenden Anliegen erreichen Sie uns auch telefonisch unter +49 851 1999 9999.</p>
|
||||
</div>
|
||||
<div class='footer'>
|
||||
<p>Mit freundlichen Grüßen<br>Ihr HexaHost.de Team</p>
|
||||
<p>Niederbayern, Deutschland</p>
|
||||
</div>
|
||||
</body>
|
||||
</html>";
|
||||
|
||||
$userMail->AltBody = "Vielen Dank für Ihre Nachricht an HexaHost.de. Wir haben Ihre Anfrage erhalten und werden uns schnellstmöglich bei Ihnen melden.";
|
||||
|
||||
$userMail->send();
|
||||
|
||||
// Success response
|
||||
echo json_encode([
|
||||
'success' => true,
|
||||
'message' => 'Ihre Nachricht wurde erfolgreich gesendet! Sie erhalten in Kürze eine Bestätigung per E-Mail.'
|
||||
]);
|
||||
|
||||
} catch (Exception $e) {
|
||||
error_log("Mail error: " . $e->getMessage());
|
||||
http_response_code(500);
|
||||
echo json_encode([
|
||||
'success' => false,
|
||||
'message' => 'Es gab ein Problem beim Senden Ihrer Nachricht. Bitte versuchen Sie es später erneut oder kontaktieren Sie uns direkt.'
|
||||
]);
|
||||
}
|
||||
?>
|
||||
@@ -127,7 +127,8 @@
|
||||
Senden Sie uns eine Nachricht - wir melden uns schnellstmöglich bei Ihnen
|
||||
</p>
|
||||
</div>
|
||||
<form class="contact-form glass-card" id="contactForm">
|
||||
<form class="contact-form glass-card" id="contactForm" action="contact-handler.php" method="POST">
|
||||
<input type="hidden" name="csrf_token" value="<?php echo generateCSRFToken(); ?>">
|
||||
<div class="form-row">
|
||||
<div class="form-group">
|
||||
<label for="firstName">Vorname *</label>
|
||||
@@ -174,14 +175,14 @@
|
||||
<div class="form-group checkbox-group">
|
||||
<label class="checkbox-label">
|
||||
<input type="checkbox" id="privacy" name="privacy" required>
|
||||
<span class="checkmark"></span>
|
||||
<!-- <span class="checkmark"></span> -->
|
||||
Ich habe die <a href="#" target="_blank">Datenschutzerklärung</a> gelesen und stimme der Verarbeitung meiner Daten zu. *
|
||||
</label>
|
||||
</div>
|
||||
<div class="form-group checkbox-group">
|
||||
<label class="checkbox-label">
|
||||
<input type="checkbox" id="newsletter" name="newsletter">
|
||||
<span class="checkmark"></span>
|
||||
<!-- <span class="checkmark"></span> -->
|
||||
Ich möchte den HexaHost.de Newsletter mit Informationen zu neuen Produkten und Angeboten erhalten.
|
||||
</label>
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user