[MM-43920] - Set Workspace Inactivity Email to only fire once and change subject (#20134)
* [MM-43920] - Set Workspace Inactivity Email to only fire once and change subject * feedback impl * temp change * revert Co-authored-by: Mattermod <mattermod@users.noreply.github.com>
Этот коммит содержится в:
коммит произвёл
GitHub
родитель
d9e3125e87
Коммит
37fd699175
@@ -11,6 +11,8 @@ import (
|
||||
"io"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"os"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
@@ -24,6 +26,8 @@ import (
|
||||
"github.com/microcosm-cc/bluemonday"
|
||||
)
|
||||
|
||||
const serverInactivityHours = 100
|
||||
|
||||
func (es *Service) SendChangeUsernameEmail(newUsername, email, locale, siteURL string) error {
|
||||
T := i18n.GetUserTranslations(locale)
|
||||
|
||||
@@ -944,6 +948,15 @@ func (es *Service) SendLicenseInactivityEmail(email, name, locale, siteURL strin
|
||||
data.Props["Playbooks"] = T("Playbooks")
|
||||
data.Props["Boards"] = T("Boards")
|
||||
|
||||
inactivityDurationHoursEnv := os.Getenv("MM_INACTIVITY_DURATION")
|
||||
inactivityDurationHours, parseError := strconv.ParseFloat(inactivityDurationHoursEnv, 64)
|
||||
if parseError != nil {
|
||||
// default to 100 hours
|
||||
inactivityDurationHours = serverInactivityHours
|
||||
}
|
||||
|
||||
data.Props["FooterDisclaimer"] = T("api.templates.server_inactivity_footer_disclaimer", map[string]interface{}{"Hours": inactivityDurationHours})
|
||||
|
||||
body, err := es.templatesContainer.RenderToString("inactivity_body", data)
|
||||
if err != nil {
|
||||
return err
|
||||
|
||||
@@ -4,19 +4,24 @@
|
||||
package app
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"strconv"
|
||||
"time"
|
||||
|
||||
"github.com/mattermost/mattermost-server/v6/model"
|
||||
"github.com/mattermost/mattermost-server/v6/shared/mlog"
|
||||
"github.com/mattermost/mattermost-server/v6/store"
|
||||
)
|
||||
|
||||
const serverInactivityHours = 100
|
||||
const inactivityEmailSent = "INACTIVITY"
|
||||
|
||||
func (s *Server) doInactivityCheck() {
|
||||
|
||||
if *s.Config().ServiceSettings.EnableDeveloper {
|
||||
mlog.Info("No activity check because developer mode is enabled")
|
||||
return
|
||||
}
|
||||
|
||||
if !*s.Config().EmailSettings.EnableInactivityEmail {
|
||||
mlog.Info("No activity check because EnableInactivityEmail is false")
|
||||
return
|
||||
@@ -27,6 +32,12 @@ func (s *Server) doInactivityCheck() {
|
||||
return
|
||||
}
|
||||
|
||||
_, sysValErr := s.Store.System().GetByName(inactivityEmailSent)
|
||||
// if there is no error which may include *store.ErrNotFound, it means this check was already flagged as done
|
||||
if sysValErr == nil {
|
||||
return
|
||||
}
|
||||
|
||||
inactivityDurationHoursEnv := os.Getenv("MM_INACTIVITY_DURATION")
|
||||
inactivityDurationHours, parseError := strconv.ParseFloat(inactivityDurationHoursEnv, 64)
|
||||
if parseError != nil {
|
||||
@@ -34,51 +45,9 @@ func (s *Server) doInactivityCheck() {
|
||||
inactivityDurationHours = serverInactivityHours
|
||||
}
|
||||
|
||||
systemValue, sysValErr := s.Store.System().GetByName("INACTIVITY")
|
||||
if sysValErr != nil {
|
||||
// any other error apart from ErrNotFound we stop execution
|
||||
if _, ok := sysValErr.(*store.ErrNotFound); !ok {
|
||||
mlog.Warn("An error occurred while getting INACTIVITY from system store", mlog.Err(sysValErr))
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
// If we have a system value, it means this job already ran atleast once.
|
||||
// we then check the last time the job ran plus the last time a post was made to determine if we
|
||||
// can remind the user to use workspace again. If no post was made, we check the last time they logged in (session)
|
||||
// and determine whether to send them a reminder.
|
||||
if systemValue != nil {
|
||||
sysT, _ := strconv.ParseInt(systemValue.Value, 10, 64)
|
||||
tt := time.Unix(sysT/1000, 0)
|
||||
timeLastSentInactivityEmail := time.Since(tt).Hours()
|
||||
|
||||
lastPostAt, _ := s.Store.Post().GetLastPostRowCreateAt()
|
||||
if lastPostAt != 0 {
|
||||
posT := time.Unix(lastPostAt/1000, 0)
|
||||
timeForLastPost := time.Since(posT).Hours()
|
||||
|
||||
if timeLastSentInactivityEmail > inactivityDurationHours && timeForLastPost > inactivityDurationHours {
|
||||
s.takeInactivityAction()
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
lastSessionAt, _ := s.Store.Session().GetLastSessionRowCreateAt()
|
||||
if lastSessionAt != 0 {
|
||||
sesT := time.Unix(lastSessionAt/1000, 0)
|
||||
timeForLastSession := time.Since(sesT).Hours()
|
||||
|
||||
if timeLastSentInactivityEmail > inactivityDurationHours && timeForLastSession > inactivityDurationHours {
|
||||
s.takeInactivityAction()
|
||||
}
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
// The first time this job runs. We check if the user has not made any posts
|
||||
// The first time this job runs. We check if the user has not made any posts in last inactivityDurationHours
|
||||
// and remind them to use the workspace. If no posts have been made. We check the last time
|
||||
// they logged in (session) and send a reminder.
|
||||
|
||||
// they logged in (session) for the last inactivityDurationHours and send a reminder.
|
||||
lastPostAt, _ := s.Store.Post().GetLastPostRowCreateAt()
|
||||
if lastPostAt != 0 {
|
||||
posT := time.Unix(lastPostAt/1000, 0)
|
||||
@@ -139,8 +108,8 @@ func (s *Server) takeInactivityAction() {
|
||||
})
|
||||
}
|
||||
|
||||
// Mark time that we sent emails. The next time we calculate
|
||||
sysVar := &model.System{Name: "INACTIVITY", Value: fmt.Sprint(model.GetMillis())}
|
||||
// Mark that we sent emails.
|
||||
sysVar := &model.System{Name: inactivityEmailSent, Value: "true"}
|
||||
if err := s.Store.System().SaveOrUpdate(sysVar); err != nil {
|
||||
mlog.Error("Unable to save INACTIVITY", mlog.Err(err))
|
||||
}
|
||||
|
||||
@@ -3499,6 +3499,10 @@
|
||||
"id": "api.templates.server_inactivity_button",
|
||||
"translation": "Open Mattermost"
|
||||
},
|
||||
{
|
||||
"id": "api.templates.server_inactivity_footer_disclaimer",
|
||||
"translation": "You received this one-time email because your Mattermost server was inactive for more than {{.Hours}} hours. This email was automatically generated by your Mattermost server."
|
||||
},
|
||||
{
|
||||
"id": "api.templates.server_inactivity_info",
|
||||
"translation": "Come and check it out!"
|
||||
@@ -3517,7 +3521,7 @@
|
||||
},
|
||||
{
|
||||
"id": "api.templates.server_inactivity_subject",
|
||||
"translation": "HEY! Open Mattermost to increase your team’s productivity!"
|
||||
"translation": "Come open Mattermost to increase your team’s productivity!"
|
||||
},
|
||||
{
|
||||
"id": "api.templates.server_inactivity_subtitle",
|
||||
|
||||
@@ -506,6 +506,11 @@
|
||||
<div class="mj-column-per-100 mj-outlook-group-fix" style="font-size:0px;text-align:left;direction:ltr;display:inline-block;vertical-align:top;width:100%;">
|
||||
<table border="0" cellpadding="0" cellspacing="0" role="presentation" style="border-top:1px solid #E5E5E5;vertical-align:top;" width="100%">
|
||||
<tbody>
|
||||
<tr>
|
||||
<td align="center" class="emailFooter" style="font-size:0px;padding:10px 25px;word-break:break-word;">
|
||||
<div style="font-family: Arial; text-align: center; font-size: 12px; line-height: 16px; color: rgba(63, 67, 80, 0.56); padding: 8px 24px 8px 24px;">{{.Props.FooterDisclaimer}}</div>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="center" class="emailFooter" style="font-size:0px;padding:10px 25px;word-break:break-word;">
|
||||
<div style="font-family: Arial; text-align: center; font-size: 12px; line-height: 16px; color: rgba(63, 67, 80, 0.56); padding: 8px 24px 8px 24px;">{{.Props.Organization}}
|
||||
|
||||
@@ -50,6 +50,9 @@
|
||||
|
||||
<mj-section padding="0px 24px 40px 24px">
|
||||
<mj-column border-top="1px solid #E5E5E5">
|
||||
<mj-text css-class="emailFooter" font-family="Arial" font-size="12px" line-height="16px" color="#3F4350">
|
||||
{{.Props.FooterDisclaimer}}
|
||||
</mj-text>
|
||||
<mj-text css-class="emailFooter" font-family="Arial" font-size="12px" line-height="16px" color="#3F4350">
|
||||
{{.Props.Organization}}
|
||||
{{.Props.FooterV2}}
|
||||
|
||||
Ссылка в новой задаче
Block a user