ExamplesOutbound
Service Signup Agent
Agent that signs up for external services and verifies via email
Overview
A service signup agent can autonomously register for external services, verify email addresses, and complete account activation flows without human intervention. This is the foundation of zero-human provisioning.
Info
This pattern enables agents to access services that require email verification, from API platforms to SaaS tools to e-commerce sites.
How It Works
- Create an inbox for the signup process
- Submit registration form using the inbox address
- Poll for confirmation email
- Extract verification link from
ctaLinks - Follow the link to complete activation
- Extract credentials or API keys from confirmation
Complete Implementation
import { DaimonClient } from 'daimon-email';
const client = new DaimonClient();
// Step 1: Create dedicated inbox for service
async function createServiceInbox(serviceName: string) {
const inbox = await client.inboxes.create({
username: `${serviceName}-${Date.now()}`,
clientId: `service-${serviceName}-primary`
});
console.log(`Created inbox for ${serviceName}: ${inbox.address}`);
return inbox;
}
// Step 2: Sign up for external service
async function signUpForService(email: string, serviceName: string) {
// Example: Sign up for a hypothetical API service
const response = await fetch('https://api.example-service.com/signup', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
email: email,
name: 'AI Agent',
company: 'Acme Corp',
use_case: 'Automated integration'
})
});
if (!response.ok) {
throw new Error(`Signup failed: ${response.statusText}`);
}
console.log(`Signup initiated for ${serviceName}`);
return await response.json();
}
// Step 3: Wait for confirmation email
async function waitForConfirmationEmail(
inboxId: string,
fromDomain: string,
timeoutSeconds: number = 300
): Promise<any> {
const startTime = Date.now();
const authedClient = new DaimonClient({ apiKey: process.env.DAIMON_API_KEY });
while (Date.now() - startTime < timeoutSeconds * 1000) {
const messages = await authedClient.inboxes.messages.list(inboxId);
const confirmationEmail = messages.find(msg =>
msg.from.includes(fromDomain) &&
(msg.subject.toLowerCase().includes('confirm') ||
msg.subject.toLowerCase().includes('verify') ||
msg.subject.toLowerCase().includes('activate'))
);
if (confirmationEmail) {
console.log(`Received confirmation email: ${confirmationEmail.subject}`);
return confirmationEmail;
}
// Poll every 5 seconds
await new Promise(resolve => setTimeout(resolve, 5000));
}
throw new Error('Timeout waiting for confirmation email');
}
// Step 4: Extract and follow verification link
async function activateAccount(confirmationEmail: any) {
// daimon.email automatically detects CTA links
const ctaLinks = confirmationEmail.ctaLinks;
if (ctaLinks.length === 0) {
throw new Error('No verification link found in email');
}
const verificationLink = ctaLinks[0]; // First CTA is usually the main action
console.log(`Found verification link: ${verificationLink.text}`);
console.log(`URL: ${verificationLink.url}`);
// "Click" the verification link
const response = await fetch(verificationLink.url, {
method: 'GET',
redirect: 'follow'
});
if (response.ok) {
console.log('Account activated successfully!');
return true;
} else {
throw new Error(`Activation failed: ${response.statusText}`);
}
}
// Step 5: Extract credentials from welcome email
async function extractCredentials(inboxId: string, fromDomain: string) {
const authedClient = new DaimonClient({ apiKey: process.env.DAIMON_API_KEY });
// Wait for welcome/credentials email
await new Promise(resolve => setTimeout(resolve, 10000)); // Wait 10s
const messages = await authedClient.inboxes.messages.list(inboxId);
const welcomeEmail = messages.find(msg =>
msg.from.includes(fromDomain) &&
(msg.subject.toLowerCase().includes('welcome') ||
msg.subject.toLowerCase().includes('getting started') ||
msg.subject.toLowerCase().includes('api key'))
);
if (!welcomeEmail) {
console.log('No credentials email found (may require manual retrieval)');
return null;
}
// Extract API key or other credentials from email body
const apiKeyMatch = welcomeEmail.body.match(/API Key:\s*([A-Za-z0-9_-]+)/);
if (apiKeyMatch) {
console.log(`Extracted API key: ${apiKeyMatch[1].substring(0, 10)}...`);
return {
apiKey: apiKeyMatch[1],
email: welcomeEmail.to
};
}
return null;
}
// Complete flow
async function completeServiceSignup(serviceName: string, fromDomain: string) {
try {
// Step 1: Create inbox
const inbox = await createServiceInbox(serviceName);
// Step 2: Sign up for service
await signUpForService(inbox.address, serviceName);
// Step 3: Wait for confirmation email
const confirmationEmail = await waitForConfirmationEmail(
inbox.id,
fromDomain,
300 // 5 minute timeout
);
// Step 4: Activate account
await activateAccount(confirmationEmail);
// Step 5: Extract credentials
const credentials = await extractCredentials(inbox.id, fromDomain);
console.log('\n✅ Service signup complete!');
console.log(`Inbox: ${inbox.address}`);
console.log(`Credentials:`, credentials);
return {
inbox,
credentials,
success: true
};
} catch (error) {
console.error('Signup failed:', error);
return {
success: false,
error: error.message
};
}
}
// Usage
completeServiceSignup('example-api', 'noreply@example-service.com');from daimon_email import DaimonClient
import requests
import time
import re
from typing import Optional, Dict
client = DaimonClient()
# Step 1: Create dedicated inbox for service
def create_service_inbox(service_name: str):
inbox = client.inboxes.create(
username=f"{service_name}-{int(time.time())}",
client_id=f"service-{service_name}-primary"
)
print(f"Created inbox for {service_name}: {inbox.address}")
return inbox
# Step 2: Sign up for external service
def sign_up_for_service(email: str, service_name: str):
# Example: Sign up for a hypothetical API service
response = requests.post('https://api.example-service.com/signup', json={
'email': email,
'name': 'AI Agent',
'company': 'Acme Corp',
'use_case': 'Automated integration'
})
response.raise_for_status()
print(f"Signup initiated for {service_name}")
return response.json()
# Step 3: Wait for confirmation email
def wait_for_confirmation_email(
inbox_id: str,
from_domain: str,
timeout_seconds: int = 300
) -> Optional[Dict]:
start_time = time.time()
authed_client = DaimonClient(api_key=os.environ.get('DAIMON_API_KEY'))
while time.time() - start_time < timeout_seconds:
messages = authed_client.inboxes.messages.list(inbox_id)
confirmation_email = next(
(msg for msg in messages
if from_domain in msg['from']
and any(keyword in msg['subject'].lower()
for keyword in ['confirm', 'verify', 'activate'])),
None
)
if confirmation_email:
print(f"Received confirmation email: {confirmation_email['subject']}")
return confirmation_email
# Poll every 5 seconds
time.sleep(5)
raise TimeoutError('Timeout waiting for confirmation email')
# Step 4: Extract and follow verification link
def activate_account(confirmation_email: Dict):
# daimon.email automatically detects CTA links
cta_links = confirmation_email.get('cta_links', [])
if not cta_links:
raise ValueError('No verification link found in email')
verification_link = cta_links[0] # First CTA is usually the main action
print(f"Found verification link: {verification_link['text']}")
print(f"URL: {verification_link['url']}")
# "Click" the verification link
response = requests.get(verification_link['url'], allow_redirects=True)
if response.ok:
print('Account activated successfully!')
return True
else:
raise Exception(f"Activation failed: {response.status_code}")
# Step 5: Extract credentials from welcome email
def extract_credentials(inbox_id: str, from_domain: str):
authed_client = DaimonClient(api_key=os.environ.get('DAIMON_API_KEY'))
# Wait for welcome/credentials email
time.sleep(10)
messages = authed_client.inboxes.messages.list(inbox_id)
welcome_email = next(
(msg for msg in messages
if from_domain in msg['from']
and any(keyword in msg['subject'].lower()
for keyword in ['welcome', 'getting started', 'api key'])),
None
)
if not welcome_email:
print('No credentials email found (may require manual retrieval)')
return None
# Extract API key or other credentials from email body
api_key_match = re.search(r'API Key:\s*([A-Za-z0-9_-]+)', welcome_email['body'])
if api_key_match:
api_key = api_key_match.group(1)
print(f"Extracted API key: {api_key[:10]}...")
return {
'api_key': api_key,
'email': welcome_email['to']
}
return None
# Complete flow
def complete_service_signup(service_name: str, from_domain: str):
try:
# Step 1: Create inbox
inbox = create_service_inbox(service_name)
# Step 2: Sign up for service
sign_up_for_service(inbox.address, service_name)
# Step 3: Wait for confirmation email
confirmation_email = wait_for_confirmation_email(
inbox.id,
from_domain,
300 # 5 minute timeout
)
# Step 4: Activate account
activate_account(confirmation_email)
# Step 5: Extract credentials
credentials = extract_credentials(inbox.id, from_domain)
print('\n✅ Service signup complete!')
print(f"Inbox: {inbox.address}")
print(f"Credentials: {credentials}")
return {
'inbox': inbox,
'credentials': credentials,
'success': True
}
except Exception as e:
print(f"Signup failed: {e}")
return {
'success': False,
'error': str(e)
}
# Usage
if __name__ == '__main__':
complete_service_signup('example-api', 'noreply@example-service.com')Real-World Examples
API Platform Signup
// Sign up for Stripe, Twilio, etc.
await completeServiceSignup('stripe', 'noreply@stripe.com');
await completeServiceSignup('twilio', 'noreply@twilio.com');SaaS Trial Activation
// Activate free trials for testing
await completeServiceSignup('datadog', 'noreply@datadoghq.com');
await completeServiceSignup('mongodb-atlas', 'noreply@mongodb.com');E-commerce Account Creation
// Create accounts on e-commerce platforms
await completeServiceSignup('shopify', 'noreply@shopify.com');Key Features
- CTA detection: Automatically identifies verification/confirmation links
- Polling with timeout: Graceful handling of delayed emails
- Credential extraction: Parse API keys and login details from emails
- Idempotent: Use
clientIdto prevent duplicate signups