Anfrageformular in iOS mit SwiftUI erstellen – Angebotsanfrage per E-Mail
Ein SwiftUI-Anfrageformular mit Auswahl von Leistung und Budget sowie Termin, das Ihnen jede Anfrage per E-Mail schickt und dem Kunden automatisch eine Bestätigung sendet – ohne Backend.
Aktualisiert:
In diesem Tutorial bauen Sie ein Formular für Angebotsanfragen in SwiftUI mit nativen Pickern: Leistung, Budget und Termin, dazu eine Beschreibung. Sie erhalten eine strukturierte E-Mail, der Kunde eine automatische Bestätigung.
Sie brauchen: ein kostenloses Frontmail-Konto, ein Xcode-Projekt mit SwiftUI und etwa zwanzig Minuten.
1. Postfach verbinden und Vorlagen anlegen
- E-Mail-Dienste → Dienst hinzufügen: Verbinden Sie Ihr Postfach oder Ihren Anbieter, Als Standard festlegen, Prüfen & speichern.
- Vorlagen → Aus der Galerie → Angebotsanfrage (Kategorie Geschäftlich) → Vorlage verwenden.
- Aus der Galerie → Automatische Antwort: Danke für Ihre Nachricht → Vorlage
verwenden; Standardwerte für
company_nameundresponse_timefestlegen und die Vorlage dann in der Anfragevorlage unter Einstellungen → Zustellung → Vorlage für automatische Antwort auswählen.
Die Anfragevorlage braucht name, email, service und details; phone, company, budget
und deadline (YYYY-MM-DD) sind optional. service und budget akzeptieren nur die Werte auf
dem Tab Parameter – verwenden Sie in der App dieselben Zeichenketten. Das Codebeispiel nutzt die
Werte der englischen Vorlage; eine auf Deutsch angelegte Vorlage hat Website, Onlineshop, Mobile
App, Beratung, Sonstiges und Unter 5.000 €, 5.000–20.000 €, 20.000–50.000 €, Über 50.000 €.
2. Mobile Apps erlauben und CAPTCHA aktivieren
- Sicherheit → Mobile Apps → Mobile Apps erlauben → Speichern.
- Anfragevorlage → Einstellungen → Schutz → CAPTCHA verlangen (Turnstile) – das gemeinsame mobile Widget von Frontmail, keine Schlüssel nötig.
3. Paket hinzufügen
File → Add Package Dependencies… → https://github.com/frontmail-dev/frontmail-swift →
Frontmail Ihrem Target hinzufügen, dann TurnstileView aus dem Turnstile-Abschnitt der
iOS-SDK-Dokumentation kopieren.
4. Formular bauen
import SwiftUI
import Frontmail
let frontmail = try! Frontmail(publicKey: "pk_…")
let services = ["Website", "E-shop", "Mobile app", "Consulting", "Other"]
let budgets = ["Under $5k", "$5k–20k", "$20k–50k", "Over $50k"]
struct QuoteRequest: Encodable {
let name: String
let email: String
let service: String
let budget: String? // nil is left out of the email
let deadline: String? // YYYY-MM-DD
let details: String
}
struct QuoteView: View {
@State private var name = ""
@State private var email = ""
@State private var service = services[0]
@State private var budget = ""
@State private var hasDeadline = false
@State private var deadline = Date()
@State private var details = ""
@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 {
Section {
TextField("Name", text: $name)
TextField("Email", text: $email)
.keyboardType(.emailAddress)
.textInputAutocapitalization(.never)
}
Section {
Picker("What do you need?", selection: $service) {
ForEach(services, id: \.self) { Text($0) }
}
Picker("Budget", selection: $budget) {
Text("Not sure yet").tag("")
ForEach(budgets, id: \.self) { Text($0) }
}
Toggle("I have a deadline", isOn: $hasDeadline)
if hasDeadline {
DatePicker("Deadline", selection: $deadline, in: Date()..., displayedComponents: .date)
}
TextField("Project details", text: $details, 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("Request a quote") { 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
let request = QuoteRequest(
name: name,
email: email,
service: service,
budget: budget.isEmpty ? nil : budget,
deadline: hasDeadline ? deadline.formatted(Date.ISO8601FormatStyle(timeZone: .current).year().month().day()) : nil,
details: details
)
do {
_ = try await frontmail.send(
templateID: "tpl_…",
params: request,
options: SendOptions(turnstileToken: token, turnstileKey: widget.turnstileKey)
)
info = "Thanks! We’ve emailed you a confirmation."
} catch let error as FrontmailError {
info = error.message
} catch {
info = error.localizedDescription
}
}
}
Optionale Eigenschaften mit dem Wert nil werden gar nicht kodiert, leere Zeilen tauchen in der
E-Mail also nie auf.
5. Testen
Senden Sie eine Anfrage mit Ihrer eigenen Adresse als Kunden-E-Mail: Sie erhalten die Anfrage und die Bestätigung, und beide erscheinen im Verlauf.
Eine Anfrage mit Bestätigung kostet zwei Credits. Gehen die Credits aus, werden Anfragen als
.heldangenommen und nach dem Aufladen automatisch versendet.
Nächste Schritte
- Aktivieren Sie Kontakte sammeln in den Einstellungen der Vorlage, um eine Liste aller Interessenten aufzubauen.
- Hängen Sie ein Briefing oder Fotos an mit
SendOptions(attachments: [.data(…)])– siehe SDK-Dokumentation.


