Documentation ¶
Overview ¶
Package emailsupport contains some more esoteric routines useful for parsing and handling email. For instance, some baroque regular expressions.
No APIs are stable. Make sure you handle your dependencies accordingly.
REGULAR EXPRESSIONS ¶
The package creates a number of exported regular expression objects, initialised at init time, pulling up the creation cost to program start. Per the documentation for the `regexp` package, “A Regexp is safe for concurrent use by multiple goroutines.”
Each regular expression comes in two forms, `Foo` and `FooUnanchored`. The short name is anchored to the start and end of the pattern namespace, so that by default if you match an variable against `EmailAddress`, you are confirming that the contents of the variable are an email address, not accidentally only matching that there's something address-like somewhere within. The longer name (I need something briefer which is still clear) provides a pattern which can be used to find a regular expression elsewhere.
Each regular expression is available as a pattern string in a form with a `Txt` prefix, which can be used to build larger regular expressions. The pattern is wrapped with `(?:...)` to be a non-capturing group which can be qualified or otherwise treated as a single unit. No regular expression has any capturing groups, letting the caller manage capturing indices.
Thus for any `Foo`, this package provides:
- TxtFoo: the regular expression as a text string, safe for embedding
- Foo: a regexp object which is anchored to start and end
- FooUnanchored: a regexp object which is not anchored
The list includes:
`EmailAddress`: an RFC5321 email address, the part within angle-brackets or as is used in SMTP. This is _not_ an RFC5322 message header email email address, with display forms and comments.
`EmailDomain`: a domain which can be used in email addresses; this is the base specification form and does not handle internationalisation, though this regexp should be correct to apply against punycode-encoded domains. This does handle embedded IPv4 and IPv6 address literals, but not the General-address-literal which is a grammar hook for future extension (because that inherently can't be handled until defined).
`EmailLHS`: the Left-Hand-Side (or "local part") of an email address; this handles unquoted and quoted forms.
`EmailAddressOrUnqualified`: either an address or a LHS, this is a form often used in mail configuration files where a domain is implicit.
`IPv4Address`, `IPv6Address`: an IPv4 or IPv6 address
`IPv4Netblock`, `IPv6Netblock`, IPNetblock: a netblock in CIDR prefix/len notation (used for source ACLs)
`IPv4Octet`: a number 0 to 255
The IPv6 address regexp is taken from RFC3986 (the one which gets it right) and is a careful copy/paste and edit of a version which has been used and gradually debugged for years, including in a tool I released called `emit_ipv6_regexp`.
The patterns used in `EmailLHS` (and thus also in items which include an email left-hand-side) can be in one of two forms, and selecting between them is a compile-time decision. The rules can be either those from RFC2822 or those from RFC5321. By default, those from RFC5321 are used. Build with a `rfc2822` build-tag to get the older definitions. If a future RFC changes the rules again, then the default patterns in this package may change; the build-tag `rfc5321` is currently unused, but is reserved for the future to force selecting the rules which are now current. It is safe (harmless) to supply that build-tag now (but not together with `rfc2822`).
Index ¶
Constants ¶
const ( TxtIPv4Octet = `(?:25[0-5]|(?:[1-9]|1[0-9]|2[0-4])?[0-9])` TxtIPv4Address = `(?:(?:` + TxtIPv4Octet + `\.){3}` + TxtIPv4Octet + `)` TxtIPv4Netblock = `(?:` + TxtIPv4Address + `/(?:[12]?[0-9]|3[0-2]))` )
Variables ¶
var ( IPv4OctetUnanchored = regexp.MustCompile(TxtIPv4Octet) IPv4Octet = regexp.MustCompile(start + TxtIPv4Octet + end) IPv4AddressUnanchored = regexp.MustCompile(TxtIPv4Address) IPv4Address = regexp.MustCompile(start + TxtIPv4Address + end) IPv4NetblockUnanchored = regexp.MustCompile(TxtIPv4Netblock) IPv4Netblock = regexp.MustCompile(start + TxtIPv4Netblock + end) )
var ( TxtIPv6Address = strings.Join([]string{`(?:`, `(?:(?:(?:`, txtIPv6H16, `:){6})`, txtIPv6LS32, `)|`, `(?:(?:::(?:`, txtIPv6H16, `:){5})`, txtIPv6LS32, `)|`, `(?:(?:(?:`, txtIPv6H16, `)?::(?:`, txtIPv6H16, `:){4})`, txtIPv6LS32, `)|`, `(?:(?:(?:(?:`, txtIPv6H16, `:){0,1}`, txtIPv6H16, `)?::(?:`, txtIPv6H16, `:){3})`, txtIPv6LS32, `)|`, `(?:(?:(?:(?:`, txtIPv6H16, `:){0,2}`, txtIPv6H16, `)?::(?:`, txtIPv6H16, `:){2})`, txtIPv6LS32, `)|`, `(?:(?:(?:(?:`, txtIPv6H16, `:){0,3}`, txtIPv6H16, `)?::`, txtIPv6H16, `:)`, txtIPv6LS32, `)|`, `(?:(?:(?:(?:`, txtIPv6H16, `:){0,4}`, txtIPv6H16, `)?::)`, txtIPv6LS32, `)|`, `(?:(?:(?:(?:`, txtIPv6H16, `:){0,5}`, txtIPv6H16, `)?::)`, txtIPv6H16, `)|`, `(?:(?:(?:(?:`, txtIPv6H16, `:){0,6}`, txtIPv6H16, `)?::))`, `)`}, "") TxtIPv6Netblock = `(?:` + TxtIPv6Address + `/(?:[1-9]?[0-9]|1[01][0-9]|12[0-8]))` TxtIPNetblock = `(?:` + TxtIPv4Netblock + `|` + TxtIPv6Netblock + `)` )
var ( IPv6AddressUnanchored = regexp.MustCompile(TxtIPv6Address) IPv6Address = regexp.MustCompile(start + TxtIPv6Address + end) IPv6NetblockUnanchored = regexp.MustCompile(TxtIPv6Netblock) IPv6Netblock = regexp.MustCompile(start + TxtIPv6Netblock + end) IPNetblockUnanchored = regexp.MustCompile(TxtIPNetblock) IPNetblock = regexp.MustCompile(start + TxtIPNetblock + end) )
var ( EmailLHSUnanchored = regexp.MustCompile(TxtEmailLHS) EmailLHS = regexp.MustCompile(start + TxtEmailLHS + end) EmailDomainUnanchored = regexp.MustCompile(TxtEmailDomain) EmailDomain = regexp.MustCompile(start + TxtEmailDomain + end) EmailAddressUnanchored = regexp.MustCompile(TxtEmailAddress) EmailAddress = regexp.MustCompile(start + TxtEmailAddress + end) EmailAddressOrUnqualifiedUnanchored = regexp.MustCompile(TxtEmailAddressOrUnqualified) EmailAddressOrUnqualified = regexp.MustCompile(start + TxtEmailAddressOrUnqualified + end) )
var TxtEmailAddress = `(?:(?:` + TxtEmailLHS + `)@(?:` + TxtEmailDomain + `))`
var TxtEmailAddressOrUnqualified = `(?:` + TxtEmailLHS + `(?:@` + TxtEmailDomain + `)?)`
var TxtEmailDomain string = deExtend(` # Domain (?: (?: # regular domain (?:[A-Za-z0-9] (?: [A-Za-z0-9-]*[A-Za-z0-9] )?) (?: \. [A-Za-z0-9] (?: [A-Za-z0-9-]*[A-Za-z0-9] )?)+ ) | (?: # address-literals \[ (?: ` + TxtIPv4Address + ` | (?: [Ii][Pp][vV]6: ` + TxtIPv6Address + ` ) ) # NOTSUPP: General-address-literal # G-A-L is a hook for future literal addresses # and only specifies tag:content \] ) )`)
var TxtEmailLHS string = deExtend(`
# Local-part
(?:
(?:
# Dot-string
(?:` + txtAText + `)+ (?: \. ` + txtAText + `+)*
) | (?:
# Quoted-string
" (?: ` + txtWrapFWS + ` (?:
(?: ` + txtQText + `+ ) |
(?: \\ ` + txtQPairFollow + ` )
) )* ` + txtWrapFWS + ` "
)
)`)
Functions ¶
This section is empty.
Types ¶
This section is empty.