Come creare un modulo di contatto in React Native (ed Expo) che invia email
Un modulo di contatto in React Native che ti invia ogni messaggio via email, con stato di invio, protezione dai bot e senza backend. Funziona con Expo e con React Native puro.
Aggiornato:
Aggiungerai un modulo di contatto a un’app React Native o Expo con il pacchetto
@frontmail/react-native: un provider, un hook useSendEmail che tiene traccia dello stato di
invio e un componente Turnstile già pronto contro i bot. L’email parte dalla tua casella di posta.
Ti serve: un account Frontmail gratuito, un progetto Expo o React Native e una decina di minuti.
1. Collega la tua casella e crea il modello
- Servizi email → Aggiungi servizio: collega Gmail, Outlook, SMTP o un provider transazionale, seleziona Imposta come predefinito, poi Verifica e salva.
- Modelli → Dalla galleria → Modulo di contatto → Usa modello. Parametri
obbligatori:
name,email,message; facoltativi:phone,topic. - Copia l’ID del modello (
tpl_…) dalla scheda Snippet.
2. Consenti le app mobile
- Sicurezza → App mobile → Consenti app mobile → Salva. Le app non inviano l’header
Origin, quindi senza questo interruttore l’API rispondeorigin_not_allowed. - Modello → Impostazioni → Protezione → Richiedi CAPTCHA (Turnstile). L’app usa il widget Turnstile condiviso di Frontmail; non ti servono chiavi Cloudflare.
3. Installa
npx expo install @frontmail/react-native @react-native-async-storage/async-storage react-native-webview
In un progetto React Native puro usa npm i con gli stessi pacchetti ed esegui npx pod-install.
4. Crea il modulo
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 non genera mai eccezioni: restituisce il risultato oppure undefined, e status passa da
idle a sending e poi a sent, held o error. I nuovi tentativi dopo un errore di rete
riusano un’unica chiave di idempotenza, così chi scrive dal treno non ti manda mai due volte lo
stesso messaggio.
5. Provalo
Avvia l’app (npx expo start), compila il modulo e tocca Send. L’email arriva nella tua
casella e in Cronologia nella dashboard.
origin_not_allowed– Consenti app mobile è disattivato o non è stato salvato.captcha_required– la verifica Turnstile non è ancora finita; il pulsante resta disattivato finché non c’è un token.invalid_template_params– un campo obbligatorio è vuoto oppure l’email non è valida.
heldsignifica che il messaggio è stato accettato mentre i tuoi crediti erano esauriti. Parte automaticamente appena ricarichi: non va perso nulla.
Prossimi passi
- Aggiungi
limitRate: { id: 'contact', throttle: 30_000 }alle opzioni del provider per consentire un messaggio ogni 30 secondi per dispositivo. - Invia una conferma all’utente con il modello Risposta automatica: grazie per il messaggio della galleria.


