Add inbucket docker image to allow local and automated testing of emails (#4901)
* add docker container for inbucket * Add way to get the emails using inbucket and add a test for reset password * add config setting to send emails * update TestEmailTest update * add another test and fix wrong assert * update per review fix lint change senders email * Revert config.json to default values for EmailSettings section * update test * add setup to make the test run
Этот коммит содержится в:
коммит произвёл
Harrison Healey
родитель
97a51b0e31
Коммит
dc54e640c2
25
Makefile
25
Makefile
@@ -85,6 +85,14 @@ start-docker:
|
|||||||
docker start mattermost-webrtc > /dev/null; \
|
docker start mattermost-webrtc > /dev/null; \
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
@if [ $(shell docker ps -a | grep -ci mattermost-inbucket) -eq 0 ]; then \
|
||||||
|
echo starting mattermost-inbucket; \
|
||||||
|
docker run --name mattermost-inbucket -p 9000:10080 -p 2500:10025 -d jhillyerd/inbucket:latest > /dev/null; \
|
||||||
|
elif [ $(shell docker ps | grep -ci mattermost-inbucket) -eq 0 ]; then \
|
||||||
|
echo restarting mattermost-inbucket; \
|
||||||
|
docker start mattermost-inbucket > /dev/null; \
|
||||||
|
fi
|
||||||
|
|
||||||
ifeq ($(BUILD_ENTERPRISE_READY),true)
|
ifeq ($(BUILD_ENTERPRISE_READY),true)
|
||||||
@echo Ldap test user test.one
|
@echo Ldap test user test.one
|
||||||
@if [ $(shell docker ps -a | grep -ci mattermost-openldap) -eq 0 ]; then \
|
@if [ $(shell docker ps -a | grep -ci mattermost-openldap) -eq 0 ]; then \
|
||||||
@@ -132,6 +140,11 @@ stop-docker:
|
|||||||
docker stop mattermost-webrtc > /dev/null; \
|
docker stop mattermost-webrtc > /dev/null; \
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
@if [ $(shell docker ps -a | grep -ci mattermost-inbucket) -eq 1 ]; then \
|
||||||
|
echo stopping mattermost-inbucket; \
|
||||||
|
docker stop mattermost-inbucket > /dev/null; \
|
||||||
|
fi
|
||||||
|
|
||||||
clean-docker:
|
clean-docker:
|
||||||
@echo Removing docker containers
|
@echo Removing docker containers
|
||||||
|
|
||||||
@@ -159,6 +172,12 @@ clean-docker:
|
|||||||
docker rm -v mattermost-webrtc > /dev/null; \
|
docker rm -v mattermost-webrtc > /dev/null; \
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
@if [ $(shell docker ps -a | grep -ci mattermost-inbucket) -eq 1 ]; then \
|
||||||
|
echo removing mattermost-inbucket; \
|
||||||
|
docker stop mattermost-inbucket > /dev/null; \
|
||||||
|
docker rm -v mattermost-inbucket > /dev/null; \
|
||||||
|
fi
|
||||||
|
|
||||||
check-client-style:
|
check-client-style:
|
||||||
@echo Checking client style
|
@echo Checking client style
|
||||||
|
|
||||||
@@ -303,6 +322,12 @@ package: build build-client
|
|||||||
@# Disable developer settings
|
@# Disable developer settings
|
||||||
sed -i'' -e 's|"ConsoleLevel": "DEBUG"|"ConsoleLevel": "INFO"|g' $(DIST_PATH)/config/config.json
|
sed -i'' -e 's|"ConsoleLevel": "DEBUG"|"ConsoleLevel": "INFO"|g' $(DIST_PATH)/config/config.json
|
||||||
|
|
||||||
|
@# Reset email sending to original configuration
|
||||||
|
sed -i'' -e 's|"SendEmailNotifications": true,|"SendEmailNotifications": false,|g' $(DIST_PATH)/config/config.json
|
||||||
|
sed -i'' -e 's|"FeedbackEmail": "test@example.com",|"FeedbackEmail": "",|g' $(DIST_PATH)/config/config.json
|
||||||
|
sed -i'' -e 's|"SMTPServer": "dockerhost",|"SMTPServer": "",|g' $(DIST_PATH)/config/config.json
|
||||||
|
sed -i'' -e 's|"SMTPPort": "2500",|"SMTPPort": "",|g' $(DIST_PATH)/config/config.json
|
||||||
|
|
||||||
@# Package webapp
|
@# Package webapp
|
||||||
mkdir -p $(DIST_PATH)/webapp/dist
|
mkdir -p $(DIST_PATH)/webapp/dist
|
||||||
cp -RL $(BUILD_WEBAPP_DIR)/dist $(DIST_PATH)/webapp
|
cp -RL $(BUILD_WEBAPP_DIR)/dist $(DIST_PATH)/webapp
|
||||||
|
|||||||
@@ -160,6 +160,22 @@ func TestRecycleDatabaseConnection(t *testing.T) {
|
|||||||
func TestEmailTest(t *testing.T) {
|
func TestEmailTest(t *testing.T) {
|
||||||
th := Setup().InitBasic().InitSystemAdmin()
|
th := Setup().InitBasic().InitSystemAdmin()
|
||||||
|
|
||||||
|
SendEmailNotifications := utils.Cfg.EmailSettings.SendEmailNotifications
|
||||||
|
SMTPServer := utils.Cfg.EmailSettings.SMTPServer
|
||||||
|
SMTPPort := utils.Cfg.EmailSettings.SMTPPort
|
||||||
|
FeedbackEmail := utils.Cfg.EmailSettings.FeedbackEmail
|
||||||
|
defer func() {
|
||||||
|
utils.Cfg.EmailSettings.SendEmailNotifications = SendEmailNotifications
|
||||||
|
utils.Cfg.EmailSettings.SMTPServer = SMTPServer
|
||||||
|
utils.Cfg.EmailSettings.SMTPPort = SMTPPort
|
||||||
|
utils.Cfg.EmailSettings.FeedbackEmail = FeedbackEmail
|
||||||
|
}()
|
||||||
|
|
||||||
|
utils.Cfg.EmailSettings.SendEmailNotifications = false
|
||||||
|
utils.Cfg.EmailSettings.SMTPServer = ""
|
||||||
|
utils.Cfg.EmailSettings.SMTPPort = ""
|
||||||
|
utils.Cfg.EmailSettings.FeedbackEmail = ""
|
||||||
|
|
||||||
if _, err := th.BasicClient.TestEmail(utils.Cfg); err == nil {
|
if _, err := th.BasicClient.TestEmail(utils.Cfg); err == nil {
|
||||||
t.Fatal("Shouldn't have permissions")
|
t.Fatal("Shouldn't have permissions")
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -59,6 +59,10 @@ func Setup() *TestHelper {
|
|||||||
utils.InitTranslations(utils.Cfg.LocalizationSettings)
|
utils.InitTranslations(utils.Cfg.LocalizationSettings)
|
||||||
utils.Cfg.TeamSettings.MaxUsersPerTeam = 50
|
utils.Cfg.TeamSettings.MaxUsersPerTeam = 50
|
||||||
*utils.Cfg.RateLimitSettings.Enable = false
|
*utils.Cfg.RateLimitSettings.Enable = false
|
||||||
|
utils.Cfg.EmailSettings.SendEmailNotifications = true
|
||||||
|
utils.Cfg.EmailSettings.SMTPServer = "dockerhost"
|
||||||
|
utils.Cfg.EmailSettings.SMTPPort = "2500"
|
||||||
|
utils.Cfg.EmailSettings.FeedbackEmail = "test@example.com"
|
||||||
utils.DisableDebugLogForTest()
|
utils.DisableDebugLogForTest()
|
||||||
app.NewServer()
|
app.NewServer()
|
||||||
app.InitStores()
|
app.InitStores()
|
||||||
|
|||||||
@@ -857,11 +857,45 @@ func TestEmailMention(t *testing.T) {
|
|||||||
th := Setup().InitBasic()
|
th := Setup().InitBasic()
|
||||||
Client := th.BasicClient
|
Client := th.BasicClient
|
||||||
channel1 := th.BasicChannel
|
channel1 := th.BasicChannel
|
||||||
|
Client.Must(Client.AddChannelMember(channel1.Id, th.BasicUser2.Id))
|
||||||
|
|
||||||
post1 := &model.Post{ChannelId: channel1.Id, Message: th.BasicUser.Username}
|
th.LoginBasic2()
|
||||||
|
//Set the notification properties
|
||||||
|
data := make(map[string]string)
|
||||||
|
data["user_id"] = th.BasicUser2.Id
|
||||||
|
data["email"] = "true"
|
||||||
|
data["desktop"] = "all"
|
||||||
|
data["desktop_sound"] = "false"
|
||||||
|
data["comments"] = "any"
|
||||||
|
Client.Must(Client.UpdateUserNotify(data))
|
||||||
|
|
||||||
|
store.Must(app.Srv.Store.Preference().Save(&model.Preferences{{
|
||||||
|
UserId: th.BasicUser2.Id,
|
||||||
|
Category: model.PREFERENCE_CATEGORY_NOTIFICATIONS,
|
||||||
|
Name: model.PREFERENCE_NAME_EMAIL_INTERVAL,
|
||||||
|
Value: "0",
|
||||||
|
}}))
|
||||||
|
|
||||||
|
//Delete all the messages before create a mention post
|
||||||
|
utils.DeleteMailBox(th.BasicUser2.Email)
|
||||||
|
|
||||||
|
//Send a mention message from user1 to user2
|
||||||
|
th.LoginBasic()
|
||||||
|
time.Sleep(10 * time.Millisecond)
|
||||||
|
post1 := &model.Post{ChannelId: channel1.Id, Message: "@" + th.BasicUser2.Username + " this is a test"}
|
||||||
post1 = Client.Must(Client.CreatePost(post1)).Data.(*model.Post)
|
post1 = Client.Must(Client.CreatePost(post1)).Data.(*model.Post)
|
||||||
|
|
||||||
// No easy way to verify the email was sent, but this will at least cause the server to throw errors if the code is broken
|
//Check if the email was send to the rigth email address and the mention
|
||||||
|
if resultsMailbox, err := utils.GetMailBox(th.BasicUser2.Email); err != nil && !strings.ContainsAny(resultsMailbox[0].To[0], th.BasicUser2.Email) {
|
||||||
|
t.Fatal("Wrong To recipient")
|
||||||
|
} else {
|
||||||
|
if resultsEmail, err := utils.GetMessageFromMailbox(th.BasicUser2.Email, resultsMailbox[0].ID); err == nil {
|
||||||
|
if !strings.Contains(resultsEmail.Body.Text, post1.Message) {
|
||||||
|
t.Log(resultsEmail.Body.Text)
|
||||||
|
t.Fatal("Received wrong Message")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1284,6 +1284,9 @@ func TestResetPassword(t *testing.T) {
|
|||||||
LinkUserToTeam(user, team)
|
LinkUserToTeam(user, team)
|
||||||
store.Must(app.Srv.Store.User().VerifyEmail(user.Id))
|
store.Must(app.Srv.Store.User().VerifyEmail(user.Id))
|
||||||
|
|
||||||
|
//Delete all the messages before check the reset password
|
||||||
|
utils.DeleteMailBox(user.Email)
|
||||||
|
|
||||||
Client.Must(Client.SendPasswordReset(user.Email))
|
Client.Must(Client.SendPasswordReset(user.Email))
|
||||||
|
|
||||||
var recovery *model.PasswordRecovery
|
var recovery *model.PasswordRecovery
|
||||||
@@ -1293,6 +1296,19 @@ func TestResetPassword(t *testing.T) {
|
|||||||
recovery = result.Data.(*model.PasswordRecovery)
|
recovery = result.Data.(*model.PasswordRecovery)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//Check if the email was send to the rigth email address and the recovery key match
|
||||||
|
if resultsMailbox, err := utils.GetMailBox(user.Email); err != nil && !strings.ContainsAny(resultsMailbox[0].To[0], user.Email) {
|
||||||
|
t.Fatal("Wrong To recipient")
|
||||||
|
} else {
|
||||||
|
if resultsEmail, err := utils.GetMessageFromMailbox(user.Email, resultsMailbox[0].ID); err == nil {
|
||||||
|
if !strings.Contains(resultsEmail.Body.Text, recovery.Code) {
|
||||||
|
t.Log(resultsEmail.Body.Text)
|
||||||
|
t.Log(recovery.Code)
|
||||||
|
t.Fatal("Received wrong recovery code")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if _, err := Client.ResetPassword(recovery.Code, ""); err == nil {
|
if _, err := Client.ResetPassword(recovery.Code, ""); err == nil {
|
||||||
t.Fatal("Should have errored - no password")
|
t.Fatal("Should have errored - no password")
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -53,6 +53,7 @@ func Setup() *TestHelper {
|
|||||||
NewServer()
|
NewServer()
|
||||||
InitStores()
|
InitStores()
|
||||||
StartServer()
|
StartServer()
|
||||||
|
utils.InitHTML()
|
||||||
utils.EnableDebugLogForTest()
|
utils.EnableDebugLogForTest()
|
||||||
Srv.Store.MarkSystemRanUnitTests()
|
Srv.Store.MarkSystemRanUnitTests()
|
||||||
|
|
||||||
|
|||||||
@@ -178,6 +178,7 @@ func TestGetExplicitMentionsAtHere(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestGetMentionKeywords(t *testing.T) {
|
func TestGetMentionKeywords(t *testing.T) {
|
||||||
|
Setup()
|
||||||
// user with username or custom mentions enabled
|
// user with username or custom mentions enabled
|
||||||
user1 := &model.User{
|
user1 := &model.User{
|
||||||
Id: model.NewId(),
|
Id: model.NewId(),
|
||||||
|
|||||||
@@ -109,15 +109,15 @@
|
|||||||
"EnableSignUpWithEmail": true,
|
"EnableSignUpWithEmail": true,
|
||||||
"EnableSignInWithEmail": true,
|
"EnableSignInWithEmail": true,
|
||||||
"EnableSignInWithUsername": true,
|
"EnableSignInWithUsername": true,
|
||||||
"SendEmailNotifications": false,
|
"SendEmailNotifications": true,
|
||||||
"RequireEmailVerification": false,
|
"RequireEmailVerification": false,
|
||||||
"FeedbackName": "",
|
"FeedbackName": "",
|
||||||
"FeedbackEmail": "",
|
"FeedbackEmail": "test@example.com",
|
||||||
"FeedbackOrganization": "",
|
"FeedbackOrganization": "",
|
||||||
"SMTPUsername": "",
|
"SMTPUsername": "",
|
||||||
"SMTPPassword": "",
|
"SMTPPassword": "",
|
||||||
"SMTPServer": "",
|
"SMTPServer": "dockerhost",
|
||||||
"SMTPPort": "",
|
"SMTPPort": "2500",
|
||||||
"ConnectionSecurity": "",
|
"ConnectionSecurity": "",
|
||||||
"InviteSalt": "",
|
"InviteSalt": "",
|
||||||
"PasswordResetSalt": "",
|
"PasswordResetSalt": "",
|
||||||
|
|||||||
115
utils/inbucket.go
Обычный файл
115
utils/inbucket.go
Обычный файл
@@ -0,0 +1,115 @@
|
|||||||
|
package utils
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
"fmt"
|
||||||
|
"net/http"
|
||||||
|
"strings"
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
INBUCKET_HOST = "http://dockerhost:9000"
|
||||||
|
INBUCKET_API = "/api/v1/mailbox/"
|
||||||
|
)
|
||||||
|
|
||||||
|
// OutputJSONHeader holds the received Header to test sending emails (inbucket)
|
||||||
|
type JSONMessageHeaderInbucket []struct {
|
||||||
|
Mailbox string
|
||||||
|
ID string `json:"Id"`
|
||||||
|
From, Subject, Date string
|
||||||
|
To []string
|
||||||
|
Size int
|
||||||
|
}
|
||||||
|
|
||||||
|
// OutputJSONMessage holds the received Message fto test sending emails (inbucket)
|
||||||
|
type JSONMessageInbucket struct {
|
||||||
|
Mailbox string
|
||||||
|
ID string `json:"Id"`
|
||||||
|
From, Subject, Date string
|
||||||
|
Size int
|
||||||
|
Header map[string][]string
|
||||||
|
Body struct {
|
||||||
|
Text string
|
||||||
|
HTML string `json:"Html"`
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func ParseEmail(email string) string {
|
||||||
|
pos := strings.Index(email, "@")
|
||||||
|
parsedEmail := email[0:pos]
|
||||||
|
return parsedEmail
|
||||||
|
}
|
||||||
|
|
||||||
|
func GetMailBox(email string) (results JSONMessageHeaderInbucket, err error) {
|
||||||
|
|
||||||
|
parsedEmail := ParseEmail(email)
|
||||||
|
|
||||||
|
url := fmt.Sprintf("%s%s%s", INBUCKET_HOST, INBUCKET_API, parsedEmail)
|
||||||
|
req, err := http.NewRequest("GET", url, nil)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
client := &http.Client{}
|
||||||
|
|
||||||
|
resp, err := client.Do(req)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
defer resp.Body.Close()
|
||||||
|
|
||||||
|
var record JSONMessageHeaderInbucket
|
||||||
|
if err := json.NewDecoder(resp.Body).Decode(&record); err != nil {
|
||||||
|
fmt.Println(err)
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return record, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func GetMessageFromMailbox(email, id string) (results JSONMessageInbucket, err error) {
|
||||||
|
|
||||||
|
parsedEmail := ParseEmail(email)
|
||||||
|
|
||||||
|
var record JSONMessageInbucket
|
||||||
|
|
||||||
|
url := fmt.Sprintf("%s%s%s/%s", INBUCKET_HOST, INBUCKET_API, parsedEmail, id)
|
||||||
|
req, err := http.NewRequest("GET", url, nil)
|
||||||
|
if err != nil {
|
||||||
|
return record, err
|
||||||
|
}
|
||||||
|
|
||||||
|
client := &http.Client{}
|
||||||
|
|
||||||
|
resp, err := client.Do(req)
|
||||||
|
if err != nil {
|
||||||
|
return record, err
|
||||||
|
}
|
||||||
|
defer resp.Body.Close()
|
||||||
|
|
||||||
|
if err := json.NewDecoder(resp.Body).Decode(&record); err != nil {
|
||||||
|
fmt.Println(err)
|
||||||
|
return record, err
|
||||||
|
}
|
||||||
|
return record, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func DeleteMailBox(email string) (err error) {
|
||||||
|
|
||||||
|
parsedEmail := ParseEmail(email)
|
||||||
|
|
||||||
|
url := fmt.Sprintf("%s%s%s", INBUCKET_HOST, INBUCKET_API, parsedEmail)
|
||||||
|
req, err := http.NewRequest("DELETE", url, nil)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
client := &http.Client{}
|
||||||
|
|
||||||
|
resp, err := client.Do(req)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
defer resp.Body.Close()
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
Ссылка в новой задаче
Block a user