Getting Started with Ephemail
Learn how to integrate Ephemail into your automated testing workflows with Playwright, Cypress, or any testing framework.
Prerequisites
- Node.js 18+ installed
- Ephemail account (sign up here)
- API key from your dashboard
API Overview
Ephemail provides a simple REST API for creating temporary email inboxes and retrieving messages. All examples use the native Fetch API - no additional packages required.
Configuration
First, create an API key in your dashboard, then add your credentials to your environment variables:
# .env
EPHEMAIL_API_URL=https://api.ephemail.declytic.com/v1
EPHEMAIL_API_KEY=eph_your_api_key_hereBasic Usage
Create a simple example to verify your setup:
const API_URL = process.env.EPHEMAIL_API_URL!;
const API_KEY = process.env.EPHEMAIL_API_KEY!;
// Helper function for API calls
async function ephemailApi(endpoint: string, options: RequestInit = {}) {
const response = await fetch(`${API_URL}${endpoint}`, {
...options,
headers: {
'Authorization': `Bearer ${API_KEY}`,
'Content-Type': 'application/json',
...options.headers,
},
});
if (!response.ok) {
throw new Error(`API error: ${response.status}`);
}
return response.json();
}
// Create a temporary inbox
const inbox = await ephemailApi('/inboxes', {
method: 'POST',
body: JSON.stringify({
expiresInSeconds: 1800, // 30 minutes
tags: { test: 'example' },
}),
});
console.log(`Created inbox: ${inbox.emailAddress}`);
// Poll for latest email (with retry logic)
let message = null;
for (let i = 0; i < 10; i++) {
const messages = await ephemailApi(`/inboxes/${inbox.id}/messages?limit=1`);
if (messages.length > 0) {
message = messages[0];
break;
}
await new Promise(resolve => setTimeout(resolve, 2500));
}
if (message) {
console.log(`Received email: ${message.subject}`);
}
// Clean up
await ephemailApi(`/inboxes/${inbox.id}`, { method: 'DELETE' });Playwright Integration
Integrate Ephemail with Playwright to test magic-link authentication flows:
import { test, expect } from '@playwright/test';
const API_URL = process.env.EPHEMAIL_API_URL!;
const API_KEY = process.env.EPHEMAIL_API_KEY!;
// Helper function for Ephemail API
async function ephemailApi(endpoint: string, options: RequestInit = {}) {
const response = await fetch(`${API_URL}${endpoint}`, {
...options,
headers: {
'Authorization': `Bearer ${API_KEY}`,
'Content-Type': 'application/json',
...options.headers,
},
});
if (!response.ok) throw new Error(`API error: ${response.status}`);
return response.json();
}
// Extract magic link from email HTML
function extractMagicLink(html: string): string | null {
const linkMatch = html.match(/href=["'](https?:\/\/[^"']*(?:magic|verify|auth|login)[^"']*)["']/i);
return linkMatch ? linkMatch[1] : null;
}
test('Complete magic link signup flow', async ({ page }) => {
// Create temporary inbox
const inbox = await ephemailApi('/inboxes', {
method: 'POST',
body: JSON.stringify({ expiresInSeconds: 1800 }),
});
console.log(`Using email: ${inbox.emailAddress}`);
// Navigate to signup page
await page.goto('https://app.example.com/signup');
// Fill in the email form
await page.fill('input[name="email"]', inbox.emailAddress);
await page.click('button[type="submit"]');
// Wait for confirmation message
await expect(page.locator('text=Check your email')).toBeVisible();
// Poll for the magic link email
let message = null;
for (let i = 0; i < 10; i++) {
const messages = await ephemailApi(`/inboxes/${inbox.id}/messages?limit=1`);
if (messages.length > 0 && messages[0].subject?.toLowerCase().includes('magic')) {
message = messages[0];
break;
}
await page.waitForTimeout(2500);
}
expect(message).toBeDefined();
// Extract and visit the magic link
const magicLink = extractMagicLink(message!.htmlBody || message!.textBody);
expect(magicLink).toBeDefined();
await page.goto(magicLink!);
// Verify successful authentication
await expect(page).toHaveURL(/\/dashboard/);
await expect(page.locator('text=Welcome')).toBeVisible();
// Clean up
await ephemailApi(`/inboxes/${inbox.id}`, { method: 'DELETE' });
});Cypress Integration
Use Ephemail in Cypress tests:
// Helper function for Ephemail API
async function ephemailApi(endpoint: string, options: RequestInit = {}) {
const API_URL = Cypress.env('EPHEMAIL_API_URL');
const API_KEY = Cypress.env('EPHEMAIL_API_KEY');
const response = await fetch(`${API_URL}${endpoint}`, {
...options,
headers: {
'Authorization': `Bearer ${API_KEY}`,
'Content-Type': 'application/json',
...options.headers,
},
});
if (!response.ok) throw new Error(`API error: ${response.status}`);
return response.json();
}
function extractMagicLink(html: string): string | null {
const linkMatch = html.match(/href=["'](https?:\/\/[^"']*(?:magic|verify|auth|login)[^"']*)["']/i);
return linkMatch ? linkMatch[1] : null;
}
describe('Magic Link Authentication', () => {
let inbox: any;
it('should complete magic link flow', async () => {
// Create inbox
inbox = await ephemailApi('/inboxes', {
method: 'POST',
body: JSON.stringify({ expiresInSeconds: 1800 }),
});
// Visit signup page
cy.visit('/signup');
cy.get('input[name="email"]').type(inbox.emailAddress);
cy.get('button[type="submit"]').click();
// Poll for email
let message = null;
for (let i = 0; i < 10; i++) {
const messages = await ephemailApi(`/inboxes/${inbox.id}/messages?limit=1`);
if (messages.length > 0) {
message = messages[0];
break;
}
cy.wait(2500);
}
// Extract magic link
const magicLink = extractMagicLink(message!.htmlBody || message!.textBody);
// Visit magic link
cy.visit(magicLink!);
// Verify authenticated
cy.url().should('include', '/dashboard');
cy.contains('Welcome').should('be.visible');
});
after(async () => {
if (inbox) {
await ephemailApi(`/inboxes/${inbox.id}`, { method: 'DELETE' });
}
});
});Advanced Usage
Filtering Emails
Use query parameters to filter for specific emails:
// Poll for a specific email with filters
const sinceTimestamp = Date.now() - 60000; // Last minute
let targetMessage = null;
for (let i = 0; i < 10; i++) {
const messages = await ephemailApi(
`/inboxes/${inbox.id}/messages?limit=10&since=${sinceTimestamp}`
);
// Filter in application code
targetMessage = messages.find((msg: any) =>
msg.from?.includes('noreply@example.com') &&
msg.subject?.includes('Verify your email')
);
if (targetMessage) break;
await new Promise(resolve => setTimeout(resolve, 2500));
}Extracting Links
Extract all links from an email:
// Extract all URLs from email HTML or text
function extractAllLinks(html: string): string[] {
const linkRegex = /href=["'](https?:\/\/[^"']+)["']/gi;
const matches = [...html.matchAll(linkRegex)];
return matches.map(match => match[1]);
}
const links = extractAllLinks(message.htmlBody || message.textBody);
for (const link of links) {
console.log(link);
}
// Or find magic/auth links specifically
function findMagicLink(html: string, allowedHosts: string[] = []): string | null {
const links = extractAllLinks(html);
return links.find(url => {
const hasAuthPattern = /(?:magic|verify|auth|login|signin|signup)/i.test(url);
const matchesHost = allowedHosts.length === 0 ||
allowedHosts.some(host => url.includes(host));
return hasAuthPattern && matchesHost;
}) || null;
}
const magicLink = findMagicLink(message.htmlBody, ['auth.example.com']);Managing Multiple Inboxes
Create and manage multiple inboxes for parallel tests:
const inboxes = await Promise.all([
ephemailApi('/inboxes', {
method: 'POST',
body: JSON.stringify({ tags: { test: 'user-1' } }),
}),
ephemailApi('/inboxes', {
method: 'POST',
body: JSON.stringify({ tags: { test: 'user-2' } }),
}),
ephemailApi('/inboxes', {
method: 'POST',
body: JSON.stringify({ tags: { test: 'user-3' } }),
}),
]);
// Run tests in parallel
await Promise.all(
inboxes.map(inbox => runTestWithInbox(inbox))
);
// Clean up all inboxes
await Promise.all(
inboxes.map(inbox => ephemailApi(`/inboxes/${inbox.id}`, { method: 'DELETE' }))
);Best Practices
- Always clean up: Delete inboxes after tests to avoid hitting limits
- Use appropriate timeouts: Set realistic timeouts based on your email provider
- Tag your inboxes: Use tags to organize and track test inboxes
- Handle failures gracefully: Implement retries for email waiting
- Use filters: Filter emails to reduce false matches and improve reliability
Troubleshooting
Email Not Received
- Verify the email was sent to the correct address
- Check that the inbox hasn't expired
- Increase timeout and retry values
- Check spam/filter settings on the sender side
API Errors
- Verify your API key is correct
- Check that you haven't exceeded your plan limits
- Ensure the API URL is correct for your environment