Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

A simple, robust email validation library for Swift, inspired by WordPress's battle-tested validation logic. Designed to be lightweight, fast, and RFC-compliant while providing convenient Swift-native APIs.

Notifications You must be signed in to change notification settings

arraypress/swift-email-validator

Open more actions menu

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

5 Commits
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Swift Email Validator

A simple, robust email validation library for Swift, inspired by WordPress's battle-tested validation logic. Designed to be lightweight, fast, and RFC-compliant while providing convenient Swift-native APIs.

Features

  • RFC 5321/5322 compliant validation
  • WordPress-inspired logic (handles billions of emails)
  • Zero dependencies - pure Swift
  • Comprehensive provider detection - recognizes major email providers
  • Swift-native APIs - feels natural in Swift code
  • High performance - optimized for speed
  • Extensive test coverage - 20+ test cases covering edge cases

Installation

Swift Package Manager

Add EmailValidator to your project using Xcode:

  1. File → Add Package Dependencies
  2. Enter: https://github.com/arraypress/swift-email-validator
  3. Select your desired version

Or add to your Package.swift:

dependencies: [
    .package(url: "https://github.com/arraypress/swift-email-validator", from: "1.0.0")
]

Quick Start

import EmailValidator

// Basic validation
"user@example.com".isEmail // true
"invalid-email".isEmail    // false

// Get normalized email (lowercased domain)
"User@EXAMPLE.COM".normalizedEmail // "User@example.com"

// Parse email components
"user@example.com".emailLocalPart // "user"
"user@example.com".emailDomain    // "example.com"

// Provider detection
"user@gmail.com".emailProvider          // "Gmail"
"user@gmail.com".isPersonalEmailProvider // true
"user@company.com".isPersonalEmailProvider // false

Core APIs

String Extensions

isEmail: Bool

Validates if the string is a properly formatted email address.

"test@example.com".isEmail  // true
"invalid".isEmail           // false

normalizedEmail: String?

Returns a normalized version with lowercased domain, or nil if invalid.

"User@EXAMPLE.COM".normalizedEmail // "User@example.com"
"invalid".normalizedEmail          // nil

emailLocalPart: String?

Extracts the username portion (before @).

"user.name@example.com".emailLocalPart // "user.name"

emailDomain: String?

Extracts the domain portion (after @).

"user@sub.example.com".emailDomain // "sub.example.com"

emailProvider: String?

Detects known email providers.

"user@gmail.com".emailProvider    // "Gmail"
"user@yahoo.com".emailProvider    // "Yahoo"
"user@company.com".emailProvider  // nil

isPersonalEmailProvider: Bool

Checks if the email is from a recognized personal email provider.

"user@gmail.com".isPersonalEmailProvider    // true
"user@company.com".isPersonalEmailProvider  // false

Array Extensions

validEmails: [String]

Filters array to only valid email addresses.

let emails = ["valid@example.com", "invalid", "another@test.org"]
emails.validEmails // ["valid@example.com", "another@test.org"]

normalizedEmails: [String]

Returns normalized versions of all valid emails.

let emails = ["User@EXAMPLE.COM", "invalid", "test@DOMAIN.ORG"]
emails.normalizedEmails // ["User@example.com", "test@domain.org"]

validEmailsIfAny: [String]?

Get valid emails if any exist, nil otherwise.

let emails = ["valid@example.com", "invalid", "another@test.org"]
if let validEmails = emails.validEmailsIfAny {
    print("Found \(validEmails.count) valid emails")
} else {
    print("No valid emails found")
}

normalizedEmailsIfAny: [String]?

Get normalized emails if any exist, nil otherwise.

let emails = ["User@EXAMPLE.COM", "invalid", "test@DOMAIN.ORG"]
if let normalized = emails.normalizedEmailsIfAny {
    print("Normalized emails: \(normalized)")
    // Result: ["User@example.com", "test@domain.org"]
} else {
    print("No valid emails to normalize")
}

hasValidEmails: Bool

Check if the collection contains any valid emails.

let emails = ["valid@example.com", "invalid", "another@test.org"]
if emails.hasValidEmails {
    print("Processing valid emails...")
    processEmails(emails.validEmails)
}

Collection Extensions

validEmailCount: Int

Counts valid email addresses in the collection.

["valid@example.com", "invalid", "another@test.org"].validEmailCount // 2

Supported Email Providers

EmailValidator recognizes these major providers:

Google

  • Gmail (gmail.com, googlemail.com)

Microsoft

  • Outlook (outlook.com + regional variants, hotmail.com + regional variants, live.com + regional variants, msn.com)

Yahoo

  • Yahoo (yahoo.com, yahoo.co.uk, yahoo.ca, yahoo.de, yahoo.fr, yahoo.com.au, and more)

Apple

  • iCloud (icloud.com, me.com, mac.com)

Privacy-Focused

  • ProtonMail (protonmail.com, proton.me)
  • Tutanota (tutanota.com, tutanota.de)
  • Hey (hey.com)

Other Major Providers

  • AOL (aol.com + regional variants)
  • Yandex (yandex.com, yandex.ru)
  • Mail.Ru (mail.ru)

European Providers

  • GMX (gmx.de, gmx.com, gmx.net)
  • Web.de (web.de)
  • Orange (orange.fr, wanadoo.fr)
  • Free (free.fr)
  • La Poste (laposte.net)

Asian Providers

  • NetEase (163.com, 126.com)
  • QQ Mail (qq.com)
  • Naver (naver.com)
  • Daum (daum.net)

Business-Oriented

  • Zoho (zoho.com, zoho.eu)

Examples

Form Validation

func validateEmailField(_ email: String) -> String? {
    guard email.isEmail else {
        return "Please enter a valid email address"
    }
    return nil
}

User Registration

func processSignup(email: String) {
    guard let normalizedEmail = email.normalizedEmail else {
        showError("Invalid email address")
        return
    }
    
    if normalizedEmail.isPersonalEmailProvider {
        // Personal email - different onboarding flow
        showPersonalOnboarding()
    } else {
        // Business email - enterprise features
        showBusinessOnboarding()
    }
    
    // Store normalized email
    user.email = normalizedEmail
}

Bulk Email Processing

func processEmailList(_ emails: [String]) {
    let validEmails = emails.validEmails
    let normalizedEmails = emails.normalizedEmails
    
    print("Found \(emails.validEmailCount) valid emails out of \(emails.count)")
    
    // Process each email
    for email in validEmails {
        if let provider = email.emailProvider {
            print("Email from \(provider): \(email)")
        }
    }
}

Email Analytics

func analyzeEmailSignups(_ emails: [String]) {
    let validEmails = emails.validEmails
    let personalCount = validEmails.filter(\.isPersonalEmailProvider).count
    let businessCount = validEmails.count - personalCount
    
    print("Personal emails: \(personalCount)")
    print("Business emails: \(businessCount)")
    
    // Group by provider
    let grouped = Dictionary(grouping: validEmails) { $0.emailProvider ?? "Other" }
    for (provider, emails) in grouped {
        print("\(provider): \(emails.count) emails")
    }
}

Optional Handling

func processEmails(_ emails: [String]) {
    // Use optional variants for cleaner code
    if let validEmails = emails.validEmailsIfAny {
        print("Processing \(validEmails.count) valid emails")
        
        if let normalized = emails.normalizedEmailsIfAny {
            // Work with normalized emails
            sendBulkEmail(to: normalized)
        }
    } else {
        print("No valid emails to process")
    }
    
    // Or use boolean check
    if emails.hasValidEmails {
        print("Found valid emails, proceeding...")
    }
}

Performance

EmailValidator is optimized for performance:

  • Individual validation: ~0.007ms per email
  • Bulk operations: ~0.001ms per email in arrays
  • Zero allocations for failed validations
  • Lazy evaluation in collection operations

Validation Rules

EmailValidator follows RFC 5321/5322 standards with these key rules:

Email Structure

  • Must contain exactly one @ symbol
  • Local part (before @) max 64 characters
  • Domain part (after @) max 253 characters
  • Total email max 254 characters
  • Minimum 6 characters total

Local Part Rules

  • No leading or trailing dots
  • No consecutive dots
  • ASCII characters only
  • Allows: letters, numbers, and !#$%&'*+-/=?^_{|}~.`

Domain Rules

  • At least two parts separated by dots
  • Each part max 63 characters
  • No leading/trailing hyphens in domain parts
  • Top-level domain must be at least 2 letters
  • ASCII letters, numbers, and hyphens only

Requirements

  • iOS 13.0+ / macOS 10.15+ / tvOS 13.0+ / watchOS 6.0+
  • Swift 5.5+
  • Xcode 13.0+

Contributing

We welcome contributions! Please:

  1. Fork the repository
  2. Create a feature branch
  3. Add tests for new functionality
  4. Ensure all tests pass
  5. Submit a pull request

License

EmailValidator is available under the MIT license. See LICENSE for details.

Credits

Validation logic inspired by WordPress's is_email() function, adapted for Swift with modern APIs and comprehensive provider detection.

About

A simple, robust email validation library for Swift, inspired by WordPress's battle-tested validation logic. Designed to be lightweight, fast, and RFC-compliant while providing convenient Swift-native APIs.

Topics

Resources

Stars

Watchers

Forks

Packages

No packages published

Languages

Morty Proxy This is a proxified and sanitized view of the page, visit original site.