package postcard import ( "context" "strings" "testing" "testing/fstest" ) func TestMailRecipientsAndSafety(t *testing.T) { t.Parallel() fsys := fstest.MapFS{ "views/mail/hello.htm": {Data: []byte(`subject = "Witaj {{ .Name }}" layout = "default" == Witaj **{{ .Name }}**. [Strona]({{ .URL }}) `)}, } cat := NewCatalog() if err := cat.Register("golem15.hello", fsys, []string{"golem15.hello::mail.hello"}, nil); err != nil { t.Fatal(err) } drv := NewMemoryDriver() mail := NewMailer(cat, drv, Options{From: "from@example.test"}) ctx := context.Background() if err := mail.Send(ctx, Message{ Template: "golem15.hello::mail.hello", To: []string{"ada@example.test"}, Cc: []string{"cc@example.test"}, Bcc: []string{"bcc@example.test"}, ReplyTo: "reply@example.test", Vars: map[string]any{"Name": "Ada", "URL": "https://example.test"}, }); err != nil { t.Fatal(err) } got := drv.Messages() if len(got) != 1 { t.Fatalf("stored %d messages", len(got)) } msg := got[0] if len(msg.To) != 1 || msg.To[0] != "ada@example.test" { t.Fatalf("To = %v", msg.To) } if len(msg.Cc) != 1 || msg.Cc[0] != "cc@example.test" { t.Fatalf("Cc = %v", msg.Cc) } if len(msg.Bcc) != 1 || msg.Bcc[0] != "bcc@example.test" { t.Fatalf("Bcc = %v", msg.Bcc) } if msg.ReplyTo != "reply@example.test" { t.Fatalf("ReplyTo = %q", msg.ReplyTo) } if msg.Subject != "Witaj Ada" { t.Fatalf("subject = %q", msg.Subject) } if !strings.Contains(msg.Text, "Witaj **Ada**.") { t.Fatalf("text = %q", msg.Text) } if !strings.Contains(msg.HTML, "Ada") || !strings.Contains(msg.HTML, `href="https://example.test"`) { t.Fatalf("html = %q", msg.HTML) } t.Run("raw tags markdown links and dangerous urls stay out of html", func(t *testing.T) { cases := []map[string]any{ {"Name": ``, "URL": "https://example.test"}, {"Name": "Ada", "URL": "javascript:alert(1)"}, {"Name": "Ada", "URL": "vbscript:msgbox(1)"}, {"Name": "Ada", "URL": "data:text/html;base64,PGh0bWw+"}, {"Name": ``, "URL": "https://example.test"}, } for _, vars := range cases { drv := NewMemoryDriver() mail := NewMailer(cat, drv, Options{From: "from@example.test"}) err := mail.Send(ctx, Message{ Template: "golem15.hello::mail.hello", To: []string{"ada@example.test"}, Vars: vars, }) if err != nil { if strings.Contains(err.Error(), "unsafe") || strings.Contains(err.Error(), "dangerous") { continue } t.Fatalf("unexpected send error for %v: %v", vars, err) } html := strings.ToLower(drv.Messages()[0].HTML) for _, banned := range []string{"