email

package
v1.2.2 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Apr 26, 2026 License: MIT Imports: 11 Imported by: 0

Documentation

Overview

Package email provides email address validation and normalization for authcore.

Validation follows RFC 5321 and RFC 5322 rules:

  • Total length 1–254 characters
  • Exactly one @ separating a non-empty local part and domain
  • Local part ≤ 64 characters
  • Domain contains at least one dot; no leading, trailing, or consecutive dots
  • Each domain label is 1–63 characters

Internationalised domain names (IDN) are supported: a Unicode domain such as "münchen.de" is converted to its ASCII punycode form ("xn--mnchen-3ya.de") during normalisation, matching what DNS actually resolves. Store the canonical ASCII form in your database so lookups are deterministic.

The single entry point is Email.ValidateAndNormalize — it normalizes (lowercase + trim + punycode) and validates in one step, returning the canonical form. Always store and query emails using this canonical form:

emailMod, _ := email.New(auth)
defer emailMod.Close()

// Registration
normalized, err := emailMod.ValidateAndNormalize(req.Email)
if err != nil {
    c.JSON(400, map[string]string{"error": errors.Unwrap(err).Error()})
    return
}
db.StoreUser(normalized, ...)

// Login lookup — same call, same canonical form, consistent results
normalized, err = emailMod.ValidateAndNormalize(req.Email)
if err != nil { ... }
user := db.FindByEmail(normalized)

Domain MX verification

VerifyDomain performs an optional DNS MX lookup to confirm the domain can receive email. Results are cached per domain using the DNS TTL (capped at DefaultCacheTTL) to avoid repeated lookups for the same domain. This check is network I/O — always call it after ValidateAndNormalize and handle ErrDomainUnresolvable as a soft failure:

err = emailMod.VerifyDomain(ctx, normalized)
if errors.Is(err, email.ErrDomainNoMX) {
    c.JSON(400, map[string]string{"error": "email domain cannot receive messages"})
    return
}
if errors.Is(err, email.ErrDomainUnresolvable) {
    log.Warn("DNS check unavailable: %v", err) // do not block the user
}

Index

Examples

Constants

View Source
const DefaultCacheTTL = 5 * time.Minute

DefaultCacheTTL is the maximum duration a domain MX lookup result is cached. Tune this value if your workload has strict freshness requirements.

Variables

View Source
var ErrDomainNoMX = errors.New("email: domain has no MX records")

ErrDomainNoMX is CLIENT-SAFE: the domain exists but has no MX records, meaning it cannot receive email. Safe to return as a 400 response:

if errors.Is(err, email.ErrDomainNoMX) {
    c.JSON(400, map[string]string{"error": "email domain cannot receive messages"})
    return
}
View Source
var ErrDomainUnresolvable = errors.New("email: domain could not be resolved")

ErrDomainUnresolvable is INTERNAL: the DNS lookup failed due to a network error, timeout, or resolver unavailability. Do NOT block the user on this — log the error and let the request proceed:

if errors.Is(err, email.ErrDomainUnresolvable) {
    log.Warn("DNS check failed, skipping: %v", err)
    // continue — don't block the user
}
View Source
var ErrInvalidEmail = errors.New("email: invalid address")

ErrInvalidEmail signals that an address failed RFC 5321/5322 validation.

CLIENT-SAFE: the wrapped reason describes exactly which rule failed and is suitable for returning in a 400 response:

normalized, err := emailMod.ValidateAndNormalize(req.Email)
if err != nil {
    c.JSON(400, map[string]string{"error": errors.Unwrap(err).Error()})
    return
}

Use errors.Is to check for this in calling code.

Functions

This section is empty.

Types

type Email

type Email struct {
	// contains filtered or unexported fields
}

Email is the email validation and normalization module. Create one instance at startup via New and reuse it — it is safe for concurrent use after construction.

Call Email.Close when the module is no longer needed to stop the background cache eviction goroutine.

func New

func New(p authcore.