Zum Inhalt springen

Kontaktformular in React Native (und Expo) erstellen, das E-Mails versendet

Ein React-Native-Kontaktformular, das Ihnen jede Nachricht per E-Mail schickt – mit Sendestatus, Bot-Schutz und ohne Backend. Funktioniert mit Expo und reinem React Native.

Aktualisiert:

Das Video ist auf Englisch; die Schritte unten sind das vollständige Tutorial.

Sie fügen einer React-Native- oder Expo-App mit dem Paket @frontmail/react-native ein Kontaktformular hinzu: einen Provider, einen useSendEmail-Hook, der den Sendestatus verfolgt, und eine fertige Turnstile-Komponente gegen Bots. Die E-Mail geht über Ihr eigenes Postfach raus.

Sie brauchen: ein kostenloses Frontmail-Konto, ein Expo- oder React-Native-Projekt und etwa zehn Minuten.

1. Postfach verbinden und Vorlage anlegen

  1. E-Mail-Dienste → Dienst hinzufügen: Verbinden Sie Gmail, Outlook, SMTP oder einen Transaktions-Anbieter, aktivieren Sie Als Standard festlegen, dann Prüfen & speichern.
  2. Vorlagen → Aus der Galerie → Kontaktformular → Vorlage verwenden. Pflichtparameter: name, email, message; optional: phone, topic.
  3. Kopieren Sie die Vorlagen-ID (tpl_…) aus dem Tab Snippets.

2. Mobile Apps erlauben

  • Sicherheit → Mobile Apps → Mobile Apps erlauben → Speichern. Apps senden keinen Origin-Header, ohne diesen Schalter antwortet die API daher mit origin_not_allowed.
  • Vorlage → Einstellungen → Schutz → CAPTCHA verlangen (Turnstile). Die App nutzt das gemeinsame Turnstile-Widget von Frontmail; Cloudflare-Schlüssel brauchen Sie nicht.

3. Installieren

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

In einem reinen React-Native-Projekt installieren Sie dieselben Pakete mit npm i und führen danach npx pod-install aus.

4. Formular bauen

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 wirft nie eine Ausnahme: Es liefert das Ergebnis oder undefined, und status wechselt von idle zu sending und dann zu sent, held oder error. Wiederholungen nach Netzwerkfehlern verwenden denselben Idempotenzschlüssel – wer im Zug sitzt, schickt Ihnen dieselbe Nachricht also nie zweimal.

5. Testen

Starten Sie die App (npx expo start), füllen Sie das Formular aus und tippen Sie auf Send. Die E-Mail landet in Ihrem Postfach und im Dashboard unter Verlauf.

  • origin_not_allowed – Mobile Apps erlauben ist ausgeschaltet oder nicht gespeichert.
  • captcha_required – die Turnstile-Prüfung ist noch nicht fertig; der Button bleibt deaktiviert, bis ein Token vorliegt.
  • invalid_template_params – ein Pflichtfeld ist leer oder die E-Mail-Adresse ungültig.

held bedeutet, dass die Nachricht angenommen wurde, während Ihre Credits aufgebraucht waren. Sie wird automatisch versendet, sobald Sie aufladen – nichts geht verloren.

Nächste Schritte

  • Ergänzen Sie limitRate: { id: 'contact', throttle: 30_000 } in den Provider-Optionen, um pro Gerät nur eine Nachricht alle 30 Sekunden zuzulassen.
  • Schicken Sie dem Nutzer eine Bestätigung mit der Vorlage Automatische Antwort: Danke für Ihre Nachricht aus der Galerie.
Alle Tutorials