Skip to content

Email Authentication Testing

VaultSandbox validates SPF, DKIM, DMARC, and reverse DNS for every email, helping you catch authentication issues before production.

Email authentication prevents:

  • Emails being marked as spam
  • Emails being rejected by receivers
  • Domain spoofing and phishing
  • Delivery failures

Testing authentication ensures your emails will be trusted by Gmail, Outlook, and other providers.

email, err := inbox.WaitForEmail(ctx, vaultsandbox.WithWaitTimeout(10*time.Second))
if err != nil {
log.Fatal(err)
}
validation := email.AuthResults.Validate()
if validation.Passed {
fmt.Println("All authentication checks passed")
} else {
fmt.Println("Authentication failures:")
for _, f := range validation.Failures {
fmt.Printf(" - %s\n", f)
}
}
auth := email.AuthResults
if auth.SPF != nil {
fmt.Printf("SPF: %s (IP: %s)\n", auth.SPF.Result, auth.SPF.IP)
}
if len(auth.DKIM) > 0 {
fmt.Printf("DKIM: %s\n", auth.DKIM[0].Result)
}
if auth.DMARC != nil {
fmt.Printf("DMARC: %s (aligned: %v)\n", auth.DMARC.Result, auth.DMARC.Aligned)
}
if auth.ReverseDNS != nil {
fmt.Printf("Reverse DNS verified: %v\n", auth.ReverseDNS.Verified)
}
func TestEmailPassesSPFCheck(t *testing.T) {
sendEmail(inbox.EmailAddress())
email, err := inbox.WaitForEmail(ctx, vaultsandbox.WithWaitTimeout(10*time.Second))
if err != nil {
t.Fatal(err)
}
if email.AuthResults.SPF == nil {
t.Fatal("expected SPF results")
}
if email.AuthResults.SPF.Result != "pass" {
t.Errorf("expected SPF pass, got %s", email.AuthResults.SPF.Result)
}
}
func TestSPFValidationDetails(t *testing.T) {
email, err := inbox.WaitForEmail(ctx, vaultsandbox.WithWaitTimeout(10*time.Second))
if err != nil {
t.Fatal(err)
}
spf := email.AuthResults.SPF
if spf != nil {
if spf.Result != "pass" {
t.Errorf("expected SPF pass, got %s", spf.Result)
}
if spf.Domain != "example.com" {
t.Errorf("expected domain example.com, got %s", spf.Domain)
}
t.Logf("SPF %s for %s from IP %s", spf.Result, spf.Domain, spf.IP)
t.Logf("Info: %s", spf.Info)
}
}
func TestHandlesSPFFailure(t *testing.T) {
email, err := inbox.WaitForEmail(ctx, vaultsandbox.WithWaitTimeout(10*time.Second))
if err != nil {
t.Fatal(err)
}
spf := email.AuthResults.SPF
if spf != nil && spf.Result != "pass" {
t.Logf("SPF %s: %s", spf.Result, spf.Info)
// Common failures
switch spf.Result {
case "fail":
t.Log("Server IP not authorized in SPF record")
t.Log("Action: Add server IP to SPF record")
case "softfail":
t.Log("Server probably not authorized (~all in SPF)")
case "none":
t.Log("No SPF record found")
t.Log("Action: Add SPF record to DNS")
}
}
}
func TestEmailHasValidDKIMSignature(t *testing.T) {
sendEmail(inbox.EmailAddress())
email, err := inbox.WaitForEmail(ctx, vaultsandbox.WithWaitTimeout(10*time.Second))
if err != nil {
t.Fatal(err)
}
if len(email.AuthResults.DKIM) == 0 {
t.Fatal("expected DKIM results")
}
if email.AuthResults.DKIM[0].Result != "pass" {
t.Errorf("expected DKIM pass, got %s", email.AuthResults.DKIM[0].Result)
}
}
func TestValidatesAllDKIMSignatures(t *testing.T) {
email, err := inbox.WaitForEmail(ctx, vaultsandbox.WithWaitTimeout(10*time.Second))
if err != nil {
t.Fatal(err)
}
dkim := email.AuthResults.DKIM
if len(dkim) > 0 {
t.Logf("Email has %d DKIM signature(s)", len(dkim))
for i, sig := range dkim {
t.Logf("Signature %d: result=%s, domain=%s, selector=%s",
i+1, sig.Result, sig.Domain, sig.Selector)
if sig.Result != "pass" {
t.Errorf("signature %d failed: %s", i+1, sig.Result)
}
}
// At least one signature should pass
anyPassed := false
for _, sig := range dkim {
if sig.Result == "pass" {
anyPassed = true
break
}
}
if !anyPassed {
t.Error("expected at least one DKIM signature to pass")
}
}
}
func TestDKIMUsesCorrectSelector(t *testing.T) {
email, err := inbox.WaitForEmail(ctx, vaultsandbox.WithWaitTimeout(10*time.Second))
if err != nil {
t.Fatal(err)
}
if len(email.AuthResults.DKIM) == 0 {
t.Fatal("expected DKIM results")
}
dkim := email.AuthResults.DKIM[0]
if dkim.Selector != "default" { // Or your expected selector
t.Errorf("expected selector 'default', got %s", dkim.Selector)
}
if dkim.Domain != "example.com" {
t.Errorf("expected domain example.com, got %s", dkim.Domain)
}
// DKIM DNS record should exist at:
// {selector}._domainkey.{domain}
t.Logf("DKIM key at: %s._domainkey.%s", dkim.Selector, dkim.Domain)
}
func TestEmailPassesDMARC(t *testing.T) {
sendEmail(inbox.EmailAddress())
email, err := inbox.WaitForEmail(ctx, vaultsandbox.WithWaitTimeout(10*time.Second))
if err != nil {
t.Fatal(err)
}
if email.AuthResults.DMARC == nil {
t.Fatal("expected DMARC results")
}
if email.AuthResults.DMARC.Result != "pass" {
t.Errorf("expected DMARC pass, got %s", email.AuthResults.DMARC.Result)
}
}
func TestDMARCPolicyIsEnforced(t *testing.T) {
email, err := inbox.WaitForEmail(ctx, vaultsandbox.WithWaitTimeout(10*time.Second))
if err != nil {
t.Fatal(err)
}
dmarc := email.AuthResults.DMARC
if dmarc != nil {
t.Logf("DMARC result: %s", dmarc.Result)
t.Logf("DMARC policy: %s", dmarc.Policy)
t.Logf("DMARC aligned: %v", dmarc.Aligned)
if dmarc.Info != "" {
t.Logf("DMARC info: %s", dmarc.Info)
}
// Policy should be restrictive in production
if dmarc.Policy != "quarantine" && dmarc.Policy != "reject" {
t.Errorf("expected restrictive policy, got %s", dmarc.Policy)
}
}
}
func TestDMARCAlignmentRequirements(t *testing.T) {
email, err := inbox.WaitForEmail(ctx, vaultsandbox.WithWaitTimeout(10*time.Second))
if err != nil {
t.Fatal(err)
}
// DMARC requires either SPF or DKIM to align with From domain
validation := email.AuthResults.Validate()
if !validation.DMARCPassed {
t.Log("DMARC failed. Checking alignment:")
t.Logf("SPF passed: %v", validation.SPFPassed)
t.Logf("DKIM passed: %v", validation.DKIMPassed)
// At least one should pass for DMARC to pass
if !validation.SPFPassed && !validation.DKIMPassed {
t.Error("neither SPF nor DKIM passed - DMARC cannot align")
}
}
}
func TestServerHasValidReverseDNS(t *testing.T) {
email, err := inbox.WaitForEmail(ctx, vaultsandbox.WithWaitTimeout(10*time.Second))
if err != nil {
t.Fatal(err)
}
rdns := email.AuthResults.ReverseDNS
if rdns != nil {
if !rdns.Verified {
t.Error("expected reverse DNS to be verified")
}
if rdns.Hostname == "" {
t.Error("expected hostname to be set")
}
t.Logf("Reverse DNS: %s -> %s", rdns.IP, rdns.Hostname)
t.Logf("Verified: %v", rdns.Verified)
if rdns.Info != "" {
t.Logf("Info: %s", rdns.Info)
}
}
}
func TestEmailPassesAllAuthenticationChecks(t *testing.T) {
app.SendProductionEmail(inbox.EmailAddress())
email, err := inbox.WaitForEmail(ctx, vaultsandbox.WithWaitTimeout(10*time.Second))
if err != nil {
t.Fatal(err)
}
validation := email.AuthResults.Validate()
// All checks should pass in production
if !validation.Passed {
t.Error("expected all authentication checks to pass")
}
if !validation.SPFPassed {
t.Error("expected SPF to pass")
}
if !validation.DKIMPassed {
t.Error("expected DKIM to pass")
}
if !validation.DMARCPassed {
t.Error("expected DMARC to pass")
}
// Log results
t.Log("Authentication Results:")
t.Logf(" SPF: %v", validation.SPFPassed)
t.Logf(" DKIM: %v", validation.DKIMPassed)
t.Logf(" DMARC: %v", validation.DMARCPassed)
t.Logf(" Reverse DNS: %v", validation.ReverseDNSPassed)
}
func TestHandlesAuthenticationFailuresGracefully(t *testing.T) {
email, err := inbox.WaitForEmail(ctx, vaultsandbox.WithWaitTimeout(10*time.Second))
if err != nil {
t.Fatal(err)
}
validation := email.AuthResults.Validate()
// Log failures without failing test (for non-production)
if !validation.Passed {
t.Log("Authentication issues detected:")
for _, failure := range validation.Failures {
t.Logf(" - %s", failure)
}
// Provide remediation steps
if !validation.SPFPassed {
t.Log("")
t.Log("To fix SPF:")
t.Log(" Add to DNS: v=spf1 ip4:YOUR_SERVER_IP -all")
}
if !validation.DKIMPassed {
t.Log("")
t.Log("To fix DKIM:")
t.Log(" 1. Generate DKIM keys")
t.Log(" 2. Add public key to DNS")
t.Log(" 3. Configure mail server to sign emails")
}
if !validation.DMARCPassed {
t.Log("")
t.Log("To fix DMARC:")
t.Log(" Add to DNS: v=DMARC1; p=none; rua=mailto:[email protected]")
}
}
// In production, this should be: if !validation.Passed { t.Fail() }
}
func TestValidatesStagingEnvironmentEmailAuth(t *testing.T) {
email, err := inbox.WaitForEmail(ctx, vaultsandbox.WithWaitTimeout(10*time.Second))
if err != nil {
t.Fatal(err)
}
auth := email.AuthResults
// SPF should be configured
if auth.SPF != nil {
if auth.SPF.Result != "pass" && auth.SPF.Result != "neutral" {
t.Logf("SPF not configured correctly: %s", auth.SPF.Result)
t.Logf("Info: %s", auth.SPF.Info)
}
}
// DKIM should be present
if len(auth.DKIM) > 0 {
anyValid := false
for _, d := range auth.DKIM {
if d.Result == "pass" {
anyValid = true
break
}
}
if !anyValid {
t.Log("No valid DKIM signatures")
t.Log("Fix: Configure DKIM signing in mail server")
}
}
}
func TestProductionEmailConfiguration(t *testing.T) {
email, err := inbox.WaitForEmail(ctx, vaultsandbox.WithWaitTimeout(10*time.Second))
if err != nil {
t.Fatal(err)
}
validation := email.AuthResults.Validate()
// Production requirements
t.Log("Production Readiness:")
t.Logf(" SPF: %v", validation.SPFPassed)
t.Logf(" DKIM: %v", validation.DKIMPassed)
t.Logf(" DMARC: %v", validation.DMARCPassed)
t.Logf(" All: %v", validation.Passed)
// Fail if not production-ready
if !validation.Passed {
t.Log("")
t.Log("Email not production-ready:")
for _, f := range validation.Failures {
t.Logf(" - %s", f)
}
t.Log("")
t.Log("Fix these issues before deploying to production.")
t.Fail()
}
}

The authresults package provides functions that return errors for validation:

import "github.com/vaultsandbox/client-go/authresults"
// Validate all checks
if err := authresults.Validate(email.AuthResults); err != nil {
log.Printf("validation failed: %v", err)
}
// Validate individual checks
if err := authresults.ValidateSPF(email.AuthResults); err != nil {
log.Printf("SPF failed: %v", err)
}
if err := authresults.ValidateDKIM(email.AuthResults); err != nil {
log.Printf("DKIM failed: %v", err)
}
if err := authresults.ValidateDMARC(email.AuthResults); err != nil {
log.Printf("DMARC failed: %v", err)
}
if err := authresults.ValidateReverseDNS(email.AuthResults); err != nil {
log.Printf("Reverse DNS failed: %v", err)
}
import (
"errors"
"github.com/vaultsandbox/client-go/authresults"
)
// Available sentinel errors:
// - authresults.ErrSPFFailed
// - authresults.ErrDKIMFailed
// - authresults.ErrDMARCFailed
// - authresults.ErrReverseDNSFailed
// - authresults.ErrNoAuthResults
if err := authresults.ValidateSPF(email.AuthResults); err != nil {
switch {
case errors.Is(err, authresults.ErrSPFFailed):
fmt.Println("SPF check failed - check your SPF record")
case errors.Is(err, authresults.ErrNoAuthResults):
fmt.Println("No SPF results available")
default:
fmt.Printf("unexpected error: %v\n", err)
}
}
if err := authresults.ValidateDKIM(email.AuthResults); err != nil {
switch {
case errors.Is(err, authresults.ErrDKIMFailed):
fmt.Println("DKIM check failed - verify DKIM signing")
case errors.Is(err, authresults.ErrNoAuthResults):
fmt.Println("No DKIM results available")
}
}
if err := authresults.ValidateDMARC(email.AuthResults); err != nil {
switch {
case errors.Is(err, authresults.ErrDMARCFailed):
fmt.Println("DMARC check failed - check alignment")
case errors.Is(err, authresults.ErrNoAuthResults):
fmt.Println("No DMARC results available")
}
}
if err := authresults.ValidateReverseDNS(email.AuthResults); err != nil {
switch {
case errors.Is(err, authresults.ErrReverseDNSFailed):
fmt.Println("Reverse DNS check failed - configure PTR record")
case errors.Is(err, authresults.ErrNoAuthResults):
fmt.Println("No reverse DNS results available")
}
}
func logAuthenticationDetails(email *vaultsandbox.Email) {
auth := email.AuthResults
fmt.Println()
fmt.Println("=== Email Authentication Details ===")
fmt.Println()
// SPF
if auth.SPF != nil {
fmt.Println("SPF:")
fmt.Printf(" Result: %s\n", auth.SPF.Result)
fmt.Printf(" Domain: %s\n", auth.SPF.Domain)
fmt.Printf(" IP: %s\n", auth.SPF.IP)
fmt.Printf(" Info: %s\n", auth.SPF.Info)
} else {
fmt.Println("SPF: No result")
}
// DKIM
if len(auth.DKIM) > 0 {
fmt.Println()
fmt.Println("DKIM:")
for i, sig := range auth.DKIM {
fmt.Printf(" Signature %d:\n", i+1)
fmt.Printf(" Result: %s\n", sig.Result)
fmt.Printf(" Domain: %s\n", sig.Domain)
fmt.Printf(" Selector: %s\n", sig.Selector)
fmt.Printf(" Info: %s\n", sig.Info)
}
} else {
fmt.Println()
fmt.Println("DKIM: No signatures")
}
// DMARC
if auth.DMARC != nil {
fmt.Println()
fmt.Println("DMARC:")
fmt.Printf(" Result: %s\n", auth.DMARC.Result)
fmt.Printf(" Domain: %s\n", auth.DMARC.Domain)
fmt.Printf(" Policy: %s\n", auth.DMARC.Policy)
fmt.Printf(" Aligned: %v\n", auth.DMARC.Aligned)
if auth.DMARC.Info != "" {
fmt.Printf(" Info: %s\n", auth.DMARC.Info)
}
} else {
fmt.Println()
fmt.Println("DMARC: No result")
}
// Reverse DNS
if auth.ReverseDNS != nil {
fmt.Println()
fmt.Println("Reverse DNS:")
fmt.Printf(" Verified: %v\n", auth.ReverseDNS.Verified)
fmt.Printf(" IP: %s\n", auth.ReverseDNS.IP)
fmt.Printf(" Hostname: %s\n", auth.ReverseDNS.Hostname)
if auth.ReverseDNS.Info != "" {
fmt.Printf(" Info: %s\n", auth.ReverseDNS.Info)
}
}
// Validation Summary
validation := auth.Validate()
fmt.Println()
fmt.Println("Validation Summary:")
if validation.Passed {
fmt.Println(" Overall: PASS")
} else {
fmt.Println(" Overall: FAIL")
fmt.Println(" Failures:")
for _, f := range validation.Failures {
fmt.Printf(" - %s\n", f)
}
}
}
// Usage
email, err := inbox.WaitForEmail(ctx, vaultsandbox.WithWaitTimeout(10*time.Second))
if err != nil {
log.Fatal(err)
}
logAuthenticationDetails(email)

For a simple pass/fail check:

if email.AuthResults.IsPassing() {
fmt.Println("All authentication checks passed")
} else {
fmt.Println("Some authentication checks failed")
}

Note: IsPassing() is equivalent to Validate().Passed and checks SPF, DKIM, and DMARC. Reverse DNS is not included in this check.