1
0
mirror of https://blitiri.com.ar/repos/chasquid synced 2025-12-17 14:37:02 +00:00
Files
go-chasquid-smtp/internal/normalize/normalize.go
Alberto Bertogli 112e492c3a Normalize domains
We should ignore the domains' case, and treat them uniformly, specially when it
comes to local domains.

This patch extends the existing normalization (IDNA, keeping domains as
UTF8 internally) to include case conversion and NFC form for
consistency.
2016-10-10 00:51:05 +01:00

75 lines
1.9 KiB
Go

// Package normalize contains functions to normalize usernames, domains and
// addresses.
package normalize
import (
"strings"
"blitiri.com.ar/go/chasquid/internal/envelope"
"golang.org/x/net/idna"
"golang.org/x/text/secure/precis"
"golang.org/x/text/unicode/norm"
)
// User normalizes an username using PRECIS.
// On error, it will also return the original username to simplify callers.
func User(user string) (string, error) {
norm, err := precis.UsernameCaseMapped.String(user)
if err != nil {
return user, err
}
return norm, nil
}
// Domain normalizes a DNS domain into a cleaned UTF-8 form.
// On error, it will also return the original domain to simplify callers.
func Domain(domain string) (string, error) {
// For now, we just convert them to lower case and make sure it's in NFC
// form for consistency.
// There are other possible transformations (like nameprep) but for our
// purposes these should be enough.
// https://tools.ietf.org/html/rfc5891#section-5.2
// https://blog.golang.org/normalization
d, err := idna.ToUnicode(domain)
if err != nil {
return domain, err
}
d = norm.NFC.String(d)
d = strings.ToLower(d)
return d, nil
}
// Name normalizes an email address, applying User and Domain to its
// respective components.
// On error, it will also return the original address to simplify callers.
func Addr(addr string) (string, error) {
user, domain := envelope.Split(addr)
user, err := User(user)
if err != nil {
return addr, err
}
domain, err = Domain(domain)
if err != nil {
return addr, err
}
return user + "@" + domain, nil
}
// Take an address with an ASCII domain, and convert it to Unicode as per
// IDNA, including basic normalization.
// The user part is unchanged.
func DomainToUnicode(addr string) (string, error) {
if addr == "<>" {
return addr, nil
}
user, domain := envelope.Split(addr)
domain, err := Domain(domain)
return user + "@" + domain, err
}