mirror of
https://github.com/1f349/lotus.git
synced 2024-12-21 23:54:10 +00:00
Start writing tests
This commit is contained in:
parent
34244834b8
commit
b35b25c11c
@ -2,11 +2,11 @@ package api
|
||||
|
||||
import (
|
||||
"github.com/1f349/lotus/imap"
|
||||
"github.com/1f349/lotus/smtp"
|
||||
"github.com/1f349/lotus/sendmail"
|
||||
)
|
||||
|
||||
type Smtp interface {
|
||||
Send(mail *smtp.Mail) error
|
||||
Send(mail *sendmail.Mail) error
|
||||
}
|
||||
|
||||
type Imap interface {
|
||||
|
@ -5,7 +5,7 @@ import (
|
||||
"errors"
|
||||
"fmt"
|
||||
postfixLookup "github.com/1f349/lotus/postfix-lookup"
|
||||
"github.com/1f349/lotus/smtp"
|
||||
"github.com/1f349/lotus/sendmail"
|
||||
"github.com/julienschmidt/httprouter"
|
||||
"log"
|
||||
"net/http"
|
||||
@ -26,7 +26,7 @@ func MessageSender(send Smtp) func(rw http.ResponseWriter, req *http.Request, pa
|
||||
}
|
||||
|
||||
// parse json body
|
||||
var j smtp.Json
|
||||
var j sendmail.Json
|
||||
err := json.NewDecoder(req.Body).Decode(&j)
|
||||
if err != nil {
|
||||
apiError(rw, http.StatusBadRequest, "Invalid JSON body")
|
||||
|
@ -1,14 +1,16 @@
|
||||
package api
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"bytes"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
postfixLookup "github.com/1f349/lotus/postfix-lookup"
|
||||
"github.com/1f349/lotus/smtp"
|
||||
"github.com/1f349/lotus/sendmail"
|
||||
"github.com/MrMelon54/mjwt/auth"
|
||||
"github.com/MrMelon54/mjwt/claims"
|
||||
"github.com/emersion/go-message/mail"
|
||||
"github.com/golang-jwt/jwt/v4"
|
||||
"github.com/julienschmidt/httprouter"
|
||||
"github.com/stretchr/testify/assert"
|
||||
@ -37,16 +39,31 @@ func init() {
|
||||
}
|
||||
|
||||
type fakeSmtp struct {
|
||||
from string
|
||||
deliver []string
|
||||
from *mail.Address
|
||||
body []byte
|
||||
}
|
||||
|
||||
func (f *fakeSmtp) Send(mail *smtp.Mail) error {
|
||||
if mail.From != f.from {
|
||||
func (f *fakeSmtp) Send(mail *sendmail.Mail) error {
|
||||
// remove the Bcc header line
|
||||
s := bufio.NewScanner(bytes.NewReader(mail.Body))
|
||||
b := new(bytes.Buffer)
|
||||
b.Grow(len(mail.Body))
|
||||
for s.Scan() {
|
||||
a := s.Text()
|
||||
if strings.HasPrefix(a, "Bcc:") {
|
||||
continue
|
||||
}
|
||||
b.WriteString(a + "\r\n")
|
||||
}
|
||||
if err := s.Err(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// check values are the same
|
||||
if mail.From.String() != f.from.String() {
|
||||
return fmt.Errorf("test fail: invalid from address")
|
||||
}
|
||||
if !slices.Equal(mail.Body, f.body) {
|
||||
if !slices.Equal(b.Bytes(), f.body) {
|
||||
return fmt.Errorf("test fail: invalid message body")
|
||||
}
|
||||
return nil
|
||||
@ -54,7 +71,7 @@ func (f *fakeSmtp) Send(mail *smtp.Mail) error {
|
||||
|
||||
type fakeFailedSmtp struct{}
|
||||
|
||||
func (f *fakeFailedSmtp) Send(mail *smtp.Mail) error {
|
||||
func (f *fakeFailedSmtp) Send(mail *sendmail.Mail) error {
|
||||
return errors.New("sending failed")
|
||||
}
|
||||
|
||||
@ -85,7 +102,7 @@ var messageSenderTestData = []struct {
|
||||
},
|
||||
{
|
||||
req: func() (*http.Request, error) {
|
||||
j, err := json.Marshal(smtp.Json{
|
||||
j, err := json.Marshal(sendmail.Json{
|
||||
From: "noreply2@example.com",
|
||||
ReplyTo: "admin@example.com",
|
||||
To: "user@example.com",
|
||||
@ -105,7 +122,7 @@ var messageSenderTestData = []struct {
|
||||
},
|
||||
{
|
||||
req: func() (*http.Request, error) {
|
||||
j, err := json.Marshal(smtp.Json{
|
||||
j, err := json.Marshal(sendmail.Json{
|
||||
From: "user@example.com",
|
||||
ReplyTo: "admin@example.com",
|
||||
To: "user@example.com",
|
||||
@ -125,7 +142,7 @@ var messageSenderTestData = []struct {
|
||||
},
|
||||
{
|
||||
req: func() (*http.Request, error) {
|
||||
j, err := json.Marshal(smtp.Json{
|
||||
j, err := json.Marshal(sendmail.Json{
|
||||
From: "noreply@example.com, user2@example.com",
|
||||
ReplyTo: "admin@example.com",
|
||||
To: "user@example.com",
|
||||
@ -145,7 +162,7 @@ var messageSenderTestData = []struct {
|
||||
},
|
||||
{
|
||||
req: func() (*http.Request, error) {
|
||||
j, err := json.Marshal(smtp.Json{
|
||||
j, err := json.Marshal(sendmail.Json{
|
||||
From: "noreply@example.com",
|
||||
ReplyTo: "admin@example.com",
|
||||
To: "user@example.com",
|
||||
@ -165,7 +182,7 @@ var messageSenderTestData = []struct {
|
||||
},
|
||||
{
|
||||
req: func() (*http.Request, error) {
|
||||
j, err := json.Marshal(smtp.Json{
|
||||
j, err := json.Marshal(sendmail.Json{
|
||||
From: "noreply@example.com",
|
||||
ReplyTo: "admin@example.com",
|
||||
To: "a <user@example.com",
|
||||
@ -185,7 +202,7 @@ var messageSenderTestData = []struct {
|
||||
},
|
||||
{
|
||||
req: func() (*http.Request, error) {
|
||||
j, err := json.Marshal(smtp.Json{
|
||||
j, err := json.Marshal(sendmail.Json{
|
||||
From: "noreply@example.com",
|
||||
ReplyTo: "admin@example.com",
|
||||
To: "a <user>",
|
||||
@ -205,7 +222,7 @@ var messageSenderTestData = []struct {
|
||||
},
|
||||
{
|
||||
req: func() (*http.Request, error) {
|
||||
j, err := json.Marshal(smtp.Json{
|
||||
j, err := json.Marshal(sendmail.Json{
|
||||
From: "noreply@example.com",
|
||||
ReplyTo: "admin@example.com",
|
||||
To: "user@example.com",
|
||||
@ -225,7 +242,7 @@ var messageSenderTestData = []struct {
|
||||
},
|
||||
{
|
||||
req: func() (*http.Request, error) {
|
||||
j, err := json.Marshal(smtp.Json{
|
||||
j, err := json.Marshal(sendmail.Json{
|
||||
From: "noreply@example.com",
|
||||
ReplyTo: "admin@example.com",
|
||||
To: "user@example.com",
|
||||
@ -241,8 +258,7 @@ var messageSenderTestData = []struct {
|
||||
return http.NewRequest(http.MethodPost, "https://api.example.com/v1/mail/message", bytes.NewReader(j))
|
||||
},
|
||||
smtp: &fakeSmtp{
|
||||
from: "noreply@example.com",
|
||||
deliver: []string{"user@example.com", "user2@example.com", "user3@example.com"},
|
||||
from: &mail.Address{Address: "noreply@example.com"},
|
||||
body: []byte("Mime-Version: 1.0\r\n" +
|
||||
"Content-Type: text/plain; charset=utf-8\r\n" +
|
||||
"Cc: <user2@example.com>\r\n" +
|
||||
@ -252,7 +268,7 @@ var messageSenderTestData = []struct {
|
||||
"Subject: Test Subject\r\n" +
|
||||
"Date: Sat, 01 Jan 2000 00:00:00 +0000\r\n" +
|
||||
"\r\n" +
|
||||
"Some plain text"),
|
||||
"Some plain text\r\n"),
|
||||
},
|
||||
claims: makeFakeAuthClaims("admin@example.com"),
|
||||
status: http.StatusAccepted,
|
||||
|
@ -2,12 +2,12 @@ package main
|
||||
|
||||
import (
|
||||
"github.com/1f349/lotus/imap"
|
||||
"github.com/1f349/lotus/smtp"
|
||||
"github.com/1f349/lotus/sendmail"
|
||||
)
|
||||
|
||||
type Conf struct {
|
||||
Listen string `yaml:"listen"`
|
||||
Audience string `yaml:"audience"`
|
||||
Smtp *smtp.Smtp `yaml:"smtp"`
|
||||
Smtp *sendmail.Smtp `yaml:"sendmail"`
|
||||
Imap *imap.Imap `yaml:"imap"`
|
||||
}
|
||||
|
@ -1,4 +1,4 @@
|
||||
package smtp
|
||||
package sendmail
|
||||
|
||||
import (
|
||||
"bytes"
|
@ -1,4 +1,4 @@
|
||||
package smtp
|
||||
package sendmail
|
||||
|
||||
import (
|
||||
"github.com/emersion/go-message/mail"
|
||||
@ -6,7 +6,7 @@ import (
|
||||
)
|
||||
|
||||
type Smtp struct {
|
||||
Server string `yaml:"server"`
|
||||
SendMailCommand string `json:"send_mail_command"`
|
||||
}
|
||||
|
||||
type Mail struct {
|
||||
@ -14,13 +14,14 @@ type Mail struct {
|
||||
Body []byte
|
||||
}
|
||||
|
||||
var execSendMail = func(from string) *exec.Cmd {
|
||||
return exec.Command("/usr/lib/sendmail", "-f", from, "-t")
|
||||
}
|
||||
var execCommand = exec.Command
|
||||
|
||||
func (s *Smtp) Send(mail *Mail) error {
|
||||
// start sendmail caller
|
||||
sendMail := execSendMail(mail.From.String())
|
||||
if s.SendMailCommand == "" {
|
||||
s.SendMailCommand = "/usr/sbin/sendmail"
|
||||
}
|
||||
sendMail := execCommand(s.SendMailCommand, "-f", mail.From.Address, "-t")
|
||||
inPipe, err := sendMail.StdinPipe()
|
||||
if err != nil {
|
||||
return err
|
||||
@ -36,5 +37,6 @@ func (s *Smtp) Send(mail *Mail) error {
|
||||
return err
|
||||
}
|
||||
|
||||
// run command
|
||||
return sendMail.Run()
|
||||
}
|
67
sendmail/sendmail_test.go
Normal file
67
sendmail/sendmail_test.go
Normal file
@ -0,0 +1,67 @@
|
||||
package sendmail
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"github.com/emersion/go-message"
|
||||
"github.com/emersion/go-message/mail"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"log"
|
||||
"net"
|
||||
"os"
|
||||
"os/exec"
|
||||
"strings"
|
||||
"testing"
|
||||
"time"
|
||||
)
|
||||
|
||||
var sendTestMessage []byte
|
||||
|
||||
func init() {
|
||||
var h mail.Header
|
||||
h.SetDate(time.Date(2000, time.January, 1, 0, 0, 0, 0, time.Local))
|
||||
h.SetSubject("Happy Millennium")
|
||||
h.SetAddressList("From", []*mail.Address{{Name: "Test", Address: "test@localhost"}})
|
||||
h.SetAddressList("To", []*mail.Address{{Name: "A", Address: "a@localhost"}})
|
||||
h.Set("Content-Type", "text/plain; charset=utf-8")
|
||||
entity, err := message.New(h.Header, strings.NewReader("Thanks"))
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
out := new(bytes.Buffer)
|
||||
if entity.WriteTo(out) != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
sendTestMessage = out.Bytes()
|
||||
}
|
||||
|
||||
func TestSmtp_Send(t *testing.T) {
|
||||
execCommand = func(name string, arg ...string) *exec.Cmd {
|
||||
cs := append([]string{"-test.run=TestHelperProcess", "--", name}, arg...)
|
||||
cmd := exec.Command(os.Args[0], cs...)
|
||||
cmd.Env = []string{"GO_WANT_HELPER_PROCESS=1"}
|
||||
return cmd
|
||||
}
|
||||
defer func() { execCommand = exec.Command }()
|
||||
|
||||
m := &Mail{From: &mail.Address{Address: "test@localhost"}, Body: sendTestMessage}
|
||||
|
||||
temp, err := os.CreateTemp("", "sendmail")
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
addr, err := net.ResolveUnixAddr("")
|
||||
assert.NoError(t, err)
|
||||
listen, err := net.ListenUnix("", addr)
|
||||
assert.NoError(t, err)
|
||||
|
||||
s := &Smtp{SendMailCommand: "/tmp/sendmailXXXXX"}
|
||||
assert.NoError(t, s.Send(m))
|
||||
}
|
||||
|
||||
func TestSmtpHelperProcess(t *testing.T) {
|
||||
if os.Getenv("GO_WANT_HELPER_PROCESS") != "1" {
|
||||
return
|
||||
}
|
||||
|
||||
}
|
@ -1,74 +0,0 @@
|
||||
package smtp
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"github.com/1f349/lotus/smtp/fake"
|
||||
"github.com/emersion/go-message"
|
||||
"github.com/emersion/go-message/mail"
|
||||
"github.com/emersion/go-smtp"
|
||||
"github.com/hydrogen18/memlistener"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"log"
|
||||
"strings"
|
||||
"testing"
|
||||
"time"
|
||||
)
|
||||
|
||||
var sendTestMessage []byte
|
||||
|
||||
func init() {
|
||||
var h mail.Header
|
||||
h.SetDate(time.Date(2000, time.January, 1, 0, 0, 0, 0, time.Local))
|
||||
h.SetSubject("Happy Millennium")
|
||||
h.SetAddressList("From", []*mail.Address{{Name: "Test", Address: "test@localhost"}})
|
||||
h.SetAddressList("To", []*mail.Address{{Name: "A", Address: "a@localhost"}})
|
||||
h.Set("Content-Type", "text/plain; charset=utf-8")
|
||||
entity, err := message.New(h.Header, strings.NewReader("Thanks"))
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
out := new(bytes.Buffer)
|
||||
if entity.WriteTo(out) != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
sendTestMessage = out.Bytes()
|
||||
}
|
||||
|
||||
func TestSmtp_Send(t *testing.T) {
|
||||
listener := memlistener.NewMemoryListener()
|
||||
serverData := make(chan []byte, 4)
|
||||
server := smtp.NewServer(&fake.SmtpBackend{Debug: serverData})
|
||||
go func() {
|
||||
_ = server.Serve(listener)
|
||||
}()
|
||||
|
||||
defaultDialer = func(addr string) (*smtp.Client, error) {
|
||||
dial, err := listener.Dial("", "")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return smtp.NewClient(dial, "localhost")
|
||||
}
|
||||
|
||||
s := &Smtp{Server: "localhost:25"}
|
||||
err := s.Send(&Mail{From: "test@localhost", Deliver: []string{"a@localhost", "b@localhost"}, Body: sendTestMessage})
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, []byte("MAIL test@localhost\n"), <-serverData)
|
||||
assert.Equal(t, []byte("RCPT a@localhost\n"), <-serverData)
|
||||
assert.Equal(t, []byte("RCPT b@localhost\n"), <-serverData)
|
||||
assert.Equal(t, append(sendTestMessage, '\r', '\n'), <-serverData)
|
||||
}
|
||||
|
||||
func TestCreateSenderSlice(t *testing.T) {
|
||||
a := []*mail.Address{{Address: "a@example.com"}, {Address: "b@example.com"}}
|
||||
b := []*mail.Address{{Address: "a@example.com"}, {Address: "c@example.com"}}
|
||||
c := []*mail.Address{{Address: "a@example.com"}, {Address: "d@example.com"}}
|
||||
assert.Equal(t, []string{
|
||||
"a@example.com",
|
||||
"b@example.com",
|
||||
"a@example.com",
|
||||
"c@example.com",
|
||||
"a@example.com",
|
||||
"d@example.com",
|
||||
}, CreateSenderSlice(a, b, c))
|
||||
}
|
Loading…
Reference in New Issue
Block a user