package email import ( "crypto/tls" "fmt" "io" "net/smtp" "os" "testing" "github.com/joho/godotenv" "github.com/kelseyhightower/envconfig" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" ) type config struct { MailUser string `required:"false" split_words:"true"` MailPassword string `required:"false" split_words:"true"` MailHost string `required:"false" split_words:"true"` MailPort string `required:"false" split_words:"true"` MailFrom string `required:"false" split_words:"true"` MailTo string `required:"false" split_words:"true"` } func newConfig(envFile string) *config { if envFile != "" { err := godotenv.Load(envFile) if err != nil { panic(fmt.Errorf("godotenv.Load: %w", err)) } } cfg := &config{} err := envconfig.Process("", cfg) if err != nil { panic(fmt.Errorf("envconfig.Process: %w", err)) } return cfg } type mockWriter struct{} func (w *mockWriter) Close() error { return nil } func (w *mockWriter) Write(p []byte) (n int, err error) { return 10, nil } // Mock SMTP Client type mockSMTP struct{} func (m *mockSMTP) StartTLS(*tls.Config) error { return nil } func (m *mockSMTP) Auth(a smtp.Auth) error { return nil } func (m *mockSMTP) Close() error { return nil } func (m *mockSMTP) Data() (io.WriteCloser, error) { return &mockWriter{}, nil } func (m *mockSMTP) Mail(from string) error { return nil } func (m *mockSMTP) Quit() error { return nil } func (m *mockSMTP) Rcpt(to string) error { return nil } func TestMockSendEmail(t *testing.T) { service := &EmailService{ auth: smtp.PlainAuth("", "", "", ""), host: "", port: "", from: "", tlsconfig: &tls.Config{ InsecureSkipVerify: true, ServerName: "", }, dial: func(hostPort string) (smtpClient, error) { return &mockSMTP{}, nil }, } emailData := EmailMessage{ To: "test@example.com", Subject: "Test Email", Body: "This is a test email.", } err := service.SendEmail(emailData) if err != nil { t.Fatalf("expected no error, got %v", err) } } func TestSendEmail(t *testing.T) { cfg := newConfig(".env.test") mailSrv := NewMailService(MailServiceConfig{ Auth: smtp.PlainAuth("", cfg.MailUser, cfg.MailPassword, cfg.MailHost), Host: cfg.MailHost, Port: cfg.MailPort, From: cfg.MailFrom, }) data := EmailMessage{ To: cfg.MailTo, Subject: "Mail Sender", Body: "Hello this is a test email", } require.NoError(t, mailSrv.SendEmail(data)) } func TestSendEmailWithAttachments(t *testing.T) { cfg := newConfig(".env.test") mailSrv := NewMailService(MailServiceConfig{ Auth: smtp.PlainAuth("", cfg.MailUser, cfg.MailPassword, cfg.MailHost), Host: cfg.MailHost, Port: cfg.MailPort, From: cfg.MailFrom, }) reader, err := os.Open("testdata/attachment1.txt") require.NoError(t, err) defer reader.Close() reader2, err := os.Open("testdata/attachment2.txt") require.NoError(t, err) defer reader2.Close() reader3, err := os.Open("testdata/attachment3.txt") require.NoError(t, err) defer reader3.Close() data := EmailMessage{ To: cfg.MailTo, Subject: "Mail Sender", Body: "Hello this is a test email", Attachments: []EmailAttachment{ { Title: "attachment1.txt", File: reader, }, { Title: "attachment2.txt", File: reader2, }, { Title: "attachment3.txt", File: reader3, }, }, } err = mailSrv.SendEmail(data) require.NoError(t, err) } func TestWithAttachments(t *testing.T) { msg := newMessage("from", "to", "subject") content, err := msg.withAttachments("body", nil) require.NoError(t, err) assert.Greater(t, len(content), 0) }