Vue.js
Email checker for Vue.js. Real-time email verification in Vue components and forms.
Integreer EmailVerify in uw Vue 3 applicaties voor realtime e-mailvalidatie. Deze handleiding behandelt zowel Composition API als Options API implementaties, van basis setup tot geavanceerde patronen.
Installatie
Installeer het EmailVerify pakket en configureer uw project.
npm install emailverifyyarn add emailverifypnpm add emailverifySnelle Start
Composition API
Gebruik de Composition API voor reactieve e-mailverificatie in uw componenten.
<template>
<div class="email-verification">
<input
v-model="email"
type="email"
placeholder="Voer e-mailadres in"
@blur="verifyEmail"
class="email-input"
/>
<div v-if="isLoading" class="status loading">
Verifieren...
</div>
<div v-else-if="result" :class="['status', result.status]">
<span v-if="result.status === 'valid'">✓ Geldig e-mailadres</span>
<span v-else-if="result.status === 'invalid'">✗ Ongeldig e-mailadres</span>
<span v-else>? Kon niet verifieren</span>
</div>
</div>
</template>
<script setup lang="ts">
import { ref } from 'vue';
import { emailverify } from 'emailverify';
const email = ref('');
const isLoading = ref(false);
const result = ref<any>(null);
const verifyEmail = async () => {
if (!email.value) return;
isLoading.value = true;
try {
result.value = await emailverify.verify({
email: email.value,
apiKey: import.meta.env.VITE_EMAILVERIFY_API_KEY
});
} catch (error) {
console.error('Verificatie mislukt:', error);
result.value = null;
} finally {
isLoading.value = false;
}
};
</script>
<style scoped>
.email-input {
padding: 8px 12px;
border: 1px solid #ccc;
border-radius: 4px;
font-size: 16px;
width: 100%;
}
.status {
margin-top: 8px;
padding: 8px 12px;
border-radius: 4px;
font-size: 14px;
}
.status.valid {
background-color: #d4edda;
color: #155724;
border: 1px solid #c3e6cb;
}
.status.invalid {
background-color: #f8d7da;
color: #721c24;
border: 1px solid #f5c6cb;
}
.status.loading {
background-color: #d1ecf1;
color: #0c5460;
border: 1px solid #bee5eb;
}
</style>Options API
Voor projecten die het Options API patroon gebruiken:
<template>
<div class="email-verification">
<input
v-model="email"
type="email"
placeholder="Voer e-mailadres in"
@blur="verifyEmail"
class="email-input"
/>
<div v-if="isLoading" class="status loading">
Verifieren...
</div>
<div v-else-if="result" :class="['status', result.status]">
{{ statusMessage }}
</div>
</div>
</template>
<script lang="ts">
import { defineComponent } from 'vue';
import { emailverify } from 'emailverify';
export default defineComponent({
name: 'EmailVerification',
data() {
return {
email: '',
isLoading: false,
result: null
};
},
computed: {
statusMessage(): string {
if (this.result?.status === 'valid') return '✓ Geldig e-mailadres';
if (this.result?.status === 'invalid') return '✗ Ongeldig e-mailadres';
return '? Kon niet verifieren';
}
},
methods: {
async verifyEmail() {
if (!this.email) return;
this.isLoading = true;
try {
this.result = await emailverify.verify({
email: this.email,
apiKey: import.meta.env.VITE_EMAILVERIFY_API_KEY
});
} catch (error) {
console.error('Verificatie mislukt:', error);
this.result = null;
} finally {
this.isLoading = false;
}
}
}
});
</script>Composables Referentie
useEmailVerification
Een aangepaste composable voor het beheren van e-mailverificatie status en logica.
import { ref, computed } from 'vue';
import { emailverify } from 'emailverify';
export function useEmailVerification(apiKey: string) {
const email = ref('');
const isLoading = ref(false);
const error = ref<string | null>(null);
const result = ref<any>(null);
const isValid = computed(() => result.value?.status === 'valid');
const isInvalid = computed(() => result.value?.status === 'invalid');
const isDisposable = computed(() => result.value?.result?.disposable || false);
const verify = async (emailToVerify?: string) => {
const emailAddress = emailToVerify || email.value;
if (!emailAddress) {
error.value = 'E-mailadres is vereist';
return;
}
isLoading.value = true;
error.value = null;
try {
result.value = await emailverify.verify({
email: emailAddress,
apiKey
});
} catch (err) {
error.value = err instanceof Error ? err.message : 'Verificatie mislukt';
result.value = null;
} finally {
isLoading.value = false;
}
};
const reset = () => {
email.value = '';
result.value = null;
error.value = null;
isLoading.value = false;
};
return {
email,
isLoading,
error,
result,
isValid,
isInvalid,
isDisposable,
verify,
reset
};
}useEmailInput
Een composable voor het afhandelen van e-mail input met debouncing en caching.
import { ref, computed, watch } from 'vue';
import { useEmailVerification } from './useEmailVerification';
const CACHE_DURATION = 30 * 60 * 1000; // 30 minuten
export function useEmailInput(apiKey: string) {
const email = ref('');
const cache = new Map<string, { result: any; timestamp: number }>();
const { verify: verifyWithAPI, isLoading, error, result } = useEmailVerification(apiKey);
const verify = async () => {
if (!email.value) return;
// Controleer cache eerst
const cached = cache.get(email.value);
if (cached && Date.now() - cached.timestamp < CACHE_DURATION) {
result.value = cached.result;
return;
}
// Verifieer met API
await verifyWithAPI(email.value);
// Cache het resultaat
if (result.value) {
cache.set(email.value, {
result: result.value,
timestamp: Date.now()
});
}
};
const clearCache = () => cache.clear();
return {
email,
isLoading,
error,
result,
verify,
clearCache
};
}Component Integratie
VeeValidate Integratie
Integreer e-mailverificatie met VeeValidate voor formuliervalidatie.
<template>
<Form @submit="onSubmit" class="form">
<div class="form-group">
<label>E-mailadres</label>
<Field
name="email"
type="email"
placeholder="uw@email.com"
v-slot="{ field, meta }"
:rules="validateEmail"
>
<input
v-bind="field"
:class="{ 'input-error': meta.touched && !meta.valid }"
@blur="verifyEmail(field.value)"
/>
</Field>
<div v-if="verificationResult" :class="['verification-status', verificationResult.status]">
{{ getStatusMessage(verificationResult) }}
</div>
<ErrorMessage name="email" class="error-message" />
</div>
<button type="submit" :disabled="isLoading">
{{ isLoading ? 'Verifieren...' : 'Verzenden' }}
</button>
</Form>
</template>
<script setup lang="ts">
import { Form, Field, ErrorMessage } from 'vee-validate';
import * as yup from 'yup';
import { ref } from 'vue';
import { useEmailVerification } from './composables/useEmailVerification';
const schema = yup.object({
email: yup.string().email('Ongeldige e-mail').required('E-mail is vereist')
});
const { verify, result: verificationResult, isLoading } = useEmailVerification(
import.meta.env.VITE_EMAILVERIFY_API_KEY
);
const validateEmail = async (value: string) => {
if (!value) return 'E-mail is vereist';
try {
await schema.validate({ email: value });
return true;
} catch {
return 'Ongeldig e-mailformaat';
}
};
const verifyEmail = async (email: string) => {
if (email) {
await verify(email);
}
};
const getStatusMessage = (result: any) => {
switch (result.status) {
case 'valid':
return '✓ Geldig e-mailadres';
case 'invalid':
return '✗ Ongeldig e-mailadres';
case 'unknown':
return '? Kon deze e-mail niet verifieren';
default:
return 'Onbekende status';
}
};
const onSubmit = (values: any) => {
if (verificationResult.value?.status === 'valid') {
console.log('Formulier verzonden:', values);
}
};
</script>
<style scoped>
.form-group {
margin-bottom: 16px;
}
label {
display: block;
margin-bottom: 8px;
font-weight: 500;
}
input {
width: 100%;
padding: 8px 12px;
border: 1px solid #ccc;
border-radius: 4px;
font-size: 14px;
}
input.input-error {
border-color: #dc3545;
background-color: #fff5f5;
}
.error-message {
color: #dc3545;
font-size: 12px;
margin-top: 4px;
}
.verification-status {
margin-top: 8px;
padding: 8px 12px;
border-radius: 4px;
font-size: 13px;
}
.verification-status.valid {
background-color: #d4edda;
color: #155724;
}
.verification-status.invalid {
background-color: #f8d7da;
color: #721c24;
}
</style>Element Plus Integratie
Gebruik EmailVerify met Element Plus formuliercomponenten.
<template>
<el-form :model="form" @submit.prevent="handleSubmit">
<el-form-item label="E-mail" prop="email">
<el-input
v-model="form.email"
type="email"
placeholder="Voer e-mail in"
@blur="verifyEmail"
:loading="isLoading"
/>
<el-alert
v-if="verificationResult"
:title="getStatusTitle()"
:type="getAlertType()"
:closable="false"
style="margin-top: 8px"
/>
</el-form-item>
<el-form-item>
<el-button
type="primary"
@click="handleSubmit"
:loading="isLoading"
>
Verzenden
</el-button>
</el-form-item>
</el-form>
</template>
<script setup lang="ts">
import { reactive, ref } from 'vue';
import { useEmailVerification } from './composables/useEmailVerification';
const form = reactive({
email: ''
});
const { verify, result: verificationResult, isLoading } = useEmailVerification(
import.meta.env.VITE_EMAILVERIFY_API_KEY
);
const verifyEmail = async () => {
if (form.email) {
await verify(form.email);
}
};
const getStatusTitle = () => {
switch (verificationResult.value?.status) {
case 'valid':
return 'E-mail is geldig';
case 'invalid':
return 'E-mail is ongeldig';
default:
return 'Kon e-mail niet verifieren';
}
};
const getAlertType = () => {
return verificationResult.value?.status === 'valid' ? 'success' : 'error';
};
const handleSubmit = async () => {
await verifyEmail();
if (verificationResult.value?.status === 'valid') {
console.log('E-mail geverifieerd, formulier verzenden...');
}
};
</script>SSR met Nuxt 3
Server-Side Verificatie
Verifieer e-mails op de server voor betere beveiliging en prestaties.
// server/api/verify-email.ts
import { emailverify } from 'emailverify';
export default defineEventHandler(async (event) => {
const { email } = await readBody(event);
if (!email) {
throw createError({
statusCode: 400,
statusMessage: 'E-mail is vereist'
});
}
try {
const result = await emailverify.verify({
email,
apiKey: process.env.EMAILVERIFY_API_KEY!
});
return result;
} catch (error) {
throw createError({
statusCode: 500,
statusMessage: 'Verificatie mislukt'
});
}
});Client-Side Integratie in Nuxt
Gebruik de server endpoint vanuit uw Nuxt componenten.
<template>
<div class="email-verification">
<input
v-model="email"
type="email"
placeholder="uw@email.com"
@blur="verifyEmail"
/>
<div v-if="pending" class="status loading">
Verifieren...
</div>
<div v-else-if="result" :class="['status', result.status]">
{{ statusMessage }}
</div>
</div>
</template>
<script setup lang="ts">
import { ref, computed } from 'vue';
const email = ref('');
const { data: result, pending, execute: verifyEmail } = await useFetch(
'/api/verify-email',
{
method: 'POST',
body: computed(() => ({ email: email.value })),
immediate: false
}
);
const statusMessage = computed(() => {
if (!result.value) return '';
switch (result.value.status) {
case 'valid':
return '✓ Geldig e-mailadres';
case 'invalid':
return '✗ Ongeldig e-mailadres';
default:
return '? Onbekende status';
}
});
</script>Geavanceerde Patronen
Gedebounced Verificatie
Verminder API-aanroepen met gedebounced e-mailverificatie.
import { ref, watch } from 'vue';
import { useEmailVerification } from './composables/useEmailVerification';
export function useDebouncedEmailVerification(apiKey: string, delay = 500) {
const email = ref('');
const debounceTimer = ref<NodeJS.Timeout | null>(null);
const { verify, ...rest } = useEmailVerification(apiKey);
watch(email, (newEmail) => {
if (debounceTimer.value) {
clearTimeout(debounceTimer.value);
}
debounceTimer.value = setTimeout(() => {
if (newEmail) {
verify(newEmail);
}
}, delay);
});
return { email, verify, ...rest };
}E-mail Caching Strategie
Implementeer intelligente caching om API-aanroepen te verminderen.
const CACHE_KEY_PREFIX = 'emailverify_';
const CACHE_DURATION = 24 * 60 * 60 * 1000; // 24 uur
export function useCachedEmailVerification(apiKey: string) {
const { verify: verifyWithAPI, result, isLoading } = useEmailVerification(apiKey);
const getCacheKey = (email: string) => `${CACHE_KEY_PREFIX}${email}`;
const verify = async (email: string) => {
const cacheKey = getCacheKey(email);
const cached = localStorage.getItem(cacheKey);
if (cached) {
const { result: cachedResult, timestamp } = JSON.parse(cached);
if (Date.now() - timestamp < CACHE_DURATION) {
result.value = cachedResult;
return;
}
}
await verifyWithAPI(email);
if (result.value) {
localStorage.setItem(
cacheKey,
JSON.stringify({
result: result.value,
timestamp: Date.now()
})
);
}
};
const clearCache = (email?: string) => {
if (email) {
localStorage.removeItem(getCacheKey(email));
} else {
const keys = Object.keys(localStorage);
keys.forEach(key => {
if (key.startsWith(CACHE_KEY_PREFIX)) {
localStorage.removeItem(key);
}
});
}
};
return { verify, result, isLoading, clearCache };
}Foutafhandeling en Retry
Implementeer robuuste foutafhandeling met retry logica.
export function useEmailVerificationWithRetry(apiKey: string, maxRetries = 3) {
const { verify: verifyWithAPI, result, isLoading, error } = useEmailVerification(apiKey);
const verifyWithRetry = async (email: string, retryCount = 0): Promise<any> => {
try {
await verifyWithAPI(email);
return result.value;
} catch (err) {
if (retryCount < maxRetries) {
// Wacht voor retry (exponential backoff)
await new Promise(resolve => setTimeout(resolve, Math.pow(2, retryCount) * 1000));
return verifyWithRetry(email, retryCount + 1);
}
throw err;
}
};
return { verifyWithRetry, result, isLoading, error };
}TypeScript Ondersteuning
De EmailVerify SDK bevat volledige TypeScript ondersteuning met type definities.
interface VerificationRequest {
email: string;
apiKey: string;
}
interface VerificationResult {
status: 'valid' | 'invalid' | 'unknown' | 'accept_all';
result: {
disposable: boolean;
smtp_valid: boolean;
format_valid: boolean;
email_provider: string;
risk_level: 'low' | 'medium' | 'high';
};
score: number;
}
interface UseEmailVerificationReturn {
email: Ref<string>;
isLoading: Ref<boolean>;
error: Ref<string | null>;
result: Ref<VerificationResult | null>;
isValid: ComputedRef<boolean>;
isInvalid: ComputedRef<boolean>;
isDisposable: ComputedRef<boolean>;
verify: (emailToVerify?: string) => Promise<void>;
reset: () => void;
}Testen
Unit Tests met Vitest
Test uw e-mailverificatie composables met Vitest.
import { describe, it, expect, vi } from 'vitest';
import { useEmailVerification } from './composables/useEmailVerification';
vi.mock('emailverify', () => ({
emailverify: {
verify: vi.fn()
}
}));
describe('useEmailVerification', () => {
it('verifieert geldig e-mailadres', async () => {
const { verify, result, isValid } = useEmailVerification('test-key');
await verify('user@example.com');
expect(result.value?.status).toBe('valid');
expect(isValid.value).toBe(true);
});
it('markeert ongeldig e-mailadres', async () => {
const { verify, result, isInvalid } = useEmailVerification('test-key');
await verify('invalid@');
expect(result.value?.status).toBe('invalid');
expect(isInvalid.value).toBe(true);
});
it('verwerkt verificatiefouten', async () => {
const { verify, error } = useEmailVerification('test-key');
try {
await verify('');
} catch (err) {
expect(error.value).toBeTruthy();
}
});
});Component Tests
Test uw Vue componenten met Vue Test Utils.
import { mount } from '@vue/test-utils';
import { describe, it, expect } from 'vitest';
import EmailVerification from './EmailVerification.vue';
describe('EmailVerification', () => {
it('rendert invoerveld', () => {
const wrapper = mount(EmailVerification);
expect(wrapper.find('input[type="email"]').exists()).toBe(true);
});
it('toont verificatiestatus', async () => {
const wrapper = mount(EmailVerification);
await wrapper.find('input').setValue('user@example.com');
await wrapper.find('input').trigger('blur');
expect(wrapper.find('.status').exists()).toBe(true);
});
it('toont laadstatus tijdens verificatie', async () => {
const wrapper = mount(EmailVerification);
await wrapper.find('input').setValue('user@example.com');
expect(wrapper.find('.status.loading').exists()).toBe(true);
});
});