Přeskočit na obsah

Jak v React Native (a Expo) udělat kontaktní formulář, který odesílá e-maily

Kontaktní formulář v React Native, který vám každou zprávu pošle e-mailem – se stavem odesílání, ochranou proti botům a bez backendu. Funguje v Expo i v čistém React Native.

Aktualizováno:

Video je v angličtině; text níže obsahuje celý návod.

Do aplikace v React Native nebo Expo přidáte kontaktní formulář s balíčkem @frontmail/react-native: provider, hook useSendEmail, který sleduje stav odesílání, a hotovou komponentu Turnstile proti botům. E-mail odchází přes vaši vlastní schránku.

Budete potřebovat: bezplatný účet Frontmail, projekt v Expo nebo React Native a zhruba deset minut.

1. Připojte schránku a vytvořte šablonu

  1. E-mailové služby → Přidat službu: připojte Gmail, Outlook, SMTP nebo transakční službu, zaškrtněte Nastavit jako výchozí a klikněte na Ověřit a uložit.
  2. Šablony → Z galerie → Kontaktní formulář → Použít šablonu. Povinné parametry: name, email, message; nepovinné: phone, topic.
  3. Na záložce Kód pro web zkopírujte ID šablony (tpl_…).

2. Povolte mobilní aplikace

  • Zabezpečení → Mobilní aplikace → Povolit mobilní aplikace → Uložit. Aplikace neposílají hlavičku Origin, takže bez tohoto přepínače API odpovídá origin_not_allowed.
  • Šablona → Nastavení → Ochrana → Vyžadovat CAPTCHA (Turnstile). Aplikace používá sdílený widget Turnstile od Frontmailu; klíče od Cloudflaru nepotřebujete.

3. Instalace

npx expo install @frontmail/react-native @react-native-async-storage/async-storage react-native-webview

V čistém projektu React Native nainstalujte stejné balíčky přes npm i a spusťte npx pod-install.

4. Postavte formulář

import { useRef, useState } from 'react';
import { Button, Text, TextInput, View } from 'react-native';
import { FrontmailProvider, TurnstileWebView, useSendEmail, type TurnstileWebViewHandle } from '@frontmail/react-native';

const options = { publicKey: 'pk_…' }; // keep the object stable

export default function App() {
  return (
    <FrontmailProvider options={options}>
      <ContactForm />
    </FrontmailProvider>
  );
}

function ContactForm() {
  const { send, status, error } = useSendEmail(null, 'tpl_…'); // null = default service
  const [name, setName] = useState('');
  const [email, setEmail] = useState('');
  const [message, setMessage] = useState('');
  const [token, setToken] = useState<string>();
  const turnstile = useRef<TurnstileWebViewHandle>(null);

  const onSend = async () => {
    await send({ name, email, message }, { turnstileToken: token });
    setToken(undefined);
    turnstile.current?.reset(); // a token works only once
  };

  if (status === 'sent' || status === 'held') return <Text>Thank you! We’ll get back to you soon.</Text>;

  return (
    <View style={{ gap: 12, padding: 16 }}>
      <TextInput placeholder="Name" value={name} onChangeText={setName} />
      <TextInput placeholder="Email" value={email} onChangeText={setEmail} keyboardType="email-address" autoCapitalize="none" />
      <TextInput placeholder="Message" value={message} onChangeText={setMessage} multiline />
      <TurnstileWebView ref={turnstile} onToken={setToken} />
      <Button title="Send" disabled={!token || status === 'sending'} onPress={onSend} />
      {error && <Text>{error.message}</Text>}
    </View>
  );
}

send nikdy nevyhodí výjimku: vrátí výsledek nebo undefined a status přechází z idle na sending a pak na sent, held nebo error. Opakované pokusy po chybách sítě používají jeden idempotency key, takže ani uživatel ve vlaku vám tutéž zprávu nepošle dvakrát.

5. Vyzkoušejte to

Spusťte aplikaci (npx expo start), vyplňte formulář a klepněte na Send. E-mail dorazí do vaší schránky a do sekce Historie v dashboardu.

  • origin_not_allowed – volba Povolit mobilní aplikace je vypnutá nebo neuložená.
  • captcha_required – kontrola Turnstile ještě neskončila; tlačítko zůstane neaktivní, dokud nemá token.
  • invalid_template_params – povinné pole je prázdné nebo e-mail není platný.

held znamená, že zpráva byla přijata ve chvíli, kdy jste měli vyčerpané kredity. Odejde automaticky, jakmile je doplníte – nic se nezahodí.

Další kroky

  • Přidejte do options provideru limitRate: { id: 'contact', throttle: 30_000 } a povolíte tak jednu zprávu za 30 sekund z jednoho zařízení.
  • Pošlete uživateli potvrzení šablonou Automatická odpověď: díky za zprávu z galerie.
Všechny návody
  • Video, 42 s

    React NativePoptávkový formulář

    Jak v React Native udělat poptávkový formulář

    Poptávkový formulář v React Native a Expo s výběrem služby, rozpočtu a termínu, který vám každou poptávku pošle e-mailem a zákazníkovi ji automaticky potvrdí.

  • Video, 42 s

    WebKontaktní formulář

    Jak přidat kontaktní formulář na web bez backendu

    Obyčejný HTML kontaktní formulář, který vám každou zprávu pošle e-mailem – bez serveru, bez PHP a bez pluginu. Funguje na každém statickém webu, od ručně psaného HTML po Astro, Hugo nebo WordPress.

  • Video, 42 s

    FlutterKontaktní formulář

    Jak ve Flutteru udělat kontaktní formulář, který odesílá e-maily

    Kontaktní formulář ve Flutteru, který vám každou zprávu pošle e-mailem – bez backendu a bez SMTP hesla v aplikaci. Funguje na Androidu, iOS, webu i desktopu s Dart balíčkem Frontmail.