Skip to content

Mobile apps

Mobile UI tests use Proxy Mail QA the same way web tests do: create a test address, type it into the app’s sign-up screen, then wait for the code or link from the email. The helpers on these pages are test code only. Nothing goes into the app you ship.

Each helper does the same things, in its own language:

  • Create a test address with a password for the form, and a date of birth, country or environment when you ask.
  • Wait for the code or link, including the link that opens the app, and skip a code already used.
  • Check the email: count what arrived (exactly one, not two), check it (SPF, DKIM, DMARC, local or http links, where its link goes), or check nothing arrives.
  • Sign in as a saved account, or borrow one no other test has while tests run in parallel.
  • Report on the pull request: with the GitHub Action, each call joins the job’s run, named by its test.
Your tests Guide
Maestro (native iOS and Android, React Native, Flutter) Maestro
XCUITest in Xcode (Swift) iOS (XCUITest)
Espresso or UI Automator in Android Studio (Kotlin) Android (Espresso)
Flutter integration_test (Dart) Flutter
Detox or Appium (JavaScript) Detox and Appium
A coding agent driving the iOS Simulator iOS apps with a coding agent

A coding agent testing an Android app in the emulator works the same way through the MCP server, with whatever tool it has to drive the emulator. We haven’t written a guide for that yet.

For what to check on each platform (cold-start links, App Links that open Chrome, exp:// links, Firebase email-link sign-in), see the mobile app guides.

Every guide reads the API key from the test run: an environment variable, an instrumentation argument or a --dart-define. Store it in your CI’s secrets. Never add it to the app’s configuration or Info.plist, where anyone with the app could read it.

The link in the email is usually an https link that opens the app: a Universal Link on iOS, an App Link on Android. Open it on the device, not in a desktop browser:

Where How
XCUITest XCUIApplication().open(url)
Espresso startActivity with an ACTION_VIEW intent (see the guide)
Maestro - openLink: ${output.link}
Detox device.openURL({ url })
Appium driver.execute('mobile: deepLink', { url, package }) (Android) or { url, bundleId } (iOS)
By hand, iOS simulator xcrun simctl openurl booted '<link>'
By hand, Android emulator adb shell "am start -W -a android.intent.action.VIEW -d '<link>'"

Links that use the app’s own scheme, like myapp://verify?token=… or Expo’s exp://…/--/verify, are picked out too, and classified the same way: waiting for a link returns them. When an email has both a web link and an app link for the same thing, the web link comes first; ask for the app one with app=true (each helper has an app option). GET /v1/addresses/{address}/messages lists every link in each email. Proxy Mail QA never opens links, and the app and the Chrome extension only let you copy app links, with the simulator and emulator commands next to them in the inbox.

Many apps show one box per digit of the code. Type the whole code into the first box: most such fields move to the next box as each digit is typed. If yours doesn’t, type one digit into each box. Before submitting, check every box has its digit: a partial code counts as a wrong attempt, and many apps lock the account after a few.

After the code or link arrives, check the email too: checkEmail with the domain your app’s links open (its Universal Link or App Link domain) returns the checks it fails, and countEmails catches a second email sent by mistake. Each guide shows them in its language, and the REST API says what each check means.

The iOS simulator reaches your computer at localhost. The Android emulator doesn’t: it reaches your computer at 10.0.2.2. If the app sends verification links to localhost, they won’t open on an emulator; see Testing links that point at localhost.

The email checks fail links to localhost or a private address, since a real user couldn’t open them. While you test against your own computer, add its host (such as localhost:3000 or 10.0.2.2:3000) to the project’s dev environments in Project settings, or with POST /v1/project/dev-hosts, and links to it pass.

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