disposable_email_validator 0.0.1
disposable_email_validator: ^0.0.1 copied to clipboard
A Dart/Flutter package for validating disposable email addresses by checking against a regularly updated list of 4000+ disposable email domains.
import 'package:flutter/material.dart';
import 'package:disposable_email_validator/disposable_email_validator.dart';
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Disposable Email Validator',
theme: ThemeData(
primarySwatch: Colors.blue,
useMaterial3: true,
),
home: const EmailValidatorPage(),
);
}
}
class EmailValidatorPage extends StatefulWidget {
const EmailValidatorPage({Key? key}) : super(key: key);
@override
State<EmailValidatorPage> createState() => _EmailValidatorPageState();
}
class _EmailValidatorPageState extends State<EmailValidatorPage> {
final _formKey = GlobalKey<FormState>();
final _emailController = TextEditingController();
final _validator = DisposableEmailValidator();
bool _isLoading = false;
String? _validationResult;
Color? _resultColor;
@override
void initState() {
super.initState();
_prefetchDomains();
}
Future<void> _prefetchDomains() async {
try {
await _validator.fetchDisposableDomains();
if (mounted) {
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(
content: Text('Loaded ${_validator.cachedDomainsCount} domains'),
backgroundColor: Colors.green,
),
);
}
} catch (e) {
if (mounted) {
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(
content: Text('Failed to load domains: $e'),
backgroundColor: Colors.orange,
),
);
}
}
}
Future<void> _validateEmail() async {
if (!_formKey.currentState!.validate()) return;
setState(() {
_isLoading = true;
_validationResult = null;
});
try {
final email = _emailController.text.trim();
final isDisposable = await _validator.isDisposable(
email,
throwOnInvalidFormat: true,
);
setState(() {
if (isDisposable) {
_validationResult = '❌ Disposable email detected!\n'
'Please use a permanent email address.';
_resultColor = Colors.red;
} else {
_validationResult = '✅ Valid email address!';
_resultColor = Colors.green;
}
});
} on InvalidEmailFormatException {
setState(() {
_validationResult = '⚠️ Invalid email format';
_resultColor = Colors.orange;
});
} on NetworkTimeoutException {
setState(() {
_validationResult = '⚠️ Network timeout. Please try again.';
_resultColor = Colors.orange;
});
} catch (e) {
setState(() {
_validationResult = '❌ Error: $e';
_resultColor = Colors.red;
});
} finally {
setState(() {
_isLoading = false;
});
}
}
@override
void dispose() {
_emailController.dispose();
_validator.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('Disposable Email Validator'),
elevation: 2,
),
body: SingleChildScrollView(
padding: const EdgeInsets.all(16.0),
child: Form(
key: _formKey,
child: Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
const SizedBox(height: 20),
const Text(
'Enter an email address to check if it\'s disposable',
style: TextStyle(fontSize: 16),
textAlign: TextAlign.center,
),
const SizedBox(height: 30),
TextFormField(
controller: _emailController,
keyboardType: TextInputType.emailAddress,
decoration: const InputDecoration(
labelText: 'Email Address',
hintText: '[email protected]',
prefixIcon: Icon(Icons.email),
border: OutlineInputBorder(),
),
validator: (value) {
if (value == null || value.trim().isEmpty) {
return 'Please enter an email address';
}
return null;
},
onFieldSubmitted: (_) => _validateEmail(),
),
const SizedBox(height: 20),
ElevatedButton(
onPressed: _isLoading ? null : _validateEmail,
style: ElevatedButton.styleFrom(
padding: const EdgeInsets.symmetric(vertical: 16),
),
child: _isLoading
? const SizedBox(
height: 20,
width: 20,
child: CircularProgressIndicator(strokeWidth: 2),
)
: const Text('Validate Email',
style: TextStyle(fontSize: 16)),
),
const SizedBox(height: 30),
if (_validationResult != null)
Card(
color: _resultColor?.withOpacity(0.1),
child: Padding(
padding: const EdgeInsets.all(16.0),
child: Text(
_validationResult!,
style: TextStyle(
fontSize: 16,
color: _resultColor,
fontWeight: FontWeight.bold,
),
textAlign: TextAlign.center,
),
),
),
const SizedBox(height: 30),
_buildInfoCard(),
const SizedBox(height: 20),
_buildExamplesCard(),
],
),
),
),
);
}
Widget _buildInfoCard() {
return Card(
child: Padding(
padding: const EdgeInsets.all(16.0),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
const Text(
'Cache Information',
style: TextStyle(fontSize: 18, fontWeight: FontWeight.bold),
),
const SizedBox(height: 12),
_buildInfoRow(
'Cached Domains',
_validator.cachedDomainsCount?.toString() ?? 'Not loaded',
),
_buildInfoRow(
'Cache Valid',
_validator.isCacheValid ? 'Yes' : 'No',
),
if (_validator.lastFetchTime != null)
_buildInfoRow(
'Last Updated',
_formatDateTime(_validator.lastFetchTime!),
),
const SizedBox(height: 12),
ElevatedButton.icon(
onPressed: () async {
try {
await _validator.fetchDisposableDomains();
setState(() {});
if (mounted) {
ScaffoldMessenger.of(context).showSnackBar(
const SnackBar(
content: Text('Cache refreshed successfully'),
backgroundColor: Colors.green,
),
);
}
} catch (e) {
if (mounted) {
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(
content: Text('Failed to refresh: $e'),
backgroundColor: Colors.red,
),
);
}
}
},
icon: const Icon(Icons.refresh),
label: const Text('Refresh Cache'),
),
],
),
),
);
}
Widget _buildExamplesCard() {
return Card(
child: Padding(
padding: const EdgeInsets.all(16.0),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
const Text(
'Try These Examples',
style: TextStyle(fontSize: 18, fontWeight: FontWeight.bold),
),
const SizedBox(height: 12),
_buildExampleButton('[email protected]', 'Valid email'),
_buildExampleButton('[email protected]', 'Disposable'),
_buildExampleButton('[email protected]', 'Disposable'),
_buildExampleButton('invalid-email', 'Invalid format'),
],
),
),
);
}
Widget _buildInfoRow(String label, String value) {
return Padding(
padding: const EdgeInsets.symmetric(vertical: 4.0),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Text(label, style: const TextStyle(fontWeight: FontWeight.w500)),
Text(value, style: const TextStyle(color: Colors.grey)),
],
),
);
}
Widget _buildExampleButton(String email, String type) {
return Padding(
padding: const EdgeInsets.only(bottom: 8.0),
child: OutlinedButton(
onPressed: () {
_emailController.text = email;
_validateEmail();
},
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Text(email),
Text(
type,
style: const TextStyle(fontSize: 12, color: Colors.grey),
),
],
),
),
);
}
String _formatDateTime(DateTime dt) {
return '${dt.hour}:${dt.minute.toString().padLeft(2, '0')} - ${dt.day}/${dt.month}/${dt.year}';
}
}