Selenium Email Testing: Automate Verification in Java and Python
Selenium is still the workhorse for cross-browser and legacy suites, but like any browser driver it can’t read email. Here’s how to test email verification with Selenium — in Java and Python — by reading the message from a disposable inbox API.
The approach
Selenium drives the browser; a disposable inbox API gives you the email. The pattern: create an inbox via Devmailr, drive the signup form with its address, then make one HTTP call to wait for the verification email and read the code.
Java (Selenium + java.net.http)
Using the JDK’s built-in HttpClient and Jackson for JSON:
String base = "https://api.devmailr.app/api";
String auth = "Bearer " + System.getenv("DEVMAILR_API_KEY");
HttpClient http = HttpClient.newHttpClient();
ObjectMapper mapper = new ObjectMapper();
// 1. Create a disposable inbox
String body = """
{"prefix": "sel-%d"}""".formatted(System.currentTimeMillis());
JsonNode inbox = mapper.readTree(http.send(
HttpRequest.newBuilder(URI.create(base + "/mailboxes"))
.header("Authorization", auth).header("Content-Type", "application/json")
.POST(HttpRequest.BodyPublishers.ofString(body)).build(),
HttpResponse.BodyHandlers.ofString()).body());
String id = inbox.get("_id").asText();
String address = inbox.get("address").asText();
// 2. Drive the signup form
driver.get("https://staging.myapp.com/signup");
driver.findElement(By.name("email")).sendKeys(address);
driver.findElement(By.name("password")).sendKeys("correct-horse-battery-staple");
driver.findElement(By.cssSelector("button[type=submit]")).click();
// 3. Wait for the verification email (server long-polls up to 60s)
JsonNode email = mapper.readTree(http.send(
HttpRequest.newBuilder(URI.create(base + "/mailboxes/" + id + "/wait?has_code=true&timeout=60"))
.header("Authorization", auth).timeout(Duration.ofSeconds(65)).build(),
HttpResponse.BodyHandlers.ofString()).body());
String code = email.get("extractedCodes").get(0).asText();
// 4. Enter the code
driver.findElement(By.name("code")).sendKeys(code);
driver.findElement(By.cssSelector("button[type=submit]")).click();Python (Selenium + requests)
import os, time, requests
from selenium import webdriver
from selenium.webdriver.common.by import By
BASE = "https://api.devmailr.app/api"
AUTH = {"Authorization": f"Bearer {os.environ['DEVMAILR_API_KEY']}"}
# 1. Create a disposable inbox
inbox = requests.post(f"{BASE}/mailboxes", headers=AUTH,
json={"prefix": f"sel-{int(time.time())}"}).json()
driver = webdriver.Chrome()
driver.get("https://staging.myapp.com/signup")
driver.find_element(By.NAME, "email").send_keys(inbox["address"])
driver.find_element(By.NAME, "password").send_keys("correct-horse-battery-staple")
driver.find_element(By.CSS_SELECTOR, "button[type=submit]").click()
# 2. Wait for the verification email (give requests a read timeout above the wait)
email = requests.get(f"{BASE}/mailboxes/{inbox['_id']}/wait", headers=AUTH,
params={"has_code": "true", "timeout": 60}, timeout=65).json()
code = email["extractedCodes"][0]
driver.find_element(By.NAME, "code").send_keys(code)
driver.find_element(By.CSS_SELECTOR, "button[type=submit]").click()
# 3. Clean up
requests.delete(f"{BASE}/mailboxes/{inbox['_id']}", headers=AUTH)Magic links
For a click-to-verify link, read primaryLink and point Selenium at it:
email = requests.get(f"{BASE}/mailboxes/{inbox['_id']}/wait", headers=AUTH,
params={"timeout": 60}, timeout=65).json()
driver.get(email["primaryLink"])Tips
- The
/waitendpoint long-polls, so set your HTTP client’s read timeout above the wait timeout (Pythontimeout=65; Java.timeout(Duration.ofSeconds(65))). - Use a unique prefix per run (a timestamp) for parallel safety.
- Keep
DEVMAILR_API_KEYin an env var / CI secret.
Related reading
Try it in two minutes
Create a disposable prefix@devmailr.app inbox over the API, send mail to it from your app, and read it in your tests. Free plan, no card required.