Reduce the coupling of the mailservice with the rest of the application (#16898)
* Reduce the coupling of the mailservice with the rest of the application * Fixing tests in CI * Simplifiying mailservice config * Addressing PR review comments * Fixing tests * Removing unnecesary type definition * Fixing ServerName usage
Этот коммит содержится в:
коммит произвёл
GitHub
родитель
69ff686667
Коммит
d06a62ce64
@@ -226,7 +226,8 @@ func (a *App) TestEmail(userID string, cfg *model.Config) *model.AppError {
|
||||
|
||||
T := utils.GetUserTranslations(user.Locale)
|
||||
license := a.Srv().License()
|
||||
if err := mailservice.SendMailUsingConfig(user.Email, T("api.admin.test_email.subject"), T("api.admin.test_email.body"), cfg, license != nil && *license.Features.Compliance, ""); err != nil {
|
||||
mailConfig := a.Srv().MailServiceConfig()
|
||||
if err := mailservice.SendMailUsingConfig(user.Email, T("api.admin.test_email.subject"), T("api.admin.test_email.body"), mailConfig, license != nil && *license.Features.Compliance, ""); err != nil {
|
||||
return model.NewAppError("testEmail", "app.admin.test_email.failure", map[string]interface{}{"Error": err.Error()}, "", http.StatusInternalServerError)
|
||||
}
|
||||
|
||||
|
||||
@@ -497,7 +497,8 @@ func (a *App) NotifyAndSetWarnMetricAck(warnMetricId string, sender *model.User,
|
||||
subject := T("api.templates.warn_metric_ack.subject")
|
||||
bodyPage.Props["Title"] = warnMetricDisplayTexts.EmailBody
|
||||
|
||||
if err := mailservice.SendMailUsingConfig(model.MM_SUPPORT_ADVISOR_ADDRESS, subject, bodyPage.Render(), a.Config(), false, sender.Email); err != nil {
|
||||
mailConfig := a.Srv().MailServiceConfig()
|
||||
if err := mailservice.SendMailUsingConfig(model.MM_SUPPORT_ADVISOR_ADDRESS, subject, bodyPage.Render(), mailConfig, false, sender.Email); err != nil {
|
||||
return model.NewAppError("NotifyAndSetWarnMetricAck", "api.email.send_warn_metric_ack.failure.app_error", map[string]interface{}{"Error": err.Error()}, "", http.StatusInternalServerError)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -22,6 +22,7 @@ import (
|
||||
"github.com/mattermost/mattermost-server/v5/config"
|
||||
"github.com/mattermost/mattermost-server/v5/mlog"
|
||||
"github.com/mattermost/mattermost-server/v5/model"
|
||||
"github.com/mattermost/mattermost-server/v5/services/mailservice"
|
||||
"github.com/mattermost/mattermost-server/v5/utils"
|
||||
)
|
||||
|
||||
@@ -450,3 +451,25 @@ func (a *App) HandleMessageExportConfig(cfg *model.Config, appCfg *model.Config)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (s *Server) MailServiceConfig() *mailservice.SMTPConfig {
|
||||
emailSettings := s.Config().EmailSettings
|
||||
hostname := utils.GetHostnameFromSiteURL(*s.Config().ServiceSettings.SiteURL)
|
||||
cfg := mailservice.SMTPConfig{
|
||||
Hostname: hostname,
|
||||
ConnectionSecurity: *emailSettings.ConnectionSecurity,
|
||||
SkipServerCertificateVerification: *emailSettings.SkipServerCertificateVerification,
|
||||
ServerName: *emailSettings.SMTPServer,
|
||||
Server: *emailSettings.SMTPServer,
|
||||
Port: *emailSettings.SMTPPort,
|
||||
ServerTimeout: *emailSettings.SMTPServerTimeout,
|
||||
Username: *emailSettings.SMTPUsername,
|
||||
Password: *emailSettings.SMTPPassword,
|
||||
EnableSMTPAuth: *emailSettings.EnableSMTPAuth,
|
||||
SendEmailNotifications: *emailSettings.SendEmailNotifications,
|
||||
FeedbackName: *emailSettings.FeedbackName,
|
||||
FeedbackEmail: *emailSettings.FeedbackEmail,
|
||||
ReplyToAddress: *emailSettings.ReplyToAddress,
|
||||
}
|
||||
return &cfg
|
||||
}
|
||||
|
||||
@@ -558,14 +558,16 @@ func (es *EmailService) sendMail(to, subject, htmlBody string) error {
|
||||
|
||||
func (es *EmailService) sendMailWithCC(to, subject, htmlBody string, ccMail string) error {
|
||||
license := es.srv.License()
|
||||
return mailservice.SendMailUsingConfig(to, subject, htmlBody, es.srv.Config(), license != nil && *license.Features.Compliance, ccMail)
|
||||
mailConfig := es.srv.MailServiceConfig()
|
||||
|
||||
return mailservice.SendMailUsingConfig(to, subject, htmlBody, mailConfig, license != nil && *license.Features.Compliance, ccMail)
|
||||
}
|
||||
|
||||
func (es *EmailService) sendMailWithEmbeddedFiles(to, subject, htmlBody string, embeddedFiles map[string]io.Reader) error {
|
||||
license := es.srv.License()
|
||||
config := es.srv.Config()
|
||||
mailConfig := es.srv.MailServiceConfig()
|
||||
|
||||
return mailservice.SendMailWithEmbeddedFilesUsingConfig(to, subject, htmlBody, embeddedFiles, config, license != nil && *license.Features.Compliance, "")
|
||||
return mailservice.SendMailWithEmbeddedFilesUsingConfig(to, subject, htmlBody, embeddedFiles, mailConfig, license != nil && *license.Features.Compliance, "")
|
||||
}
|
||||
|
||||
func (es *EmailService) CreateVerifyEmailToken(userID string, newEmail string) (*model.Token, *model.AppError) {
|
||||
|
||||
@@ -115,7 +115,9 @@ func (s *Server) DoSecurityUpdateCheck() {
|
||||
for _, user := range users {
|
||||
mlog.Info("Sending security bulletin", mlog.String("bulletin_id", bulletin.Id), mlog.String("user_email", user.Email))
|
||||
license := s.License()
|
||||
mailservice.SendMailUsingConfig(user.Email, utils.T("mattermost.bulletin.subject"), string(body), s.Config(), license != nil && *license.Features.Compliance, "")
|
||||
mailConfig := s.MailServiceConfig()
|
||||
|
||||
mailservice.SendMailUsingConfig(user.Email, utils.T("mattermost.bulletin.subject"), string(body), mailConfig, license != nil && *license.Features.Compliance, "")
|
||||
}
|
||||
|
||||
bulletinSeen := &model.System{Name: "SecurityBulletin_" + bulletin.Id, Value: bulletin.Id}
|
||||
|
||||
@@ -487,7 +487,9 @@ func NewServer(options ...Option) (*Server, error) {
|
||||
}
|
||||
s.WebSocketRouter.app = fakeApp
|
||||
|
||||
if nErr := mailservice.TestConnection(s.Config()); nErr != nil {
|
||||
mailConfig := s.MailServiceConfig()
|
||||
|
||||
if nErr := mailservice.TestConnection(mailConfig); nErr != nil {
|
||||
mlog.Error("Mail server connection test is failed", mlog.Err(nErr))
|
||||
}
|
||||
|
||||
|
||||
@@ -18,11 +18,30 @@ import (
|
||||
gomail "gopkg.in/mail.v2"
|
||||
|
||||
"github.com/mattermost/mattermost-server/v5/mlog"
|
||||
"github.com/mattermost/mattermost-server/v5/model"
|
||||
"github.com/mattermost/mattermost-server/v5/services/filesstore"
|
||||
"github.com/mattermost/mattermost-server/v5/utils"
|
||||
)
|
||||
|
||||
const (
|
||||
TLS = "TLS"
|
||||
StartTLS = "STARTTLS"
|
||||
)
|
||||
|
||||
type SMTPConfig struct {
|
||||
ConnectionSecurity string
|
||||
SkipServerCertificateVerification bool
|
||||
Hostname string
|
||||
ServerName string
|
||||
Server string
|
||||
Port string
|
||||
ServerTimeout int
|
||||
Username string
|
||||
Password string
|
||||
EnableSMTPAuth bool
|
||||
SendEmailNotifications bool
|
||||
FeedbackName string
|
||||
FeedbackEmail string
|
||||
ReplyToAddress string
|
||||
}
|
||||
|
||||
type mailData struct {
|
||||
mimeTo string
|
||||
smtpTo string
|
||||
@@ -31,7 +50,6 @@ type mailData struct {
|
||||
replyTo mail.Address
|
||||
subject string
|
||||
htmlBody string
|
||||
attachments []*model.FileInfo
|
||||
embeddedFiles map[string]io.Reader
|
||||
mimeHeaders map[string]string
|
||||
}
|
||||
@@ -48,29 +66,17 @@ func encodeRFC2047Word(s string) string {
|
||||
return mime.BEncoding.Encode("utf-8", s)
|
||||
}
|
||||
|
||||
type SmtpConnectionInfo struct {
|
||||
SmtpUsername string
|
||||
SmtpPassword string
|
||||
SmtpServerName string
|
||||
SmtpServerHost string
|
||||
SmtpPort string
|
||||
SmtpServerTimeout int
|
||||
SkipCertVerification bool
|
||||
ConnectionSecurity string
|
||||
Auth bool
|
||||
}
|
||||
|
||||
type authChooser struct {
|
||||
smtp.Auth
|
||||
connectionInfo *SmtpConnectionInfo
|
||||
config *SMTPConfig
|
||||
}
|
||||
|
||||
func (a *authChooser) Start(server *smtp.ServerInfo) (string, []byte, error) {
|
||||
smtpAddress := a.connectionInfo.SmtpServerName + ":" + a.connectionInfo.SmtpPort
|
||||
a.Auth = LoginAuth(a.connectionInfo.SmtpUsername, a.connectionInfo.SmtpPassword, smtpAddress)
|
||||
smtpAddress := a.config.ServerName + ":" + a.config.Port
|
||||
a.Auth = LoginAuth(a.config.Username, a.config.Password, smtpAddress)
|
||||
for _, method := range server.Auth {
|
||||
if method == "PLAIN" {
|
||||
a.Auth = smtp.PlainAuth("", a.connectionInfo.SmtpUsername, a.connectionInfo.SmtpPassword, a.connectionInfo.SmtpServerName+":"+a.connectionInfo.SmtpPort)
|
||||
a.Auth = smtp.PlainAuth("", a.config.Username, a.config.Password, a.config.ServerName+":"+a.config.Port)
|
||||
break
|
||||
}
|
||||
}
|
||||
@@ -111,19 +117,19 @@ func (a *loginAuth) Next(fromServer []byte, more bool) ([]byte, error) {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
func ConnectToSMTPServerAdvanced(connectionInfo *SmtpConnectionInfo) (net.Conn, error) {
|
||||
func ConnectToSMTPServerAdvanced(config *SMTPConfig) (net.Conn, error) {
|
||||
var conn net.Conn
|
||||
var err error
|
||||
|
||||
smtpAddress := connectionInfo.SmtpServerHost + ":" + connectionInfo.SmtpPort
|
||||
smtpAddress := config.Server + ":" + config.Port
|
||||
dialer := &net.Dialer{
|
||||
Timeout: time.Duration(connectionInfo.SmtpServerTimeout) * time.Second,
|
||||
Timeout: time.Duration(config.ServerTimeout) * time.Second,
|
||||
}
|
||||
|
||||
if connectionInfo.ConnectionSecurity == model.CONN_SECURITY_TLS {
|
||||
if config.ConnectionSecurity == TLS {
|
||||
tlsconfig := &tls.Config{
|
||||
InsecureSkipVerify: connectionInfo.SkipCertVerification,
|
||||
ServerName: connectionInfo.SmtpServerName,
|
||||
InsecureSkipVerify: config.SkipServerCertificateVerification,
|
||||
ServerName: config.ServerName,
|
||||
}
|
||||
|
||||
conn, err = tls.DialWithDialer(dialer, "tcp", smtpAddress, tlsconfig)
|
||||
@@ -140,20 +146,11 @@ func ConnectToSMTPServerAdvanced(connectionInfo *SmtpConnectionInfo) (net.Conn,
|
||||
return conn, nil
|
||||
}
|
||||
|
||||
func ConnectToSMTPServer(config *model.Config) (net.Conn, error) {
|
||||
return ConnectToSMTPServerAdvanced(
|
||||
&SmtpConnectionInfo{
|
||||
ConnectionSecurity: *config.EmailSettings.ConnectionSecurity,
|
||||
SkipCertVerification: *config.EmailSettings.SkipServerCertificateVerification,
|
||||
SmtpServerName: *config.EmailSettings.SMTPServer,
|
||||
SmtpServerHost: *config.EmailSettings.SMTPServer,
|
||||
SmtpPort: *config.EmailSettings.SMTPPort,
|
||||
SmtpServerTimeout: *config.EmailSettings.SMTPServerTimeout,
|
||||
},
|
||||
)
|
||||
func ConnectToSMTPServer(config *SMTPConfig) (net.Conn, error) {
|
||||
return ConnectToSMTPServerAdvanced(config)
|
||||
}
|
||||
|
||||
func NewSMTPClientAdvanced(ctx context.Context, conn net.Conn, hostname string, connectionInfo *SmtpConnectionInfo) (*smtp.Client, error) {
|
||||
func NewSMTPClientAdvanced(ctx context.Context, conn net.Conn, config *SMTPConfig) (*smtp.Client, error) {
|
||||
ctx, cancel := context.WithCancel(ctx)
|
||||
defer cancel()
|
||||
|
||||
@@ -161,7 +158,7 @@ func NewSMTPClientAdvanced(ctx context.Context, conn net.Conn, hostname string,
|
||||
ec := make(chan error)
|
||||
go func() {
|
||||
var err error
|
||||
c, err = smtp.NewClient(conn, connectionInfo.SmtpServerName+":"+connectionInfo.SmtpPort)
|
||||
c, err = smtp.NewClient(conn, config.ServerName+":"+config.Port)
|
||||
if err != nil {
|
||||
ec <- err
|
||||
return
|
||||
@@ -179,50 +176,39 @@ func NewSMTPClientAdvanced(ctx context.Context, conn net.Conn, hostname string,
|
||||
return nil, errors.Wrap(err, "unable to connect to the SMTP server")
|
||||
}
|
||||
|
||||
if hostname != "" {
|
||||
err := c.Hello(hostname)
|
||||
if config.Hostname != "" {
|
||||
err := c.Hello(config.Hostname)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "unable to send hello message")
|
||||
}
|
||||
}
|
||||
|
||||
if connectionInfo.ConnectionSecurity == model.CONN_SECURITY_STARTTLS {
|
||||
if config.ConnectionSecurity == StartTLS {
|
||||
tlsconfig := &tls.Config{
|
||||
InsecureSkipVerify: connectionInfo.SkipCertVerification,
|
||||
ServerName: connectionInfo.SmtpServerName,
|
||||
InsecureSkipVerify: config.SkipServerCertificateVerification,
|
||||
ServerName: config.ServerName,
|
||||
}
|
||||
c.StartTLS(tlsconfig)
|
||||
}
|
||||
|
||||
if connectionInfo.Auth {
|
||||
if err := c.Auth(&authChooser{connectionInfo: connectionInfo}); err != nil {
|
||||
if config.EnableSMTPAuth {
|
||||
if err := c.Auth(&authChooser{config: config}); err != nil {
|
||||
return nil, errors.Wrap(err, "authentication failed")
|
||||
}
|
||||
}
|
||||
return c, nil
|
||||
}
|
||||
|
||||
func NewSMTPClient(ctx context.Context, conn net.Conn, config *model.Config) (*smtp.Client, error) {
|
||||
func NewSMTPClient(ctx context.Context, conn net.Conn, config *SMTPConfig) (*smtp.Client, error) {
|
||||
return NewSMTPClientAdvanced(
|
||||
ctx,
|
||||
conn,
|
||||
utils.GetHostnameFromSiteURL(*config.ServiceSettings.SiteURL),
|
||||
&SmtpConnectionInfo{
|
||||
ConnectionSecurity: *config.EmailSettings.ConnectionSecurity,
|
||||
SkipCertVerification: *config.EmailSettings.SkipServerCertificateVerification,
|
||||
SmtpServerName: *config.EmailSettings.SMTPServer,
|
||||
SmtpServerHost: *config.EmailSettings.SMTPServer,
|
||||
SmtpPort: *config.EmailSettings.SMTPPort,
|
||||
SmtpServerTimeout: *config.EmailSettings.SMTPServerTimeout,
|
||||
Auth: *config.EmailSettings.EnableSMTPAuth,
|
||||
SmtpUsername: *config.EmailSettings.SMTPUsername,
|
||||
SmtpPassword: *config.EmailSettings.SMTPPassword,
|
||||
},
|
||||
config,
|
||||
)
|
||||
}
|
||||
|
||||
func TestConnection(config *model.Config) error {
|
||||
if !*config.EmailSettings.SendEmailNotifications {
|
||||
func TestConnection(config *SMTPConfig) error {
|
||||
if !config.SendEmailNotifications {
|
||||
return errors.New("SendEmailNotifications is not true")
|
||||
}
|
||||
|
||||
@@ -232,7 +218,7 @@ func TestConnection(config *model.Config) error {
|
||||
}
|
||||
defer conn.Close()
|
||||
|
||||
sec := *config.EmailSettings.SMTPServerTimeout
|
||||
sec := config.ServerTimeout
|
||||
|
||||
ctx := context.Background()
|
||||
ctx, cancel := context.WithTimeout(ctx, time.Duration(sec)*time.Second)
|
||||
@@ -248,9 +234,9 @@ func TestConnection(config *model.Config) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func SendMailWithEmbeddedFilesUsingConfig(to, subject, htmlBody string, embeddedFiles map[string]io.Reader, config *model.Config, enableComplianceFeatures bool, ccMail string) error {
|
||||
fromMail := mail.Address{Name: *config.EmailSettings.FeedbackName, Address: *config.EmailSettings.FeedbackEmail}
|
||||
replyTo := mail.Address{Name: *config.EmailSettings.FeedbackName, Address: *config.EmailSettings.ReplyToAddress}
|
||||
func SendMailWithEmbeddedFilesUsingConfig(to, subject, htmlBody string, embeddedFiles map[string]io.Reader, config *SMTPConfig, enableComplianceFeatures bool, ccMail string) error {
|
||||
fromMail := mail.Address{Name: config.FeedbackName, Address: config.FeedbackEmail}
|
||||
replyTo := mail.Address{Name: config.FeedbackName, Address: config.ReplyToAddress}
|
||||
|
||||
mail := mailData{
|
||||
mimeTo: to,
|
||||
@@ -266,13 +252,13 @@ func SendMailWithEmbeddedFilesUsingConfig(to, subject, htmlBody string, embedded
|
||||
return sendMailUsingConfigAdvanced(mail, config, enableComplianceFeatures)
|
||||
}
|
||||
|
||||
func SendMailUsingConfig(to, subject, htmlBody string, config *model.Config, enableComplianceFeatures bool, ccMail string) error {
|
||||
func SendMailUsingConfig(to, subject, htmlBody string, config *SMTPConfig, enableComplianceFeatures bool, ccMail string) error {
|
||||
return SendMailWithEmbeddedFilesUsingConfig(to, subject, htmlBody, nil, config, enableComplianceFeatures, ccMail)
|
||||
}
|
||||
|
||||
// allows for sending an email with attachments and differing MIME/SMTP recipients
|
||||
func sendMailUsingConfigAdvanced(mail mailData, config *model.Config, enableComplianceFeatures bool) error {
|
||||
if *config.EmailSettings.SMTPServer == "" {
|
||||
// allows for sending an email with differing MIME/SMTP recipients
|
||||
func sendMailUsingConfigAdvanced(mail mailData, config *SMTPConfig, enableComplianceFeatures bool) error {
|
||||
if config.Server == "" {
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -282,7 +268,7 @@ func sendMailUsingConfigAdvanced(mail mailData, config *model.Config, enableComp
|
||||
}
|
||||
defer conn.Close()
|
||||
|
||||
sec := *config.EmailSettings.SMTPServerTimeout
|
||||
sec := config.ServerTimeout
|
||||
|
||||
ctx := context.Background()
|
||||
ctx, cancel := context.WithTimeout(ctx, time.Duration(sec)*time.Second)
|
||||
@@ -295,15 +281,10 @@ func sendMailUsingConfigAdvanced(mail mailData, config *model.Config, enableComp
|
||||
defer c.Quit()
|
||||
defer c.Close()
|
||||
|
||||
fileBackend, nErr := filesstore.NewFileBackend(config.FileSettings.ToFileBackendSettings(enableComplianceFeatures))
|
||||
if nErr != nil {
|
||||
return errors.Wrap(nErr, "unable to initialize file backend")
|
||||
}
|
||||
|
||||
return SendMail(c, mail, fileBackend, time.Now())
|
||||
return SendMail(c, mail, time.Now())
|
||||
}
|
||||
|
||||
func SendMail(c smtpClient, mail mailData, fileBackend filesstore.FileBackend, date time.Time) error {
|
||||
func SendMail(c smtpClient, mail mailData, date time.Time) error {
|
||||
mlog.Debug("sending mail", mlog.String("to", mail.smtpTo), mlog.String("subject", mail.subject))
|
||||
|
||||
htmlMessage := "\r\n<html><body>" + mail.htmlBody + "</body></html>"
|
||||
@@ -345,20 +326,6 @@ func SendMail(c smtpClient, mail mailData, fileBackend filesstore.FileBackend, d
|
||||
m.EmbedReader(name, reader)
|
||||
}
|
||||
|
||||
for _, fileInfo := range mail.attachments {
|
||||
bytes, nErr := fileBackend.ReadFile(fileInfo.Path)
|
||||
if nErr != nil {
|
||||
return errors.Wrap(err, "failed to read attachment")
|
||||
}
|
||||
|
||||
m.Attach(fileInfo.Name, gomail.SetCopyFunc(func(writer io.Writer) error {
|
||||
if _, nErr = writer.Write(bytes); nErr != nil {
|
||||
return errors.Wrap(err, "failed to write attachment to email")
|
||||
}
|
||||
return nil
|
||||
}))
|
||||
}
|
||||
|
||||
if err = c.Mail(mail.from.Address); err != nil {
|
||||
return errors.Wrap(err, "failed to set the from address")
|
||||
}
|
||||
|
||||
@@ -6,7 +6,6 @@ package mailservice
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"fmt"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"net"
|
||||
@@ -19,16 +18,38 @@ import (
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
|
||||
"github.com/mattermost/mattermost-server/v5/config"
|
||||
"github.com/mattermost/mattermost-server/v5/model"
|
||||
"github.com/mattermost/mattermost-server/v5/services/filesstore"
|
||||
"github.com/mattermost/mattermost-server/v5/utils"
|
||||
)
|
||||
|
||||
func getConfig() *SMTPConfig {
|
||||
server := os.Getenv("MM_EMAILSETTINGS_SMTPSERVER")
|
||||
if server == "" {
|
||||
server = "localhost"
|
||||
}
|
||||
port := os.Getenv("MM_EMAILSETTINGS_SMTPPORT")
|
||||
if port == "" {
|
||||
port = "10025"
|
||||
}
|
||||
|
||||
return &SMTPConfig{
|
||||
ConnectionSecurity: "",
|
||||
SkipServerCertificateVerification: false,
|
||||
Hostname: "localhost",
|
||||
ServerName: server,
|
||||
Server: server,
|
||||
Port: port,
|
||||
ServerTimeout: 10,
|
||||
Username: "",
|
||||
Password: "",
|
||||
EnableSMTPAuth: false,
|
||||
SendEmailNotifications: true,
|
||||
FeedbackName: "",
|
||||
FeedbackEmail: "test@example.com",
|
||||
ReplyToAddress: "test@example.com",
|
||||
}
|
||||
}
|
||||
|
||||
func TestMailConnectionFromConfig(t *testing.T) {
|
||||
store := config.NewTestMemoryStore()
|
||||
cfg := store.Get()
|
||||
cfg := getConfig()
|
||||
|
||||
conn, err := ConnectToSMTPServer(cfg)
|
||||
require.NoError(t, err, "Should connect to the SMTP Server %v", err)
|
||||
@@ -37,8 +58,8 @@ func TestMailConnectionFromConfig(t *testing.T) {
|
||||
|
||||
require.NoError(t, err, "Should get new SMTP client")
|
||||
|
||||
*cfg.EmailSettings.SMTPServer = "wrongServer"
|
||||
*cfg.EmailSettings.SMTPPort = "553"
|
||||
cfg.Server = "wrongServer"
|
||||
cfg.Port = "553"
|
||||
|
||||
_, err = ConnectToSMTPServer(cfg)
|
||||
|
||||
@@ -46,56 +67,23 @@ func TestMailConnectionFromConfig(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestMailConnectionAdvanced(t *testing.T) {
|
||||
store := config.NewTestMemoryStore()
|
||||
cfg := store.Get()
|
||||
cfg := getConfig()
|
||||
|
||||
conn, err := ConnectToSMTPServerAdvanced(
|
||||
&SmtpConnectionInfo{
|
||||
ConnectionSecurity: *cfg.EmailSettings.ConnectionSecurity,
|
||||
SkipCertVerification: *cfg.EmailSettings.SkipServerCertificateVerification,
|
||||
SmtpServerName: *cfg.EmailSettings.SMTPServer,
|
||||
SmtpServerHost: *cfg.EmailSettings.SMTPServer,
|
||||
SmtpPort: *cfg.EmailSettings.SMTPPort,
|
||||
},
|
||||
)
|
||||
conn, err := ConnectToSMTPServerAdvanced(cfg)
|
||||
require.NoError(t, err, "Should connect to the SMTP Server")
|
||||
defer conn.Close()
|
||||
|
||||
_, err2 := NewSMTPClientAdvanced(
|
||||
context.Background(),
|
||||
conn,
|
||||
utils.GetHostnameFromSiteURL(*cfg.ServiceSettings.SiteURL),
|
||||
&SmtpConnectionInfo{
|
||||
ConnectionSecurity: *cfg.EmailSettings.ConnectionSecurity,
|
||||
SkipCertVerification: *cfg.EmailSettings.SkipServerCertificateVerification,
|
||||
SmtpServerName: *cfg.EmailSettings.SMTPServer,
|
||||
SmtpServerHost: *cfg.EmailSettings.SMTPServer,
|
||||
SmtpPort: *cfg.EmailSettings.SMTPPort,
|
||||
Auth: *cfg.EmailSettings.EnableSMTPAuth,
|
||||
SmtpUsername: *cfg.EmailSettings.SMTPUsername,
|
||||
SmtpPassword: *cfg.EmailSettings.SMTPPassword,
|
||||
SmtpServerTimeout: 1,
|
||||
},
|
||||
)
|
||||
_, err2 := NewSMTPClientAdvanced(context.Background(), conn, cfg)
|
||||
require.NoError(t, err2, "Should get new SMTP client")
|
||||
|
||||
l, err3 := net.Listen("tcp", "localhost:") // emulate nc -l <random-port>
|
||||
require.NoError(t, err3, "Should've open a network socket and listen")
|
||||
defer l.Close()
|
||||
cfg.Server = strings.Split(l.Addr().String(), ":")[0]
|
||||
cfg.Port = strings.Split(l.Addr().String(), ":")[1]
|
||||
cfg.ServerTimeout = 1
|
||||
|
||||
connInfo := &SmtpConnectionInfo{
|
||||
ConnectionSecurity: *cfg.EmailSettings.ConnectionSecurity,
|
||||
SkipCertVerification: *cfg.EmailSettings.SkipServerCertificateVerification,
|
||||
SmtpServerName: *cfg.EmailSettings.SMTPServer,
|
||||
SmtpServerHost: strings.Split(l.Addr().String(), ":")[0],
|
||||
SmtpPort: strings.Split(l.Addr().String(), ":")[1],
|
||||
Auth: *cfg.EmailSettings.EnableSMTPAuth,
|
||||
SmtpUsername: *cfg.EmailSettings.SMTPUsername,
|
||||
SmtpPassword: *cfg.EmailSettings.SMTPPassword,
|
||||
SmtpServerTimeout: 1,
|
||||
}
|
||||
|
||||
conn2, err := ConnectToSMTPServerAdvanced(connInfo)
|
||||
conn2, err := ConnectToSMTPServerAdvanced(cfg)
|
||||
require.NoError(t, err, "Should connect to the SMTP Server")
|
||||
defer conn2.Close()
|
||||
|
||||
@@ -106,33 +94,20 @@ func TestMailConnectionAdvanced(t *testing.T) {
|
||||
_, err4 := NewSMTPClientAdvanced(
|
||||
ctx,
|
||||
conn2,
|
||||
utils.GetHostnameFromSiteURL(*cfg.ServiceSettings.SiteURL),
|
||||
connInfo,
|
||||
cfg,
|
||||
)
|
||||
require.Error(t, err4, "Should get a timeout get while creating a new SMTP client")
|
||||
assert.Contains(t, err4.Error(), "unable to connect to the SMTP server")
|
||||
|
||||
_, err5 := ConnectToSMTPServerAdvanced(
|
||||
&SmtpConnectionInfo{
|
||||
ConnectionSecurity: *cfg.EmailSettings.ConnectionSecurity,
|
||||
SkipCertVerification: *cfg.EmailSettings.SkipServerCertificateVerification,
|
||||
SmtpServerName: "wrongServer",
|
||||
SmtpServerHost: "wrongServer",
|
||||
SmtpPort: "553",
|
||||
},
|
||||
)
|
||||
cfg.Server = "wrongServer"
|
||||
cfg.Port = "553"
|
||||
|
||||
_, err5 := ConnectToSMTPServerAdvanced(cfg)
|
||||
require.Error(t, err5, "Should not connect to the SMTP Server")
|
||||
}
|
||||
|
||||
func TestSendMailUsingConfig(t *testing.T) {
|
||||
utils.T = utils.GetUserTranslations("en")
|
||||
|
||||
fsInner, err := config.NewFileStore("config.json", false)
|
||||
require.NoError(t, err)
|
||||
fs, err := config.NewStoreFromBacking(fsInner, nil, false)
|
||||
require.NoError(t, err)
|
||||
|
||||
cfg := fs.Get()
|
||||
cfg := getConfig()
|
||||
|
||||
var emailTo = "test@example.com"
|
||||
var emailSubject = "Testing this email"
|
||||
@@ -166,14 +141,7 @@ func TestSendMailUsingConfig(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestSendMailWithEmbeddedFilesUsingConfig(t *testing.T) {
|
||||
utils.T = utils.GetUserTranslations("en")
|
||||
|
||||
fsInner, err := config.NewFileStore("config.json", false)
|
||||
require.NoError(t, err)
|
||||
fs, err := config.NewStoreFromBacking(fsInner, nil, false)
|
||||
require.NoError(t, err)
|
||||
|
||||
cfg := fs.Get()
|
||||
cfg := getConfig()
|
||||
|
||||
var emailTo = "test@example.com"
|
||||
var emailSubject = "Testing this email"
|
||||
@@ -213,42 +181,23 @@ func TestSendMailWithEmbeddedFilesUsingConfig(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestSendMailUsingConfigAdvanced(t *testing.T) {
|
||||
utils.T = utils.GetUserTranslations("en")
|
||||
|
||||
fsInner, err := config.NewFileStore("config.json", false)
|
||||
require.NoError(t, err)
|
||||
fs, err := config.NewStoreFromBacking(fsInner, nil, false)
|
||||
require.NoError(t, err)
|
||||
|
||||
cfg := fs.Get()
|
||||
cfg := getConfig()
|
||||
|
||||
//Delete all the messages before check the sample email
|
||||
DeleteMailBox("test2@example.com")
|
||||
|
||||
fileBackend, err := filesstore.NewFileBackend(cfg.FileSettings.ToFileBackendSettings(true))
|
||||
assert.NoError(t, err)
|
||||
|
||||
// create two files with the same name that will both be attached to the email
|
||||
filePath1 := fmt.Sprintf("test1/%s", "file1.txt")
|
||||
filePath2 := fmt.Sprintf("test2/%s", "file2.txt")
|
||||
fileContents1 := []byte("hello world")
|
||||
fileContents2 := []byte("foo bar")
|
||||
_, err = fileBackend.WriteFile(bytes.NewReader(fileContents1), filePath1)
|
||||
assert.NoError(t, err)
|
||||
_, err = fileBackend.WriteFile(bytes.NewReader(fileContents2), filePath2)
|
||||
assert.NoError(t, err)
|
||||
defer fileBackend.RemoveFile(filePath1)
|
||||
defer fileBackend.RemoveFile(filePath2)
|
||||
file1, err := ioutil.TempFile("", "*")
|
||||
require.NoError(t, err)
|
||||
defer os.Remove(file1.Name())
|
||||
file1.Write([]byte("hello world"))
|
||||
file1.Close()
|
||||
file2, err := ioutil.TempFile("", "*")
|
||||
|
||||
attachments := make([]*model.FileInfo, 2)
|
||||
attachments[0] = &model.FileInfo{
|
||||
Name: "file1.txt",
|
||||
Path: filePath1,
|
||||
}
|
||||
attachments[1] = &model.FileInfo{
|
||||
Name: "file2.txt",
|
||||
Path: filePath2,
|
||||
}
|
||||
require.NoError(t, err)
|
||||
defer os.Remove(file2.Name())
|
||||
file2.Write([]byte("foo bar"))
|
||||
file2.Close()
|
||||
|
||||
embeddedFiles := map[string]io.Reader{
|
||||
"test": bytes.NewReader([]byte("test data")),
|
||||
@@ -264,7 +213,6 @@ func TestSendMailUsingConfigAdvanced(t *testing.T) {
|
||||
replyTo: mail.Address{Name: "ReplyTo", Address: "reply_to@mattermost.com"},
|
||||
subject: "Testing this email",
|
||||
htmlBody: "This is a test from autobot",
|
||||
attachments: attachments,
|
||||
embeddedFiles: embeddedFiles,
|
||||
mimeHeaders: headers,
|
||||
}
|
||||
@@ -297,37 +245,16 @@ func TestSendMailUsingConfigAdvanced(t *testing.T) {
|
||||
|
||||
// check that the custom mime headers came through - header case seems to get mutated
|
||||
assert.Equal(t, "TestValue", resultsEmail.Header["Testheader"][0])
|
||||
|
||||
// ensure that the attachments were successfully sent
|
||||
assert.Len(t, resultsEmail.Attachments, 3)
|
||||
|
||||
attachmentsFilenames := []string{
|
||||
resultsEmail.Attachments[0].Filename,
|
||||
resultsEmail.Attachments[1].Filename,
|
||||
resultsEmail.Attachments[2].Filename,
|
||||
}
|
||||
assert.Contains(t, attachmentsFilenames, "file1.txt")
|
||||
assert.Contains(t, attachmentsFilenames, "file2.txt")
|
||||
assert.Contains(t, attachmentsFilenames, "test")
|
||||
|
||||
attachment1 := string(resultsEmail.Attachments[0].Bytes)
|
||||
attachment2 := string(resultsEmail.Attachments[1].Bytes)
|
||||
attachment3 := string(resultsEmail.Attachments[2].Bytes)
|
||||
attachmentsData := []string{attachment1, attachment2, attachment3}
|
||||
|
||||
assert.Contains(t, attachmentsData, string(fileContents1))
|
||||
assert.Contains(t, attachmentsData, string(fileContents2))
|
||||
assert.Contains(t, attachmentsData, "test data")
|
||||
}
|
||||
|
||||
func TestAuthMethods(t *testing.T) {
|
||||
auth := &authChooser{
|
||||
connectionInfo: &SmtpConnectionInfo{
|
||||
SmtpUsername: "test",
|
||||
SmtpPassword: "fakepass",
|
||||
SmtpServerName: "fakeserver",
|
||||
SmtpServerHost: "fakeserver",
|
||||
SmtpPort: "25",
|
||||
config: &SMTPConfig{
|
||||
Username: "test",
|
||||
Password: "fakepass",
|
||||
ServerName: "fakeserver",
|
||||
Server: "fakeserver",
|
||||
Port: "25",
|
||||
},
|
||||
}
|
||||
tests := []struct {
|
||||
@@ -394,13 +321,6 @@ func TestSendMail(t *testing.T) {
|
||||
dir, err := ioutil.TempDir(".", "mail-test-")
|
||||
require.NoError(t, err)
|
||||
defer os.RemoveAll(dir)
|
||||
settings := model.FileSettings{
|
||||
DriverName: model.NewString(model.IMAGE_DRIVER_LOCAL),
|
||||
Directory: &dir,
|
||||
}
|
||||
settings.SetDefaults(true)
|
||||
mockBackend, err := filesstore.NewFileBackend(settings.ToFileBackendSettings(true))
|
||||
require.NoError(t, err)
|
||||
mocm := &mockMailer{}
|
||||
|
||||
testCases := map[string]struct {
|
||||
@@ -422,8 +342,8 @@ func TestSendMail(t *testing.T) {
|
||||
|
||||
for testName, tc := range testCases {
|
||||
t.Run(testName, func(t *testing.T) {
|
||||
mail := mailData{"", "", mail.Address{}, "", tc.replyTo, "", "", nil, nil, nil}
|
||||
err = SendMail(mocm, mail, mockBackend, time.Now())
|
||||
mail := mailData{"", "", mail.Address{}, "", tc.replyTo, "", "", nil, nil}
|
||||
err = SendMail(mocm, mail, time.Now())
|
||||
require.NoError(t, err)
|
||||
if tc.contains != "" {
|
||||
require.Contains(t, string(mocm.data), tc.contains)
|
||||
|
||||
Ссылка в новой задаче
Block a user