Przejdź do treści

Formularz kontaktowy z wysyłką e-mail

  • Formularze
  • poziom: początkujący
  • aktualizacja: 12 lipca 2026

Formularz kontaktowy to absolutny klasyk — potrzebuje go niemal każda strona. Poniższy skrypt to jeden plik, który wyświetla formularz, sprawdza poprawność danych, chroni przed prostymi botami i wysyła wiadomość na Twój adres e-mail.

Skrypt stosuje wzorzec Post/Redirect/Get — po udanej wysyłce przekierowuje na tę samą stronę, dzięki czemu odświeżenie strony nie wyśle wiadomości drugi raz.

PHP 126 linii Pobierz .php
<?php
/**
 * Formularz kontaktowy z wysyłką e-mail — skryptyPHP.com
 * Zapisz jako: kontakt.php
 */

session_start();

// ── USTAWIENIA ──────────────────────────────────────────────
$adres_docelowy = 'twoj@email.pl';            // tu przyjdą wiadomości
$adres_nadawcy  = 'formularz@twojadomena.pl'; // adres w TWOJEJ domenie (ważne dla dostarczalności!)

$bledy   = [];
$dane    = ['imie' => '', 'email' => '', 'tresc' => ''];
$wyslano = $_SESSION['wyslano'] ?? false;
unset($_SESSION['wyslano']);

if ($_SERVER['REQUEST_METHOD'] === 'POST') {

    // Honeypot — ukryte pole, które wypełniają tylko boty
    if (trim($_POST['www'] ?? '') !== '') {
        exit; // bot — kończymy bez komunikatu
    }

    $dane['imie']  = trim($_POST['imie'] ?? '');
    $dane['email'] = trim($_POST['email'] ?? '');
    $dane['tresc'] = trim($_POST['tresc'] ?? '');

    // Walidacja
    if ($dane['imie'] === '' || mb_strlen($dane['imie']) > 100) {
        $bledy[] = 'Podaj swoje imię (maksymalnie 100 znaków).';
    }
    if (!filter_var($dane['email'], FILTER_VALIDATE_EMAIL)) {
        $bledy[] = 'Podaj poprawny adres e-mail.';
    }
    if (mb_strlen($dane['tresc']) < 10) {
        $bledy[] = 'Wiadomość musi mieć co najmniej 10 znaków.';
    }
    if (mb_strlen($dane['tresc']) > 5000) {
        $bledy[] = 'Wiadomość jest za długa (maksymalnie 5000 znaków).';
    }

    // Wysyłka
    if (!$bledy) {
        $temat = 'Wiadomość ze strony od: ' . $dane['imie'];

        $naglowki = 'From: ' . $adres_nadawcy . "\r\n"
                  . 'Reply-To: ' . $dane['email'] . "\r\n"
                  . 'MIME-Version: 1.0' . "\r\n"
                  . 'Content-Type: text/plain; charset=UTF-8' . "\r\n";

        $tresc_maila = "Imię: {$dane['imie']}\n"
                     . "E-mail: {$dane['email']}\n"
                     . "Data: " . date('Y-m-d H:i:s') . "\n\n"
                     . $dane['tresc'];

        // Temat kodujemy, aby polskie znaki wyświetlały się poprawnie
        $temat_zakodowany = '=?UTF-8?B?' . base64_encode($temat) . '?=';

        if (mail($adres_docelowy, $temat_zakodowany, $tresc_maila, $naglowki)) {
            $_SESSION['wyslano'] = true;
            header('Location: ' . $_SERVER['REQUEST_URI']); // wzorzec PRG
            exit;
        }
        $bledy[] = 'Nie udało się wysłać wiadomości. Spróbuj ponownie później.';
    }
}
?>
<!DOCTYPE html>
<html lang="pl">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Kontakt</title>
<style>
    .formularz { max-width: 480px; font-family: sans-serif; }
    .formularz label { display: block; margin: 12px 0 4px; font-weight: bold; }
    .formularz input, .formularz textarea {
        width: 100%; padding: 8px; box-sizing: border-box;
        border: 1px solid #bbb; border-radius: 4px;
    }
    .formularz button { margin-top: 14px; padding: 10px 24px; cursor: pointer; }
    .bledy   { color: #b00020; }
    .sukces  { color: #1b7a2f; font-weight: bold; }
    .ukryte  { position: absolute; left: -9999px; } /* pole-pułapka */
</style>
</head>
<body>

<form class="formularz" method="post" action="">
    <h2>Napisz do nas</h2>

    <?php if ($wyslano): ?>
        <p class="sukces">Dziękujemy! Twoja wiadomość została wysłana.</p>
    <?php endif; ?>

    <?php if ($bledy): ?>
        <ul class="bledy">
            <?php foreach ($bledy as $blad): ?>
                <li><?= htmlspecialchars($blad) ?></li>
            <?php endforeach; ?>
        </ul>
    <?php endif; ?>

    <label for="imie">Imię</label>
    <input type="text" id="imie" name="imie" required
           value="<?= htmlspecialchars($dane['imie']) ?>">

    <label for="email">E-mail</label>
    <input type="email" id="email" name="email" required
           value="<?= htmlspecialchars($dane['email']) ?>">

    <label for="tresc">Wiadomość</label>
    <textarea id="tresc" name="tresc" rows="6" required><?= htmlspecialchars($dane['tresc']) ?></textarea>

    <!-- Honeypot: człowiek tego pola nie widzi i nie wypełnia -->
    <div class="ukryte" aria-hidden="true">
        <label for="www">Zostaw to pole puste</label>
        <input type="text" id="www" name="www" tabindex="-1" autocomplete="off">
    </div>

    <button type="submit">Wyślij wiadomość</button>
</form>

</body>
</html>

Jak użyć tego skryptu

  1. Zapisz kod jako kontakt.php i wgraj na serwer z obsługą PHP.
  2. W ustawieniach na górze pliku wpisz swój adres e-mail ($adres_docelowy) oraz adres nadawcy w swojej domenie ($adres_nadawcy), np. formularz@twojadomena.pl.
  3. Otwórz stronę w przeglądarce i wyślij testową wiadomość.
  4. Jeśli wiadomości nie dochodzą, sprawdź folder spam i upewnij się, że Twój hosting pozwala na wysyłkę funkcją mail().

Warto wiedzieć

  • Adres w polu From powinien być w Twojej domenie — inaczej serwery pocztowe często odrzucają wiadomość jako spam. Adres piszącego trafia do Reply-To, więc „Odpowiedz" zadziała normalnie.
  • Walidacja filter_var(..., FILTER_VALIDATE_EMAIL) przy okazji blokuje próby wstrzyknięcia dodatkowych nagłówków do e-maila.
  • Honeypot zatrzymuje proste boty. Przy większym spamie dołóż CAPTCHA — gotowy skrypt znajdziesz w kategorii Formularze.
  • Na hostingu współdzielonym limity wysyłki bywają niskie; przy dużym ruchu rozważ wysyłkę przez SMTP (np. biblioteką PHPMailer).
#formularz #mail #kontakt #honeypot #walidacja

Podobne skrypty