dkim

package
v0.0.5 Latest Latest
Warning

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

Go to latest
Published: Oct 30, 2022 License: MIT Imports: 13 Imported by: 0

README

DKIM (DomainKeys Identified Mail) middleware

This middleware allows the DKIM signing of mails with go-mail using the github.com/emersion/go-msgauth library as basis. In case you are using other middlewares, this should be the last to be applies, since alteration of the message after signing it, the verification will fail.

Example

package main

import (
	"log"

	"github.com/wneessen/go-mail"
	"github.com/wneessen/go-mail-middleware/dkim"
)

const rsaKey = `-----BEGIN RSA PRIVATE KEY-----
MIICX[...]
-----END RSA PRIVATE KEY-----`

func main() {
	// First we need a config for our DKIM signer middleware
	sc, err := dkim.NewConfig("example.com", "mail",
		dkim.WithHeaderFields(mail.HeaderDate.String(),
			mail.HeaderFrom.String(), mail.HeaderTo.String(),
			mail.HeaderSubject.String()),
	)
	if err != nil {
		log.Fatalf("failed to create new config: %s", err)
	}

	// We then create a new middleware based of our RSA key and the config
	// we just created
	mw, err := dkim.NewFromRSAKey([]byte(rsaKey), sc)
	if err != nil {
		log.Fatalf("failed to create new middleware from RSA key: %s", err)
	}

	// Finally we create a new mail.Msg with our middleware assigned
	m := mail.NewMsg(mail.WithMiddleware(mw))
	if err := m.From("toni.sender@example.com"); err != nil {
		log.Fatalf("failed to set From address: %s", err)
	}
	if err := m.To("tina.recipient@example.com"); err != nil {
		log.Fatalf("failed to set To address: %s", err)
	}
	m.Subject("This is my first mail with go-mail!")
	m.SetBodyString(mail.TypeTextPlain, "Do you like this mail? I certainly do!")
	c, err := mail.NewClient("smtp.example.com", mail.WithPort(25),
		mail.WithSMTPAuth(mail.SMTPAuthPlain),
		mail.WithUsername("my_username"), mail.WithPassword("extremely_secret_pass"))
	if err != nil {
		log.Fatalf("failed to create mail client: %s", err)
	}
	if err := c.DialAndSend(m); err != nil {
		log.Fatalf("failed to send mail: %s", err)
	}
}

Documentation

Index

Constants

View Source
const Type mail.MiddlewareType = "dkim"

Type is the type of Middleware

Variables

View Source
var (
	ErrInvalidHashAlgo         = errors.New("unsupported hashing algorithm")
	ErrInvalidCanonicalization = errors.New("unsupported canonicalization type")
	ErrDecodePEMFailed         = errors.New("failed to decode PEM block")
	ErrNotEd25519Key           = errors.New("provided key is not of type Ed25519")
	ErrInvalidExpiration       = errors.New("expiration date must be in the future")
	ErrEmptySelector           = errors.New("DKIM domain selector must not be empty")
	ErrFromRequired            = errors.New(`the "From" field is required`)
)

Functions

This section is empty.

Types

type Middleware

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

Middleware is the middleware struct for the DKIM middleware

func NewFromEd25519Key

func NewFromEd25519Key(k []byte, sc *SignerConfig) (*Middleware, error)

NewFromEd25519Key returns a new Signer instance from a given PEM encoded Ed25519 private key

func NewFromRSAKey

func NewFromRSAKey(k []byte, sc *SignerConfig) (*Middleware, error)

NewFromRSAKey returns a new Middlware from a given RSA private key byte slice and a SignerConfig

func (Middleware) Handle

func (d Middleware) Handle(m *mail.Msg) *mail.Msg

Handle is the handler method that satisfies the mail.Middleware interface

func (Middleware) Type

func (d Middleware) Type() mail.MiddlewareType

Type returns the MiddlewareType for this Middleware

type SignerConfig

type SignerConfig struct {
	// AUID represents the DKIM Agent or User Identifier (AUID)
	// See: https://datatracker.ietf.org/doc/html/rfc6376#section-2.6
	//
	// A single identifier that refers to the agent or user on behalf of
	// whom the Signing Domain Identifier (SDID) has taken responsibility.
	// The AUID comprises a domain name and an optional <local-part>.  The
	// domain name is the same as that used for the SDID or is a subdomain
	// of it.  For DKIM processing, the domain name portion of the AUID has
	// only basic domain name semantics; any possible owner-specific
	// semantics are outside the scope of DKIM.
	//
	// AUID is optional and can be empty
	AUID string

	// CanonicalizationHeader defines the type of Canonicalization used for the mail.Msg header
	// Some mail systems modify email in transit, potentially invalidating a
	// signature.  For most Signers, mild modification of email is
	// immaterial to validation of the DKIM domain name's use.  For such
	// Signers, a canonicalization algorithm that survives modest in-transit
	// modification is preferred.
	//
	// If no canonicalization is defines, we default to CanonicalizationSimple
	//
	// See: https://datatracker.ietf.org/doc/html/rfc6376#section-3.4
	// See also: canonicalization.go#L7
	CanonicalizationHeader dkim.Canonicalization

	// CanonicalizationBody defines the type of Canonicalization used for the mail.Msg body
	// Some mail systems modify email in transit, potentially invalidating a
	// signature.  For most Signers, mild modification of email is
	// immaterial to validation of the DKIM domain name's use.  For such
	// Signers, a canonicalization algorithm that survives modest in-transit
	// modification is preferred.
	//
	// If no canonicalization is defines, we default to CanonicalizationSimple
	//
	// See: https://datatracker.ietf.org/doc/html/rfc6376#section-3.4
	// See also: canonicalization.go#L7
	CanonicalizationBody dkim.Canonicalization

	// Domain represents the DKIM Signing Domain Identifier (SDID)
	// See: https://datatracker.ietf.org/doc/html/rfc6376#section-2.5
	//
	// A single domain name that is the mandatory payload output of DKIM
	// and that refers to the identity claiming some responsibility for
	// the message by signing it.
	//
	// Domain MUST not be empty
	Domain string

	// Expiration is an optional expiration time of the signature.
	// See: https://www.rfc-editor.org/rfc/rfc6376.html#section-3.5
	//
	// Signatures MAY be considered invalid if the verification time at
	// the Verifier is past the expiration date. The verification
	// time should be the time that the message was first received at
	// the administrative domain of the Verifier if that time is
	// reliably available; otherwise, the current time should be
	// used.  The value of the "x=" tag MUST be greater than the value
	// of the "t=" tag if both are present.
	Expiration time.Time

	// HashAlgo represents the DKIM Hash Algorithms
	// See: https://datatracker.ietf.org/doc/html/rfc6376#section-7.7
	//
	// DKIM supports the following hashing algorithms
	//   - SHA256: This is the default and prefered algorithm
	//   - SHA1:   Due to comptibility reasons SHA1 is still supported but is
	//             not recommended to use it, since the SHA1 hashing algorithm has
	//             been proven to be broken
	HashAlgo crypto.Hash

	// HeaderFields is an optional list of header fields that should be used in
	// the signature. If the list is empty, all header fields will be used.
	//
	// If a list of headers is given via the HeaderFields slice, the FROM header
	// is always required.
	//
	// For a list of recommended signature headers, please refer to:
	// https://www.rfc-editor.org/rfc/rfc6376.html#section-5.4.1
	HeaderFields []string

	// Selector represents the DKIM domain selectors
	// See: https://datatracker.ietf.org/doc/html/rfc6376#section-3.1
	//
	// To support multiple concurrent public keys per signing domain, the
	// key namespace is subdivided using "selectors".  For example,
	// selectors might indicate the names of office locations (e.g.,
	// "sanfrancisco", "coolumbeach", and "reykjavik"), the signing date
	// (e.g., "january2005", "february2005", etc.), or even an individual
	// user.
	//
	// Selector MUST not be empty
	Selector string
}

func NewConfig

func NewConfig(d string, s string, o ...SignerOption) (*SignerConfig, error)

NewConfig returns a new SignerConfig struct. It requires a domain name d and a domain selector s. All other values can be prefilled using the With*() SignerOption methods

func (*SignerConfig) CanonicalizationIsValid

func (sc *SignerConfig) CanonicalizationIsValid(c dkim.Canonicalization) bool

CanonicalizationIsValid returns true if a the provided Canonicalization is a valid value for the SignerConfig

func (*SignerConfig) HashAlgoIsValid

func (sc *SignerConfig) HashAlgoIsValid(ha crypto.Hash) bool

HashAlgoIsValid returns true if a the provided crypto.Hash is a valid algorithm for the SignerConfig

func (*SignerConfig) SetAUID

func (sc *SignerConfig) SetAUID(a string)

SetAUID sets/overrides the AUID of the SignerConfig

func (*SignerConfig) SetBodyCanonicalization

func (sc *SignerConfig) SetBodyCanonicalization(c dkim.Canonicalization) error

SetBodyCanonicalization sets/overrides the Canonicalization of the SignerConfig

func (*SignerConfig) SetExpiration

func (sc *SignerConfig) SetExpiration(x time.Time) error

SetExpiration sets/overrides the Expiration of the SignerConfig

func (*SignerConfig) SetHashAlgo

func (sc *SignerConfig) SetHashAlgo(ha crypto.Hash) error

SetHashAlgo sets/override the hashing algorithm of the SignerConfig

func (*SignerConfig) SetHeaderCanonicalization

func (sc *SignerConfig) SetHeaderCanonicalization(c dkim.Canonicalization) error

SetHeaderCanonicalization sets/overrides the Canonicalization of the SignerConfig

func (*SignerConfig) SetHeaderFields

func (sc *SignerConfig) SetHeaderFields(fl ...string) error

SetHeaderFields sets/override the HeaderFields of the SignerConfig

func (*SignerConfig) SetSelector

func (sc *SignerConfig) SetSelector(s string) error

SetSelector overrides the Selector of the SignerConfig

type SignerOption

type SignerOption func(config *SignerConfig) error

SignerOption returns a function that can be used for grouping SignerConfig options

func WithAUID

func WithAUID(a string) SignerOption

WithAUID provides the optional AUID value for the SignerConfig

func WithBodyCanonicalization

func WithBodyCanonicalization(c dkim.Canonicalization) SignerOption

WithBodyCanonicalization provides the Canonicalization for the message body in the SignerConfig

func WithExpiration

func WithExpiration(x time.Time) SignerOption

WithExpiration provides the optional expiration time value for the SignerConfig

func WithHashAlgo

func WithHashAlgo(ha crypto.Hash) SignerOption

WithHashAlgo provides the Hashing algorithm to the SignerConfig

func WithHeaderCanonicalization

func WithHeaderCanonicalization(c dkim.Canonicalization) SignerOption

WithHeaderCanonicalization provides the Canonicalization for the message header in the SignerConfig

func WithHeaderFields

func WithHeaderFields(fl ...string) SignerOption

WithHeaderFields provides a list of header field names that should be included in the DKIM signature

Jump to

Keyboard shortcuts

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