Code Examples
Ready-to-use code examples for integrating ValidMail into your applications in multiple languages.
JS
JavaScript / Node.js
Basic Email Verification
// Using fetch (Node.js 18+ or browser)
async function verifyEmail(email) {
const response = await fetch('https://validmail.io/api/v1/verify', {
method: 'POST',
headers: {
'Authorization': `Bearer ${process.env.VALIDMAIL_API_KEY}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({ email }),
});
if (!response.ok) {
throw new Error(`Verification failed: ${response.status}`);
}
return response.json();
}
// Usage
const result = await verifyEmail('user@example.com');
console.log(result.status); // 'valid', 'invalid', 'risky', or 'unknown'
console.log(result.score); // 0-100With Axios and Error Handling
import axios from 'axios';
const validmail = axios.create({
baseURL: 'https://validmail.io/api/v1',
headers: {
'Authorization': `Bearer ${process.env.VALIDMAIL_API_KEY}`,
'Content-Type': 'application/json',
},
});
async function verifyEmail(email) {
try {
const { data } = await validmail.post('/verify', { email });
return data;
} catch (error) {
if (error.response) {
const { code, message } = error.response.data.error;
if (code === 'RATE_LIMITED') {
const retryAfter = error.response.headers['retry-after'];
throw new Error(`Rate limited. Retry after ${retryAfter}s`);
}
throw new Error(`${code}: ${message}`);
}
throw error;
}
}
// Batch verification with concurrency control
async function verifyEmails(emails, concurrency = 5) {
const results = [];
for (let i = 0; i < emails.length; i += concurrency) {
const batch = emails.slice(i, i + concurrency);
const batchResults = await Promise.all(
batch.map(email => verifyEmail(email).catch(err => ({
email,
status: 'error',
error: err.message,
})))
);
results.push(...batchResults);
// Small delay between batches to respect rate limits
if (i + concurrency < emails.length) {
await new Promise(r => setTimeout(r, 200));
}
}
return results;
}Express.js Middleware
import express from 'express';
const app = express();
app.use(express.json());
// Middleware to validate email in request body
async function validateEmail(req, res, next) {
const { email } = req.body;
if (!email) {
return res.status(400).json({ error: 'Email is required' });
}
try {
const response = await fetch('https://validmail.io/api/v1/verify', {
method: 'POST',
headers: {
'Authorization': `Bearer ${process.env.VALIDMAIL_API_KEY}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({ email }),
});
const result = await response.json();
if (result.status === 'invalid') {
return res.status(400).json({
error: 'Invalid email address',
details: result.verdict,
});
}
// Attach validation result to request
req.emailValidation = result;
next();
} catch (error) {
// Don't block on verification errors
console.error('Email validation error:', error);
next();
}
}
// Use in routes
app.post('/signup', validateEmail, (req, res) => {
const { email } = req.body;
const validation = req.emailValidation;
// Proceed with signup, maybe warn for risky emails
if (validation?.status === 'risky') {
console.log(`Warning: Risky email signup: ${email}`);
}
// ... signup logic
});PY
Python
Basic Verification
import os
import requests
def verify_email(email: str) -> dict:
"""Verify a single email address."""
response = requests.post(
'https://validmail.io/api/v1/verify',
headers={
'Authorization': f'Bearer {os.environ["VALIDMAIL_API_KEY"]}',
'Content-Type': 'application/json',
},
json={'email': email},
timeout=30
)
response.raise_for_status()
return response.json()
# Usage
result = verify_email('user@example.com')
print(f"Status: {result['status']}")
print(f"Score: {result['score']}")Class-based Client with Retry Logic
import os
import time
import requests
from typing import Optional, List, Dict
from dataclasses import dataclass
@dataclass
class VerificationResult:
email: str
status: str
score: int
verdict: str
checks: dict
class ValidMailClient:
def __init__(self, api_key: Optional[str] = None):
self.api_key = api_key or os.environ.get('VALIDMAIL_API_KEY')
self.base_url = 'https://validmail.io/api/v1'
self.session = requests.Session()
self.session.headers.update({
'Authorization': f'Bearer {self.api_key}',
'Content-Type': 'application/json',
})
def verify(self, email: str, retries: int = 3) -> VerificationResult:
"""Verify email with automatic retry on rate limits."""
for attempt in range(retries):
response = self.session.post(
f'{self.base_url}/verify',
json={'email': email},
timeout=30
)
if response.status_code == 429:
retry_after = int(response.headers.get('Retry-After', 60))
time.sleep(retry_after)
continue
response.raise_for_status()
data = response.json()
return VerificationResult(
email=data['email'],
status=data['status'],
score=data['score'],
verdict=data['verdict'],
checks=data['checks']
)
raise Exception('Max retries exceeded')
def verify_batch(self, emails: List[str]) -> List[VerificationResult]:
"""Verify multiple emails."""
results = []
for email in emails:
try:
result = self.verify(email)
results.append(result)
except Exception as e:
results.append(VerificationResult(
email=email,
status='error',
score=0,
verdict=str(e),
checks={}
))
time.sleep(0.1) # Rate limiting
return results
# Usage
client = ValidMailClient()
result = client.verify('user@example.com')
print(f"{result.email}: {result.status} ({result.score})")Django Integration
# validators.py
import requests
from django.conf import settings
from django.core.exceptions import ValidationError
def validate_email_deliverable(email):
"""Django validator for email deliverability."""
try:
response = requests.post(
'https://validmail.io/api/v1/verify',
headers={
'Authorization': f'Bearer {settings.VALIDMAIL_API_KEY}',
'Content-Type': 'application/json',
},
json={'email': email},
timeout=10
)
result = response.json()
if result['status'] == 'invalid':
raise ValidationError(
f'This email address is invalid: {result["verdict"]}'
)
if result['checks'].get('disposable'):
raise ValidationError(
'Disposable email addresses are not allowed'
)
except requests.RequestException:
# Don't block on network errors
pass
# models.py
from django.db import models
from .validators import validate_email_deliverable
class User(models.Model):
email = models.EmailField(
unique=True,
validators=[validate_email_deliverable]
)
# ... other fields
# forms.py
from django import forms
from .validators import validate_email_deliverable
class SignupForm(forms.Form):
email = forms.EmailField(validators=[validate_email_deliverable])
password = forms.CharField(widget=forms.PasswordInput)PHP
PHP
Basic Verification
<?php
function verifyEmail(string $email): array {
$apiKey = getenv('VALIDMAIL_API_KEY');
$ch = curl_init('https://validmail.io/api/v1/verify');
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_POST => true,
CURLOPT_HTTPHEADER => [
'Authorization: Bearer ' . $apiKey,
'Content-Type: application/json',
],
CURLOPT_POSTFIELDS => json_encode(['email' => $email]),
CURLOPT_TIMEOUT => 30,
]);
$response = curl_exec($ch);
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);
if ($httpCode !== 200) {
throw new Exception("Verification failed: HTTP $httpCode");
}
return json_decode($response, true);
}
// Usage
try {
$result = verifyEmail('user@example.com');
echo "Status: " . $result['status'] . "\n";
echo "Score: " . $result['score'] . "\n";
} catch (Exception $e) {
echo "Error: " . $e->getMessage();
}Laravel Integration
<?php
// app/Services/ValidMailService.php
namespace App\Services;
use Illuminate\Support\Facades\Http;
use Illuminate\Support\Facades\Cache;
class ValidMailService
{
protected string $apiKey;
protected string $baseUrl = 'https://validmail.io/api/v1';
public function __construct()
{
$this->apiKey = config('services.validmail.key');
}
public function verify(string $email): array
{
// Cache results for 24 hours
return Cache::remember(
'email_verification_' . md5($email),
now()->addHours(24),
fn() => $this->doVerify($email)
);
}
protected function doVerify(string $email): array
{
$response = Http::withToken($this->apiKey)
->timeout(30)
->post("{$this->baseUrl}/verify", [
'email' => $email,
]);
if ($response->status() === 429) {
$retryAfter = $response->header('Retry-After', 60);
throw new \Exception("Rate limited. Retry after {$retryAfter}s");
}
$response->throw();
return $response->json();
}
}
// app/Rules/DeliverableEmail.php
namespace App\Rules;
use App\Services\ValidMailService;
use Illuminate\Contracts\Validation\Rule;
class DeliverableEmail implements Rule
{
protected string $message = 'This email address is not valid.';
public function passes($attribute, $value): bool
{
try {
$service = app(ValidMailService::class);
$result = $service->verify($value);
if ($result['status'] === 'invalid') {
$this->message = $result['verdict'];
return false;
}
if ($result['checks']['disposable'] ?? false) {
$this->message = 'Disposable emails are not allowed.';
return false;
}
return true;
} catch (\Exception $e) {
// Log error but don't block
\Log::warning('Email verification failed', ['error' => $e->getMessage()]);
return true;
}
}
public function message(): string
{
return $this->message;
}
}
// Usage in controller
public function register(Request $request)
{
$request->validate([
'email' => ['required', 'email', new DeliverableEmail],
'password' => ['required', 'min:8'],
]);
// ...
}RB
Ruby
Basic Verification with HTTParty
require 'httparty'
class ValidMail
include HTTParty
base_uri 'https://validmail.io/api/v1'
def initialize(api_key = ENV['VALIDMAIL_API_KEY'])
@api_key = api_key
end
def verify(email)
response = self.class.post('/verify',
headers: {
'Authorization' => "Bearer #{@api_key}",
'Content-Type' => 'application/json'
},
body: { email: email }.to_json,
timeout: 30
)
raise "Verification failed: #{response.code}" unless response.success?
response.parsed_response
end
end
# Usage
client = ValidMail.new
result = client.verify('user@example.com')
puts "Status: #{result['status']}"
puts "Score: #{result['score']}"Rails ActiveModel Validator
# app/validators/deliverable_email_validator.rb
class DeliverableEmailValidator < ActiveModel::EachValidator
def validate_each(record, attribute, value)
return if value.blank?
result = verify_email(value)
case result['status']
when 'invalid'
record.errors.add(attribute, result['verdict'])
when 'risky'
if result.dig('checks', 'disposable')
record.errors.add(attribute, 'disposable emails are not allowed')
end
end
rescue => e
Rails.logger.warn "Email verification failed: #{e.message}"
# Don't block on errors
end
private
def verify_email(email)
Rails.cache.fetch("email_verification_#{email}", expires_in: 24.hours) do
response = HTTParty.post(
'https://validmail.io/api/v1/verify',
headers: {
'Authorization' => "Bearer #{ENV['VALIDMAIL_API_KEY']}",
'Content-Type' => 'application/json'
},
body: { email: email }.to_json,
timeout: 30
)
response.parsed_response
end
end
end
# app/models/user.rb
class User < ApplicationRecord
validates :email, presence: true, deliverable_email: true
endGO
Go
HTTP Client
package validmail
import (
"bytes"
"encoding/json"
"fmt"
"net/http"
"os"
"time"
)
type Client struct {
apiKey string
baseURL string
httpClient *http.Client
}
type VerifyRequest struct {
Email string `json:"email"`
}
type VerifyResponse struct {
Email string `json:"email"`
Status string `json:"status"`
Score int `json:"score"`
Verdict string `json:"verdict"`
Checks map[string]interface{} `json:"checks"`
}
func NewClient(apiKey string) *Client {
if apiKey == "" {
apiKey = os.Getenv("VALIDMAIL_API_KEY")
}
return &Client{
apiKey: apiKey,
baseURL: "https://validmail.io/api/v1",
httpClient: &http.Client{
Timeout: 30 * time.Second,
},
}
}
func (c *Client) Verify(email string) (*VerifyResponse, error) {
body, _ := json.Marshal(VerifyRequest{Email: email})
req, err := http.NewRequest("POST", c.baseURL+"/verify", bytes.NewBuffer(body))
if err != nil {
return nil, err
}
req.Header.Set("Authorization", "Bearer "+c.apiKey)
req.Header.Set("Content-Type", "application/json")
resp, err := c.httpClient.Do(req)
if err != nil {
return nil, err
}
defer resp.Body.Close()
if resp.StatusCode != http.StatusOK {
return nil, fmt.Errorf("verification failed: %d", resp.StatusCode)
}
var result VerifyResponse
if err := json.NewDecoder(resp.Body).Decode(&result); err != nil {
return nil, err
}
return &result, nil
}
// Usage
func main() {
client := NewClient("")
result, err := client.Verify("user@example.com")
if err != nil {
panic(err)
}
fmt.Printf("Status: %s, Score: %d\n", result.Status, result.Score)
}cURL
Single Email Verification
curl -X POST https://validmail.io/api/v1/verify \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{"email": "user@example.com"}'Bulk Verification
# Create bulk job
curl -X POST https://validmail.io/api/v1/bulk \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"emails": ["user1@example.com", "user2@example.com"],
"name": "My List"
}'
# Check status
curl https://validmail.io/api/v1/bulk/bulk_abc123 \
-H "Authorization: Bearer YOUR_API_KEY"
# Download results
curl https://validmail.io/api/v1/bulk/bulk_abc123/download \
-H "Authorization: Bearer YOUR_API_KEY"