# Email Verifier Bulk

## Overview

[Bulk Email Verifier](https://tomba.io/bulks/email-verifier) ensures your email lists maintain high deliverability rates by validating email addresses at scale. Reduce bounce rates, protect your sender reputation, and improve campaign performance with comprehensive email verification.

### Key Features

- **Deliverability Validation**: Verify email addresses for deliverability and validity
- **Bulk Processing**: Verify up to 10,000 emails per operation
- **Detailed Results**: Get comprehensive verification status for each email
- **Bounce Reduction**: Eliminate invalid emails before sending campaigns
- **Sender Protection**: Maintain good sender reputation and domain health
- **Export Options**: Download verified, invalid, and risky email lists separately

### How Email Verifier Bulk Works

1. **Upload Email List**: Provide email addresses for verification
2. **Configure Verification**: Set verification parameters and quality thresholds
3. **Process Verification**: Launch comprehensive email validation
4. **Review Results**: Examine verification status for each email
5. **Export Clean Lists**: Download verified emails ready for campaigns

### Limitations

- You can only verify up to 50 email addresses per domain name every 24 hours and 10,000 email addresses per bulk
- Webmail email addresses like Gmail or Outlook and disposable email addresses are skipped
- Some special or unexpected characters may be deleted in the file
- Duplicate and invalid lines won't be imported

## Go SDK Integration

### Installation

```bash
go get github.com/tomba-io/go
```

### Basic Setup

```go
package main

import (
    "fmt"
    "log"
    "time"

    "github.com/tomba-io/go/tomba"
    "github.com/tomba-io/go/tomba/models"
)

func main() {
    // Initialize Tomba client
    client := tomba.NewTomba("your-api-key", "your-secret-key")

    // Your email verification code here
}
```

### Creating Email Verifier Bulk with List

```go
// Create verifier bulk with email list
emailList := `john.doe@example.com
jane.smith@company.com
user@startup.io
contact@business.net
info@organization.org`

params := &models.BulkCreateParams{
    Name:    "Email List Verification - Marketing Campaign",
    List:    emailList,
    Sources: false,  // Don't include sources for verification
    Verify:  true,   // This is verification, so set to true
    Notifie: true,   // Send notification when complete
}

// Create the verification bulk
response, err := client.CreateBulk(models.BulkTypeVerifier, params)
if err != nil {
    log.Fatal("Failed to create verifier bulk:", err)
}

bulkID := *response.Data.ID
fmt.Printf("Created verifier bulk with ID: %d\n", bulkID)
```

### Creating Verifier Bulk from CSV File

```go
// Create verifier bulk from CSV file
params := &models.BulkCreateParams{
    Name:      "Customer Database Verification",
    Delimiter: ",",
    Column:    2,      // Email column (1-based index)
    Sources:   false,
    Notifie:   true,
}

// Upload CSV and create verification bulk
response, err := client.CreateBulkWithFile(
    models.BulkTypeVerifier,
    params,
    "/path/to/email-list.csv",
)
if err != nil {
    log.Fatal("Failed to create bulk with file:", err)
}

bulkID := *response.Data.ID
fmt.Printf("Created verification bulk: %d\n", bulkID)
```

### Launching and Monitoring Verification

```go
// Launch the verification process
launchResponse, err := client.LaunchBulk(models.BulkTypeVerifier, bulkID)
if err != nil {
    log.Fatal("Failed to launch verification:", err)
}

fmt.Println("Email verification started!")

// Monitor verification progress
startTime := time.Now()
for {
    progress, err := client.GetBulkProgress(models.BulkTypeVerifier, bulkID)
    if err != nil {
        log.Printf("Error checking progress: %v", err)
        time.Sleep(30 * time.Second)
        continue
    }

    elapsed := time.Since(startTime).Round(time.Second)
    fmt.Printf("Verification: %d%% complete (%d processed) - %v elapsed\n",
        progress.Progress,
        progress.Processed,
        elapsed,
    )

    if progress.Status {
        fmt.Println("Email verification completed!")
        break
    }

    // Check every 20 seconds for verification (faster than other operations)
    time.Sleep(20 * time.Second)
}
```

### Retrieving Verification Results

```go
// Get detailed verification results
bulk, err := client.GetBulk(models.BulkTypeVerifier, bulkID)
if err != nil {
    log.Fatal("Failed to get bulk details:", err)
}

bulkInfo := bulk.Data[0]
fmt.Printf("Verification Summary:\n")
fmt.Printf("- Bulk Name: %s\n", bulkInfo.Name)
fmt.Printf("- Status: %v\n", bulkInfo.Status)
fmt.Printf("- Total Processed: %d\n", bulkInfo.Processed)

if bulkInfo.VerifyCost != nil {
    fmt.Printf("- Verification Cost: %d credits\n", *bulkInfo.VerifyCost)
}

// Download all verification results
err = client.SaveBulkResults(
    models.BulkTypeVerifier,
    bulkID,
    "verification-results.csv",
    "full",
)
if err != nil {
    log.Fatal("Failed to download results:", err)
}

fmt.Println("Verification results saved to verification-results.csv")
```

### Downloading Segmented Results

```go
// Download only valid/deliverable emails
err = client.SaveBulkResults(
    models.BulkTypeVerifier,
    bulkID,
    "valid-emails.csv",
    "valid",
)
if err != nil {
    log.Printf("Error downloading valid emails: %v", err)
} else {
    fmt.Println("Valid emails saved to valid-emails.csv")
}

// Download emails that couldn't be verified or are risky
err = client.SaveBulkResults(
    models.BulkTypeVerifier,
    bulkID,
    "unverifiable-emails.csv",
    "not_found",
)
if err != nil {
    log.Printf("Error downloading unverifiable emails: %v", err)
} else {
    fmt.Println("Unverifiable emails saved to unverifiable-emails.csv")
}
```

### Single Email Verification (for comparison)

```go
// Verify a single email address
email := "test@example.com"
verifyResult, err := client.EmailVerifier(email)
if err != nil {
    log.Printf("Failed to verify %s: %v", email, err)
} else {
    fmt.Printf("Single verification result for %s:\n", email)
    fmt.Printf("- Status: %s\n", verifyResult.Data.Result)
    fmt.Printf("- Score: %d\n", verifyResult.Data.Score)
    fmt.Printf("- SMTP Check: %v\n", verifyResult.Data.SMTPCheck)
    fmt.Printf("- MX Found: %v\n", verifyResult.Data.MXFound)
}
```

### Managing Verifier Bulk Operations

```go
// List all verifier bulks
params := &models.BulkGetParams{
    Page:      1,
    Limit:     15,
    Direction: "desc",
    Filter:    "all",
}

bulks, err := client.GetAllVerifierBulks(params)
if err != nil {
    log.Fatal("Failed to get verifier bulks:", err)
}

fmt.Printf("Verifier Operations (%d found):\n", len(bulks.Data))
for _, bulk := range bulks.Data {
    status := "In Progress"
    if bulk.Status {
        status = "Completed"
    }

    fmt.Printf("- %s (ID: %d) - %s - %d%% complete\n",
        bulk.Name, bulk.BulkID, status, bulk.Progress)
}

// Cleanup: Archive old verifications
for _, bulk := range bulks.Data {
    if bulk.Status && bulk.Expired {
        _, err := client.ArchiveBulk(models.BulkTypeVerifier, bulk.BulkID)
        if err != nil {
            log.Printf("Failed to archive bulk %d: %v", bulk.BulkID, err)
        } else {
            fmt.Printf("Archived expired bulk: %s\n", bulk.Name)
        }
    }
}
```

### Advanced Example: Complete Verification Workflow

```go
func verifyEmailList(client *tomba.Tomba, csvPath string, emailColumn int) (*VerificationSummary, error) {
    // Step 1: Create verification bulk
    params := &models.BulkCreateParams{
        Name:      fmt.Sprintf("Email Verification - %s", time.Now().Format("2006-01-02 15:04")),
        Delimiter: ",",
        Column:    emailColumn,
        Sources:   false,
        Notifie:   true,
    }

    response, err := client.CreateBulkWithFile(models.BulkTypeVerifier, params, csvPath)
    if err != nil {
        return nil, fmt.Errorf("failed to create verification bulk: %w", err)
    }

    bulkID := *response.Data.ID
    log.Printf("Created verification bulk: %d", bulkID)

    // Step 2: Launch verification
    _, err = client.LaunchBulk(models.BulkTypeVerifier, bulkID)
    if err != nil {
        return nil, fmt.Errorf("failed to launch verification: %w", err)
    }

    log.Println("Email verification in progress...")

    // Step 3: Monitor with detailed progress
    timeout := time.After(20 * time.Minute) // Verification is usually faster
    ticker := time.NewTicker(15 * time.Second)
    defer ticker.Stop()

    startTime := time.Now()

    for {
        select {
        case <-timeout:
            return nil, fmt.Errorf("verification timed out after 20 minutes")

        case <-ticker.C:
            progress, err := client.GetBulkProgress(models.BulkTypeVerifier, bulkID)
            if err != nil {
                log.Printf("Error checking progress: %v", err)
                continue
            }

            if progress.Progress%20 == 0 || progress.Status { // Log every 20%
                elapsed := time.Since(startTime).Round(time.Second)
                log.Printf("Verification: %d%% (%d processed) - %v",
                    progress.Progress, progress.Processed, elapsed)
            }

            if progress.Status {
                // Step 4: Get final results
                bulk, err := client.GetBulk(models.BulkTypeVerifier, bulkID)
                if err != nil {
                    return nil, fmt.Errorf("failed to get final results: %w", err)
                }

                info := bulk.Data[0]

                // Step 5: Download results
                timestamp := time.Now().Format("20060102-150405")
                validFile := fmt.Sprintf("valid-emails-%s.csv", timestamp)
                invalidFile := fmt.Sprintf("invalid-emails-%s.csv", timestamp)

                // Download valid emails
                err = client.SaveBulkResults(models.BulkTypeVerifier, bulkID, validFile, "valid")
                if err != nil {
                    log.Printf("Warning: Failed to save valid emails: %v", err)
                }

                // Download invalid/unverifiable emails
                err = client.SaveBulkResults(models.BulkTypeVerifier, bulkID, invalidFile, "not_found")
                if err != nil {
                    log.Printf("Warning: Failed to save invalid emails: %v", err)
                }

                // Build summary
                summary := &VerificationSummary{
                    BulkID:       bulkID,
                    Name:         info.Name,
                    TotalEmails:  info.Processed,
                    Duration:     time.Since(startTime),
                    ValidFile:    validFile,
                    InvalidFile:  invalidFile,
                }

                if info.VerifyCost != nil {
                    summary.CreditsCost = *info.VerifyCost
                }

                log.Printf("Verification completed! Processed %d emails in %v",
                    summary.TotalEmails, summary.Duration.Round(time.Second))

                return summary, nil
            }
        }
    }
}

// Summary structure for verification results
type VerificationSummary struct {
    BulkID      int64
    Name        string
    TotalEmails int
    CreditsCost int
    Duration    time.Duration
    ValidFile   string
    InvalidFile string
}

func (s *VerificationSummary) String() string {
    return fmt.Sprintf(`
Verification Summary:
- Bulk ID: %d
- Name: %s
- Total Emails: %d
- Credits Used: %d
- Duration: %v
- Valid Emails: %s
- Invalid Emails: %s`,
        s.BulkID, s.Name, s.TotalEmails, s.CreditsCost,
        s.Duration.Round(time.Second), s.ValidFile, s.InvalidFile)
}

// Usage example
func main() {
    client := tomba.NewTomba("your-api-key", "your-secret-key")

    summary, err := verifyEmailList(client, "email-list.csv", 1)
    if err != nil {
        log.Fatal("Verification failed:", err)
    }

    fmt.Println(summary)
}
```

### CSV File Format Examples

**Simple Email List**

```text
email
john.doe@example.com
jane@company.com
invalid-email@
user@nonexistent-domain.xyz
contact@business.net
```

**With Additional Data**

```text
name,email,company
John Doe,john.doe@example.com,Example Corp
Jane Smith,jane@company.com,Tech Company
Invalid User,invalid-email@,Unknown
Test User,user@nonexistent.xyz,Fake Company
```

## Best Practices

- **Regular Verification**: Verify email lists regularly, especially before major campaigns
- **List Hygiene**: Remove invalid and risky emails from your marketing lists
- **Domain Limits**: Respect per-domain verification limits to maintain service quality
- **Quality Thresholds**: Set appropriate quality standards for your use case
- **Campaign Integration**: Integrate verification into your email marketing workflow
- **Batch Processing**: Process large lists in smaller batches for better management
- **Result Segmentation**: Separate valid, invalid, and risky emails for targeted action
- **Cost Monitoring**: Track verification costs and optimize for budget efficiency
- **Sender Reputation**: Use verification to maintain good sender reputation scores
- **Compliance**: Ensure verification practices comply with email marketing regulations
