Overview

Keystone’s email testing system enables automated tests to create temporary email inboxes, receive emails, and extract verification codes, links, and other data. This feature is essential for testing email-based workflows like user registration, password resets, and order confirmations.

Key Features

  • On-demand inbox creation - Generate unique email addresses for each test
  • Real-time email delivery - Receive emails via SendGrid webhooks
  • Data extraction - Extract codes, links, and custom patterns from emails
  • Organization isolation - Complete separation between different organizations
  • Auto-cleanup - Inboxes automatically expire after 24 hours

How It Works

The email testing workflow follows these steps:
  1. Create Inbox → Generate a unique test email address
  2. Use in Application → Fill forms with the test email
  3. Wait for Email → Poll until the email arrives
  4. Extract Data → Get verification codes, links, or custom content
  5. Continue Testing → Use extracted data in subsequent steps

Email Address Format

Email addresses follow this format: +@withkeystonemail.com Examples:
  • acmecorp123456+signup-test@withkeystonemail.com
  • testorg7890ab+password-reset@withkeystonemail.com
Components:
  • org_prefix: Unique identifier for your organization (auto-generated)
  • inbox_name: Your chosen inbox identifier
  • @withkeystonemail.com: Keystone’s email domain

Email Testing Steps

EMAIL_CREATE_INBOX

Creates or retrieves a test email inbox for receiving emails during test execution.
inboxName
string
required
Unique name for the inbox. Use timestamps or random values for uniqueness across test runs.
email
string
Custom email address to use instead of auto-generated format
storeAs
string
required
Variable name to store the generated email address

WAIT_FOR_EMAIL

Waits for an email to arrive in the specified inbox with optional filtering.
inbox
string
required
Email address to check. Supports variable interpolation.
timeout
number
default:"60"
Maximum wait time in seconds
fromAddress
string
Filter by sender address (partial match)
subject
string
Filter by email subject (partial match)
storeAs
string
Variable name to store the received email data

EMAIL_EXTRACT

Extracts specific data from a received email.
emailVariable
string
required
Variable containing email data from WAIT_FOR_EMAIL
extractType
enum
required
Type of extraction:
  • code - Extract verification codes (6-digit, 4-digit, alphanumeric)
  • link - Extract URLs from the email
  • subject - Get the email subject line
  • sender - Get the sender email address
  • custom - Use custom regex pattern
For link type: text of the link to find
pattern
string
For custom type: regex pattern to match
storeAs
string
required
Variable name to store the extracted value

Complete Examples

User Signup Flow

  1. Create email inbox
    • Step type: EMAIL_CREATE_INBOX
    • Inbox name: signup-
    • Store as: TEST_EMAIL
  2. Fill signup form
    • Type email address using variable
    • Type password
    • Click signup button
  3. Wait for verification email
    • Step type: WAIT_FOR_EMAIL
    • Check inbox:
    • Subject filter: “Verify your email”
    • Timeout: 30 seconds
    • Store as: VERIFY_EMAIL
  4. Extract verification code
    • Step type: EMAIL_EXTRACT
    • From variable: VERIFY_EMAIL
    • Extract type: code
    • Store as: VERIFY_CODE
  5. Complete verification
    • Type verification code using
    • Click verify button

Password Reset Flow

  1. Setup test email
    • Step type: EMAIL_CREATE_INBOX
    • Inbox name: reset-pw-test
    • Store as: USER_EMAIL
  2. Request password reset
    • Navigate to forgot password page
    • Type email using
    • Click reset button
  3. Get reset link from email
    • Step type: WAIT_FOR_EMAIL
    • Check inbox:
    • Subject filter: “Reset your password”
    • Store as: RESET_EMAIL
  4. Extract reset link
    • Step type: EMAIL_EXTRACT
    • From variable: RESET_EMAIL
    • Extract type: link
    • Link text: “Reset Password”
    • Store as: RESET_URL
  5. Complete password reset
    • Navigate to
    • Type new password

Order Confirmation

  1. Setup customer email
    • Step type: EMAIL_CREATE_INBOX
    • Inbox name: order-test
    • Store as: CUSTOMER_EMAIL
  2. Complete purchase
    • (Your checkout steps here)
  3. Wait for order confirmation
    • Step type: WAIT_FOR_EMAIL
    • Check inbox:
    • From filter: orders@shop.com
    • Subject filter: “Order Confirmation”
    • Store as: ORDER_EMAIL
  4. Extract order number
    • Step type: EMAIL_EXTRACT
    • From variable: ORDER_EMAIL
    • Extract type: custom
    • Pattern: Order #(\w+)
    • Store as: ORDER_ID
  5. Verify order
    • Navigate to order status page using

Advanced Usage

Using Timestamps for Unique Inboxes

To ensure unique inbox names across test runs:
  • Step type: EMAIL_CREATE_INBOX
  • Inbox name: test-
  • Store as: UNIQUE_EMAIL
The variable automatically generates a unique identifier.

Multiple Email Filtering

When expecting multiple emails, use filters to find the right one:
  • Step type: WAIT_FOR_EMAIL
  • Check inbox:
  • From filter: billing@company.com
  • Subject filter: “Invoice”
  • Timeout: 120 seconds
  • Store as: INVOICE_EMAIL

Extracting Multiple Values

You can extract different data from the same email: First extraction - Get verification code:
  • Step type: EMAIL_EXTRACT
  • From variable: SIGNUP_EMAIL
  • Extract type: code
  • Store as: CODE
Second extraction - Get activation link:
  • Step type: EMAIL_EXTRACT
  • From variable: SIGNUP_EMAIL
  • Extract type: link
  • Link text: “Activate”
  • Store as: ACTIVATION_URL

Code Pattern Recognition

The system automatically recognizes various code formats:
  • 6-digit codes: 123456
  • 4-digit codes: 1234
  • Alphanumeric: ABC123
  • Labeled codes: Code: 123456, PIN: 1234
  • OTP formats: OTP: 567890

Troubleshooting

Common Issues

Best Practices

  1. Use unique inbox names - Add timestamps or random values
  2. Set reasonable timeouts - 30-60 seconds usually sufficient
  3. Use filters wisely - Only when multiple emails expected
  4. Store email data - Always use storeAs in WAIT_FOR_EMAIL
  5. Test incrementally - Verify each step works before adding more

Debug Information

Email data structure contains these fields:
  • id: Unique email identifier
  • subject: Email subject line
  • from: Sender email address
  • to: Recipient email address
  • text: Plain text email body
  • html: HTML email body
  • headers: Email headers (Message-ID, Date, etc.)
  • received_at: Timestamp when email was received

Technical Details

Infrastructure

  • Email Domain: withkeystonemail.com
  • Provider: SendGrid Inbound Parse
  • Storage: PostgreSQL
  • Cleanup: Automatic after 24 hours
  • Rate Limits: 100 emails/hour per organization

Security

  • Organization-level isolation
  • No cross-organization email access
  • Automatic expiration
  • API key authentication for runners

Limitations

  • Maximum email size: 10MB
  • Attachment support: Basic (stored references)
  • Custom domains: Not currently supported
  • Email sending: Receive-only system

Email Flow Architecture

The email testing system follows this flow:
  1. Your Application → Sends email via your email service
  2. SendGrid → Receives and processes the email
  3. Webhook Delivery → SendGrid forwards to Keystone
  4. Keystone Backend → Stores email in database
  5. Test Runner → Polls for new emails
  6. Email Retrieved → Test continues with email data
The email system is idempotent - re-running tests with the same inbox name will clear previous emails and start fresh.