- docs/database: models, migrations, queries and pagination, relations, casts and validation, attachments and transactions (lagoon.Transaction, lagoon.AfterCommit, nested savepoints, lagoon.OnDatabase) - docs/services: configuration, events, routing with auth groups, rate limiting, authentication, the OAuth server, mail and localization - runnable Examples for lagoon, attach, compass, surf, wire, bouncer, wristband, postcard, phrasebook and festival; lagoon TestDocs* regions run on the package's Postgres harness through DocsDB - 15 new required pages
74 lines
2.0 KiB
Go
74 lines
2.0 KiB
Go
package postcard_test
|
|
|
|
import (
|
|
"context"
|
|
"fmt"
|
|
"strings"
|
|
"testing/fstest"
|
|
|
|
"git.golem15.com/golem15/summercms/modules/postcard"
|
|
)
|
|
|
|
// mailFS stands in for the plugin's embedded views/mail directory.
|
|
var mailFS = fstest.MapFS{
|
|
"views/mail/welcome.htm": {Data: []byte(`subject = "Welcome, {{ .name }}"
|
|
layout = "blog"
|
|
description = "Sent after registration"
|
|
==
|
|
Hi **{{ .name }}**, thanks for joining the blog.
|
|
`)},
|
|
"views/mail/layouts/blog.htm": {Data: []byte(`name = "Blog"
|
|
==
|
|
{{ .Content }}
|
|
|
|
-- The Acme blog
|
|
==
|
|
<div class="blog-mail">{{ .Content }}</div>
|
|
<style>{{ .brandCss }}{{ .css }}</style>
|
|
`)},
|
|
}
|
|
|
|
func ExampleMailer_Send() {
|
|
// At boot, postcard.BootPlugin registers what pact.HasMailTemplates
|
|
// declares; a test registers the same thing directly.
|
|
cat := postcard.NewCatalog()
|
|
err := cat.Register("acme.blog", mailFS,
|
|
[]string{"acme.blog::mail.welcome"},
|
|
map[string]string{"blog": "acme.blog::mail.layouts.blog"})
|
|
if err != nil {
|
|
fmt.Println(err)
|
|
return
|
|
}
|
|
driver := postcard.NewMemoryDriver() // mail.driver: memory
|
|
mailer := postcard.NewMailer(cat, driver, postcard.Options{From: "blog@example.com"})
|
|
|
|
err = mailer.Send(context.Background(), postcard.Message{
|
|
Template: "acme.blog::mail.welcome",
|
|
To: []string{"ada@example.com"},
|
|
Vars: map[string]any{"name": "Ada"},
|
|
})
|
|
if err != nil {
|
|
fmt.Println(err)
|
|
return
|
|
}
|
|
sent := driver.Messages()[0]
|
|
fmt.Println(sent.From, sent.To, sent.Subject)
|
|
fmt.Println(sent.Text)
|
|
fmt.Println(strings.Contains(sent.HTML, `<div class="blog-mail"><p>Hi <strong>Ada</strong>`))
|
|
|
|
// Header injection is refused before any driver sees the message.
|
|
err = mailer.Send(context.Background(), postcard.Message{
|
|
Template: "acme.blog::mail.welcome",
|
|
To: []string{"ada@example.com\r\nBcc: all@example.com"},
|
|
Vars: map[string]any{"name": "Ada"},
|
|
})
|
|
fmt.Println(err != nil, len(driver.Messages()))
|
|
// Output:
|
|
// blog@example.com [ada@example.com] Welcome, Ada
|
|
// Hi **Ada**, thanks for joining the blog.
|
|
//
|
|
// -- The Acme blog
|
|
// true
|
|
// true 1
|
|
}
|