go-addr

module
v0.0.0-...-2b86a76 Latest Latest
Warning

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

Go to latest
Published: Jan 5, 2022 License: MIT

README

RFC 5322 Email Address Parser for Go

This aims at being a complete and correct RFC 5322 email address parser. It is not aimed at being fast. I wish I could say the same for the built in net/mail package, but as of this writing, the built-in library is incapable of parsing obsolete forms (which make up much of the Internet). This is still unlikely to be capable of parsing every address or list of addresses found in the wild. The world of email is just a dangerous place.

This is written in pure Go using a hand-written recursive descent parser. This is actually a port of a similar library I wrote for Raku.

Synopsis

package main

import (
    "fmt"

    "github.com/zostay/go-addr/pkg/addr"
)

func main() {
    addresses := "\"J.R.R. Tolkein\" <j.r.r.tolkein@example.com>, \"C.S. Lewis\" <jack@example.com>"
    as, err := addr.ParseEmailAddressList(addresses)
    if err != nil {
        panic(err)
    }

    for _, a := range as {
        fmt.Println("Name: " + a.DisplayName())
        fmt.Println("Addr: " + a.Address())
    }

    // Output: 
    // Name: J.R.R. Tolkein
    // Addr: j.r.r.tolkein@example.com
    // Name: C.S. Lewis
    // Addr: jack@example.com
}

Description

This is intended to provide a more complete email address parsing apparatus that I can trust and tweak to suit my needs.

Email Address Formats Parsed

This library uses terminology taken from RFC 5322.

Address

An email address is either a mailbox or a group. (See below.)

Address List

An email address list is a list of of mailboxes or groups or mixture of both separated by commas.

For example:

"J.R.R. Tolkein" <j.r.r.tolkein@example.com>,
"C.S. Lewis" <jack@example.com>,
Distopian: "George Orwell" <bb.is.watching@example.com,
"Aldous Huxley" <soma@example.com>,
mockingjay@exampel.com;,
"Alexander Dumas" <ad@example.com>

This list contains three mailboxes and one group, which contains three more mailboxes.

Mailbox

An email mailbox is what most people think of as an email address. It's either just a plain email address or it's a display name paired with an email address in angle brackets or just an email address. Mailboxes may also contain comments, which is just text inside of matched pairs of parentheses.

"Douglas Adams" <da@example.com> (DON'T PANIC!)

Mailbox List

This is a list of mailboxes without groups separated by commas.

Group

This is a single group mailbox, which is a name followed by a colon, followed by zero or more mailboxes separated by commas and is ended by a semi-colon.

AddrSpec

In RFC 5322, the email address with no decoration is called an addr-spec. includes just the email address itself.

Obsolete Forms

This parser also works for parsing obsolete forms that go all the way back to RFC 822.

Parsing Functions

These are all part of the github.com/zostay/go-addr/pkg/addr package. All of these functions may return an error if there's a problem during the parse or if parser can't find an address in the input.

If the input string starts with something that can be parsed as an email address, but can't be completely parsed, then the part that can be parsed will be returned and a PartialParseError will be returned as the error. This has a Remainder field that can be used to retrieve the unparsed part:

package main

import (
	"errors"
	"fmt"

	"github.com/zostay/go-addr/pkg/addr"
)

func main() {
	mb, err := addr.ParseEmailMailbox(
		"\"CS\" <charles.sheffield@example.com> and extra text",
	)

	var r string
	var ppe addr.PartialParseError
	if errors.As(err, &ppe) {
		r = ppe.Remainder
	} else if err != nil {
		panic(err)
	}

	fmt.Printf("Parsed: %s\n", mb)
	fmt.Printf("Remainder: %s\n", r)
    
    // Output:
    // Parsed: "CS" <charles.sheffield@example.com>
    // Remainder: and extra text
}
addr.ParseEmailAddress

func ParseEmailAddress(a string) (addr.Address, error)

This parses a single email address. This can parse either a mailbox address or a group list. The object returned will be either an addr.Group or an addr.Mailbox.

addr.ParseEmailAddressList

func ParseEmailAddressList(a string) (addr.AddressList, error)

An addr.AddressList is a slice of addr.Address. This will parse a list of mailbox and/or group email addresses separated by commas.

addr.ParseEmailMailbox

func ParseEmailMailbox(a string) (*addr.Mailbox, error)

This will parse a single mailbox address.

addr.ParseMailMailboxList

func ParseEmailMailboxList(a string) (addr.MailboxList, error)

An addr.MailboxList is a slice of *addr.Mailbox. This will parse a list of mailbox email addresses separated by commas.

addr.ParseEmailGroup

func ParseEmailGroup(a string) (*addr.Group, error)

This will parse a single group address.

addr.ParseEmailAddrSpec(a string) (*addr.AddrSpec, error)`

func ParseEmailAddrSpec(a string) (*addr.AddrSpec, error)

This will parse a single addr-spec.

net/mail

If you want to convert mailbox email addresses from this library into those of the net/mail package built-in to Go, you just need to do the following:

package main

import (
    "fmt"
    "net/mail"

    "github.com/zostay/go-addr/pkg/addr"
)

func main() {
    addrmb, _ := addr.ParseEmailMailbox("\"David Weber\" <honorh@example.com>")
    mailmb := mail.Address{addrmb.DisplayName(), addrmb.Address()}
    fmt.Println(mailmb)
    // Output: {David Weber honorh@example.com}
}

That's simple enough and there are enough other useful mail handling libraries out there, I didn't bother providing a conversion helper. You can write your own in a couple lines of Go.

Copyright 2020 Andrew Sterling Hanenkamp

Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

Directories

Path Synopsis
pkg
addr
Package addr is the primary entry point for working with email addresses.
Package addr is the primary entry point for working with email addresses.
addr/encoding
Package encoding defines a custom CharsetReader for expanding the encodings that are available for the MIME word decoders used when parsing email addresses.
Package encoding defines a custom CharsetReader for expanding the encodings that are available for the MIME word decoders used when parsing email addresses.
format
Package format provides some tools for formatting and outputting correct RFC 5322 email address strings.
Package format provides some tools for formatting and outputting correct RFC 5322 email address strings.
rd
Package rd provides recursive descent parser helpers.
Package rd provides recursive descent parser helpers.
rfc5234
Package rfc5234 implements an RFC 5234 parser which provides basic productions used by the RFC 5322 parser.
Package rfc5234 implements an RFC 5234 parser which provides basic productions used by the RFC 5322 parser.
rfc5322
Package rfc5322 is a parser for RFC 5322 email addresses.
Package rfc5322 is a parser for RFC 5322 email addresses.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL