Files
hanko/backend/test/mailslurper.go
Matthew H. Irby 97ba5cff99 1030 - Refactor SMTP settings to be outside of passcode config (#1121)
* 1030 - Refactor SMTP settings to be outside of passcode config

* Backwards compatibility of SMTP settings

* Do not error if root smtp and passcode smtp are defined. Log warning instead

* Update warning message
2024-01-30 09:34:10 +01:00

185 lines
4.4 KiB
Go

package test
import (
"bytes"
"encoding/json"
"fmt"
"github.com/google/uuid"
"github.com/ory/dockertest/v3"
"github.com/ory/dockertest/v3/docker"
"io"
"net/http"
"net/smtp"
"time"
)
type TestMailslurper struct {
Id string
pool *dockertest.Pool
resource *dockertest.Resource
httpUrl string
SmtpHost string
SmtpPort string
}
func StartMailslurper() (*TestMailslurper, error) {
pool, err := dockertest.NewPool("")
if err != nil {
return nil, fmt.Errorf("could not construct pool: %w", err)
}
err = pool.Client.Ping()
if err != nil {
return nil, fmt.Errorf("could not connect to docker: %w", err)
}
id := uuid.New().String()
options := getMailslurperOptions(id)
if err != nil {
return nil, fmt.Errorf("could not create docker run options: %w", err)
}
resource, err := pool.RunWithOptions(options, func(config *docker.HostConfig) {
config.AutoRemove = true
config.RestartPolicy = docker.RestartPolicy{Name: "no"}
})
if err != nil {
return nil, fmt.Errorf("could not start resource: %w", err)
}
hostAndPort := resource.GetHostPort("8085/tcp")
dsn := fmt.Sprintf("http://%s", hostAndPort)
_ = resource.Expire(120)
pool.MaxWait = 30 * time.Second
if err = pool.Retry(func() error {
_, err = http.Get(fmt.Sprintf("%s/mail", dsn))
return err
}); err != nil {
return nil, fmt.Errorf("could not connect to docker: %w", err)
}
smtpPort := resource.GetPort("2500/tcp")
smtpHostAndPort := resource.GetHostPort("2500/tcp")
if err = pool.Retry(func() error {
client, err := smtp.Dial(fmt.Sprintf("%s", smtpHostAndPort))
defer client.Close()
return err
}); err != nil {
return nil, fmt.Errorf("could not connect to SMTP port: %w", err)
}
return &TestMailslurper{
Id: id,
pool: pool,
resource: resource,
httpUrl: dsn,
SmtpHost: "localhost",
SmtpPort: smtpPort,
}, nil
}
func PurgeMailslurper(instance *TestMailslurper) error {
if instance == nil {
return nil
}
if err := instance.pool.Purge(instance.resource); err != nil {
return fmt.Errorf("could not purge resource: %w", err)
}
return nil
}
func getMailslurperOptions(id string) *dockertest.RunOptions {
return &dockertest.RunOptions{
Repository: "marcopas/docker-mailslurper",
Tag: "latest",
ExposedPorts: []string{
"8085/tcp",
"2500/tcp",
},
Name: fmt.Sprintf("mailslurper-%s", id),
}
}
type GetEmailResponse struct {
MailItems []GetEmailResponseMailItem `json:"mailItems"`
TotalRecords int `json:"totalRecords"`
}
type GetEmailResponseMailItem struct {
Id string `json:"id"`
DateSent string `json:"dateSent"`
FromAddress string `json:"fromAddress"`
ToAddresses []string `json:"toAddresses"`
Subject string `json:"subject"`
Body string `json:"body"`
ContentType string `json:"contentType"`
}
func (m *TestMailslurper) GetEmails() (*GetEmailResponse, error) {
m.addBuffer()
response, err := http.Get(fmt.Sprintf("%s/mail", m.httpUrl))
if err != nil {
return nil, fmt.Errorf("failed to get emails from mailslurper: %w", err)
}
defer response.Body.Close()
body, err := io.ReadAll(response.Body)
if err != nil {
return nil, fmt.Errorf("failed to read response body: %w", err)
}
var result GetEmailResponse
if err := json.Unmarshal(body, &result); err != nil {
return nil, fmt.Errorf("failed to unmarshal response body: %w", err)
}
return &result, nil
}
type DeleteEmailsRequest struct {
PruneCode string `json:"pruneCode" required:"true"`
}
func (m *TestMailslurper) DeleteEmails() error {
m.addBuffer()
request := DeleteEmailsRequest{
PruneCode: "all",
}
bodyJson, err := json.Marshal(request)
if err != nil {
return fmt.Errorf("failed to marshal request body: %w", err)
}
httpReq, err := http.NewRequest(http.MethodDelete, fmt.Sprintf("%s/mail", m.httpUrl), bytes.NewReader(bodyJson))
httpReq.Header.Set("Content-Type", "application/json")
if err != nil {
return fmt.Errorf("failed to create request: %w", err)
}
client := http.Client{}
response, err := client.Do(httpReq)
defer response.Body.Close()
if err != nil {
return fmt.Errorf("failed to delete emails from mailslurper: %w", err)
}
if response.StatusCode != http.StatusOK {
return fmt.Errorf("failed to delete emails from mailslurper: %w", err)
}
return nil
}
func (m *TestMailslurper) addBuffer() {
// Allow buffer time for HTTP server to catch up with received emails
time.Sleep(15 * time.Millisecond)
}