Building an Email Verifier in Go: A Step-by-Step Guide

Kushal AgrawalKushal Agrawal
3 min read

Introduction

Verifying email addresses is an essential task for developers working on email automation, marketing, or user validation systems. An email verifier tool helps check if an email is valid, reducing bounce rates and ensuring smoother communication. In this blog, we’ll build an email verifier tool using Go. This tool will:

  1. Validate the email format.

  2. Verify the domain has valid Mail Exchange (MX) records.

  3. Perform an SMTP handshake to check if the email can receive messages.

By the end, you'll have a working tool. Let’s dive in!

Step 1: Prerequisites

Before we start, ensure the following:

  • Go installed: Download and set it up from golang.org.

  • Basic understanding of Go: Familiarity with packages and functions will help.

  • Networking concepts: A basic grasp of DNS, MX records, and SMTP is a plus.

Step 2: Project Overview

Our tool will consist of three main components:

  1. Email Syntax Validation: Uses regex to check if the email is formatted correctly.

  2. MX Record Lookup: Fetches the domain's mail servers.

  3. SMTP Verification: Simulates sending an email to check deliverability.

Here’s the step-by-step implementation.

Step 3: Email Syntax Validation

First, let’s validate the email format. We’ll use a regular expression (regex) to check if the email meets the standard structure:

func validateEmailFormat(email string) bool {
    pattern := `^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$`
    regex := regexp.MustCompile(pattern)
    return regex.MatchString(email)
}

This function returns true if the email matches the regex pattern, ensuring it’s structured like user@domain.com.

Step 4: Domain MX Record Lookup

Next, we’ll fetch the domain's MX records to ensure it has valid mail servers. This is done using Go’s net package

func getMXRecords(domain string) ([]*net.MX, error) {
    mxRecords, err := net.LookupMX(domain)
    if err != nil {
        return nil, fmt.Errorf("failed to fetch MX records for domain %s: %w", domain, err)
    }
    return mxRecords, nil
}

Step 5: SMTP Verification

The final step is to connect to the mail server using SMTP and simulate sending an email. If the server accepts the recipient email, it’s valid:

func smtpCheck(mxServer, email string) error {
    client, err := smtp.Dial(mxServer + ":25")
    if err != nil {
        return fmt.Errorf("SMTP dial error: %w", err)
    }
    defer client.Close()

    client.Hello("localhost") // Identify ourselves to the server
    client.Mail("test@example.com") // Use a fake sender
    err = client.Rcpt(email) // Check if the recipient is accepted

    return err // Return any error from the RCPT command
}

Step 6: Combining It All Together

Now, let’s combine all the components into a single function to verify an email:

func verifyEmail(email string) (bool, error) {
    // Step 1: Validate email syntax
    if !validateEmailFormat(email) {
        return false, fmt.Errorf("invalid email format")
    }

    // Step 2: Extract domain and fetch MX records
    parts := strings.Split(email, "@")
    if len(parts) != 2 {
        return false, fmt.Errorf("invalid email structure")
    }
    domain := parts[1]

    mxRecords, err := getMXRecords(domain)
    if err != nil {
        return false, fmt.Errorf("domain verification failed: %w", err)
    }

    // Step 3: Check SMTP server for deliverability
    for _, mx := range mxRecords {
        err := smtpCheck(mx.Host, email)
        if err == nil {
            return true, nil // Valid email found
        }
    }
    return false, fmt.Errorf("email verification failed")
}

Step 7: Testing the Tool

To test the tool, call the verifyEmail function in your main method:

func main() {
    email := "example@domain.com"
    fmt.Printf("Verifying email: %s\n", email)

    valid, err := verifyEmail(email)
    if valid {
        fmt.Println("The email is valid and ready to receive messages!")
    } else {
        fmt.Printf("Email verification failed: %v\n", err)
    }
}

Run the program in your terminal:

go run email_verifier.go

Conclusion

In this blog, we built an email verifier tool in Go from scratch. This project is a fantastic way to dive into networking, SMTP, and DNS handling. Whether you’re managing email lists or learning Go, this tool is a valuable addition to your arsenal.

Want to see more projects like this? Share your thoughts or suggestions in the comments below. Don’t forget to like and share this blog with your developer community! 🚀

Thank you❤️❤️

0
Subscribe to my newsletter

Read articles from Kushal Agrawal directly inside your inbox. Subscribe to the newsletter, and don't miss out.

Written by

Kushal Agrawal
Kushal Agrawal