= 2) return strtoupper(mb_substr($parts[0], 0, 1) . mb_substr($parts[1], 0, 1)); return strtoupper(mb_substr($name, 0, 2)); } function avatarHtml(array $user, string $size = '32px'): string { $initials = userInitials($user['name']); $farbe = htmlspecialchars($user['farbe'] ?? '#2563eb'); $name = htmlspecialchars($user['name']); if (!empty($user['avatar_url'])) { return "\"{$name}\""; } return "{$initials}"; } // ── XSS-Schutz ──────────────────────────────────────────────────────────────── function h(string $s): string { return htmlspecialchars($s, ENT_QUOTES, 'UTF-8'); } // ── Packliste-Kategorien ────────────────────────────────────────────────────── $PACKEN_KATEGORIEN = [ 'kleidung' => ['label' => 'Kleidung', 'icon' => 'πŸ‘•'], 'dokumente' => ['label' => 'Dokumente', 'icon' => 'πŸ“„'], 'elektronik' => ['label' => 'Elektronik', 'icon' => 'πŸ”Œ'], 'medizin' => ['label' => 'Medizin', 'icon' => 'πŸ’Š'], 'toilette' => ['label' => 'Toilette', 'icon' => '🧴'], 'essen' => ['label' => 'Essen & Trinken', 'icon' => '🍿'], 'strand' => ['label' => 'Strand', 'icon' => 'πŸ–'], 'sport' => ['label' => 'Sport', 'icon' => '⚽'], 'sonstiges' => ['label' => 'Sonstiges', 'icon' => 'πŸ“¦'], ]; $UPLOAD_TYPEN = [ 'application/pdf' => 'PDF', 'image/jpeg' => 'JPG', 'image/png' => 'PNG', 'image/gif' => 'GIF', 'image/webp' => 'WEBP', 'application/msword' => 'Word', 'application/vnd.openxmlformats-officedocument.wordprocessingml.document' => 'Word', ]; // ── E-Mail-Versand ──────────────────────────────────────────────────────────── function sendMail(string $to, string $subject, string $htmlBody): bool { $fromName = '=?UTF-8?B?' . base64_encode(MAIL_FROM_NAME) . '?='; $subjectEncoded = '=?UTF-8?B?' . base64_encode($subject) . '?='; $boundary = md5(uniqid()); $headers = "From: {$fromName} <" . MAIL_FROM . ">\r\n"; $headers .= "Reply-To: " . MAIL_FROM . "\r\n"; $headers .= "MIME-Version: 1.0\r\n"; $headers .= "Content-Type: multipart/alternative; boundary=\"{$boundary}\"\r\n"; $headers .= "X-Mailer: PHP/" . phpversion(); $plain = strip_tags(str_replace(['
', '
', '
', '

', ''], "\n", $htmlBody)); $plain = preg_replace('/\n{3,}/', "\n\n", trim($plain)); $body = "--{$boundary}\r\n"; $body .= "Content-Type: text/plain; charset=UTF-8\r\n"; $body .= "Content-Transfer-Encoding: base64\r\n\r\n"; $body .= chunk_split(base64_encode($plain)) . "\r\n"; $body .= "--{$boundary}\r\n"; $body .= "Content-Type: text/html; charset=UTF-8\r\n"; $body .= "Content-Transfer-Encoding: base64\r\n\r\n"; $body .= chunk_split(base64_encode($htmlBody)) . "\r\n"; $body .= "--{$boundary}--"; return mail($to, $subjectEncoded, $body, $headers); } function sendInviteMail(string $toEmail, string $tripName, string $inviteLink, string $inviterName): bool { $subject = $inviterName . ' laedt dich zu "' . $tripName . '" ein'; $html = '
πŸ“‘

LΓΌtte Planer

Hallo!

' . htmlspecialchars($inviterName) . ' hat dich zur Reise β€ž' . htmlspecialchars($tripName) . '" eingeladen.

Einladung annehmen

Oder kopiere diesen Link in deinen Browser:
' . htmlspecialchars($inviteLink) . '


LΓΌtte Planer Β· Reisen planen & teilen

'; return sendMail($toEmail, $subject, $html); } function sendAddedToTripMail(string $toEmail, string $toName, string $tripName, string $tripUrl, string $inviterName): bool { $subject = 'Du wurdest zu "' . $tripName . '" hinzugefuegt'; $html = '
πŸ“‘

LΓΌtte Planer

Hallo ' . htmlspecialchars($toName) . '!

' . htmlspecialchars($inviterName) . ' hat dich zur Reise β€ž' . htmlspecialchars($tripName) . '" hinzugefΓΌgt.

Zur Reise

LΓΌtte Planer Β· Reisen planen & teilen

'; return sendMail($toEmail, $subject, $html); }