{"id":29651278,"url":"https://github.com/arraypress/wp-email-utils","last_synced_at":"2025-07-22T05:06:31.486Z","repository":{"id":302528217,"uuid":"1011296962","full_name":"arraypress/wp-email-utils","owner":"arraypress","description":"A lean WordPress library for email address operations, validation, anonymization, and privacy-compliant handling with comprehensive disposable domain detection.","archived":false,"fork":false,"pushed_at":"2025-07-02T21:01:28.000Z","size":38,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2025-07-02T22:19:25.092Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"PHP","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/arraypress.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null}},"created_at":"2025-06-30T15:43:40.000Z","updated_at":"2025-07-02T21:01:31.000Z","dependencies_parsed_at":"2025-07-02T22:19:28.269Z","dependency_job_id":"4ed8b854-a517-4a6b-b3ed-8f7024ab9422","html_url":"https://github.com/arraypress/wp-email-utils","commit_stats":null,"previous_names":["arraypress/wp-email-utils"],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/arraypress/wp-email-utils","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/arraypress%2Fwp-email-utils","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/arraypress%2Fwp-email-utils/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/arraypress%2Fwp-email-utils/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/arraypress%2Fwp-email-utils/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/arraypress","download_url":"https://codeload.github.com/arraypress/wp-email-utils/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/arraypress%2Fwp-email-utils/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":266430669,"owners_count":23927169,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","status":"online","status_checked_at":"2025-07-22T02:00:09.085Z","response_time":66,"last_error":null,"robots_txt_status":null,"robots_txt_updated_at":null,"robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2025-07-22T05:06:30.819Z","updated_at":"2025-07-22T05:06:31.465Z","avatar_url":"https://github.com/arraypress.png","language":"PHP","readme":"# WordPress Email Utilities\n\nA lightweight PHP library for email address operations, validation, anonymization, and privacy-compliant handling. Designed with clean APIs and efficient bulk operations.\n\n## Features\n\n* 🎯 **Clean API**: Separate classes for single (`Email`) and multiple (`Emails`) operations\n* 🔒 **Privacy First**: Built-in anonymization and masking for GDPR compliance\n* 📧 **Full Validation**: Comprehensive email validation and verification\n* 🏷️ **Subaddressing**: Complete support for email subaddressing (plus addressing)\n* 🔍 **Smart Detection**: Provider categorization with 5000+ disposable domains\n* 📊 **Bulk Operations**: Efficient processing of multiple email addresses\n* 🛡️ **Security Ready**: Domain pattern matching and filtering utilities\n* ⚡ **Lean Design**: Lazy-loaded data files, optimized for performance\n* 🗂️ **Comprehensive Lists**: Includes curated allowlist and blocklist\n\n## Requirements\n\n* PHP 7.4 or later\n\n## Installation\n\n```bash\ncomposer require arraypress/email-utils\n```\n\n## Basic Usage\n\n### Single Email Operations (`Email` class)\n\n```php\nuse ArrayPress\\EmailUtils\\Email;\n\n// Validation\nif ( Email::is_valid( 'user@example.com' ) ) {\n\t// Valid email address\n}\n\n// Get parts\n$domain = Email::get_domain( 'user@example.com' );     // \"example.com\"\n$local  = Email::get_local( 'user@example.com' );      // \"user\"\n\n// Privacy \u0026 anonymization\n$anonymous = Email::anonymize( 'john.doe@example.com' );\n// Returns: \"jo***@ex***.com\"\n\n$masked = Email::mask( 'john.doe@example.com', 2, 1 );\n// Returns: \"jo****e@example.com\"\n\n// Normalization\n$normalized = Email::normalize( ' USER@EXAMPLE.COM ' );\n// Returns: \"user@example.com\"\n```\n\n### Multiple Email Operations (`Emails` class)\n\n```php\nuse ArrayPress\\EmailUtils\\Emails;\n\n$emails = [\n\t'valid@example.com',\n\t'invalid-email',\n\t'user+tag@gmail.com',\n\t'test@disposable.com'\n];\n\n// Bulk validation\n$valid_emails       = Emails::filter( $emails );        // Get only valid emails\n$invalid_emails     = Emails::invalid( $emails );       // Get only invalid emails  \n$validation_results = Emails::validate( $emails );      // Get all results\n\n// Bulk anonymization and hashing\n$anonymous_emails = Emails::anonymize( $emails );\n$hashed_emails    = Emails::hash( $emails );\n\n// Extract from text\n$text      = \"Contact us at support@company.com or sales@company.com\";\n$extracted = Emails::extract( $text );\n// Returns: [\"support@company.com\", \"sales@company.com\"]\n```\n\n## Advanced Features\n\n### Provider Detection\n\n```php\n// Check provider types\n$is_common    = Email::is_common_provider( 'user@gmail.com' );           // true\n$is_authority = Email::is_authority_provider( 'user@icloud.com' );    // true\n\n// Disposable email detection (with 5000+ domains)\n$is_disposable = Email::is_disposable( 'user@10minutemail.com' );     // true (basic)\n$is_disposable = Email::is_disposable( 'user@obscure-temp.site', true ); // true (extended)\n\n// Check against allowlist (trusted domains)\n$is_trusted = Email::is_allowlisted( 'gmail.com' );                   // true\n\n// Get disposable domain statistics\n$stats = Email::get_disposable_stats();\n// Returns: ['basic_count' =\u003e 5, 'extended_count' =\u003e 5247, 'allowlist_count' =\u003e 185, ...]\n\n// Bulk provider analysis\n$provider_stats = Emails::count_by_provider_type( $emails, true ); // use extended list\n// Returns: ['common' =\u003e 5, 'authority' =\u003e 3, 'disposable' =\u003e 12, 'other' =\u003e 1]\n```\n\n### Email Hashing \u0026 Privacy\n\n```php\nuse ArrayPress\\EmailUtils\\Email;\nuse ArrayPress\\EmailUtils\\Utils;\n\n// Simple hashing (uses WordPress salts automatically)\n$hashed = Email::hash( 'user@gmail.com' );\n// Returns: \"wp_salted_hash@gmail.com\"\n\n// Full privacy (hash domain too)\n$private = Email::hash( 'user@gmail.com', true );\n// Returns: \"hash1@hash2\"\n\n// Short hash for IDs\n$short_id = Email::hash( 'user@gmail.com', false, 8 );\n// Returns: \"a1b2c3d4\" (truncated)\n\n// Custom salt\n$custom = Email::hash( 'user@gmail.com', false, 0, 'my_salt' );\n\n// Bulk hashing\n$hashed_emails  = Emails::hash( $emails );           // Basic hashing\n$private_emails = Emails::hash( $emails, true );    // Hash domains too\n$short_ids      = Emails::hash( $emails, false, 8 );     // 8-char truncated\n\n// Direct WordPress utilities\n$wp_salt     = Utils::get_wordpress_salt();\n$secure_hash = Utils::hash( 'any_value', 'sha256', 'custom_salt' );\n```\n\n### Disposable Email Management\n\n```php\n// Remove all disposable emails from a list\n$clean_emails = Emails::remove_disposable( $emails );\n\n// Get only disposable emails\n$disposable_emails = Emails::filter_disposable( $emails );\n\n// Custom disposable domain lists\nEmail::load_custom_disposable_domains( '/path/to/custom-disposable.txt' );\nEmail::load_custom_allowlist( '/path/to/trusted-domains.txt' );\n```\n\n\u003e **Disposable Domain Lists:** This library includes comprehensive disposable email domain lists from the [disposable-email-domains](https://github.com/disposable-email-domains/disposable-email-domains) project. This actively maintained repository is trusted by major platforms including PyPI and contains over 5,000 known disposable email domains.\n\n## Data Sources \u0026 Credits\n\nThe disposable email detection in this library is powered by:\n\n- **[disposable-email-domains](https://github.com/disposable-email-domains/disposable-email-domains)** - The most comprehensive and actively maintained list of disposable email domains\n- **Used by major platforms** including PyPI (Python Package Index)\n- **Community maintained** with regular updates and contributions\n- **License:** CC0 (Public Domain)\n\nTo update the disposable domain lists in your project:\n\n1. Download the latest lists from the [disposable-email-domains repository](https://github.com/disposable-email-domains/disposable-email-domains)\n2. Replace the files in your `data/` directory:\n   - `disposable_email_blocklist.conf`\n   - `allowlist.conf`\n3. The library will automatically use the updated lists on next load\n\n### Subaddressing Support\n\n```php\n// Check for subaddressing\n$has_tag = Email::is_subaddressed( 'user+shopping@gmail.com' );  // true\n\n// Extract parts\n$base = Email::get_base_address( 'user+shopping@gmail.com' );    // \"user@gmail.com\"\n$tag  = Email::get_subaddress( 'user+shopping@gmail.com' );       // \"shopping\"\n\n// Add subaddressing\n$tagged = Email::add_subaddress( 'user@gmail.com', 'newsletters' );\n// Returns: \"user+newsletters@gmail.com\"\n\n// Create purpose-specific emails\n$shopping_email = Email::create_tagged( 'user@gmail.com', 'shopping', '2024' );\n// Returns: \"user+shopping-2024@gmail.com\"\n\n// Bulk operations\n$base_addresses    = Emails::to_base_addresses( $emails );\n$subaddressed_only = Emails::filter_subaddressed( $emails );\n```\n\n### Domain Operations\n\n```php\n// Group by domain\n$grouped = Emails::group_by_domain( $emails );\n// Returns: ['gmail.com' =\u003e [...], 'yahoo.com' =\u003e [...]]\n\n// Count by domain\n$domain_counts = Emails::count_by_domain( $emails );\n$gmail_count   = Emails::count_by_domain( $emails, 'gmail.com' );\n\n// Pattern matching\n$patterns = [ '*.company.com', 'gmail.com', '.edu' ];\n$matches  = Emails::filter_by_domain_patterns( $emails, $patterns );\n\n// Provider filtering\n$gmail_emails      = Emails::filter_by_provider_type( $emails, 'common' );\n$disposable_emails = Emails::filter_by_provider_type( $emails, 'disposable' );\n```\n\n### Spam Detection \u0026 Scoring\n\n```php\n// Get spam score (0-100, higher = more suspicious)\n$score = Email::get_spam_score( 'user123456@suspicious-domain.tk' );\n\n// Bulk scoring\n$scores = Emails::get_spam_scores( $emails );\n\n// Filter by spam threshold\n$clean_emails = Emails::filter_by_spam_score( $emails, 30 ); // Keep emails with score \u003c= 30\n```\n\n### Email Analysis \u0026 Statistics\n\n```php\n// Get comprehensive statistics\n$stats = Emails::get_statistics($emails);\n/*\nReturns:\n[\n    'total' =\u003e 100,\n    'valid' =\u003e 95,\n    'invalid' =\u003e 5,\n    'valid_percent' =\u003e 95.0,\n    'subaddressed' =\u003e 12,\n    'provider_types' =\u003e ['common' =\u003e 60, 'authority' =\u003e 20, 'disposable' =\u003e 5, 'other' =\u003e 10],\n    'unique_domains' =\u003e 25,\n    'top_domains' =\u003e ['gmail.com' =\u003e 30, 'yahoo.com' =\u003e 15, ...]\n]\n*/\n```\n\n### Duplicate Management\n\n```php\n$emails_with_duplicates = [\n\t'user@example.com',\n\t'USER@EXAMPLE.COM',\n\t'user+tag@example.com',\n\t'user@example.com'\n];\n\n// Remove exact duplicates\n$unique = Emails::remove_duplicates( $emails_with_duplicates );\n\n// Remove duplicates ignoring subaddressing\n$unique_base = Emails::remove_duplicates( $emails_with_duplicates, true );\n\n// Compare ignoring subaddressing\n$same_base = Email::compare_ignoring_subaddress(\n\t'user+tag1@gmail.com',\n\t'user+tag2@gmail.com'\n); // true\n```\n\n## Privacy \u0026 GDPR Compliance\n\nThe library is designed with privacy in mind:\n\n### Anonymization Methods\n\n```php\n// Full anonymization - safe for storage\n$anonymous = Email::anonymize( 'john.doe@company.com' );\n// Returns: \"jo***@co***.com\"\n\n// Display masking - safe for UI display\n$masked = Email::mask( 'john.doe@company.com', 3, 2 );\n// Returns: \"joh***oe@company.com\"\n\n// Check if already anonymized\n$is_anon = Email::is_anonymized( 'jo***@co***.com' ); // true\n```\n\n### Bulk Privacy Operations\n\n```php\n// Anonymize multiple emails for analytics\n$anonymous_emails = Emails::anonymize_all( $user_emails );\n\n// Normalize for consistent storage\n$normalized_emails = Emails::normalize_all( $user_emails );\n```\n\n## Validation \u0026 Verification\n\n```php\n// Basic validation\n$is_valid = Email::is_valid( 'user@example.com' );\n\n// MX record verification\n$has_mx = Email::has_valid_mx( 'user@example.com' );\n\n// International domain support\n$ascii_email = Email::to_ascii( 'user@tëst.com' );\n\n// Private/internal email detection\n$is_private = Email::is_private( 'user@localhost' );\n```\n\n## Use Cases\n\n### Email List Cleaning\n\n```php\n$cleaned_emails = Emails::clean( $emails );\n```\n\n### Newsletter Signup Validation\n\n```php\nfunction validate_newsletter_signup( string $email ): array {\n\t$result = [ 'valid' =\u003e false, 'warnings' =\u003e [] ];\n\n\tif ( ! Email::is_valid( $email ) ) {\n\t\treturn $result;\n\t}\n\n\t$result['valid'] = true;\n\n\t// Check against 5000+ disposable domains\n\tif ( Email::is_disposable( $email, true ) ) {\n\t\t$result['warnings'][] = 'Disposable email detected';\n\t}\n\n\t// Check if it's allowlisted (trusted)\n\tif ( Email::is_allowlisted( $email ) ) {\n\t\t$result['trusted'] = true;\n\t}\n\n\tif ( Email::get_spam_score( $email ) \u003e 50 ) {\n\t\t$result['warnings'][] = 'High spam score';\n\t}\n\n\tif ( ! Email::has_valid_mx( $email ) ) {\n\t\t$result['warnings'][] = 'No MX records found';\n\t}\n\n\treturn $result;\n}\n```\n\n### Privacy-Compliant Analytics\n\n```php\nfunction log_user_analytics( string $email ): void {\n\t// Store only anonymized email for analytics\n\t$anonymous_email = Email::anonymize( $email );\n\t$domain          = Email::get_domain( $email );\n\t$provider_type   = Email::is_common_provider( $email ) ? 'common' : 'other';\n\n\t// Safe to store these anonymized/aggregated values\n\tanalytics_log( [\n\t\t'email_hash'    =\u003e $anonymous_email,\n\t\t'domain'        =\u003e $domain,\n\t\t'provider_type' =\u003e $provider_type\n\t] );\n}\n```\n\n## API Reference\n\n### Email Class (Single Operations)\n\n**Validation:**\n- `is_valid( string $email ): bool`\n- `has_valid_mx( string $email ): bool`\n- `get_spam_score( string $email, bool $check_mx = false ): int`\n\n**Parts \u0026 Information:**\n- `get_domain( string $email ): ?string`\n- `get_local( string $email ): ?string`\n- `normalize( string $email ): ?string`\n- `to_ascii( string $email ): ?string`\n- `to_ascii( string $email ): ?string`\n\n**Privacy:**\n- `anonymize( string $email ): ?string`\n- `mask( string $email, int $show_first = 1, int $show_last = 1 ): ?string`\n- `is_anonymized( string $email ): bool`\n\n**Provider Detection:**\n- `is_common_provider( string $email ): bool`\n- `is_authority_provider( string $email ): bool`\n- `is_disposable( string $email ): bool`\n- `is_private( string $email ): bool`\n\n**Subaddressing:**\n- `is_subaddressed( string $email ): bool`\n- `get_base_address( string $email ): ?string`\n- `get_subaddress( string $email ): ?string`\n- `add_subaddress( string $email, string $tag ): ?string`\n- `create_tagged( string $email, string $purpose, ?string $suffix = null ): ?string`\n\n### Emails Class (Bulk Operations)\n\n**Validation \u0026 Filtering:**\n- `validate( array $emails ): array`        # Get validation results for all\n- `filter( array $emails ): array`          # Return only valid emails\n- `invalid( array $emails ): array`         # Return only invalid emails\n- `filter_by_spam_score( array $emails, int $threshold = 50, bool $check_mx = false ): array`\n\n**Text Processing:**\n- `extract( string $text ): array`                # Extract emails from text\n- `remove_duplicates( array $emails, bool $ignore_subaddress = false ): array`\n- `normalize( array $emails ): array`\n\n**Privacy:**\n- `anonymize_all( array $emails ): array`\n\n**Analysis:**\n- `group_by_domain( array $emails ): array`\n- `count_by_domain( array $emails, ?string $domain = null)`\n- `count_by_provider_type( array $emails ): array`\n- `get_statistics( array $emails ): array`\n\n**Hashing:**\n- `hash( array $emails, bool $hash_domain = false, int $length = 0, string $salt = '' ): array`\n\n## Utils Class (WordPress Integration)\n\n**WordPress Utilities:**\n- `get_wordpress_salt(): string`                    # Get WordPress-derived salt\n- `hash(string $value, string $algorithm = 'sha256', string $salt = '' ): string` # Hash with WP salts\n\n## Error Handling\n\nAll methods return `null`, `false`, or empty arrays for invalid inputs rather than throwing exceptions, making them safe for direct use in conditionals.\n\n## Contributing\n\nContributions are welcome! Please feel free to submit a Pull Request.\n\n**Disposable Domain Updates:** The disposable email domain lists are maintained by the [disposable-email-domains](https://github.com/disposable-email-domains/disposable-email-domains) project. To add or remove domains from the blocklist, please contribute directly to their repository.\n\n## License\n\nThis project is licensed under the GPL-2.0-or-later License.\n\n**Disposable Domain Lists:** Licensed under CC0 (Public Domain) by the disposable-email-domains project.\n\n## Support\n\n- [Documentation](https://github.com/arraypress/wp-email-utils)\n- [Issue Tracker](https://github.com/arraypress/wp-email-utils/issues)\n- [Disposable Email Domains Project](https://github.com/disposable-email-domains/disposable-email-domains)","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Farraypress%2Fwp-email-utils","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Farraypress%2Fwp-email-utils","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Farraypress%2Fwp-email-utils/lists"}