PHP Email Validation

Complete guide to email validation in PHP

What You'll Learn

  • Integrate VerifyForge API using cURL
  • Create reusable validation functions
  • Validate emails in PHP applications
  • Handle errors gracefully
  • Implement bulk validation
  • Best practices for production

Prerequisites

  • PHP 8+ installed
  • cURL extension enabled
  • Basic knowledge of PHP
  • VerifyForge API key (get free key)

Quick Start

<?php

$apiKey = 'your_api_key';
$email = 'user@example.com';

$ch = curl_init();
curl_setopt_array($ch, [
    CURLOPT_URL => "https://verifyforge.com/api/validate?email=" . urlencode($email),
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_HTTPHEADER => [
        "X-API-Key: $apiKey"
    ],
]);

$response = curl_exec($ch);
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);

if ($httpCode === 200) {
    $result = json_decode($response, true);

    if ($result['data']['isValid']) {
        echo "✓ Email is valid!\n";
        echo "Reachability: " . $result['data']['reachability'] . "\n";
    }
}

Tutorial 1: Email Validation Class

<?php
// EmailValidator.php

class EmailValidator
{
    private string $apiKey;
    private string $baseUrl;

    public function __construct(string $apiKey, string $baseUrl = 'https://verifyforge.com')
    {
        $this->apiKey = $apiKey;
        $this->baseUrl = $baseUrl;
    }

    public function validate(string $email): ?array
    {
        $ch = curl_init();

        curl_setopt_array($ch, [
            CURLOPT_URL => $this->baseUrl . "/api/validate?email=" . urlencode($email),
            CURLOPT_RETURNTRANSFER => true,
            CURLOPT_TIMEOUT => 30,
            CURLOPT_HTTPHEADER => [
                "X-API-Key: {$this->apiKey}",
                "Content-Type: application/json"
            ],
        ]);

        $response = curl_exec($ch);
        $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
        $error = curl_error($ch);
        curl_close($ch);

        if ($error) {
            throw new Exception("cURL error: $error");
        }

        if ($httpCode !== 200) {
            throw new Exception("API error: HTTP $httpCode");
        }

        $result = json_decode($response, true);

        if (json_last_error() !== JSON_ERROR_NONE) {
            throw new Exception("JSON decode error: " . json_last_error_msg());
        }

        return $result['data'] ?? null;
    }

    public function validateBulk(array $emails): ?array
    {
        $ch = curl_init();

        $payload = json_encode(['emails' => $emails]);

        curl_setopt_array($ch, [
            CURLOPT_URL => $this->baseUrl . "/api/validate/bulk",
            CURLOPT_RETURNTRANSFER => true,
            CURLOPT_POST => true,
            CURLOPT_POSTFIELDS => $payload,
            CURLOPT_TIMEOUT => 60,
            CURLOPT_HTTPHEADER => [
                "X-API-Key: {$this->apiKey}",
                "Content-Type: application/json",
                "Content-Length: " . strlen($payload)
            ],
        ]);

        $response = curl_exec($ch);
        $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
        curl_close($ch);

        if ($httpCode !== 200) {
            return null;
        }

        return json_decode($response, true);
    }

    public function isValid(string $email): bool
    {
        try {
            $result = $this->validate($email);
            return $result['isValid'] ?? false;
        } catch (Exception $e) {
            error_log("Email validation error: " . $e->getMessage());
            return false;
        }
    }
}

Tutorial 2: Form Validation

<?php
// registration.php

require_once 'EmailValidator.php';

$validator = new EmailValidator($_ENV['VERIFYFORGE_API_KEY']);
$errors = [];

if ($_SERVER['REQUEST_METHOD'] === 'POST') {
    $email = $_POST['email'] ?? '';
    $name = $_POST['name'] ?? '';

    // Basic validation
    if (empty($name)) {
        $errors['name'] = 'Name is required';
    }

    if (empty($email)) {
        $errors['email'] = 'Email is required';
    } elseif (!filter_var($email, FILTER_VALIDATE_EMAIL)) {
        $errors['email'] = 'Invalid email format';
    } else {
        // VerifyForge validation
        try {
            $result = $validator->validate($email);

            if (!$result['isValid']) {
                $errors['email'] = 'This email address is not valid';
            } elseif ($result['disposable']) {
                $errors['email'] = 'Temporary email addresses are not allowed';
            } elseif ($result['reachability'] === 'invalid') {
                $errors['email'] = 'This email cannot receive mail';
            }
        } catch (Exception $e) {
            error_log("Validation error: " . $e->getMessage());
            // Allow form submission if validation service fails
        }
    }

    // If no errors, process registration
    if (empty($errors)) {
        // Save user to database
        // ...

        header('Location: /success');
        exit;
    }
}
?>

<!DOCTYPE html>
<html>
<head>
    <title>Registration</title>
</head>
<body>
    <form method="POST">
        <div>
            <label>Name:</label>
            <input type="text" name="name" value="<?= htmlspecialchars($_POST['name'] ?? '') ?>">
            <?php if (isset($errors['name'])): ?>
                <span class="error"><?= $errors['name'] ?></span>
            <?php endif; ?>
        </div>

        <div>
            <label>Email:</label>
            <input type="email" name="email" value="<?= htmlspecialchars($_POST['email'] ?? '') ?>">
            <?php if (isset($errors['email'])): ?>
                <span class="error"><?= $errors['email'] ?></span>
            <?php endif; ?>
        </div>

        <button type="submit">Register</button>
    </form>
</body>
</html>

Tutorial 3: API Endpoint

<?php
// api/validate.php

header('Content-Type: application/json');

require_once '../EmailValidator.php';

$validator = new EmailValidator($_ENV['VERIFYFORGE_API_KEY']);

if ($_SERVER['REQUEST_METHOD'] !== 'POST') {
    http_response_code(405);
    echo json_encode(['error' => 'Method not allowed']);
    exit;
}

$input = json_decode(file_get_contents('php://input'), true);
$email = $input['email'] ?? '';

if (empty($email)) {
    http_response_code(400);
    echo json_encode(['error' => 'Email is required']);
    exit;
}

try {
    $result = $validator->validate($email);

    echo json_encode([
        'success' => true,
        'data' => [
            'email' => $result['email'],
            'isValid' => $result['isValid'],
            'reachability' => $result['reachability'],
            'disposable' => $result['disposable'],
            'roleAccount' => $result['roleAccount'],
            'suggestion' => $result['suggestion'] ?? null,
        ]
    ]);

} catch (Exception $e) {
    http_response_code(500);
    echo json_encode(['error' => 'Validation failed']);
}

Best Practices

1. Environment Variables

<?php
// Load from .env file
$envFile = __DIR__ . '/.env';
if (file_exists($envFile)) {
    $lines = file($envFile, FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES);
    foreach ($lines as $line) {
        if (strpos($line, '=') !== false && strpos($line, '#') !== 0) {
            list($key, $value) = explode('=', $line, 2);
            $_ENV[trim($key)] = trim($value);
        }
    }
}

$apiKey = $_ENV['VERIFYFORGE_API_KEY'] ?? '';

2. Caching

<?php
class CachedEmailValidator extends EmailValidator
{
    private string $cacheDir;

    public function __construct(string $apiKey, string $cacheDir = '/tmp/email_cache')
    {
        parent::__construct($apiKey);
        $this->cacheDir = $cacheDir;

        if (!is_dir($cacheDir)) {
            mkdir($cacheDir, 0755, true);
        }
    }

    public function validate(string $email): ?array
    {
        $cacheKey = md5($email);
        $cacheFile = $this->cacheDir . '/' . $cacheKey;

        // Check cache
        if (file_exists($cacheFile)) {
            $cached = json_decode(file_get_contents($cacheFile), true);
            $age = time() - $cached['timestamp'];

            if ($age < 3600) { // 1 hour cache
                return $cached['data'];
            }
        }

        // Validate
        $result = parent::validate($email);

        // Cache result
        file_put_contents($cacheFile, json_encode([
            'data' => $result,
            'timestamp' => time()
        ]));

        return $result;
    }
}

3. Error Handling

<?php
function validateEmailSafely(string $email, EmailValidator $validator): array
{
    try {
        $result = $validator->validate($email);
        return [
            'success' => true,
            'data' => $result
        ];
    } catch (Exception $e) {
        error_log("Email validation failed: " . $e->getMessage());
        return [
            'success' => false,
            'error' => 'Validation service unavailable'
        ];
    }
}

Complete Example: Newsletter Subscription

<?php
// subscribe.php

require_once 'EmailValidator.php';

session_start();

$validator = new EmailValidator($_ENV['VERIFYFORGE_API_KEY']);
$message = '';
$messageType = '';

if ($_SERVER['REQUEST_METHOD'] === 'POST') {
    $email = filter_var($_POST['email'] ?? '', FILTER_SANITIZE_EMAIL);

    if (empty($email)) {
        $message = 'Email is required';
        $messageType = 'error';
    } elseif (!filter_var($email, FILTER_VALIDATE_EMAIL)) {
        $message = 'Invalid email format';
        $messageType = 'error';
    } else {
        try {
            $result = $validator->validate($email);

            if (!$result['isValid']) {
                $message = 'Please enter a valid email address';
                $messageType = 'error';
            } elseif ($result['disposable']) {
                $message = 'Temporary email addresses are not allowed';
                $messageType = 'error';
            } elseif ($result['reachability'] === 'risky') {
                $message = 'This email appears risky. Please use another email.';
                $messageType = 'error';
            } else {
                // Save to database
                // $db->insert('subscribers', ['email' => $email]);

                $message = 'Successfully subscribed to our newsletter!';
                $messageType = 'success';
                $_POST = []; // Clear form
            }
        } catch (Exception $e) {
            error_log("Subscription error: " . $e->getMessage());
            $message = 'Subscription failed. Please try again.';
            $messageType = 'error';
        }
    }
}
?>

<!DOCTYPE html>
<html>
<head>
    <title>Newsletter Subscription</title>
    <style>
        .success { color: green; }
        .error { color: red; }
    </style>
</head>
<body>
    <h1>Subscribe to Our Newsletter</h1>

    <?php if ($message): ?>
        <div class="<?= $messageType ?>">
            <?= htmlspecialchars($message) ?>
        </div>
    <?php endif; ?>

    <form method="POST">
        <input
            type="email"
            name="email"
            placeholder="your@email.com"
            value="<?= htmlspecialchars($_POST['email'] ?? '') ?>"
            required
        />
        <button type="submit">Subscribe</button>
    </form>
</body>
</html>

Troubleshooting

Problem: cURL not enabled

Solution: Enable in php.ini: extension=curl

Problem: SSL certificate errors

Solution: Update CA bundle or disable verification (not recommended for production):

curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);

Problem: Timeout errors

Solution: Increase timeout:

curl_setopt($ch, CURLOPT_TIMEOUT, 60);

Next Steps