[MM-48528] Add support for SendGrid X-SMTPAPI header in email sends (#22296)
* Add support for SendGrid X-SMTPAPI header for categorizing sent emails to track performance * Implement feedback * Remove unnecessary struct --------- Co-authored-by: Mattermost Build <build@mattermost.com>
Этот коммит содержится в:
@@ -195,7 +195,7 @@ func (a *App) TestEmail(userID string, cfg *model.Config) *model.AppError {
|
|||||||
T := i18n.GetUserTranslations(user.Locale)
|
T := i18n.GetUserTranslations(user.Locale)
|
||||||
license := a.Srv().License()
|
license := a.Srv().License()
|
||||||
mailConfig := a.Srv().MailServiceConfig()
|
mailConfig := a.Srv().MailServiceConfig()
|
||||||
if err := mail.SendMailUsingConfig(user.Email, T("api.admin.test_email.subject"), T("api.admin.test_email.body"), mailConfig, license != nil && *license.Features.Compliance, "", "", "", ""); err != nil {
|
if err := mail.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]any{"Error": err.Error()}, "", http.StatusInternalServerError)
|
return model.NewAppError("testEmail", "app.admin.test_email.failure", map[string]any{"Error": err.Error()}, "", http.StatusInternalServerError)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -194,7 +194,7 @@ func (a *App) NotifyAndSetWarnMetricAck(warnMetricId string, sender *model.User,
|
|||||||
return model.NewAppError("NotifyAndSetWarnMetricAck", "api.email.send_warn_metric_ack.failure.app_error", map[string]any{"Error": err.Error()}, "", http.StatusInternalServerError)
|
return model.NewAppError("NotifyAndSetWarnMetricAck", "api.email.send_warn_metric_ack.failure.app_error", map[string]any{"Error": err.Error()}, "", http.StatusInternalServerError)
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := mail.SendMailUsingConfig(model.MmSupportAdvisorAddress, subject, body, mailConfig, false, "", "", "", sender.Email); err != nil {
|
if err := mail.SendMailUsingConfig(model.MmSupportAdvisorAddress, subject, body, mailConfig, false, "", "", "", sender.Email, "NotifyAndSetWarnMetricAck"); err != nil {
|
||||||
return model.NewAppError("NotifyAndSetWarnMetricAck", "api.email.send_warn_metric_ack.failure.app_error", map[string]any{"Error": err.Error()}, "", http.StatusInternalServerError)
|
return model.NewAppError("NotifyAndSetWarnMetricAck", "api.email.send_warn_metric_ack.failure.app_error", map[string]any{"Error": err.Error()}, "", http.StatusInternalServerError)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -27,6 +27,15 @@ import (
|
|||||||
|
|
||||||
const serverInactivityHours = 100
|
const serverInactivityHours = 100
|
||||||
|
|
||||||
|
// Returns category if enabled is true (default false)
|
||||||
|
// If "" is returned when enabled is false, the category headers aren't attached to the email
|
||||||
|
func getSendGridCategory(category string, enabled bool) string {
|
||||||
|
if enabled {
|
||||||
|
return category
|
||||||
|
}
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
func (es *Service) SendChangeUsernameEmail(newUsername, email, locale, siteURL string) error {
|
func (es *Service) SendChangeUsernameEmail(newUsername, email, locale, siteURL string) error {
|
||||||
T := i18n.GetUserTranslations(locale)
|
T := i18n.GetUserTranslations(locale)
|
||||||
|
|
||||||
@@ -46,7 +55,7 @@ func (es *Service) SendChangeUsernameEmail(newUsername, email, locale, siteURL s
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := es.sendMail(email, subject, body); err != nil {
|
if err := es.sendMail(email, subject, body, "ChangeUsernameEmail"); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -79,7 +88,7 @@ func (es *Service) SendEmailChangeVerifyEmail(newUserEmail, locale, siteURL, tok
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := es.sendMail(newUserEmail, subject, body); err != nil {
|
if err := es.sendMail(newUserEmail, subject, body, "EmailChangeVerifyEmail"); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -105,7 +114,7 @@ func (es *Service) SendEmailChangeEmail(oldEmail, newEmail, locale, siteURL stri
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := es.sendMail(oldEmail, subject, body); err != nil {
|
if err := es.sendMail(oldEmail, subject, body, "EmailChangeEmail"); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -143,7 +152,7 @@ func (es *Service) SendVerifyEmail(userEmail, locale, siteURL, token, redirect s
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := es.sendMail(userEmail, subject, body); err != nil {
|
if err := es.sendMail(userEmail, subject, body, "VerifyEmail"); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -168,7 +177,7 @@ func (es *Service) SendSignInChangeEmail(email, method, locale, siteURL string)
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := es.sendMail(email, subject, body); err != nil {
|
if err := es.sendMail(email, subject, body, "SignInChangeEmail"); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -226,7 +235,7 @@ func (es *Service) SendWelcomeEmail(userID string, email string, verified bool,
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := es.sendMail(email, subject, body); err != nil {
|
if err := es.sendMail(email, subject, body, "WelcomeEmail"); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -259,11 +268,11 @@ func (es *Service) SendCloudUpgradeConfirmationEmail(userEmail, name, date, loca
|
|||||||
}
|
}
|
||||||
|
|
||||||
if isYearly {
|
if isYearly {
|
||||||
if err := es.SendMailWithEmbeddedFilesAndCustomReplyTo(userEmail, subject, body, *es.config().SupportSettings.SupportEmail, embeddedFiles); err != nil {
|
if err := es.SendMailWithEmbeddedFilesAndCustomReplyTo(userEmail, subject, body, *es.config().SupportSettings.SupportEmail, embeddedFiles, "CloudUpgradeConfirmationEmail"); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if err := es.sendEmailWithCustomReplyTo(userEmail, subject, body, *es.config().SupportSettings.SupportEmail); err != nil {
|
if err := es.sendEmailWithCustomReplyTo(userEmail, subject, body, *es.config().SupportSettings.SupportEmail, "CloudUpgradeConfirmationEmail"); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -304,7 +313,7 @@ func (es *Service) SendCloudWelcomeEmail(userEmail, locale, teamInviteID, workSp
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := es.sendEmailWithCustomReplyTo(userEmail, subject, body, *es.config().SupportSettings.SupportEmail); err != nil {
|
if err := es.sendEmailWithCustomReplyTo(userEmail, subject, body, *es.config().SupportSettings.SupportEmail, "CloudWelcomeEmail"); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -330,7 +339,7 @@ func (es *Service) SendPasswordChangeEmail(email, method, locale, siteURL string
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := es.sendMail(email, subject, body); err != nil {
|
if err := es.sendMail(email, subject, body, "PasswordChangeEmail"); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -355,7 +364,7 @@ func (es *Service) SendUserAccessTokenAddedEmail(email, locale, siteURL string)
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := es.sendMail(email, subject, body); err != nil {
|
if err := es.sendMail(email, subject, body, "UserAccessTokenAddedEmail"); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -385,7 +394,7 @@ func (es *Service) SendPasswordResetEmail(email string, token *model.Token, loca
|
|||||||
return false, err
|
return false, err
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := es.sendMail(email, subject, body); err != nil {
|
if err := es.sendMail(email, subject, body, "PasswordResetEmail"); err != nil {
|
||||||
return false, err
|
return false, err
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -415,7 +424,7 @@ func (es *Service) SendMfaChangeEmail(email string, activated bool, locale, site
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := es.sendMail(email, subject, body); err != nil {
|
if err := es.sendMail(email, subject, body, "MfaChangeEmail"); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -501,7 +510,7 @@ func (es *Service) SendInviteEmails(
|
|||||||
mlog.Error("Failed to send invite email successfully ", mlog.Err(err))
|
mlog.Error("Failed to send invite email successfully ", mlog.Err(err))
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := es.sendMail(invite, subject, body); err != nil {
|
if err := es.sendMail(invite, subject, body, "InviteEmail"); err != nil {
|
||||||
mlog.Error("Failed to send invite email successfully ", mlog.Err(err))
|
mlog.Error("Failed to send invite email successfully ", mlog.Err(err))
|
||||||
if errorWhenNotSent {
|
if errorWhenNotSent {
|
||||||
return SendMailError
|
return SendMailError
|
||||||
@@ -617,7 +626,7 @@ func (es *Service) SendGuestInviteEmails(
|
|||||||
mlog.Error("Failed to send invite email successfully", mlog.Err(err))
|
mlog.Error("Failed to send invite email successfully", mlog.Err(err))
|
||||||
}
|
}
|
||||||
|
|
||||||
if nErr := es.SendMailWithEmbeddedFiles(invite, subject, body, embeddedFiles, "", "", ""); nErr != nil {
|
if nErr := es.SendMailWithEmbeddedFiles(invite, subject, body, embeddedFiles, "", "", "", "InviteEmail"); nErr != nil {
|
||||||
mlog.Error("Failed to send invite email successfully", mlog.Err(nErr))
|
mlog.Error("Failed to send invite email successfully", mlog.Err(nErr))
|
||||||
if errorWhenNotSent {
|
if errorWhenNotSent {
|
||||||
return SendMailError
|
return SendMailError
|
||||||
@@ -765,7 +774,7 @@ func (es *Service) SendInviteEmailsToTeamAndChannels(
|
|||||||
mlog.Error("Failed to send invite email successfully ", mlog.Err(err))
|
mlog.Error("Failed to send invite email successfully ", mlog.Err(err))
|
||||||
}
|
}
|
||||||
|
|
||||||
if nErr := es.SendMailWithEmbeddedFiles(invite, subject, body, embeddedFiles, "", "", ""); nErr != nil {
|
if nErr := es.SendMailWithEmbeddedFiles(invite, subject, body, embeddedFiles, "", "", "", "InviteEmailToTeamsAndChannels"); nErr != nil {
|
||||||
mlog.Error("Failed to send invite email successfully", mlog.Err(nErr))
|
mlog.Error("Failed to send invite email successfully", mlog.Err(nErr))
|
||||||
if errorWhenNotSent {
|
if errorWhenNotSent {
|
||||||
inviteWithError := &model.EmailInviteWithError{
|
inviteWithError := &model.EmailInviteWithError{
|
||||||
@@ -828,7 +837,7 @@ func (es *Service) SendDeactivateAccountEmail(email string, locale, siteURL stri
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := es.sendMail(email, subject, body); err != nil { // this needs to receive the header options
|
if err := es.sendMail(email, subject, body, "DeactivateAccountEmail"); err != nil { // this needs to receive the header options
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -839,39 +848,47 @@ func (es *Service) SendNotificationMail(to, subject, htmlBody string) error {
|
|||||||
if !*es.config().EmailSettings.SendEmailNotifications {
|
if !*es.config().EmailSettings.SendEmailNotifications {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
return es.sendMail(to, subject, htmlBody)
|
return es.sendMail(to, subject, htmlBody, "NotificationEmail")
|
||||||
}
|
}
|
||||||
|
|
||||||
func (es *Service) sendMail(to, subject, htmlBody string) error {
|
func (es *Service) sendMail(to, subject, htmlBody, category string) error {
|
||||||
return es.sendMailWithCC(to, subject, htmlBody, "")
|
return es.sendMailWithCC(to, subject, htmlBody, "", category)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (es *Service) sendEmailWithCustomReplyTo(to, subject, htmlBody, replyToAddress string) error {
|
func (es *Service) sendEmailWithCustomReplyTo(to, subject, htmlBody, replyToAddress, category string) error {
|
||||||
license := es.license()
|
license := es.license()
|
||||||
mailConfig := es.mailServiceConfig(replyToAddress)
|
mailConfig := es.mailServiceConfig(replyToAddress)
|
||||||
|
|
||||||
return mail.SendMailUsingConfig(to, subject, htmlBody, mailConfig, license != nil && *license.Features.Compliance, "", "", "", "")
|
category = getSendGridCategory(category, license.IsCloud())
|
||||||
|
|
||||||
|
return mail.SendMailUsingConfig(to, subject, htmlBody, mailConfig, license != nil && *license.Features.Compliance, "", "", "", "", category)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (es *Service) sendMailWithCC(to, subject, htmlBody string, ccMail string) error {
|
func (es *Service) sendMailWithCC(to, subject, htmlBody, ccMail, category string) error {
|
||||||
license := es.license()
|
license := es.license()
|
||||||
mailConfig := es.mailServiceConfig("")
|
mailConfig := es.mailServiceConfig("")
|
||||||
|
|
||||||
return mail.SendMailUsingConfig(to, subject, htmlBody, mailConfig, license != nil && *license.Features.Compliance, "", "", "", ccMail)
|
category = getSendGridCategory(category, license.IsCloud())
|
||||||
|
|
||||||
|
return mail.SendMailUsingConfig(to, subject, htmlBody, mailConfig, license != nil && *license.Features.Compliance, "", "", "", ccMail, category)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (es *Service) SendMailWithEmbeddedFilesAndCustomReplyTo(to, subject, htmlBody, replyToAddress string, embeddedFiles map[string]io.Reader) error {
|
func (es *Service) SendMailWithEmbeddedFilesAndCustomReplyTo(to, subject, htmlBody, replyToAddress string, embeddedFiles map[string]io.Reader, category string) error {
|
||||||
license := es.license()
|
license := es.license()
|
||||||
mailConfig := es.mailServiceConfig(replyToAddress)
|
mailConfig := es.mailServiceConfig(replyToAddress)
|
||||||
|
|
||||||
return mail.SendMailWithEmbeddedFilesUsingConfig(to, subject, htmlBody, embeddedFiles, mailConfig, license != nil && *license.Features.Compliance, "", "", "", "")
|
category = getSendGridCategory(category, license.IsCloud())
|
||||||
|
|
||||||
|
return mail.SendMailWithEmbeddedFilesUsingConfig(to, subject, htmlBody, embeddedFiles, mailConfig, license != nil && *license.Features.Compliance, "", "", "", "", category)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (es *Service) SendMailWithEmbeddedFiles(to, subject, htmlBody string, embeddedFiles map[string]io.Reader, messageID string, inReplyTo string, references string) error {
|
func (es *Service) SendMailWithEmbeddedFiles(to, subject, htmlBody string, embeddedFiles map[string]io.Reader, messageID string, inReplyTo string, references string, category string) error {
|
||||||
license := es.license()
|
license := es.license()
|
||||||
mailConfig := es.mailServiceConfig("")
|
mailConfig := es.mailServiceConfig("")
|
||||||
|
|
||||||
return mail.SendMailWithEmbeddedFilesUsingConfig(to, subject, htmlBody, embeddedFiles, mailConfig, license != nil && *license.Features.Compliance, messageID, inReplyTo, references, "")
|
category = getSendGridCategory(category, license.IsCloud())
|
||||||
|
|
||||||
|
return mail.SendMailWithEmbeddedFilesUsingConfig(to, subject, htmlBody, embeddedFiles, mailConfig, license != nil && *license.Features.Compliance, messageID, inReplyTo, references, "", category)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (es *Service) InvalidateVerifyEmailTokensForUser(userID string) *model.AppError {
|
func (es *Service) InvalidateVerifyEmailTokensForUser(userID string) *model.AppError {
|
||||||
@@ -965,7 +982,7 @@ func (es *Service) SendLicenseInactivityEmail(email, name, locale, siteURL strin
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := es.sendMail(email, subject, body); err != nil {
|
if err := es.sendMail(email, subject, body, "LicenseInactivityEmail"); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -993,7 +1010,7 @@ func (es *Service) SendLicenseUpForRenewalEmail(email, name, locale, siteURL, re
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := es.sendMail(email, subject, body); err != nil {
|
if err := es.sendMail(email, subject, body, "LicenseUpForRenewal"); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1026,7 +1043,7 @@ func (es *Service) SendPaymentFailedEmail(email string, locale string, failedPay
|
|||||||
return false, err
|
return false, err
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := es.sendEmailWithCustomReplyTo(email, subject, body, *es.config().SupportSettings.SupportEmail); err != nil {
|
if err := es.sendEmailWithCustomReplyTo(email, subject, body, *es.config().SupportSettings.SupportEmail, "PaymentFailed"); err != nil {
|
||||||
return false, err
|
return false, err
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1053,7 +1070,7 @@ func (es *Service) SendNoCardPaymentFailedEmail(email string, locale string, sit
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := es.sendEmailWithCustomReplyTo(email, subject, body, *es.config().SupportSettings.SupportEmail); err != nil {
|
if err := es.sendEmailWithCustomReplyTo(email, subject, body, *es.config().SupportSettings.SupportEmail, "NoCardPaymentFailed"); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1083,7 +1100,7 @@ func (es *Service) SendDelinquencyEmail7(email, locale, siteURL, planName string
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := es.sendEmailWithCustomReplyTo(email, subject, body, *es.config().SupportSettings.SupportEmail); err != nil {
|
if err := es.sendEmailWithCustomReplyTo(email, subject, body, *es.config().SupportSettings.SupportEmail, "Delinquency7"); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1112,7 +1129,7 @@ func (es *Service) SendDelinquencyEmail14(email, locale, siteURL, planName strin
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := es.sendEmailWithCustomReplyTo(email, subject, body, *es.config().SupportSettings.SupportEmail); err != nil {
|
if err := es.sendEmailWithCustomReplyTo(email, subject, body, *es.config().SupportSettings.SupportEmail, "Delinquency14"); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1142,7 +1159,7 @@ func (es *Service) SendDelinquencyEmail30(email, locale, siteURL, planName strin
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := es.sendEmailWithCustomReplyTo(email, subject, body, *es.config().SupportSettings.SupportEmail); err != nil {
|
if err := es.sendEmailWithCustomReplyTo(email, subject, body, *es.config().SupportSettings.SupportEmail, "Delinquency30"); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1174,7 +1191,7 @@ func (es *Service) SendDelinquencyEmail45(email, locale, siteURL, planName, deli
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := es.sendEmailWithCustomReplyTo(email, subject, body, *es.config().SupportSettings.SupportEmail); err != nil {
|
if err := es.sendEmailWithCustomReplyTo(email, subject, body, *es.config().SupportSettings.SupportEmail, "Delinquency45"); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1207,7 +1224,7 @@ func (es *Service) SendDelinquencyEmail60(email, locale, siteURL string) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := es.sendEmailWithCustomReplyTo(email, subject, body, *es.config().SupportSettings.SupportEmail); err != nil {
|
if err := es.sendEmailWithCustomReplyTo(email, subject, body, *es.config().SupportSettings.SupportEmail, "Delinquency60"); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1240,7 +1257,7 @@ func (es *Service) SendDelinquencyEmail75(email, locale, siteURL, planName, deli
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := es.sendEmailWithCustomReplyTo(email, subject, body, *es.config().SupportSettings.SupportEmail); err != nil {
|
if err := es.sendEmailWithCustomReplyTo(email, subject, body, *es.config().SupportSettings.SupportEmail, "Delinquency75"); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1272,7 +1289,7 @@ func (es *Service) SendDelinquencyEmail90(email, locale, siteURL string) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := es.sendEmailWithCustomReplyTo(email, subject, body, *es.config().SupportSettings.SupportEmail); err != nil {
|
if err := es.sendEmailWithCustomReplyTo(email, subject, body, *es.config().SupportSettings.SupportEmail, "Delinquency90"); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1297,7 +1314,7 @@ func (es *Service) SendRemoveExpiredLicenseEmail(renewalLink, email string, loca
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := es.sendMail(email, subject, body); err != nil {
|
if err := es.sendMail(email, subject, body, "RemoveExpiredLicense"); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -346,7 +346,7 @@ func (es *Service) sendBatchedEmailNotification(userID string, notifications []*
|
|||||||
mlog.Error("Unable to render email", mlog.Err(renderErr))
|
mlog.Error("Unable to render email", mlog.Err(renderErr))
|
||||||
}
|
}
|
||||||
|
|
||||||
if nErr := es.SendMailWithEmbeddedFiles(user.Email, subject, renderedPage, embeddedFiles, "", "", ""); nErr != nil {
|
if nErr := es.SendMailWithEmbeddedFiles(user.Email, subject, renderedPage, embeddedFiles, "", "", "", "BatchedEmailNotification"); nErr != nil {
|
||||||
mlog.Warn("Unable to send batched email notification", mlog.String("email", user.Email), mlog.Err(nErr))
|
mlog.Warn("Unable to send batched email notification", mlog.String("email", user.Email), mlog.Err(nErr))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -372,13 +372,13 @@ func (_m *ServiceInterface) SendLicenseUpForRenewalEmail(_a0 string, name string
|
|||||||
return r0
|
return r0
|
||||||
}
|
}
|
||||||
|
|
||||||
// SendMailWithEmbeddedFiles provides a mock function with given fields: to, subject, htmlBody, embeddedFiles, messageID, inReplyTo, references
|
// SendMailWithEmbeddedFiles provides a mock function with given fields: to, subject, htmlBody, embeddedFiles, messageID, inReplyTo, references, category
|
||||||
func (_m *ServiceInterface) SendMailWithEmbeddedFiles(to string, subject string, htmlBody string, embeddedFiles map[string]io.Reader, messageID string, inReplyTo string, references string) error {
|
func (_m *ServiceInterface) SendMailWithEmbeddedFiles(to string, subject string, htmlBody string, embeddedFiles map[string]io.Reader, messageID string, inReplyTo string, references string, category string) error {
|
||||||
ret := _m.Called(to, subject, htmlBody, embeddedFiles, messageID, inReplyTo, references)
|
ret := _m.Called(to, subject, htmlBody, embeddedFiles, messageID, inReplyTo, references, category)
|
||||||
|
|
||||||
var r0 error
|
var r0 error
|
||||||
if rf, ok := ret.Get(0).(func(string, string, string, map[string]io.Reader, string, string, string) error); ok {
|
if rf, ok := ret.Get(0).(func(string, string, string, map[string]io.Reader, string, string, string, string) error); ok {
|
||||||
r0 = rf(to, subject, htmlBody, embeddedFiles, messageID, inReplyTo, references)
|
r0 = rf(to, subject, htmlBody, embeddedFiles, messageID, inReplyTo, references, category)
|
||||||
} else {
|
} else {
|
||||||
r0 = ret.Error(0)
|
r0 = ret.Error(0)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -140,7 +140,7 @@ type ServiceInterface interface {
|
|||||||
SendInviteEmailsToTeamAndChannels(team *model.Team, channels []*model.Channel, senderName string, senderUserId string, senderProfileImage []byte, invites []string, siteURL string, reminderData *model.TeamInviteReminderData, message string, errorWhenNotSent bool, isSystemAdmin bool, isFirstAdmin bool) ([]*model.EmailInviteWithError, error)
|
SendInviteEmailsToTeamAndChannels(team *model.Team, channels []*model.Channel, senderName string, senderUserId string, senderProfileImage []byte, invites []string, siteURL string, reminderData *model.TeamInviteReminderData, message string, errorWhenNotSent bool, isSystemAdmin bool, isFirstAdmin bool) ([]*model.EmailInviteWithError, error)
|
||||||
SendDeactivateAccountEmail(email string, locale, siteURL string) error
|
SendDeactivateAccountEmail(email string, locale, siteURL string) error
|
||||||
SendNotificationMail(to, subject, htmlBody string) error
|
SendNotificationMail(to, subject, htmlBody string) error
|
||||||
SendMailWithEmbeddedFiles(to, subject, htmlBody string, embeddedFiles map[string]io.Reader, messageID string, inReplyTo string, references string) error
|
SendMailWithEmbeddedFiles(to, subject, htmlBody string, embeddedFiles map[string]io.Reader, messageID string, inReplyTo string, references string, category string) error
|
||||||
SendLicenseUpForRenewalEmail(email, name, locale, siteURL, renewalLink string, daysToExpiration int) error
|
SendLicenseUpForRenewalEmail(email, name, locale, siteURL, renewalLink string, daysToExpiration int) error
|
||||||
SendPaymentFailedEmail(email string, locale string, failedPayment *model.FailedPayment, planName, siteURL string) (bool, error)
|
SendPaymentFailedEmail(email string, locale string, failedPayment *model.FailedPayment, planName, siteURL string) (bool, error)
|
||||||
// Cloud delinquency email sequence
|
// Cloud delinquency email sequence
|
||||||
|
|||||||
@@ -130,7 +130,7 @@ func (a *App) sendNotificationEmail(c request.CTX, notification *PostNotificatio
|
|||||||
}
|
}
|
||||||
|
|
||||||
a.Srv().Go(func() {
|
a.Srv().Go(func() {
|
||||||
if nErr := a.Srv().EmailService.SendMailWithEmbeddedFiles(user.Email, html.UnescapeString(subjectText), bodyText, embeddedFiles, messageID, inReplyTo, references); nErr != nil {
|
if nErr := a.Srv().EmailService.SendMailWithEmbeddedFiles(user.Email, html.UnescapeString(subjectText), bodyText, embeddedFiles, messageID, inReplyTo, references, "Notification"); nErr != nil {
|
||||||
mlog.Error("Error while sending the email", mlog.String("user_email", user.Email), mlog.Err(nErr))
|
mlog.Error("Error while sending the email", mlog.String("user_email", user.Email), mlog.Err(nErr))
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -121,7 +121,7 @@ func (s *Server) DoSecurityUpdateCheck() {
|
|||||||
mlog.Info("Sending security bulletin", mlog.String("bulletin_id", bulletin.Id), mlog.String("user_email", user.Email))
|
mlog.Info("Sending security bulletin", mlog.String("bulletin_id", bulletin.Id), mlog.String("user_email", user.Email))
|
||||||
license := s.License()
|
license := s.License()
|
||||||
mailConfig := s.MailServiceConfig()
|
mailConfig := s.MailServiceConfig()
|
||||||
mail.SendMailUsingConfig(user.Email, i18n.T("mattermost.bulletin.subject"), string(body), mailConfig, license != nil && *license.Features.Compliance, "", "", "", "")
|
mail.SendMailUsingConfig(user.Email, i18n.T("mattermost.bulletin.subject"), string(body), mailConfig, license != nil && *license.Features.Compliance, "", "", "", "", "SecurityUpdateCheck")
|
||||||
}
|
}
|
||||||
|
|
||||||
bulletinSeen := &model.System{Name: "SecurityBulletin_" + bulletin.Id, Value: bulletin.Id}
|
bulletinSeen := &model.System{Name: "SecurityBulletin_" + bulletin.Id, Value: bulletin.Id}
|
||||||
|
|||||||
@@ -57,6 +57,7 @@ type mailData struct {
|
|||||||
messageID string
|
messageID string
|
||||||
inReplyTo string
|
inReplyTo string
|
||||||
references string
|
references string
|
||||||
|
category string
|
||||||
}
|
}
|
||||||
|
|
||||||
// smtpClient is implemented by an smtp.Client. See https://golang.org/pkg/net/smtp/#Client.
|
// smtpClient is implemented by an smtp.Client. See https://golang.org/pkg/net/smtp/#Client.
|
||||||
@@ -234,7 +235,7 @@ func TestConnection(config *SMTPConfig) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func SendMailWithEmbeddedFilesUsingConfig(to, subject, htmlBody string, embeddedFiles map[string]io.Reader, config *SMTPConfig, enableComplianceFeatures bool, messageID string, inReplyTo string, references string, ccMail string) error {
|
func SendMailWithEmbeddedFilesUsingConfig(to, subject, htmlBody string, embeddedFiles map[string]io.Reader, config *SMTPConfig, enableComplianceFeatures bool, messageID string, inReplyTo string, references string, ccMail string, category string) error {
|
||||||
fromMail := mail.Address{Name: config.FeedbackName, Address: config.FeedbackEmail}
|
fromMail := mail.Address{Name: config.FeedbackName, Address: config.FeedbackEmail}
|
||||||
replyTo := mail.Address{Name: config.FeedbackName, Address: config.ReplyToAddress}
|
replyTo := mail.Address{Name: config.FeedbackName, Address: config.ReplyToAddress}
|
||||||
|
|
||||||
@@ -250,13 +251,14 @@ func SendMailWithEmbeddedFilesUsingConfig(to, subject, htmlBody string, embedded
|
|||||||
messageID: messageID,
|
messageID: messageID,
|
||||||
inReplyTo: inReplyTo,
|
inReplyTo: inReplyTo,
|
||||||
references: references,
|
references: references,
|
||||||
|
category: category,
|
||||||
}
|
}
|
||||||
|
|
||||||
return sendMailUsingConfigAdvanced(mail, config)
|
return sendMailUsingConfigAdvanced(mail, config)
|
||||||
}
|
}
|
||||||
|
|
||||||
func SendMailUsingConfig(to, subject, htmlBody string, config *SMTPConfig, enableComplianceFeatures bool, messageID string, inReplyTo string, references string, ccMail string) error {
|
func SendMailUsingConfig(to, subject, htmlBody string, config *SMTPConfig, enableComplianceFeatures bool, messageID string, inReplyTo string, references string, ccMail, category string) error {
|
||||||
return SendMailWithEmbeddedFilesUsingConfig(to, subject, htmlBody, nil, config, enableComplianceFeatures, messageID, inReplyTo, references, ccMail)
|
return SendMailWithEmbeddedFilesUsingConfig(to, subject, htmlBody, nil, config, enableComplianceFeatures, messageID, inReplyTo, references, ccMail, category)
|
||||||
}
|
}
|
||||||
|
|
||||||
// allows for sending an email with differing MIME/SMTP recipients
|
// allows for sending an email with differing MIME/SMTP recipients
|
||||||
@@ -287,6 +289,8 @@ func sendMailUsingConfigAdvanced(mail mailData, config *SMTPConfig) error {
|
|||||||
return sendMail(c, mail, time.Now(), config)
|
return sendMail(c, mail, time.Now(), config)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const SendGridXSMTPAPIHeader = "X-SMTPAPI"
|
||||||
|
|
||||||
func sendMail(c smtpClient, mail mailData, date time.Time, config *SMTPConfig) error {
|
func sendMail(c smtpClient, mail mailData, date time.Time, config *SMTPConfig) error {
|
||||||
mlog.Debug("sending mail", mlog.String("to", mail.smtpTo), mlog.String("subject", mail.subject))
|
mlog.Debug("sending mail", mlog.String("to", mail.smtpTo), mlog.String("subject", mail.subject))
|
||||||
|
|
||||||
@@ -307,6 +311,11 @@ func sendMail(c smtpClient, mail mailData, date time.Time, config *SMTPConfig) e
|
|||||||
"Precedence": {"bulk"},
|
"Precedence": {"bulk"},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if mail.category != "" {
|
||||||
|
sendgridHeader := fmt.Sprintf(`{"category": %q}`, mail.category)
|
||||||
|
headers[SendGridXSMTPAPIHeader] = []string{sendgridHeader}
|
||||||
|
}
|
||||||
|
|
||||||
if mail.replyTo.Address != "" {
|
if mail.replyTo.Address != "" {
|
||||||
headers["Reply-To"] = []string{mail.replyTo.String()}
|
headers["Reply-To"] = []string{mail.replyTo.String()}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -124,7 +124,7 @@ func TestSendMailUsingConfig(t *testing.T) {
|
|||||||
//Delete all the messages before check the sample email
|
//Delete all the messages before check the sample email
|
||||||
DeleteMailBox(emailTo)
|
DeleteMailBox(emailTo)
|
||||||
|
|
||||||
err2 := SendMailUsingConfig(emailTo, emailSubject, emailBody, cfg, true, "", "", "", emailCC)
|
err2 := SendMailUsingConfig(emailTo, emailSubject, emailBody, cfg, true, "", "", "", emailCC, "")
|
||||||
require.NoError(t, err2, "Should connect to the SMTP Server")
|
require.NoError(t, err2, "Should connect to the SMTP Server")
|
||||||
|
|
||||||
//Check if the email was send to the right email address
|
//Check if the email was send to the right email address
|
||||||
@@ -162,7 +162,7 @@ func TestSendMailWithEmbeddedFilesUsingConfig(t *testing.T) {
|
|||||||
"test1.png": bytes.NewReader([]byte("xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx")),
|
"test1.png": bytes.NewReader([]byte("xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx")),
|
||||||
"test2.png": bytes.NewReader([]byte("xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx")),
|
"test2.png": bytes.NewReader([]byte("xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx")),
|
||||||
}
|
}
|
||||||
err2 := SendMailWithEmbeddedFilesUsingConfig(emailTo, emailSubject, emailBody, embeddedFiles, cfg, true, "", "", "", emailCC)
|
err2 := SendMailWithEmbeddedFilesUsingConfig(emailTo, emailSubject, emailBody, embeddedFiles, cfg, true, "", "", "", emailCC, "")
|
||||||
require.NoError(t, err2, "Should connect to the SMTP Server")
|
require.NoError(t, err2, "Should connect to the SMTP Server")
|
||||||
|
|
||||||
//Check if the email was send to the right email address
|
//Check if the email was send to the right email address
|
||||||
@@ -407,7 +407,7 @@ func TestSendMail(t *testing.T) {
|
|||||||
|
|
||||||
for testName, tc := range testCases {
|
for testName, tc := range testCases {
|
||||||
t.Run(testName, func(t *testing.T) {
|
t.Run(testName, func(t *testing.T) {
|
||||||
mail := mailData{"", "", mail.Address{}, "", tc.replyTo, "", "", nil, nil, tc.messageID, tc.inReplyTo, tc.references}
|
mail := mailData{"", "", mail.Address{}, "", tc.replyTo, "", "", nil, nil, tc.messageID, tc.inReplyTo, tc.references, ""}
|
||||||
cfg := getConfig()
|
cfg := getConfig()
|
||||||
err = sendMail(mocm, mail, time.Now(), cfg)
|
err = sendMail(mocm, mail, time.Now(), cfg)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|||||||
Ссылка в новой задаче
Block a user