---
title: "Test sign-up emails in a SwiftUI or UIKit app · Proxy Mail QA"
description: "Test email codes, magic links and Universal Links in an iOS app built with SwiftUI or UIKit: by hand in the simulator, in XCUITest, or with a coding agent."
url: https://proxymail.qa/mobile/ios-sign-up-testing
---

1. [Home](https://proxymail.qa/)
2. [Mobile apps](https://proxymail.qa/mobile)

# Testing sign-up emails in an iOS app (SwiftUI or UIKit)

The iOS simulator has no Mail app, so the code or link your app emails has to be read somewhere else and brought back into the app. Here's how to do that by hand, in XCUITest, and with a coding agent, plus the link bugs worth checking while you're there.

Updated October 18, 2026

## Why sign-up emails are awkward to test on iOS

- **There’s no inbox on the device.** The simulator has no Mail app, and signing a real email account into a test iPhone means one shared inbox full of codes from every run.
- **Links have to open the app, not Safari.** A verify or magic link is usually an `https` Universal Link. It opens your app only when Associated Domains is set up correctly; otherwise it opens in Safari and the sign-in finishes in the wrong place, or not at all.
- **Custom-scheme links can’t be clicked from a laptop.** A `myapp://verify?token=…` link does nothing in a desktop browser, so a tester reading mail on their Mac can’t just click it.
- **Single-use links break if anything opens them first.** Link scanners and previews in some mail setups use them up. Proxy Mail QA never opens or prefetches a link.

## Test it by hand in the simulator

1. **Create an address** in Proxy Mail QA. Turn on a persona and a generated password if your sign-up form asks for a name or a strong password.
2. **Sign up in the simulator** with it. The simulator shares your Mac’s clipboard, so copy the address on the Mac and paste it into the app.
3. **Get the code.** It appears on the address’s row with a **Copy** button within seconds of arriving. Paste it into the app.
4. **Or open the link in the app.** Copy the link and run `xcrun simctl openurl booted '<link>'` in Terminal. For a `myapp://` link the inbox shows that command next to the link, ready to copy. iOS asks “Open in ‘YourApp’?” the first time a custom scheme opens.

## Automate it with XCUITest

Add the small Swift helper from the [XCUITest guide](https://proxymail.qa/docs/xcuitest) to your UI test target, set `PROXYMAIL_QA_API_KEY` in the scheme or test plan, and the test reads the code itself:

Swift

```swift
let qa = try ProxyMailQA()
let account = try await qa.createAddress()
let app = XCUIApplication()
app.launch()

app.textFields["Email"].tap()
app.textFields["Email"].typeText(account.address)
let submitted = Date()
app.buttons["Create account"].tap()

let code = try await qa.waitForCode(account.address, since: submitted)
app.textFields["Code"].typeText(code)

```

For a link, `app.open(try await qa.waitForLink(account.address, since: submitted))` opens it the way tapping it in an email would, without the “Open in” prompt. If the email has both a web link and a `myapp://` one, pass `app: true` to get the app’s.

The same helper checks the email itself (`checkEmail` with your Universal Link domain, and `countEmails` for duplicates), signs in as a saved test account, and adds each test to the pull request’s report: see the [XCUITest guide](https://proxymail.qa/docs/xcuitest#check-the-email-not-just-the-code).

## Or let a coding agent do it

Claude Code, Codex and Cursor can drive the simulator, create the address, type it in and read the code over Proxy Mail QA’s MCP server. See [iOS apps with a coding agent](https://proxymail.qa/docs/ios-agents).

## What to check in SwiftUI and UIKit

- **The email field doesn’t change what’s typed.** Without `.textInputAutocapitalization(.never)` and `.autocorrectionDisabled()` in SwiftUI (or `autocapitalizationType = .none` and `autocorrectionType = .no` in UIKit), iOS can capitalise or “correct” an address. Use `.keyboardType(.emailAddress)` and `.textContentType(.emailAddress)` too.
- **The code field offers AutoFill.** `.textContentType(.oneTimeCode)` in SwiftUI, or `textContentType = .oneTimeCode` in UIKit, lets iOS suggest the code above the keyboard on a real device.
- **The link works from a cold start.** This is the most common bug. In SwiftUI, `.onOpenURL` receives both Universal Links and custom-scheme links whether the app was running or not. In UIKit, a link that launches the app arrives in `scene(_:willConnectTo:options:)` (in `connectionOptions.userActivities` or `urlContexts`), not in `scene(_:continue:)` or `scene(_:openURLContexts:)`. Test with the app closed as well as open.
- **The link is still single-use.** Open it twice: the second time should explain that it has been used, not crash or sign in again.
- **It doesn’t point at your Mac.** A link to `localhost` opens in the simulator, which shares your Mac’s network, but nowhere else. Proxy Mail QA flags local links; see [links that point at localhost](https://proxymail.qa/solve/localhost-links).

Using Firebase email-link sign-in? It has its own setup on iOS: see [Firebase email-link sign-in on mobile](https://proxymail.qa/mobile/firebase-email-link).

## Try it on your next sign-up test

Free plan, no credit card. Create an address and watch the code or link arrive.

[Create a free account](https://app.proxymail.qa/?mode=signup)

## Questions

### Can I read email in the iOS simulator?

Not with Mail: the simulator doesn't include it. Read the email in Proxy Mail QA instead, on your Mac, and paste the code into the simulator (it shares your Mac's clipboard) or open the link with xcrun simctl openurl booted followed by the link.

### Why does my Universal Link open Safari instead of my app?

iOS opens the app only when its Associated Domains entitlement lists the link's domain and that domain serves an apple-app-site-association file naming the app. iOS reads the file through Apple's CDN when the app is installed, so after fixing it, delete and reinstall the app. For a staging domain the CDN can't reach, add ?mode=developer to the entry while you develop.

### Does the API key go in my app?

No. The helper and the key belong to the UI test target only, with the key passed in from the test run (the scheme, the test plan or CI secrets). Nothing about Proxy Mail QA ships in your app.

### Can I test codes sent by text message?

No. Proxy Mail QA receives email only. Codes sent by SMS need a different tool.

## Related guides

- [Test sign-up emails in an Android app (Kotlin)Codes and App Links on the emulator, by hand or in Espresso, and why a link opens Chrome instead of your app.](https://proxymail.qa/mobile/android-sign-up-testing)
- [Test sign-up emails and magic links in React Native and Expoexp:// and myapp:// links from Expo Go and development builds, opened in the simulator or from Detox.](https://proxymail.qa/mobile/react-native-expo)
- [Test sign-up emails in a Flutter appCodes in integration tests, deep links on both platforms, and Supabase or Firebase redirects that open the app.](https://proxymail.qa/mobile/flutter)
- [Test Firebase email-link sign-in on iOS and AndroidThe setup after Dynamic Links shut down, and how to test the link opening the app on the same and another device.](https://proxymail.qa/mobile/firebase-email-link)

[See every email testing problem we solve](https://proxymail.qa/solve)
