chatdesk-ui/auth_v2.169.0/internal/mailer/validate_test.go

288 lines
7.3 KiB
Go

package mailer
import (
"context"
"fmt"
"net/http"
"net/http/httptest"
"sync/atomic"
"testing"
"time"
"github.com/stretchr/testify/require"
"github.com/supabase/auth/internal/conf"
)
func TestEmalValidatorService(t *testing.T) {
ctx := context.Background()
ctx, cancel := context.WithTimeout(ctx, time.Second*60)
defer cancel()
testResVal := new(atomic.Value)
testResVal.Store(`{"valid": true}`)
testHdrsVal := new(atomic.Value)
testHdrsVal.Store(map[string]string{"apikey": "test"})
// testHeaders := map[string][]string{"apikey": []string{"test"}}
testHeaders := `{"apikey": ["test"]}`
ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
key := r.Header.Get("apikey")
if key == "" {
fmt.Fprintln(w, `{"error": true}`)
return
}
fmt.Fprintln(w, testResVal.Load().(string))
}))
defer ts.Close()
// Return nil err from service
// when svc and extended checks both report email as valid
{
testResVal.Store(`{"valid": true}`)
cfg := conf.MailerConfiguration{
EmailValidationExtended: true,
EmailValidationServiceURL: ts.URL,
EmailValidationServiceHeaders: testHeaders,
}
if err := cfg.Validate(); err != nil {
t.Fatal(err)
}
ev := newEmailValidator(cfg)
err := ev.Validate(ctx, "chris.stockton@supabase.io")
if err != nil {
t.Fatalf("exp nil err; got %v", err)
}
}
// Return nil err from service when
// extended is disabled for a known invalid address
// service reports valid
{
testResVal.Store(`{"valid": true}`)
cfg := conf.MailerConfiguration{
EmailValidationExtended: false,
EmailValidationServiceURL: ts.URL,
EmailValidationServiceHeaders: testHeaders,
}
if err := cfg.Validate(); err != nil {
t.Fatal(err)
}
ev := newEmailValidator(cfg)
err := ev.Validate(ctx, "test@gmail.com")
if err != nil {
t.Fatalf("exp nil err; got %v", err)
}
}
// Return nil err from service when
// extended is disabled for a known invalid address
// service is disabled for a known invalid address
{
testResVal.Store(`{"valid": false}`)
cfg := conf.MailerConfiguration{
EmailValidationExtended: false,
EmailValidationServiceURL: "",
EmailValidationServiceHeaders: "",
}
if err := cfg.Validate(); err != nil {
t.Fatal(err)
}
ev := newEmailValidator(cfg)
err := ev.Validate(ctx, "test@gmail.com")
if err != nil {
t.Fatalf("exp nil err; got %v", err)
}
}
// Return err from service when
// extended reports invalid
// service is disabled for a known invalid address
{
testResVal.Store(`{"valid": true}`)
cfg := conf.MailerConfiguration{
EmailValidationExtended: true,
EmailValidationServiceURL: "",
EmailValidationServiceHeaders: "",
}
if err := cfg.Validate(); err != nil {
t.Fatal(err)
}
ev := newEmailValidator(cfg)
err := ev.Validate(ctx, "test@gmail.com")
if err == nil {
t.Fatal("exp non-nil err")
}
}
// Return err from service when
// extended reports invalid
// service reports valid
{
testResVal.Store(`{"valid": true}`)
cfg := conf.MailerConfiguration{
EmailValidationExtended: true,
EmailValidationServiceURL: ts.URL,
EmailValidationServiceHeaders: testHeaders,
}
if err := cfg.Validate(); err != nil {
t.Fatal(err)
}
ev := newEmailValidator(cfg)
err := ev.Validate(ctx, "test@gmail.com")
if err == nil {
t.Fatal("exp non-nil err")
}
}
// Return err from service when
// extended reports valid
// service reports invalid
{
testResVal.Store(`{"valid": false}`)
cfg := conf.MailerConfiguration{
EmailValidationExtended: true,
EmailValidationServiceURL: ts.URL,
EmailValidationServiceHeaders: testHeaders,
}
if err := cfg.Validate(); err != nil {
t.Fatal(err)
}
ev := newEmailValidator(cfg)
err := ev.Validate(ctx, "chris.stockton@supabase.io")
if err == nil {
t.Fatal("exp non-nil err")
}
}
// Return err from service when
// extended reports invalid
// service reports invalid
{
testResVal.Store(`{"valid": false}`)
cfg := conf.MailerConfiguration{
EmailValidationExtended: false,
EmailValidationServiceURL: ts.URL,
EmailValidationServiceHeaders: testHeaders,
}
if err := cfg.Validate(); err != nil {
t.Fatal(err)
}
ev := newEmailValidator(cfg)
err := ev.Validate(ctx, "test@gmail.com")
if err == nil {
t.Fatal("exp non-nil err")
}
}
}
func TestValidateEmailExtended(t *testing.T) {
ctx := context.Background()
ctx, cancel := context.WithTimeout(ctx, time.Second*60)
defer cancel()
cases := []struct {
email string
timeout time.Duration
err string
}{
// valid (has mx record)
{email: "a@supabase.io"},
{email: "support@supabase.io"},
{email: "chris.stockton@supabase.io"},
// bad format
{email: "", err: "invalid_email_format"},
{email: "io", err: "invalid_email_format"},
{email: "supabase.io", err: "invalid_email_format"},
{email: "@supabase.io", err: "invalid_email_format"},
{email: "test@.supabase.io", err: "invalid_email_format"},
// invalid: valid mx records, but invalid and often typed
// (invalidEmailMap)
{email: "test@email.com", err: "invalid_email_address"},
{email: "test@gmail.com", err: "invalid_email_address"},
{email: "test@test.com", err: "invalid_email_dns"},
// very common typo
{email: "test@gamil.com", err: "invalid_email_dns"},
// invalid: valid mx records, but invalid and often typed
// (invalidHostMap)
{email: "a@example.com", err: "invalid_email_dns"},
{email: "a@example.net", err: "invalid_email_dns"},
{email: "a@example.org", err: "invalid_email_dns"},
// invalid: no mx records
{email: "a@test", err: "invalid_email_dns"},
{email: "test@local", err: "invalid_email_dns"},
{email: "test@test.local", err: "invalid_email_dns"},
{email: "test@example", err: "invalid_email_dns"},
{email: "test@invalid", err: "invalid_email_dns"},
// valid but not actually valid and typed a lot
{email: "a@invalid", err: "invalid_email_dns"},
{email: "a@a.invalid", err: "invalid_email_dns"},
{email: "test@invalid", err: "invalid_email_dns"},
// various invalid emails
{email: "test@test.localhost", err: "invalid_email_dns"},
{email: "test@invalid.example.com", err: "invalid_email_dns"},
{email: "test@no.such.email.host.supabase.io", err: "invalid_email_dns"},
// this low timeout should simulate a dns timeout, which should
// not be treated as an invalid email.
{email: "validemail@probablyaaaaaaaanotarealdomain.com",
timeout: time.Millisecond},
// likewise for a valid email
{email: "support@supabase.io", timeout: time.Millisecond},
}
cfg := conf.MailerConfiguration{
EmailValidationExtended: true,
EmailValidationServiceURL: "",
EmailValidationServiceHeaders: "",
}
ev := newEmailValidator(cfg)
for idx, tc := range cases {
func(timeout time.Duration) {
if timeout == 0 {
timeout = validateEmailTimeout
}
ctx, cancel := context.WithTimeout(ctx, timeout)
defer cancel()
now := time.Now()
err := ev.Validate(ctx, tc.email)
dur := time.Since(now)
if max := timeout + (time.Millisecond * 50); max < dur {
t.Fatal("timeout was not respected")
}
t.Logf("tc #%v - email %q", idx, tc.email)
if tc.err != "" {
require.Error(t, err)
require.Contains(t, err.Error(), tc.err)
return
}
require.NoError(t, err)
}(tc.timeout)
}
}