Kontaktformular in iOS mit Swift und SwiftUI erstellen
Ein SwiftUI-Kontaktformular, das Ihnen jede Nachricht über Ihr eigenes Postfach schickt – ohne Backend und ohne SMTP-Passwort in der App. Mit dem Frontmail-Swift-Paket.
Aktualisiert:
Sie fügen einer iOS-App mit SwiftUI und dem Frontmail-Swift-Paket ein Kontaktformular hinzu. Die App enthält nur einen öffentlichen Schlüssel; Frontmail versendet die E-Mail über Ihr Postfach – kein SMTP-Passwort in der App und kein Server, den Sie warten müssen.
Sie brauchen: ein kostenloses Frontmail-Konto, ein Xcode-Projekt mit SwiftUI und etwa fünfzehn Minuten.
1. Postfach verbinden und Vorlage anlegen
- E-Mail-Dienste → Dienst hinzufügen: Verbinden Sie Gmail, Outlook, SMTP oder einen Transaktions-Anbieter, aktivieren Sie Als Standard festlegen, dann Prüfen & speichern.
- Vorlagen → Aus der Galerie → Kontaktformular → Vorlage verwenden.
Pflichtparameter:
name,email,message; optional:phone,topic. - 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, bis dahin antwortet die API daher mitorigin_not_allowed. - Vorlage → Einstellungen → Schutz → CAPTCHA verlangen (Turnstile). Apps nutzen das gemeinsame Turnstile-Widget von Frontmail; Cloudflare-Schlüssel brauchen Sie nicht.
3. Paket hinzufügen
Wählen Sie in Xcode File → Add Package Dependencies…, geben Sie
https://github.com/frontmail-dev/frontmail-swift ein und fügen Sie die Bibliothek Frontmail
Ihrem App-Target hinzu. Kopieren Sie dann TurnstileView aus dem Turnstile-Abschnitt der
iOS-SDK-Dokumentation in Ihr Projekt – ein kleines UIViewRepresentable um WKWebView, das Ihnen
gehört.
4. Formular bauen
import SwiftUI
import Frontmail
let frontmail = try! Frontmail(publicKey: "pk_…") // create once, share
struct ContactMessage: Encodable {
let name: String
let email: String
let message: String
}
struct ContactView: View {
@State private var name = ""
@State private var email = ""
@State private var message = ""
@State private var widget: Turnstile.Widget?
@State private var token: String?
@State private var resetID = 0
@State private var info = ""
var body: some View {
Form {
TextField("Name", text: $name)
TextField("Email", text: $email)
.keyboardType(.emailAddress)
.textInputAutocapitalization(.never)
TextField("Message", text: $message, axis: .vertical)
.lineLimit(4...8)
if let widget {
TurnstileView(widget: widget, size: .flexible, resetID: resetID) { event in
if case let .token(t) = event { token = t } else { token = nil }
}
.frame(height: Turnstile.Size.flexible.recommendedHeight)
}
Button("Send") { Task { await send() } }
.disabled(token == nil)
Text(info)
}
.task { widget = try? await Turnstile.widget(client: frontmail) }
}
private func send() async {
guard let widget, let token else { return }
defer { self.token = nil; resetID += 1 } // a token works only once
do {
_ = try await frontmail.send(
templateID: "tpl_…",
params: ContactMessage(name: name, email: email, message: message),
options: SendOptions(turnstileToken: token, turnstileKey: widget.turnstileKey)
)
info = "Thank you! We’ll get back to you soon."
} catch let error as FrontmailError {
info = error.message
} catch {
info = error.localizedDescription
}
}
}
Als Parameter funktioniert jede Encodable-Struktur, sodass der Compiler die Feldnamen für Sie
prüft. Netzwerkfehler und 5xx-Antworten werden mit einem einzigen Idempotenzschlüssel
wiederholt – keine doppelten E-Mails bei wackliger Verbindung.
5. Testen
Starten Sie die App im Simulator oder auf einem Gerät, füllen Sie das Formular aus und tippen Sie auf Send. Die E-Mail landet in Ihrem Postfach und erscheint im Dashboard unter Verlauf.
origin_not_allowed– Mobile Apps erlauben ist ausgeschaltet oder nicht gespeichert.captcha_required– noch kein Turnstile-Token; Send bleibt deaktiviert, bis die Prüfung abgeschlossen ist.invalid_template_params– ein Pflichtfeld ist leer oder die E-Mail-Adresse ungültig.
Wenn Ihre Credits aufgebraucht sind, wird die Nachricht mit dem Status
.heldangenommen und nach dem Aufladen automatisch versendet – es geht nichts verloren.
Nächste Schritte
- Bestätigen Sie dem Nutzer die Nachricht mit der Vorlage Automatische Antwort: Danke für Ihre Nachricht aus der Galerie.
- Senden Sie
SendOptions(locale: Locale.preferredLanguages.first), um eine Sprachvariante der Vorlage in der Sprache des Nutzers zu verwenden.


