github.com/gigforks/mattermost-server@v4.9.1-0.20180619094218-800d97fa55d0+incompatible/app/email.go (about)

     1  // Copyright (c) 2017-present Mattermost, Inc. All Rights Reserved.
     2  // See License.txt for license information.
     3  
     4  package app
     5  
     6  import (
     7  	"fmt"
     8  	"net/url"
     9  
    10  	"net/http"
    11  
    12  	"github.com/nicksnyder/go-i18n/i18n"
    13  
    14  	"github.com/mattermost/mattermost-server/mlog"
    15  	"github.com/mattermost/mattermost-server/model"
    16  	"github.com/mattermost/mattermost-server/utils"
    17  )
    18  
    19  func (a *App) SendChangeUsernameEmail(oldUsername, newUsername, email, locale, siteURL string) *model.AppError {
    20  	T := utils.GetUserTranslations(locale)
    21  
    22  	subject := T("api.templates.username_change_subject",
    23  		map[string]interface{}{"SiteName": a.ClientConfig()["SiteName"],
    24  			"TeamDisplayName": a.Config().TeamSettings.SiteName})
    25  
    26  	bodyPage := a.NewEmailTemplate("email_change_body", locale)
    27  	bodyPage.Props["SiteURL"] = siteURL
    28  	bodyPage.Props["Title"] = T("api.templates.username_change_body.title")
    29  	bodyPage.Html["Info"] = utils.TranslateAsHtml(T, "api.templates.username_change_body.info",
    30  		map[string]interface{}{"TeamDisplayName": a.Config().TeamSettings.SiteName, "NewUsername": newUsername})
    31  
    32  	if err := a.SendMail(email, subject, bodyPage.Render()); err != nil {
    33  		return model.NewAppError("SendChangeUsernameEmail", "api.user.send_email_change_username_and_forget.error", nil, err.Error(), http.StatusInternalServerError)
    34  	}
    35  
    36  	return nil
    37  }
    38  
    39  func (a *App) SendEmailChangeVerifyEmail(newUserEmail, locale, siteURL, token string) *model.AppError {
    40  	T := utils.GetUserTranslations(locale)
    41  
    42  	link := fmt.Sprintf("%s/do_verify_email?token=%s&email=%s", siteURL, token, url.QueryEscape(newUserEmail))
    43  
    44  	subject := T("api.templates.email_change_verify_subject",
    45  		map[string]interface{}{"SiteName": a.ClientConfig()["SiteName"],
    46  			"TeamDisplayName": a.Config().TeamSettings.SiteName})
    47  
    48  	bodyPage := a.NewEmailTemplate("email_change_verify_body", locale)
    49  	bodyPage.Props["SiteURL"] = siteURL
    50  	bodyPage.Props["Title"] = T("api.templates.email_change_verify_body.title")
    51  	bodyPage.Props["Info"] = T("api.templates.email_change_verify_body.info",
    52  		map[string]interface{}{"TeamDisplayName": a.Config().TeamSettings.SiteName})
    53  	bodyPage.Props["VerifyUrl"] = link
    54  	bodyPage.Props["VerifyButton"] = T("api.templates.email_change_verify_body.button")
    55  
    56  	if err := a.SendMail(newUserEmail, subject, bodyPage.Render()); err != nil {
    57  		return model.NewAppError("SendEmailChangeVerifyEmail", "api.user.send_email_change_verify_email_and_forget.error", nil, err.Error(), http.StatusInternalServerError)
    58  	}
    59  
    60  	return nil
    61  }
    62  
    63  func (a *App) SendEmailChangeEmail(oldEmail, newEmail, locale, siteURL string) *model.AppError {
    64  	T := utils.GetUserTranslations(locale)
    65  
    66  	subject := T("api.templates.email_change_subject",
    67  		map[string]interface{}{"SiteName": a.ClientConfig()["SiteName"],
    68  			"TeamDisplayName": a.Config().TeamSettings.SiteName})
    69  
    70  	bodyPage := a.NewEmailTemplate("email_change_body", locale)
    71  	bodyPage.Props["SiteURL"] = siteURL
    72  	bodyPage.Props["Title"] = T("api.templates.email_change_body.title")
    73  	bodyPage.Html["Info"] = utils.TranslateAsHtml(T, "api.templates.email_change_body.info",
    74  		map[string]interface{}{"TeamDisplayName": a.Config().TeamSettings.SiteName, "NewEmail": newEmail})
    75  
    76  	if err := a.SendMail(oldEmail, subject, bodyPage.Render()); err != nil {
    77  		return model.NewAppError("SendEmailChangeEmail", "api.user.send_email_change_email_and_forget.error", nil, err.Error(), http.StatusInternalServerError)
    78  	}
    79  
    80  	return nil
    81  }
    82  
    83  func (a *App) SendVerifyEmail(userEmail, locale, siteURL, token string) *model.AppError {
    84  	T := utils.GetUserTranslations(locale)
    85  
    86  	link := fmt.Sprintf("%s/do_verify_email?token=%s&email=%s", siteURL, token, url.QueryEscape(userEmail))
    87  
    88  	url, _ := url.Parse(siteURL)
    89  
    90  	subject := T("api.templates.verify_subject",
    91  		map[string]interface{}{"SiteName": a.ClientConfig()["SiteName"]})
    92  
    93  	bodyPage := a.NewEmailTemplate("verify_body", locale)
    94  	bodyPage.Props["SiteURL"] = siteURL
    95  	bodyPage.Props["Title"] = T("api.templates.verify_body.title", map[string]interface{}{"ServerURL": url.Host})
    96  	bodyPage.Props["Info"] = T("api.templates.verify_body.info")
    97  	bodyPage.Props["VerifyUrl"] = link
    98  	bodyPage.Props["Button"] = T("api.templates.verify_body.button")
    99  
   100  	if err := a.SendMail(userEmail, subject, bodyPage.Render()); err != nil {
   101  		return model.NewAppError("SendVerifyEmail", "api.user.send_verify_email_and_forget.failed.error", nil, err.Error(), http.StatusInternalServerError)
   102  	}
   103  
   104  	return nil
   105  }
   106  
   107  func (a *App) SendSignInChangeEmail(email, method, locale, siteURL string) *model.AppError {
   108  	T := utils.GetUserTranslations(locale)
   109  
   110  	subject := T("api.templates.signin_change_email.subject",
   111  		map[string]interface{}{"SiteName": a.ClientConfig()["SiteName"]})
   112  
   113  	bodyPage := a.NewEmailTemplate("signin_change_body", locale)
   114  	bodyPage.Props["SiteURL"] = siteURL
   115  	bodyPage.Props["Title"] = T("api.templates.signin_change_email.body.title")
   116  	bodyPage.Html["Info"] = utils.TranslateAsHtml(T, "api.templates.signin_change_email.body.info",
   117  		map[string]interface{}{"SiteName": a.ClientConfig()["SiteName"], "Method": method})
   118  
   119  	if err := a.SendMail(email, subject, bodyPage.Render()); err != nil {
   120  		return model.NewAppError("SendSignInChangeEmail", "api.user.send_sign_in_change_email_and_forget.error", nil, err.Error(), http.StatusInternalServerError)
   121  	}
   122  
   123  	return nil
   124  }
   125  
   126  func (a *App) SendWelcomeEmail(userId string, email string, verified bool, locale, siteURL string) *model.AppError {
   127  	T := utils.GetUserTranslations(locale)
   128  
   129  	rawUrl, _ := url.Parse(siteURL)
   130  
   131  	subject := T("api.templates.welcome_subject",
   132  		map[string]interface{}{"SiteName": a.ClientConfig()["SiteName"],
   133  			"ServerURL": rawUrl.Host})
   134  
   135  	bodyPage := a.NewEmailTemplate("welcome_body", locale)
   136  	bodyPage.Props["SiteURL"] = siteURL
   137  	bodyPage.Props["Title"] = T("api.templates.welcome_body.title", map[string]interface{}{"ServerURL": rawUrl.Host})
   138  	bodyPage.Props["Info"] = T("api.templates.welcome_body.info")
   139  	bodyPage.Props["Button"] = T("api.templates.welcome_body.button")
   140  	bodyPage.Props["Info2"] = T("api.templates.welcome_body.info2")
   141  	bodyPage.Props["Info3"] = T("api.templates.welcome_body.info3")
   142  	bodyPage.Props["SiteURL"] = siteURL
   143  
   144  	if *a.Config().NativeAppSettings.AppDownloadLink != "" {
   145  		bodyPage.Props["AppDownloadInfo"] = T("api.templates.welcome_body.app_download_info")
   146  		bodyPage.Props["AppDownloadLink"] = *a.Config().NativeAppSettings.AppDownloadLink
   147  	}
   148  
   149  	if !verified {
   150  		token, err := a.CreateVerifyEmailToken(userId)
   151  		if err != nil {
   152  			return err
   153  		}
   154  		link := fmt.Sprintf("%s/do_verify_email?token=%s&email=%s", siteURL, token.Token, url.QueryEscape(email))
   155  		bodyPage.Props["VerifyUrl"] = link
   156  	}
   157  
   158  	if err := a.SendMail(email, subject, bodyPage.Render()); err != nil {
   159  		return model.NewAppError("SendWelcomeEmail", "api.user.send_welcome_email_and_forget.failed.error", nil, err.Error(), http.StatusInternalServerError)
   160  	}
   161  
   162  	return nil
   163  }
   164  
   165  func (a *App) SendPasswordChangeEmail(email, method, locale, siteURL string) *model.AppError {
   166  	T := utils.GetUserTranslations(locale)
   167  
   168  	subject := T("api.templates.password_change_subject",
   169  		map[string]interface{}{"SiteName": a.ClientConfig()["SiteName"],
   170  			"TeamDisplayName": a.Config().TeamSettings.SiteName})
   171  
   172  	bodyPage := a.NewEmailTemplate("password_change_body", locale)
   173  	bodyPage.Props["SiteURL"] = siteURL
   174  	bodyPage.Props["Title"] = T("api.templates.password_change_body.title")
   175  	bodyPage.Html["Info"] = utils.TranslateAsHtml(T, "api.templates.password_change_body.info",
   176  		map[string]interface{}{"TeamDisplayName": a.Config().TeamSettings.SiteName, "TeamURL": siteURL, "Method": method})
   177  
   178  	if err := a.SendMail(email, subject, bodyPage.Render()); err != nil {
   179  		return model.NewAppError("SendPasswordChangeEmail", "api.user.send_password_change_email_and_forget.error", nil, err.Error(), http.StatusInternalServerError)
   180  	}
   181  
   182  	return nil
   183  }
   184  
   185  func (a *App) SendUserAccessTokenAddedEmail(email, locale string) *model.AppError {
   186  	T := utils.GetUserTranslations(locale)
   187  
   188  	subject := T("api.templates.user_access_token_subject",
   189  		map[string]interface{}{"SiteName": a.ClientConfig()["SiteName"]})
   190  
   191  	bodyPage := a.NewEmailTemplate("password_change_body", locale)
   192  	bodyPage.Props["Title"] = T("api.templates.user_access_token_body.title")
   193  	bodyPage.Html["Info"] = utils.TranslateAsHtml(T, "api.templates.user_access_token_body.info",
   194  		map[string]interface{}{"SiteName": a.ClientConfig()["SiteName"], "SiteURL": a.GetSiteURL()})
   195  
   196  	if err := a.SendMail(email, subject, bodyPage.Render()); err != nil {
   197  		return model.NewAppError("SendUserAccessTokenAddedEmail", "api.user.send_user_access_token.error", nil, err.Error(), http.StatusInternalServerError)
   198  	}
   199  
   200  	return nil
   201  }
   202  
   203  func (a *App) SendPasswordResetEmail(email string, token *model.Token, locale, siteURL string) (bool, *model.AppError) {
   204  
   205  	T := utils.GetUserTranslations(locale)
   206  
   207  	link := fmt.Sprintf("%s/reset_password_complete?token=%s", siteURL, url.QueryEscape(token.Token))
   208  
   209  	subject := T("api.templates.reset_subject",
   210  		map[string]interface{}{"SiteName": a.ClientConfig()["SiteName"]})
   211  
   212  	bodyPage := a.NewEmailTemplate("reset_body", locale)
   213  	bodyPage.Props["SiteURL"] = siteURL
   214  	bodyPage.Props["Title"] = T("api.templates.reset_body.title")
   215  	bodyPage.Html["Info"] = utils.TranslateAsHtml(T, "api.templates.reset_body.info", nil)
   216  	bodyPage.Props["ResetUrl"] = link
   217  	bodyPage.Props["Button"] = T("api.templates.reset_body.button")
   218  
   219  	if err := a.SendMail(email, subject, bodyPage.Render()); err != nil {
   220  		return false, model.NewAppError("SendPasswordReset", "api.user.send_password_reset.send.app_error", nil, "err="+err.Message, http.StatusInternalServerError)
   221  	}
   222  
   223  	return true, nil
   224  }
   225  
   226  func (a *App) SendMfaChangeEmail(email string, activated bool, locale, siteURL string) *model.AppError {
   227  	T := utils.GetUserTranslations(locale)
   228  
   229  	subject := T("api.templates.mfa_change_subject",
   230  		map[string]interface{}{"SiteName": a.ClientConfig()["SiteName"]})
   231  
   232  	bodyPage := a.NewEmailTemplate("mfa_change_body", locale)
   233  	bodyPage.Props["SiteURL"] = siteURL
   234  
   235  	bodyText := ""
   236  	if activated {
   237  		bodyText = "api.templates.mfa_activated_body.info"
   238  		bodyPage.Props["Title"] = T("api.templates.mfa_activated_body.title")
   239  	} else {
   240  		bodyText = "api.templates.mfa_deactivated_body.info"
   241  		bodyPage.Props["Title"] = T("api.templates.mfa_deactivated_body.title")
   242  	}
   243  
   244  	bodyPage.Html["Info"] = utils.TranslateAsHtml(T, bodyText, map[string]interface{}{"SiteURL": siteURL})
   245  
   246  	if err := a.SendMail(email, subject, bodyPage.Render()); err != nil {
   247  		return model.NewAppError("SendMfaChangeEmail", "api.user.send_mfa_change_email.error", nil, err.Error(), http.StatusInternalServerError)
   248  	}
   249  
   250  	return nil
   251  }
   252  
   253  func (a *App) SendInviteEmails(team *model.Team, senderName string, invites []string, siteURL string) {
   254  	for _, invite := range invites {
   255  		if len(invite) > 0 {
   256  			senderRole := utils.T("api.team.invite_members.member")
   257  
   258  			subject := utils.T("api.templates.invite_subject",
   259  				map[string]interface{}{"SenderName": senderName,
   260  					"TeamDisplayName": team.DisplayName,
   261  					"SiteName":        a.ClientConfig()["SiteName"]})
   262  
   263  			bodyPage := a.NewEmailTemplate("invite_body", model.DEFAULT_LOCALE)
   264  			bodyPage.Props["SiteURL"] = siteURL
   265  			bodyPage.Props["Title"] = utils.T("api.templates.invite_body.title")
   266  			bodyPage.Html["Info"] = utils.TranslateAsHtml(utils.T, "api.templates.invite_body.info",
   267  				map[string]interface{}{"SenderStatus": senderRole, "SenderName": senderName, "TeamDisplayName": team.DisplayName})
   268  			bodyPage.Props["Info"] = map[string]interface{}{}
   269  			bodyPage.Props["Button"] = utils.T("api.templates.invite_body.button")
   270  			bodyPage.Html["ExtraInfo"] = utils.TranslateAsHtml(utils.T, "api.templates.invite_body.extra_info",
   271  				map[string]interface{}{"TeamDisplayName": team.DisplayName, "TeamURL": siteURL + "/" + team.Name})
   272  
   273  			token := model.NewToken(
   274  				TOKEN_TYPE_TEAM_INVITATION,
   275  				model.MapToJson(map[string]string{"teamId": team.Id, "email": invite}),
   276  			)
   277  
   278  			props := make(map[string]string)
   279  			props["email"] = invite
   280  			props["display_name"] = team.DisplayName
   281  			props["name"] = team.Name
   282  			data := model.MapToJson(props)
   283  
   284  			if result := <-a.Srv.Store.Token().Save(token); result.Err != nil {
   285  				mlog.Error(fmt.Sprintf("Failed to send invite email successfully err=%v", result.Err))
   286  				continue
   287  			}
   288  			bodyPage.Props["Link"] = fmt.Sprintf("%s/signup_user_complete/?d=%s&t=%s", siteURL, url.QueryEscape(data), url.QueryEscape(token.Token))
   289  
   290  			if !a.Config().EmailSettings.SendEmailNotifications {
   291  				mlog.Info(fmt.Sprintf("sending invitation to %v %v", invite, bodyPage.Props["Link"]))
   292  			}
   293  
   294  			if err := a.SendMail(invite, subject, bodyPage.Render()); err != nil {
   295  				mlog.Error(fmt.Sprintf("Failed to send invite email successfully err=%v", err))
   296  			}
   297  		}
   298  	}
   299  }
   300  
   301  func (a *App) NewEmailTemplate(name, locale string) *utils.HTMLTemplate {
   302  	t := utils.NewHTMLTemplate(a.HTMLTemplates(), name)
   303  
   304  	var localT i18n.TranslateFunc
   305  	if locale != "" {
   306  		localT = utils.GetUserTranslations(locale)
   307  	} else {
   308  		localT = utils.T
   309  	}
   310  
   311  	t.Props["Footer"] = localT("api.templates.email_footer")
   312  
   313  	if *a.Config().EmailSettings.FeedbackOrganization != "" {
   314  		t.Props["Organization"] = localT("api.templates.email_organization") + *a.Config().EmailSettings.FeedbackOrganization
   315  	} else {
   316  		t.Props["Organization"] = ""
   317  	}
   318  
   319  	t.Html["EmailInfo"] = utils.TranslateAsHtml(localT, "api.templates.email_info",
   320  		map[string]interface{}{"SupportEmail": *a.Config().SupportSettings.SupportEmail, "SiteName": a.Config().TeamSettings.SiteName})
   321  
   322  	return t
   323  }
   324  
   325  func (a *App) SendMail(to, subject, htmlBody string) *model.AppError {
   326  	license := a.License()
   327  	return utils.SendMailUsingConfig(to, subject, htmlBody, a.Config(), license != nil && *license.Features.Compliance)
   328  }