Skip to content

DKIM Signing Example

Winni Neessen edited this page Jul 4, 2026 · 1 revision

This example shows how to enable native DKIM signing in go-mail.

go-mail v0.8.0 added native DKIM signing, so you no longer need the go-mail-middleware package to DKIM-sign your messages. The signer key can be loaded straight from a PEM file using the newly added mail.PrivKeyFromPEM function.

Test on play.go.dev

package main

import (
	"context"
	"log"
	"os"

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

func main() {
	ctx, cancel := context.WithCancel(context.Background())
	defer cancel()
	
	// Load the DKIM private key from a PEM file and decode it into a crypto.Signer
	pemBytes, err := os.ReadFile("dkim-private.pem")
	if err != nil {
		log.Fatalf("failed to read DKIM private key: %s", err)
	}
	signerKey, err := mail.PrivKeyFromPEM(pemBytes)
	if err != nil {
		log.Fatalf("failed to parse DKIM private key: %s", err)
	}

	message := mail.NewMsg()
	if err = message.From("toni.tester@example.com"); err != nil {
		log.Fatalf("failed to set FROM address: %s", err)
	}
	if err = message.To("tina.tester@example.com"); err != nil {
		log.Fatalf("failed to set TO address: %s", err)
	}
	message.Subject("This is my first test mail with go-mail!")
	message.SetBodyString(mail.TypeTextPlain, "This will be the content of the mail.")

	// Initialize the DKIM signer for our domain and selector, then attach it to the message
	dkimSigner := mail.NewDKIMSigner("example.com", "2026a", signerKey)
	message.SetDKIM(dkimSigner)

	// Deliver the mails via SMTP
	client, err := mail.NewClient(os.Getenv("SMTP_HOST"),
		mail.WithSMTPAuth(mail.SMTPAuthAutoDiscover), mail.WithTLSPortPolicy(mail.TLSMandatory),
		mail.WithUsername(os.Getenv("SMTP_USER")), mail.WithPassword(os.Getenv("SMTP_PASS")),
	)
	if err != nil {
		log.Fatalf("failed to create new mail delivery client: %s", err)
	}
	if err := client.DialAndSendWithContext(ctx, message); err != nil {
		log.Fatalf("failed to deliver mail: %s", err)
	}
	log.Printf("Test mail successfully delivered.")
}

Most of the code is explained in the Simple-Mailer-Example. Check out that page for detailed explanations.

The main differences to the Simple Mailer Example are, that we load our DKIM signer key from a PEM file in the first few lines of code. The mail.PrivKeyFromPEM function decodes a PEM-encoded private key into a crypto.Signer. It accepts both PKCS#1 (RSA PRIVATE KEY) and PKCS#8 (PRIVATE KEY) encodings and supports RSA and Ed25519 keys , which makes the returned signer ready to be passed directly to NewDKIMSigner .

Later, when our message is composed, we create a DKIM signer with mail.NewDKIMSigner, providing three parameters:

  • domain: the signing domain published in DNS (the d= tag)
  • selector: the selector used to locate the public key in DNS (the s= tag)
  • privKey: the crypto.Signer we loaded from the PEM file, used to produce the signature

Finally we attach the signer to the message via Msg.SetDKIM , which makes sure that, once the mail is rendered during the delivery process, the mail is DKIM signed before it is sent out.

Signing every message on a Client

If you send multiple messages through the same Client and don't want to configure DKIM on each Msg individually, you can register the signer once at the client level with mail.WithAlwaysDKIMSign. Note that a signer configured on the client always takes precedence over any DKIM configuration set on the individual Msg.

client, err := mail.NewClient(os.Getenv("SMTP_HOST"),
	mail.WithSMTPAuth(mail.SMTPAuthAutoDiscover), mail.WithTLSPortPolicy(mail.TLSMandatory),
	mail.WithUsername(os.Getenv("SMTP_USER")), mail.WithPassword(os.Getenv("SMTP_PASS")),
	mail.WithAlwaysDKIMSign(dkimSigner),
)

Clone this wiki locally