Přeskočit na obsah

Jak udělat kontaktní formulář v iOS ve Swiftu a SwiftUI

Kontaktní formulář ve SwiftUI, který vám každou zprávu pošle e-mailem přes vaši vlastní schránku – bez backendu a bez SMTP hesla v aplikaci. Používá Swift balíček Frontmail.

Aktualizováno:

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

Do aplikace pro iOS přidáte kontaktní formulář ve SwiftUI se Swift balíčkem Frontmail. Aplikace obsahuje jen veřejný klíč; e-mail odešle Frontmail přes vaši schránku, takže v aplikaci není žádné SMTP heslo a nemusíte udržovat žádný server.

Budete potřebovat: bezplatný účet Frontmail, projekt v Xcode se SwiftUI a zhruba patnáct 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 do té doby API odpovídá origin_not_allowed.
  • Šablona → Nastavení → Ochrana → Vyžadovat CAPTCHA (Turnstile). Aplikace používají sdílený widget Turnstile od Frontmailu; klíče od Cloudflaru nepotřebujete.

3. Přidejte balíček

V Xcode zvolte File → Add Package Dependencies…, zadejte https://github.com/frontmail-dev/frontmail-swift a přidejte knihovnu Frontmail do targetu aplikace. Pak si z části o Turnstile v dokumentaci iOS SDK zkopírujte do projektu TurnstileView – malý UIViewRepresentable kolem WKWebView, který patří vám.

4. Postavte formulář

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
        }
    }
}

Jako parametry funguje libovolná struktura Encodable, takže názvy polí za vás zkontroluje kompilátor. Chyby sítě a odpovědi 5xx se opakují s jedním idempotency key – ani na nestabilním připojení nevzniknou duplicitní e-maily.

5. Vyzkoušejte to

Spusťte aplikaci v simulátoru nebo na zařízení, vyplňte formulář a klepněte na Send. E-mail dorazí do vaší schránky a objeví se v sekci Historie v dashboardu.

  • origin_not_allowed – volba Povolit mobilní aplikace je vypnutá nebo neuložená.
  • captcha_required – zatím chybí token Turnstile; Send zůstane neaktivní, dokud kontrola nedoběhne.
  • invalid_template_params – povinné pole je prázdné nebo e-mail není platný.

Když vám dojdou kredity, zpráva se přijme se stavem .held a po dobití se odešle automaticky – nic se neztratí.

Další kroky

  • Potvrďte uživateli přijetí zprávy šablonou Automatická odpověď: díky za zprávu z galerie.
  • Pošlete SendOptions(locale: Locale.preferredLanguages.first), aby se použila jazyková verze šablony v jazyce uživatele.
Všechny návody
  • Video, 42 s

    iOS (Swift)Poptávkový formulář

    Jak udělat poptávkový formulář v iOS ve SwiftUI

    Poptávkový formulář ve SwiftUI s výběrem služby a rozpočtu a termínem, který vám každou poptávku pošle e-mailem a zákazníkovi automaticky potvrdí přijetí – bez backendu.

  • 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.