Vue.js
Email checker for Vue.js. Real-time email verification in Vue components and forms.
Integre EmailVerify en sus aplicaciones Vue 3 para validación de correo en tiempo real. Esta guía cubre tanto la implementación con Composition API como con Options API, desde la configuración básica hasta patrones avanzados.
Instalación
Instale el paquete EmailVerify y configure su proyecto.
npm install emailverifyyarn add emailverifypnpm add emailverifyInicio Rápido
Composition API
Use la Composition API para verificación de correo reactiva en sus componentes.
<template>
<div class="email-verification">
<input
v-model="email"
type="email"
placeholder="Enter email address"
@blur="verifyEmail"
class="email-input"
/>
<div v-if="isLoading" class="status loading">
Verifying...
</div>
<div v-else-if="result" :class="['status', result.status]">
<span v-if="result.status === 'valid'">✓ Valid email</span>
<span v-else-if="result.status === 'invalid'">✗ Invalid email</span>
<span v-else>? Could not verify</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('Verification failed:', 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
Para proyectos que utilizan el patrón Options API:
<template>
<div class="email-verification">
<input
v-model="email"
type="email"
placeholder="Enter email address"
@blur="verifyEmail"
class="email-input"
/>
<div v-if="isLoading" class="status loading">
Verifying...
</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 '✓ Valid email';
if (this.result?.status === 'invalid') return '✗ Invalid email';
return '? Could not verify';
}
},
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('Verification failed:', error);
this.result = null;
} finally {
this.isLoading = false;
}
}
}
});
</script>Referencia de Composables
useEmailVerification
Un composable personalizado para gestionar el estado y la lógica de verificación de correo.
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 = 'Email address is required';
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 : 'Verification failed';
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
Un composable para gestionar la entrada de correo con debouncing y almacenamiento en caché.
import { ref, computed, watch } from 'vue';
import { useEmailVerification } from './useEmailVerification';
const CACHE_DURATION = 30 * 60 * 1000; // 30 minutes
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;
// Check cache first
const cached = cache.get(email.value);
if (cached && Date.now() - cached.timestamp < CACHE_DURATION) {
result.value = cached.result;
return;
}
// Verify with API
await verifyWithAPI(email.value);
// Cache the result
if (result.value) {
cache.set(email.value, {
result: result.value,
timestamp: Date.now()
});
}
};
const clearCache = () => cache.clear();
return {
email,
isLoading,
error,
result,
verify,
clearCache
};
}Integración de Componentes
Integración con VeeValidate
Integre la verificación de correo con VeeValidate para validación de formularios.
<template>
<Form @submit="onSubmit" class="form">
<div class="form-group">
<label>Email Address</label>
<Field
name="email"
type="email"
placeholder="your@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 ? 'Verifying...' : 'Submit' }}
</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('Invalid email').required('Email is required')
});
const { verify, result: verificationResult, isLoading } = useEmailVerification(
import.meta.env.VITE_EMAILVERIFY_API_KEY
);
const validateEmail = async (value: string) => {
if (!value) return 'Email is required';
try {
await schema.validate({ email: value });
return true;
} catch {
return 'Invalid email format';
}
};
const verifyEmail = async (email: string) => {
if (email) {
await verify(email);
}
};
const getStatusMessage = (result: any) => {
switch (result.status) {
case 'valid':
return '✓ Valid email address';
case 'invalid':
return '✗ Invalid email address';
case 'unknown':
return '? Could not verify this email';
default:
return 'Unknown status';
}
};
const onSubmit = (values: any) => {
if (verificationResult.value?.status === 'valid') {
console.log('Form submitted:', 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>Integración con Element Plus
Use EmailVerify con los componentes de formulario de Element Plus.
<template>
<el-form :model="form" @submit.prevent="handleSubmit">
<el-form-item label="Email" prop="email">
<el-input
v-model="form.email"
type="email"
placeholder="Enter email"
@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"
>
Submit
</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 'Email is valid';
case 'invalid':
return 'Email is invalid';
default:
return 'Could not verify email';
}
};
const getAlertType = () => {
return verificationResult.value?.status === 'valid' ? 'success' : 'error';
};
const handleSubmit = async () => {
await verifyEmail();
if (verificationResult.value?.status === 'valid') {
console.log('Email verified, submitting form...');
}
};
</script>SSR con Nuxt 3
Verificación del Lado del Servidor
Verifique correos en el servidor para mayor seguridad y rendimiento.
// 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: 'Email is required'
});
}
try {
const result = await emailverify.verify({
email,
apiKey: process.env.EMAILVERIFY_API_KEY!
});
return result;
} catch (error) {
throw createError({
statusCode: 500,
statusMessage: 'Verification failed'
});
}
});Integración del Lado del Cliente en Nuxt
Use el endpoint del servidor desde sus componentes Nuxt.
<template>
<div class="email-verification">
<input
v-model="email"
type="email"
placeholder="your@email.com"
@blur="verifyEmail"
/>
<div v-if="pending" class="status loading">
Verifying...
</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 '✓ Valid email';
case 'invalid':
return '✗ Invalid email';
default:
return '? Unknown status';
}
});
</script>Patrones Avanzados
Verificación con Debounce
Reduzca las llamadas a la API con verificación de correo con debounce.
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 };
}Estrategia de Almacenamiento en Caché
Implemente un almacenamiento en caché inteligente para reducir las llamadas a la API.
const CACHE_KEY_PREFIX = 'emailverify_';
const CACHE_DURATION = 24 * 60 * 60 * 1000; // 24 hours
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 };
}Manejo de Errores y Reintentos
Implemente un manejo de errores robusto con lógica de reintentos.
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) {
// Wait before 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 };
}Soporte de TypeScript
El SDK de EmailVerify incluye soporte completo de TypeScript con definiciones de tipos.
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;
}Pruebas
Pruebas Unitarias con Vitest
Pruebe sus composables de verificación de correo con Vitest.
import { describe, it, expect, vi } from 'vitest';
import { useEmailVerification } from './composables/useEmailVerification';
vi.mock('emailverify', () => ({
emailverify: {
verify: vi.fn()
}
}));
describe('useEmailVerification', () => {
it('verifies valid email', 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('marks invalid email', async () => {
const { verify, result, isInvalid } = useEmailVerification('test-key');
await verify('invalid@');
expect(result.value?.status).toBe('invalid');
expect(isInvalid.value).toBe(true);
});
it('handles verification errors', async () => {
const { verify, error } = useEmailVerification('test-key');
try {
await verify('');
} catch (err) {
expect(error.value).toBeTruthy();
}
});
});Pruebas de Componentes
Pruebe sus componentes Vue con Vue Test Utils.
import { mount } from '@vue/test-utils';
import { describe, it, expect } from 'vitest';
import EmailVerification from './EmailVerification.vue';
describe('EmailVerification', () => {
it('renders input field', () => {
const wrapper = mount(EmailVerification);
expect(wrapper.find('input[type="email"]').exists()).toBe(true);
});
it('shows verification status', 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('shows loading state during verification', async () => {
const wrapper = mount(EmailVerification);
await wrapper.find('input').setValue('user@example.com');
expect(wrapper.find('.status.loading').exists()).toBe(true);
});
});