diff --git a/internal/api/client/account/account_test.go b/internal/api/client/account/account_test.go index 9dc27457a..8e9bc132a 100644 --- a/internal/api/client/account/account_test.go +++ b/internal/api/client/account/account_test.go @@ -31,6 +31,7 @@ type AccountStandardTestSuite struct { federator federation.Federator processor processing.Processor emailSender email.Sender + sentEmails map[string]string // standard suite models testTokens map[string]*gtsmodel.Token @@ -61,7 +62,8 @@ func (suite *AccountStandardTestSuite) SetupTest() { suite.storage = testrig.NewTestStorage() testrig.InitTestLog() suite.federator = testrig.NewTestFederator(suite.db, testrig.NewTestTransportController(testrig.NewMockHTTPClient(nil), suite.db), suite.storage) - suite.emailSender = testrig.NewEmailSender("../../../../web/template/") + suite.sentEmails = make(map[string]string) + suite.emailSender = testrig.NewEmailSender("../../../../web/template/", suite.sentEmails) suite.processor = testrig.NewTestProcessor(suite.db, suite.storage, suite.federator, suite.emailSender) suite.accountModule = account.New(suite.config, suite.processor).(*account.Module) testrig.StandardDBSetup(suite.db, nil) diff --git a/internal/api/client/fileserver/servefile_test.go b/internal/api/client/fileserver/servefile_test.go index 0d21d1231..ab5cfadf2 100644 --- a/internal/api/client/fileserver/servefile_test.go +++ b/internal/api/client/fileserver/servefile_test.go @@ -80,7 +80,7 @@ func (suite *ServeFileTestSuite) SetupSuite() { testrig.InitTestLog() suite.storage = testrig.NewTestStorage() suite.federator = testrig.NewTestFederator(suite.db, testrig.NewTestTransportController(testrig.NewMockHTTPClient(nil), suite.db), suite.storage) - suite.emailSender = testrig.NewEmailSender("../../../../web/template/") + suite.emailSender = testrig.NewEmailSender("../../../../web/template/", nil) suite.processor = testrig.NewTestProcessor(suite.db, suite.storage, suite.federator, suite.emailSender) suite.tc = testrig.NewTestTypeConverter(suite.db) diff --git a/internal/api/client/followrequest/followrequest_test.go b/internal/api/client/followrequest/followrequest_test.go index 98c69f22b..94f6cbb0e 100644 --- a/internal/api/client/followrequest/followrequest_test.go +++ b/internal/api/client/followrequest/followrequest_test.go @@ -75,7 +75,7 @@ func (suite *FollowRequestStandardTestSuite) SetupTest() { suite.db = testrig.NewTestDB() suite.storage = testrig.NewTestStorage() suite.federator = testrig.NewTestFederator(suite.db, testrig.NewTestTransportController(testrig.NewMockHTTPClient(nil), suite.db), suite.storage) - suite.emailSender = testrig.NewEmailSender("../../../../web/template/") + suite.emailSender = testrig.NewEmailSender("../../../../web/template/", nil) suite.processor = testrig.NewTestProcessor(suite.db, suite.storage, suite.federator, suite.emailSender) suite.followRequestModule = followrequest.New(suite.config, suite.processor).(*followrequest.Module) testrig.StandardDBSetup(suite.db, nil) diff --git a/internal/api/client/media/mediacreate_test.go b/internal/api/client/media/mediacreate_test.go index 7e7f80b48..2bc598499 100644 --- a/internal/api/client/media/mediacreate_test.go +++ b/internal/api/client/media/mediacreate_test.go @@ -86,7 +86,7 @@ func (suite *MediaCreateTestSuite) SetupSuite() { suite.mediaHandler = testrig.NewTestMediaHandler(suite.db, suite.storage) suite.oauthServer = testrig.NewTestOauthServer(suite.db) suite.federator = testrig.NewTestFederator(suite.db, testrig.NewTestTransportController(testrig.NewMockHTTPClient(nil), suite.db), suite.storage) - suite.emailSender = testrig.NewEmailSender("../../../../web/template/") + suite.emailSender = testrig.NewEmailSender("../../../../web/template/", nil) suite.processor = testrig.NewTestProcessor(suite.db, suite.storage, suite.federator, suite.emailSender) // setup module being tested diff --git a/internal/api/client/status/status_test.go b/internal/api/client/status/status_test.go index f47380305..fa8c9823e 100644 --- a/internal/api/client/status/status_test.go +++ b/internal/api/client/status/status_test.go @@ -69,10 +69,11 @@ func (suite *StatusStandardTestSuite) SetupSuite() { func (suite *StatusStandardTestSuite) SetupTest() { suite.config = testrig.NewTestConfig() suite.db = testrig.NewTestDB() + suite.tc = testrig.NewTestTypeConverter(suite.db) suite.storage = testrig.NewTestStorage() testrig.InitTestLog() suite.federator = testrig.NewTestFederator(suite.db, testrig.NewTestTransportController(testrig.NewMockHTTPClient(nil), suite.db), suite.storage) - suite.emailSender = testrig.NewEmailSender("../../../../web/template/") + suite.emailSender = testrig.NewEmailSender("../../../../web/template/", nil) suite.processor = testrig.NewTestProcessor(suite.db, suite.storage, suite.federator, suite.emailSender) suite.statusModule = status.New(suite.config, suite.processor).(*status.Module) testrig.StandardDBSetup(suite.db, nil) diff --git a/internal/api/client/user/user_test.go b/internal/api/client/user/user_test.go index 9ad1185c3..fe420b5c9 100644 --- a/internal/api/client/user/user_test.go +++ b/internal/api/client/user/user_test.go @@ -48,6 +48,8 @@ type UserStandardTestSuite struct { testUsers map[string]*gtsmodel.User testAccounts map[string]*gtsmodel.Account + sentEmails map[string]string + userModule *user.Module } @@ -63,7 +65,8 @@ func (suite *UserStandardTestSuite) SetupTest() { testrig.InitTestLog() suite.tc = testrig.NewTestTypeConverter(suite.db) suite.federator = testrig.NewTestFederator(suite.db, testrig.NewTestTransportController(testrig.NewMockHTTPClient(nil), suite.db), suite.storage) - suite.emailSender = testrig.NewEmailSender("../../../../web/template/") + suite.sentEmails = make(map[string]string) + suite.emailSender = testrig.NewEmailSender("../../../../web/template/", suite.sentEmails) suite.processor = testrig.NewTestProcessor(suite.db, suite.storage, suite.federator, suite.emailSender) suite.userModule = user.New(suite.config, suite.processor).(*user.Module) testrig.StandardDBSetup(suite.db, suite.testAccounts) diff --git a/internal/api/s2s/user/inboxpost_test.go b/internal/api/s2s/user/inboxpost_test.go index 527fcdd50..86b34fe5e 100644 --- a/internal/api/s2s/user/inboxpost_test.go +++ b/internal/api/s2s/user/inboxpost_test.go @@ -85,7 +85,7 @@ func (suite *InboxPostTestSuite) TestPostBlock() { tc := testrig.NewTestTransportController(testrig.NewMockHTTPClient(nil), suite.db) federator := testrig.NewTestFederator(suite.db, tc, suite.storage) - emailSender := testrig.NewEmailSender("../../../../web/template/") + emailSender := testrig.NewEmailSender("../../../../web/template/", nil) processor := testrig.NewTestProcessor(suite.db, suite.storage, federator, emailSender) userModule := user.New(suite.config, processor).(*user.Module) @@ -185,7 +185,7 @@ func (suite *InboxPostTestSuite) TestPostUnblock() { tc := testrig.NewTestTransportController(testrig.NewMockHTTPClient(nil), suite.db) federator := testrig.NewTestFederator(suite.db, tc, suite.storage) - emailSender := testrig.NewEmailSender("../../../../web/template/") + emailSender := testrig.NewEmailSender("../../../../web/template/", nil) processor := testrig.NewTestProcessor(suite.db, suite.storage, federator, emailSender) userModule := user.New(suite.config, processor).(*user.Module) @@ -275,7 +275,7 @@ func (suite *InboxPostTestSuite) TestPostUpdate() { tc := testrig.NewTestTransportController(testrig.NewMockHTTPClient(nil), suite.db) federator := testrig.NewTestFederator(suite.db, tc, suite.storage) - emailSender := testrig.NewEmailSender("../../../../web/template/") + emailSender := testrig.NewEmailSender("../../../../web/template/", nil) processor := testrig.NewTestProcessor(suite.db, suite.storage, federator, emailSender) userModule := user.New(suite.config, processor).(*user.Module) @@ -394,7 +394,7 @@ func (suite *InboxPostTestSuite) TestPostDelete() { tc := testrig.NewTestTransportController(testrig.NewMockHTTPClient(nil), suite.db) federator := testrig.NewTestFederator(suite.db, tc, suite.storage) - emailSender := testrig.NewEmailSender("../../../../web/template/") + emailSender := testrig.NewEmailSender("../../../../web/template/", nil) processor := testrig.NewTestProcessor(suite.db, suite.storage, federator, emailSender) err = processor.Start(context.Background()) suite.NoError(err) diff --git a/internal/api/s2s/user/repliesget_test.go b/internal/api/s2s/user/repliesget_test.go index 85ddd0164..32cd0c366 100644 --- a/internal/api/s2s/user/repliesget_test.go +++ b/internal/api/s2s/user/repliesget_test.go @@ -49,7 +49,7 @@ func (suite *RepliesGetTestSuite) TestGetReplies() { tc := testrig.NewTestTransportController(testrig.NewMockHTTPClient(nil), suite.db) federator := testrig.NewTestFederator(suite.db, tc, suite.storage) - emailSender := testrig.NewEmailSender("../../../../web/template/") + emailSender := testrig.NewEmailSender("../../../../web/template/", nil) processor := testrig.NewTestProcessor(suite.db, suite.storage, federator, emailSender) userModule := user.New(suite.config, processor).(*user.Module) @@ -109,7 +109,7 @@ func (suite *RepliesGetTestSuite) TestGetRepliesNext() { tc := testrig.NewTestTransportController(testrig.NewMockHTTPClient(nil), suite.db) federator := testrig.NewTestFederator(suite.db, tc, suite.storage) - emailSender := testrig.NewEmailSender("../../../../web/template/") + emailSender := testrig.NewEmailSender("../../../../web/template/", nil) processor := testrig.NewTestProcessor(suite.db, suite.storage, federator, emailSender) userModule := user.New(suite.config, processor).(*user.Module) @@ -172,7 +172,7 @@ func (suite *RepliesGetTestSuite) TestGetRepliesLast() { tc := testrig.NewTestTransportController(testrig.NewMockHTTPClient(nil), suite.db) federator := testrig.NewTestFederator(suite.db, tc, suite.storage) - emailSender := testrig.NewEmailSender("../../../../web/template/") + emailSender := testrig.NewEmailSender("../../../../web/template/", nil) processor := testrig.NewTestProcessor(suite.db, suite.storage, federator, emailSender) userModule := user.New(suite.config, processor).(*user.Module) diff --git a/internal/api/s2s/user/user_test.go b/internal/api/s2s/user/user_test.go index e03428188..fc4232bde 100644 --- a/internal/api/s2s/user/user_test.go +++ b/internal/api/s2s/user/user_test.go @@ -77,7 +77,7 @@ func (suite *UserStandardTestSuite) SetupTest() { suite.storage = testrig.NewTestStorage() testrig.InitTestLog() suite.federator = testrig.NewTestFederator(suite.db, testrig.NewTestTransportController(testrig.NewMockHTTPClient(nil), suite.db), suite.storage) - suite.emailSender = testrig.NewEmailSender("../../../../web/template/") + suite.emailSender = testrig.NewEmailSender("../../../../web/template/", nil) suite.processor = testrig.NewTestProcessor(suite.db, suite.storage, suite.federator, suite.emailSender) suite.userModule = user.New(suite.config, suite.processor).(*user.Module) suite.securityModule = security.New(suite.config, suite.db).(*security.Module) diff --git a/internal/api/s2s/user/userget_test.go b/internal/api/s2s/user/userget_test.go index 694b11962..68f16fc76 100644 --- a/internal/api/s2s/user/userget_test.go +++ b/internal/api/s2s/user/userget_test.go @@ -47,7 +47,7 @@ func (suite *UserGetTestSuite) TestGetUser() { tc := testrig.NewTestTransportController(testrig.NewMockHTTPClient(nil), suite.db) federator := testrig.NewTestFederator(suite.db, tc, suite.storage) - emailSender := testrig.NewEmailSender("../../../../web/template/") + emailSender := testrig.NewEmailSender("../../../../web/template/", nil) processor := testrig.NewTestProcessor(suite.db, suite.storage, federator, emailSender) userModule := user.New(suite.config, processor).(*user.Module) diff --git a/internal/api/s2s/webfinger/webfinger_test.go b/internal/api/s2s/webfinger/webfinger_test.go index 3a7697e66..69fd32408 100644 --- a/internal/api/s2s/webfinger/webfinger_test.go +++ b/internal/api/s2s/webfinger/webfinger_test.go @@ -80,7 +80,7 @@ func (suite *WebfingerStandardTestSuite) SetupTest() { suite.storage = testrig.NewTestStorage() testrig.InitTestLog() suite.federator = testrig.NewTestFederator(suite.db, testrig.NewTestTransportController(testrig.NewMockHTTPClient(nil), suite.db), suite.storage) - suite.emailSender = testrig.NewEmailSender("../../../../web/template/") + suite.emailSender = testrig.NewEmailSender("../../../../web/template/", nil) suite.processor = testrig.NewTestProcessor(suite.db, suite.storage, suite.federator, suite.emailSender) suite.webfingerModule = webfinger.New(suite.config, suite.processor).(*webfinger.Module) suite.securityModule = security.New(suite.config, suite.db).(*security.Module) diff --git a/internal/cliactions/testrig/testrig.go b/internal/cliactions/testrig/testrig.go index 8295692ba..c6e9b79aa 100644 --- a/internal/cliactions/testrig/testrig.go +++ b/internal/cliactions/testrig/testrig.go @@ -62,7 +62,7 @@ var Start cliactions.GTSAction = func(ctx context.Context, _ *config.Config) err }), dbService) federator := testrig.NewTestFederator(dbService, transportController, storageBackend) - emailSender := testrig.NewEmailSender("./web/template/") + emailSender := testrig.NewEmailSender("./web/template/", nil) processor := testrig.NewTestProcessor(dbService, storageBackend, federator, emailSender) if err := processor.Start(ctx); err != nil { diff --git a/internal/email/confirm.go b/internal/email/confirm.go index d6b3a2407..78f661fe1 100644 --- a/internal/email/confirm.go +++ b/internal/email/confirm.go @@ -19,6 +19,7 @@ package email import ( + "bytes" "net/smtp" ) @@ -28,12 +29,13 @@ const ( ) func (s *sender) SendConfirmEmail(toAddress string, data ConfirmData) error { - confirmBody, err := s.ExecuteTemplate(confirmTemplate, data) - if err != nil { + buf := &bytes.Buffer{} + if err := s.template.ExecuteTemplate(buf, confirmTemplate, data); err != nil { return err } + confirmBody := buf.String() - msg := s.AssembleMessage(confirmSubject, confirmBody, toAddress) + msg := assembleMessage(confirmSubject, confirmBody, toAddress, s.from) return smtp.SendMail(s.hostAddress, s.auth, s.from, []string{toAddress}, msg) } diff --git a/internal/email/noop.go b/internal/email/noopsender.go similarity index 56% rename from internal/email/noop.go rename to internal/email/noopsender.go index e80c078a4..8e01711ec 100644 --- a/internal/email/noop.go +++ b/internal/email/noopsender.go @@ -18,40 +18,58 @@ package email +import ( + "bytes" + "html/template" +) + // NewNoopSender returns a no-op email sender that will just execute the given sendCallback -// every time it would otherwise send an email. -// -// The 'data' parameter in the callback will be either a ConfirmData or a ResetData struct. +// every time it would otherwise send an email to the given toAddress with the given message value. // // Passing a nil function is also acceptable, in which case the send functions will just return nil. -func NewNoopSender(sendCallback func (toAddress string, data interface{})) Sender { +func NewNoopSender(templateBaseDir string, sendCallback func(toAddress string, message string)) (Sender, error) { + t, err := loadTemplates(templateBaseDir) + if err != nil { + return nil, err + } + return &noopSender{ sendCallback: sendCallback, - } + template: t, + }, nil } type noopSender struct { - sendCallback func (toAddress string, data interface{}) + sendCallback func(toAddress string, message string) + template *template.Template } func (s *noopSender) SendConfirmEmail(toAddress string, data ConfirmData) error { + buf := &bytes.Buffer{} + if err := s.template.ExecuteTemplate(buf, confirmTemplate, data); err != nil { + return err + } + confirmBody := buf.String() + + msg := assembleMessage(confirmSubject, confirmBody, toAddress, "test@example.org") + if s.sendCallback != nil { - s.sendCallback(toAddress, data) + s.sendCallback(toAddress, string(msg)) } return nil } func (s *noopSender) SendResetEmail(toAddress string, data ResetData) error { + buf := &bytes.Buffer{} + if err := s.template.ExecuteTemplate(buf, resetTemplate, data); err != nil { + return err + } + resetBody := buf.String() + + msg := assembleMessage(resetSubject, resetBody, toAddress, "test@example.org") + if s.sendCallback != nil { - s.sendCallback(toAddress, data) + s.sendCallback(toAddress, string(msg)) } return nil } - -func (s *noopSender) ExecuteTemplate(templateName string, data interface{}) (string, error) { - return "", nil -} - -func (s *noopSender) AssembleMessage(mailSubject string, mailBody string, mailTo string) []byte { - return []byte{} -} diff --git a/internal/email/reset.go b/internal/email/reset.go index a0cd377f6..786777f1b 100644 --- a/internal/email/reset.go +++ b/internal/email/reset.go @@ -19,6 +19,7 @@ package email import ( + "bytes" "net/smtp" ) @@ -28,12 +29,13 @@ const ( ) func (s *sender) SendResetEmail(toAddress string, data ResetData) error { - resetBody, err := s.ExecuteTemplate(resetTemplate, data) - if err != nil { + buf := &bytes.Buffer{} + if err := s.template.ExecuteTemplate(buf, resetTemplate, data); err != nil { return err } + resetBody := buf.String() - msg := s.AssembleMessage(resetSubject, resetBody, toAddress) + msg := assembleMessage(resetSubject, resetBody, toAddress, s.from) return smtp.SendMail(s.hostAddress, s.auth, s.from, []string{toAddress}, msg) } diff --git a/internal/email/email.go b/internal/email/sender.go similarity index 64% rename from internal/email/email.go rename to internal/email/sender.go index 69015e252..a6a9abe55 100644 --- a/internal/email/email.go +++ b/internal/email/sender.go @@ -22,8 +22,6 @@ import ( "fmt" "html/template" "net/smtp" - "os" - "path/filepath" "github.com/superseriousbusiness/gotosocial/internal/config" ) @@ -35,18 +33,11 @@ type Sender interface { // SendResetEmail sends a 'reset your password' style email to the given toAddress, with the given data. SendResetEmail(toAddress string, data ResetData) error - - // ExecuteTemplate returns templated HTML using the given templateName and data. Mostly you won't need to call this, - // and can just call one of the 'Send' functions instead (which calls this under the hood anyway). - ExecuteTemplate(templateName string, data interface{}) (string, error) - // AssembleMessage concacenates the mailSubject, the mime header, mailTo, mailFrom and the mailBody in - // an appropriate format for sending via net/smtp. Mostly you won't need to call this, but it's provided just in case. - AssembleMessage(mailSubject string, mailBody string, mailTo string) []byte } // NewSender returns a new email Sender interface with the given configuration, or an error if something goes wrong. func NewSender(cfg *config.Config) (Sender, error) { - t, err := loadTemplates(cfg) + t, err := loadTemplates(cfg.TemplateConfig.BaseDir) if err != nil { return nil, err } @@ -67,15 +58,3 @@ type sender struct { auth smtp.Auth template *template.Template } - -// loadTemplates loads html templates for use in emails -func loadTemplates(cfg *config.Config) (*template.Template, error) { - cwd, err := os.Getwd() - if err != nil { - return nil, fmt.Errorf("error getting current working directory: %s", err) - } - - // look for all templates that start with 'email_' - tmPath := filepath.Join(cwd, fmt.Sprintf("%semail_*", cfg.TemplateConfig.BaseDir)) - return template.ParseGlob(tmPath) -} diff --git a/internal/email/email_test.go b/internal/email/sender_test.go similarity index 87% rename from internal/email/email_test.go rename to internal/email/sender_test.go index 54d7e7144..4e2619546 100644 --- a/internal/email/email_test.go +++ b/internal/email/sender_test.go @@ -28,9 +28,12 @@ type EmailTestSuite struct { suite.Suite sender email.Sender + + sentEmails map[string]string } func (suite *EmailTestSuite) SetupTest() { testrig.InitTestLog() - suite.sender = testrig.NewEmailSender("../../web/template/") + suite.sentEmails = make(map[string]string) + suite.sender = testrig.NewEmailSender("../../web/template/", suite.sentEmails) } diff --git a/internal/email/util.go b/internal/email/util.go index 87933b130..1d3db5802 100644 --- a/internal/email/util.go +++ b/internal/email/util.go @@ -19,8 +19,10 @@ package email import ( - "bytes" "fmt" + "html/template" + "os" + "path/filepath" ) const ( @@ -28,16 +30,19 @@ const ( Content-Type: text/html;` ) -func (s *sender) ExecuteTemplate(templateName string, data interface{}) (string, error) { - buf := &bytes.Buffer{} - if err := s.template.ExecuteTemplate(buf, templateName, data); err != nil { - return "", err +func loadTemplates(templateBaseDir string) (*template.Template, error) { + cwd, err := os.Getwd() + if err != nil { + return nil, fmt.Errorf("error getting current working directory: %s", err) } - return buf.String(), nil + + // look for all templates that start with 'email_' + tmPath := filepath.Join(cwd, fmt.Sprintf("%semail_*", templateBaseDir)) + return template.ParseGlob(tmPath) } -func (s *sender) AssembleMessage(mailSubject string, mailBody string, mailTo string) []byte { - from := fmt.Sprintf("From: GoToSocial <%s>", s.from) +func assembleMessage(mailSubject string, mailBody string, mailTo string, mailFrom string) []byte { + from := fmt.Sprintf("From: GoToSocial <%s>", mailFrom) to := fmt.Sprintf("To: %s", mailTo) msg := []byte( diff --git a/internal/email/util_test.go b/internal/email/util_test.go index ce06f09d0..201bcd92d 100644 --- a/internal/email/util_test.go +++ b/internal/email/util_test.go @@ -36,12 +36,10 @@ func (suite *UtilTestSuite) TestTemplateConfirm() { InstanceName: "Test Instance", ConfirmLink: "https://example.org/confirm_email?token=ee24f71d-e615-43f9-afae-385c0799b7fa", } - mailBody, err := suite.sender.ExecuteTemplate("email_confirm.tmpl", confirmData) - suite.NoError(err) - suite.Equal("\n\n \n
\n\n You are receiving this mail because you've requested an account on Test Instance.\n
\n\n We just need to confirm that this is your email address. To confirm your email, click here or paste the following in your browser's address bar:\n
\n\n \n https://example.org/confirm_email?token=ee24f71d-e615-43f9-afae-385c0799b7fa\n \n
\n If you believe you've been sent this email in error, feel free to ignore it, or contact the administrator of Test Instance.\n
\n