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);
