func signupTeam(c *Context, w http.ResponseWriter, r *http.Request) { if !utils.Cfg.EmailSettings.EnableSignUpWithEmail { c.Err = model.NewLocAppError("signupTeam", "api.team.signup_team.email_disabled.app_error", nil, "") c.Err.StatusCode = http.StatusNotImplemented return } m := model.MapFromJson(r.Body) email := strings.ToLower(strings.TrimSpace(m["email"])) if len(email) == 0 { c.SetInvalidParam("signupTeam", "email") return } if !isTeamCreationAllowed(c, email) { return } subjectPage := utils.NewHTMLTemplate("signup_team_subject", c.Locale) subjectPage.Props["Subject"] = c.T("api.templates.signup_team_subject", map[string]interface{}{"SiteName": utils.ClientCfg["SiteName"]}) bodyPage := utils.NewHTMLTemplate("signup_team_body", c.Locale) bodyPage.Props["SiteURL"] = c.GetSiteURL() bodyPage.Props["Title"] = c.T("api.templates.signup_team_body.title") bodyPage.Props["Button"] = c.T("api.templates.signup_team_body.button") bodyPage.Html["Info"] = template.HTML(c.T("api.templates.signup_team_body.info", map[string]interface{}{"SiteName": utils.ClientCfg["SiteName"]})) props := make(map[string]string) props["email"] = email props["time"] = fmt.Sprintf("%v", model.GetMillis()) data := model.MapToJson(props) hash := model.HashPassword(fmt.Sprintf("%v:%v", data, utils.Cfg.EmailSettings.InviteSalt)) bodyPage.Props["Link"] = fmt.Sprintf("%s/signup_team_complete/?d=%s&h=%s", c.GetSiteURL(), url.QueryEscape(data), url.QueryEscape(hash)) if err := utils.SendMail(email, subjectPage.Render(), bodyPage.Render()); err != nil { c.Err = err return } if !utils.Cfg.EmailSettings.RequireEmailVerification { m["follow_link"] = fmt.Sprintf("/signup_team_complete/?d=%s&h=%s", url.QueryEscape(data), url.QueryEscape(hash)) } w.Header().Set("Access-Control-Allow-Origin", " *") w.Write([]byte(model.MapToJson(m))) }
func sendBatchedEmailNotification(userId string, notifications []*batchedNotification) { uchan := Srv.Store.User().Get(userId) pchan := Srv.Store.Preference().Get(userId, model.PREFERENCE_CATEGORY_DISPLAY_SETTINGS, model.PREFERENCE_NAME_DISPLAY_NAME_FORMAT) var user *model.User if result := <-uchan; result.Err != nil { l4g.Warn("api.email_batching.send_batched_email_notification.user.app_error") return } else { user = result.Data.(*model.User) } translateFunc := utils.GetUserTranslations(user.Locale) var displayNameFormat string if result := <-pchan; result.Err != nil && result.Err.DetailedError != sql.ErrNoRows.Error() { l4g.Warn("api.email_batching.send_batched_email_notification.preferences.app_error") return } else if result.Err != nil { // no display name format saved, so fall back to default displayNameFormat = model.PREFERENCE_DEFAULT_DISPLAY_NAME_FORMAT } else { displayNameFormat = result.Data.(model.Preference).Value } var contents string for _, notification := range notifications { template := utils.NewHTMLTemplate("post_batched_post", user.Locale) contents += renderBatchedPost(template, notification.post, notification.teamName, displayNameFormat, translateFunc) } tm := time.Unix(notifications[0].post.CreateAt/1000, 0) subject := translateFunc("api.email_batching.send_batched_email_notification.subject", len(notifications), map[string]interface{}{ "SiteName": utils.Cfg.TeamSettings.SiteName, "Year": tm.Year(), "Month": translateFunc(tm.Month().String()), "Day": tm.Day(), }) body := utils.NewHTMLTemplate("post_batched_body", user.Locale) body.Props["SiteURL"] = *utils.Cfg.ServiceSettings.SiteURL body.Props["Posts"] = template.HTML(contents) body.Props["BodyText"] = translateFunc("api.email_batching.send_batched_email_notification.body_text", len(notifications)) if err := utils.SendMail(user.Email, subject, body.Render()); err != nil { l4g.Warn(utils.T("api.email_batchings.send_batched_email_notification.send.app_error"), user.Email, err) } }
func InviteMembers(c *Context, team *model.Team, user *model.User, invites []string) { for _, invite := range invites { if len(invite) > 0 { sender := user.GetDisplayName() senderRole := "" if c.IsTeamAdmin() { senderRole = c.T("api.team.invite_members.admin") } else { senderRole = c.T("api.team.invite_members.member") } subjectPage := utils.NewHTMLTemplate("invite_subject", c.Locale) subjectPage.Props["Subject"] = c.T("api.templates.invite_subject", map[string]interface{}{"SenderName": sender, "TeamDisplayName": team.DisplayName, "SiteName": utils.ClientCfg["SiteName"]}) bodyPage := utils.NewHTMLTemplate("invite_body", c.Locale) bodyPage.Props["SiteURL"] = c.GetSiteURL() bodyPage.Props["Title"] = c.T("api.templates.invite_body.title") bodyPage.Html["Info"] = template.HTML(c.T("api.templates.invite_body.info", map[string]interface{}{"SenderStatus": senderRole, "SenderName": sender, "TeamDisplayName": team.DisplayName})) bodyPage.Props["Button"] = c.T("api.templates.invite_body.button") bodyPage.Html["ExtraInfo"] = template.HTML(c.T("api.templates.invite_body.extra_info", map[string]interface{}{"TeamDisplayName": team.DisplayName, "TeamURL": c.GetTeamURL()})) props := make(map[string]string) props["email"] = invite props["id"] = team.Id props["display_name"] = team.DisplayName props["name"] = team.Name props["time"] = fmt.Sprintf("%v", model.GetMillis()) data := model.MapToJson(props) hash := model.HashPassword(fmt.Sprintf("%v:%v", data, utils.Cfg.EmailSettings.InviteSalt)) bodyPage.Props["Link"] = fmt.Sprintf("%s/signup_user_complete/?d=%s&h=%s", c.GetSiteURL(), url.QueryEscape(data), url.QueryEscape(hash)) if !utils.Cfg.EmailSettings.SendEmailNotifications { l4g.Info(utils.T("api.team.invite_members.sending.info"), invite, bodyPage.Props["Link"]) } if err := utils.SendMail(invite, subjectPage.Render(), bodyPage.Render()); err != nil { l4g.Error(utils.T("api.team.invite_members.send.error"), err) } } } }
func authorizeOAuth(c *Context, w http.ResponseWriter, r *http.Request) { if !utils.Cfg.ServiceSettings.EnableOAuthServiceProvider { c.Err = model.NewLocAppError("authorizeOAuth", "web.authorize_oauth.disabled.app_error", nil, "") c.Err.StatusCode = http.StatusNotImplemented return } responseType := r.URL.Query().Get("response_type") clientId := r.URL.Query().Get("client_id") redirect := r.URL.Query().Get("redirect_uri") scope := r.URL.Query().Get("scope") state := r.URL.Query().Get("state") if len(responseType) == 0 || len(clientId) == 0 || len(redirect) == 0 { c.Err = model.NewLocAppError("authorizeOAuth", "web.authorize_oauth.missing.app_error", nil, "") return } var app *model.OAuthApp if result := <-Srv.Store.OAuth().GetApp(clientId); result.Err != nil { c.Err = result.Err return } else { app = result.Data.(*model.OAuthApp) } var team *model.Team if result := <-Srv.Store.Team().Get(c.TeamId); result.Err != nil { c.Err = result.Err return } else { team = result.Data.(*model.Team) } page := utils.NewHTMLTemplate("authorize", c.Locale) page.Props["Title"] = c.T("web.authorize_oauth.title") page.Props["TeamName"] = team.Name page.Props["AppName"] = app.Name page.Props["ResponseType"] = responseType page.Props["ClientId"] = clientId page.Props["RedirectUri"] = redirect page.Props["Scope"] = scope page.Props["State"] = state if err := page.RenderToWriter(w); err != nil { c.SetUnknownError(page.TemplateName, err.Error()) } }
func InviteMembers(team *model.Team, senderName string, invites []string) { for _, invite := range invites { if len(invite) > 0 { senderRole := utils.T("api.team.invite_members.member") subject := utils.T("api.templates.invite_subject", map[string]interface{}{"SenderName": senderName, "TeamDisplayName": team.DisplayName, "SiteName": utils.ClientCfg["SiteName"]}) bodyPage := utils.NewHTMLTemplate("invite_body", model.DEFAULT_LOCALE) bodyPage.Props["SiteURL"] = *utils.Cfg.ServiceSettings.SiteURL bodyPage.Props["Title"] = utils.T("api.templates.invite_body.title") bodyPage.Html["Info"] = template.HTML(utils.T("api.templates.invite_body.info", map[string]interface{}{"SenderStatus": senderRole, "SenderName": senderName, "TeamDisplayName": team.DisplayName})) bodyPage.Props["Button"] = utils.T("api.templates.invite_body.button") bodyPage.Html["ExtraInfo"] = template.HTML(utils.T("api.templates.invite_body.extra_info", map[string]interface{}{"TeamDisplayName": team.DisplayName, "TeamURL": *utils.Cfg.ServiceSettings.SiteURL + "/" + team.Name})) props := make(map[string]string) props["email"] = invite props["id"] = team.Id props["display_name"] = team.DisplayName props["name"] = team.Name props["time"] = fmt.Sprintf("%v", model.GetMillis()) data := model.MapToJson(props) hash := model.HashPassword(fmt.Sprintf("%v:%v", data, utils.Cfg.EmailSettings.InviteSalt)) bodyPage.Props["Link"] = fmt.Sprintf("%s/signup_user_complete/?d=%s&h=%s", *utils.Cfg.ServiceSettings.SiteURL, url.QueryEscape(data), url.QueryEscape(hash)) if !utils.Cfg.EmailSettings.SendEmailNotifications { l4g.Info(utils.T("api.team.invite_members.sending.info"), invite, bodyPage.Props["Link"]) } if err := utils.SendMail(invite, subject, bodyPage.Render()); err != nil { l4g.Error(utils.T("api.team.invite_members.send.error"), err) } } } }
func sendNotifications(c *Context, post *model.Post, team *model.Team, channel *model.Channel, profileMap map[string]*model.User, members []model.ChannelMember) { var channelName string var bodyText string var subjectText string var mentionedUsers []string if _, ok := profileMap[post.UserId]; !ok { l4g.Error(utils.T("api.post.send_notifications_and_forget.user_id.error"), post.UserId) return } senderName := profileMap[post.UserId].Username toEmailMap := make(map[string]bool) if channel.Type == model.CHANNEL_DIRECT { var otherUserId string if userIds := strings.Split(channel.Name, "__"); userIds[0] == post.UserId { otherUserId = userIds[1] channelName = profileMap[userIds[1]].Username } else { otherUserId = userIds[0] channelName = profileMap[userIds[0]].Username } otherUser := profileMap[otherUserId] sendEmail := true if _, ok := otherUser.NotifyProps["email"]; ok && otherUser.NotifyProps["email"] == "false" { sendEmail = false } if sendEmail && (otherUser.IsOffline() || otherUser.IsAway()) { toEmailMap[otherUserId] = true } } else { // Find out who is a member of the channel, only keep those profiles tempProfileMap := make(map[string]*model.User) for _, member := range members { tempProfileMap[member.UserId] = profileMap[member.UserId] } profileMap = tempProfileMap // Build map for keywords keywordMap := make(map[string][]string) for _, profile := range profileMap { if len(profile.NotifyProps["mention_keys"]) > 0 { // Add all the user's mention keys splitKeys := strings.Split(profile.NotifyProps["mention_keys"], ",") for _, k := range splitKeys { keywordMap[k] = append(keywordMap[strings.ToLower(k)], profile.Id) } } // If turned on, add the user's case sensitive first name if profile.NotifyProps["first_name"] == "true" { keywordMap[profile.FirstName] = append(keywordMap[profile.FirstName], profile.Id) } // Add @all to keywords if user has them turned on // if profile.NotifyProps["all"] == "true" { // keywordMap["@all"] = append(keywordMap["@all"], profile.Id) // } // Add @channel to keywords if user has them turned on if profile.NotifyProps["channel"] == "true" { keywordMap["@channel"] = append(keywordMap["@channel"], profile.Id) } } // Build a map as a list of unique user_ids that are mentioned in this post splitF := func(c rune) bool { return model.SplitRunes[c] } splitMessage := strings.Fields(post.Message) for _, word := range splitMessage { var userIds []string // Non-case-sensitive check for regular keys if ids, match := keywordMap[strings.ToLower(word)]; match { userIds = append(userIds, ids...) } // Case-sensitive check for first name if ids, match := keywordMap[word]; match { userIds = append(userIds, ids...) } if len(userIds) == 0 { // No matches were found with the string split just on whitespace so try further splitting // the message on punctuation splitWords := strings.FieldsFunc(word, splitF) for _, splitWord := range splitWords { // Non-case-sensitive check for regular keys if ids, match := keywordMap[strings.ToLower(splitWord)]; match { userIds = append(userIds, ids...) } // Case-sensitive check for first name if ids, match := keywordMap[splitWord]; match { userIds = append(userIds, ids...) } } } for _, userId := range userIds { if post.UserId == userId && post.Props["from_webhook"] != "true" { continue } sendEmail := true if _, ok := profileMap[userId].NotifyProps["email"]; ok && profileMap[userId].NotifyProps["email"] == "false" { sendEmail = false } if sendEmail && (profileMap[userId].IsAway() || profileMap[userId].IsOffline()) { toEmailMap[userId] = true } else { toEmailMap[userId] = false } } } for id := range toEmailMap { updateMentionCountAndForget(post.ChannelId, id) } } if len(toEmailMap) != 0 { mentionedUsers = make([]string, 0, len(toEmailMap)) for k := range toEmailMap { mentionedUsers = append(mentionedUsers, k) } teamURL := c.GetSiteURL() + "/" + team.Name // Build and send the emails tm := time.Unix(post.CreateAt/1000, 0) for id, doSend := range toEmailMap { if !doSend { continue } // skip if inactive if profileMap[id].DeleteAt > 0 { continue } userLocale := utils.GetUserTranslations(profileMap[id].Locale) if channel.Type == model.CHANNEL_DIRECT { bodyText = userLocale("api.post.send_notifications_and_forget.message_body") subjectText = userLocale("api.post.send_notifications_and_forget.message_subject") } else { bodyText = userLocale("api.post.send_notifications_and_forget.mention_body") subjectText = userLocale("api.post.send_notifications_and_forget.mention_subject") channelName = channel.DisplayName } month := userLocale(tm.Month().String()) day := fmt.Sprintf("%d", tm.Day()) year := fmt.Sprintf("%d", tm.Year()) zone, _ := tm.Zone() subjectPage := utils.NewHTMLTemplate("post_subject", profileMap[id].Locale) subjectPage.Props["Subject"] = userLocale("api.templates.post_subject", map[string]interface{}{"SubjectText": subjectText, "TeamDisplayName": team.DisplayName, "Month": month[:3], "Day": day, "Year": year}) subjectPage.Props["SiteName"] = utils.Cfg.TeamSettings.SiteName bodyPage := utils.NewHTMLTemplate("post_body", profileMap[id].Locale) bodyPage.Props["SiteURL"] = c.GetSiteURL() bodyPage.Props["PostMessage"] = model.ClearMentionTags(post.Message) bodyPage.Props["TeamLink"] = teamURL + "/channels/" + channel.Name bodyPage.Props["BodyText"] = bodyText bodyPage.Props["Button"] = userLocale("api.templates.post_body.button") bodyPage.Html["Info"] = template.HTML(userLocale("api.templates.post_body.info", map[string]interface{}{"ChannelName": channelName, "SenderName": senderName, "Hour": fmt.Sprintf("%02d", tm.Hour()), "Minute": fmt.Sprintf("%02d", tm.Minute()), "TimeZone": zone, "Month": month, "Day": day})) // attempt to fill in a message body if the post doesn't have any text if len(strings.TrimSpace(bodyPage.Props["PostMessage"])) == 0 && len(post.Filenames) > 0 { // extract the filenames from their paths and determine what type of files are attached filenames := make([]string, len(post.Filenames)) onlyImages := true for i, filename := range post.Filenames { var err error if filenames[i], err = url.QueryUnescape(filepath.Base(filename)); err != nil { // this should never error since filepath was escaped using url.QueryEscape filenames[i] = filepath.Base(filename) } ext := filepath.Ext(filename) onlyImages = onlyImages && model.IsFileExtImage(ext) } filenamesString := strings.Join(filenames, ", ") var attachmentPrefix string if onlyImages { attachmentPrefix = "Image" } else { attachmentPrefix = "File" } if len(post.Filenames) > 1 { attachmentPrefix += "s" } bodyPage.Props["PostMessage"] = userLocale("api.post.send_notifications_and_forget.sent", map[string]interface{}{"Prefix": attachmentPrefix, "Filenames": filenamesString}) } if err := utils.SendMail(profileMap[id].Email, subjectPage.Render(), bodyPage.Render()); err != nil { l4g.Error(utils.T("api.post.send_notifications_and_forget.send.error"), profileMap[id].Email, err) } if *utils.Cfg.EmailSettings.SendPushNotifications { sessionChan := Srv.Store.Session().GetSessions(id) if result := <-sessionChan; result.Err != nil { l4g.Error(utils.T("api.post.send_notifications_and_forget.sessions.error"), id, result.Err) } else { sessions := result.Data.([]*model.Session) alreadySeen := make(map[string]string) pushServer := *utils.Cfg.EmailSettings.PushNotificationServer if pushServer == model.MHPNS && (!utils.IsLicensed || !*utils.License.Features.MHPNS) { l4g.Warn(utils.T("api.post.send_notifications_and_forget.push_notification.mhpnsWarn")) } else { for _, session := range sessions { if len(session.DeviceId) > 0 && alreadySeen[session.DeviceId] == "" && (strings.HasPrefix(session.DeviceId, model.PUSH_NOTIFY_APPLE+":") || strings.HasPrefix(session.DeviceId, model.PUSH_NOTIFY_ANDROID+":")) { alreadySeen[session.DeviceId] = session.DeviceId msg := model.PushNotification{} if badge := <-Srv.Store.User().GetUnreadCount(id); badge.Err != nil { msg.Badge = 1 l4g.Error(utils.T("store.sql_user.get_unread_count.app_error"), id, badge.Err) } else { msg.Badge = int(badge.Data.(int64)) } msg.ServerId = utils.CfgDiagnosticId msg.ChannelId = channel.Id msg.ChannelName = channel.Name if strings.HasPrefix(session.DeviceId, model.PUSH_NOTIFY_APPLE+":") { msg.Platform = model.PUSH_NOTIFY_APPLE msg.DeviceId = strings.TrimPrefix(session.DeviceId, model.PUSH_NOTIFY_APPLE+":") } else if strings.HasPrefix(session.DeviceId, model.PUSH_NOTIFY_ANDROID+":") { msg.Platform = model.PUSH_NOTIFY_ANDROID msg.DeviceId = strings.TrimPrefix(session.DeviceId, model.PUSH_NOTIFY_ANDROID+":") } if *utils.Cfg.EmailSettings.PushNotificationContents == model.FULL_NOTIFICATION { if channel.Type == model.CHANNEL_DIRECT { msg.Category = model.CATEGORY_DM msg.Message = "@" + senderName + ": " + model.ClearMentionTags(post.Message) } else { msg.Message = "@" + senderName + " @ " + channelName + ": " + model.ClearMentionTags(post.Message) } } else { if channel.Type == model.CHANNEL_DIRECT { msg.Category = model.CATEGORY_DM msg.Message = senderName + userLocale("api.post.send_notifications_and_forget.push_message") } else { msg.Message = senderName + userLocale("api.post.send_notifications_and_forget.push_mention") + channelName } } tr := &http.Transport{ TLSClientConfig: &tls.Config{InsecureSkipVerify: *utils.Cfg.ServiceSettings.EnableInsecureOutgoingConnections}, } httpClient := &http.Client{Transport: tr} request, _ := http.NewRequest("POST", pushServer+model.API_URL_SUFFIX_V1+"/send_push", strings.NewReader(msg.ToJson())) l4g.Debug(utils.T("api.post.send_notifications_and_forget.push_notification.debug"), msg.DeviceId, msg.Message) if _, err := httpClient.Do(request); err != nil { l4g.Error(utils.T("api.post.send_notifications_and_forget.push_notification.error"), id, err) } } } } } } } } message := model.NewMessage(c.TeamId, post.ChannelId, post.UserId, model.ACTION_POSTED) message.Add("post", post.ToJson()) message.Add("channel_type", channel.Type) if len(post.Filenames) != 0 { message.Add("otherFile", "true") for _, filename := range post.Filenames { ext := filepath.Ext(filename) if model.IsFileExtImage(ext) { message.Add("image", "true") break } } } if len(mentionedUsers) != 0 { message.Add("mentions", model.ArrayToJson(mentionedUsers)) } PublishAndForget(message) }
func sendNotificationEmail(c *Context, post *model.Post, user *model.User, channel *model.Channel, team *model.Team, senderName string, sender *model.User) { // skip if inactive if user.DeleteAt > 0 { return } if channel.Type == model.CHANNEL_DIRECT && channel.TeamId != team.Id { // this message is a cross-team DM so it we need to find a team that the recipient is on to use in the link if result := <-Srv.Store.Team().GetTeamsByUserId(user.Id); result.Err != nil { l4g.Error(utils.T("api.post.send_notifications_and_forget.get_teams.error"), user.Id, result.Err) return } else { // if the recipient isn't in the current user's team, just pick one teams := result.Data.([]*model.Team) found := false for i := range teams { if teams[i].Id == team.Id { found = true break } } if !found { team = teams[0] } } } if *utils.Cfg.EmailSettings.EnableEmailBatching { var sendBatched bool if result := <-Srv.Store.Preference().Get(user.Id, model.PREFERENCE_CATEGORY_NOTIFICATIONS, model.PREFERENCE_NAME_EMAIL_INTERVAL); result.Err != nil { // if the call fails, assume it hasn't been set and use the default sendBatched = false } else { // default to not using batching if the setting is set to immediate sendBatched = result.Data.(model.Preference).Value != model.PREFERENCE_DEFAULT_EMAIL_INTERVAL } if sendBatched { if err := AddNotificationEmailToBatch(user, post, team); err == nil { return } } // fall back to sending a single email if we can't batch it for some reason } var channelName string var bodyText string var subjectText string var mailTemplate string var mailParameters map[string]interface{} teamURL := c.GetSiteURL() + "/" + team.Name tm := time.Unix(post.CreateAt/1000, 0) userLocale := utils.GetUserTranslations(user.Locale) month := userLocale(tm.Month().String()) day := fmt.Sprintf("%d", tm.Day()) year := fmt.Sprintf("%d", tm.Year()) zone, _ := tm.Zone() if channel.Type == model.CHANNEL_DIRECT { bodyText = userLocale("api.post.send_notifications_and_forget.message_body") subjectText = userLocale("api.post.send_notifications_and_forget.message_subject") senderDisplayName := senderName if sender != nil { if result := <-Srv.Store.Preference().Get(user.Id, model.PREFERENCE_CATEGORY_DISPLAY_SETTINGS, "name_format"); result.Err != nil { // Show default sender's name if user doesn't set display settings. senderDisplayName = senderName } else { senderDisplayName = sender.GetDisplayNameForPreference(result.Data.(model.Preference).Value) } } mailTemplate = "api.templates.post_subject_in_direct_message" mailParameters = map[string]interface{}{"SubjectText": subjectText, "TeamDisplayName": team.DisplayName, "SenderDisplayName": senderDisplayName, "Month": month, "Day": day, "Year": year} } else { bodyText = userLocale("api.post.send_notifications_and_forget.mention_body") subjectText = userLocale("api.post.send_notifications_and_forget.mention_subject") channelName = channel.DisplayName mailTemplate = "api.templates.post_subject_in_channel" mailParameters = map[string]interface{}{"SubjectText": subjectText, "TeamDisplayName": team.DisplayName, "ChannelName": channelName, "Month": month, "Day": day, "Year": year} } subjectPage := utils.NewHTMLTemplate("post_subject", user.Locale) subjectPage.Props["Subject"] = userLocale(mailTemplate, mailParameters) subjectPage.Props["SiteName"] = utils.Cfg.TeamSettings.SiteName bodyPage := utils.NewHTMLTemplate("post_body", user.Locale) bodyPage.Props["SiteURL"] = c.GetSiteURL() bodyPage.Props["PostMessage"] = getMessageForNotification(post, userLocale) bodyPage.Props["TeamLink"] = teamURL + "/pl/" + post.Id bodyPage.Props["BodyText"] = bodyText bodyPage.Props["Button"] = userLocale("api.templates.post_body.button") bodyPage.Html["Info"] = template.HTML(userLocale("api.templates.post_body.info", map[string]interface{}{"ChannelName": channelName, "SenderName": senderName, "Hour": fmt.Sprintf("%02d", tm.Hour()), "Minute": fmt.Sprintf("%02d", tm.Minute()), "TimeZone": zone, "Month": month, "Day": day})) if err := utils.SendMail(user.Email, html.UnescapeString(subjectPage.Render()), bodyPage.Render()); err != nil { l4g.Error(utils.T("api.post.send_notifications_and_forget.send.error"), user.Email, err) } }
func convertTeamTo30(primaryTeamName string, team *TeamForUpgrade, uniqueEmails map[string]bool, uniqueUsernames map[string]bool) []*UserForUpgrade { store := api.Srv.Store.(*store.SqlStore) var users []*UserForUpgrade if _, err := store.GetMaster().Select(&users, "SELECT Users.Id, Users.Username, Users.Email, Users.Roles, Users.TeamId FROM Users WHERE Users.TeamId = :TeamId", map[string]interface{}{"TeamId": team.Id}); err != nil { l4g.Error("Failed to load profiles for team details=%v", err) flushLogAndExit(1) } var members []*model.TeamMember if result := <-api.Srv.Store.Team().GetMembers(team.Id); result.Err != nil { l4g.Error("Failed to load team membership details=%v", result.Err) flushLogAndExit(1) } else { members = result.Data.([]*model.TeamMember) } for _, user := range users { shouldUpdateUser := false previousRole := user.Roles previousEmail := user.Email previousUsername := user.Username member := &model.TeamMember{ TeamId: team.Id, UserId: user.Id, } if model.IsInRole(user.Roles, model.ROLE_TEAM_ADMIN) { member.Roles = model.ROLE_TEAM_ADMIN user.Roles = "" shouldUpdateUser = true } exists := false for _, member := range members { if member.UserId == user.Id { exists = true break } } if !exists { if result := <-api.Srv.Store.Team().SaveMember(member); result.Err != nil { l4g.Error("Failed to save membership for %v details=%v", user.Email, result.Err) flushLogAndExit(1) } } err := api.MoveFile( "teams/"+team.Id+"/users/"+user.Id+"/profile.png", "users/"+user.Id+"/profile.png", ) if err != nil { l4g.Warn("No profile image to move for %v", user.Email) } if uniqueEmails[user.Email] { shouldUpdateUser = true emailParts := strings.Split(user.Email, "@") if len(emailParts) == 2 { user.Email = emailParts[0] + "+" + team.Name + "@" + emailParts[1] } else { user.Email = user.Email + "." + team.Name } if len(user.Email) > 127 { user.Email = user.Email[:127] } } if uniqueUsernames[user.Username] { shouldUpdateUser = true user.Username = team.Name + "." + user.Username if len(user.Username) > 63 { user.Username = user.Username[:63] } } if shouldUpdateUser { if _, err := store.GetMaster().Exec(` UPDATE Users SET Email = :Email, Username = :Username, Roles = :Roles WHERE Id = :Id `, map[string]interface{}{ "Email": user.Email, "Username": user.Username, "Roles": user.Roles, "Id": user.Id, }, ); err != nil { l4g.Error("Failed to update user %v details=%v", user.Email, err) flushLogAndExit(1) } l4g.Info("modified user_id=%v, changed email from=%v to=%v, changed username from=%v to %v changed roles from=%v to=%v", user.Id, previousEmail, user.Email, previousUsername, user.Username, previousRole, user.Roles) emailChanged := previousEmail != user.Email usernameChanged := previousUsername != user.Username if emailChanged || usernameChanged { bodyPage := utils.NewHTMLTemplate("upgrade_30_body", "") EmailChanged := "" UsernameChanged := "" if emailChanged { EmailChanged = "true" } if usernameChanged { UsernameChanged = "true" } bodyPage.Html["Info"] = template.HTML(utils.T("api.templates.upgrade_30_body.info", map[string]interface{}{ "SiteName": utils.ClientCfg["SiteName"], "TeamName": team.Name, "Email": user.Email, "Username": user.Username, "EmailChanged": EmailChanged, "UsernameChanged": UsernameChanged, })) utils.SendMail( previousEmail, utils.T("api.templates.upgrade_30_subject.info"), bodyPage.Render(), ) } } uniqueEmails[user.Email] = true uniqueUsernames[user.Username] = true } return users }
func sendNotificationEmail(c *Context, post *model.Post, user *model.User, channel *model.Channel, team *model.Team, senderName string) { // skip if inactive if user.DeleteAt > 0 { return } var channelName string var bodyText string var subjectText string teamURL := c.GetSiteURL() + "/" + team.Name tm := time.Unix(post.CreateAt/1000, 0) userLocale := utils.GetUserTranslations(user.Locale) if channel.Type == model.CHANNEL_DIRECT { bodyText = userLocale("api.post.send_notifications_and_forget.message_body") subjectText = userLocale("api.post.send_notifications_and_forget.message_subject") channelName = senderName } else { bodyText = userLocale("api.post.send_notifications_and_forget.mention_body") subjectText = userLocale("api.post.send_notifications_and_forget.mention_subject") channelName = channel.DisplayName } month := userLocale(tm.Month().String()) day := fmt.Sprintf("%d", tm.Day()) year := fmt.Sprintf("%d", tm.Year()) zone, _ := tm.Zone() subjectPage := utils.NewHTMLTemplate("post_subject", user.Locale) subjectPage.Props["Subject"] = userLocale("api.templates.post_subject", map[string]interface{}{"SubjectText": subjectText, "TeamDisplayName": team.DisplayName, "Month": month[:3], "Day": day, "Year": year}) subjectPage.Props["SiteName"] = utils.Cfg.TeamSettings.SiteName bodyPage := utils.NewHTMLTemplate("post_body", user.Locale) bodyPage.Props["SiteURL"] = c.GetSiteURL() bodyPage.Props["PostMessage"] = model.ClearMentionTags(post.Message) bodyPage.Props["TeamLink"] = teamURL + "/pl/" + post.Id bodyPage.Props["BodyText"] = bodyText bodyPage.Props["Button"] = userLocale("api.templates.post_body.button") bodyPage.Html["Info"] = template.HTML(userLocale("api.templates.post_body.info", map[string]interface{}{"ChannelName": channelName, "SenderName": senderName, "Hour": fmt.Sprintf("%02d", tm.Hour()), "Minute": fmt.Sprintf("%02d", tm.Minute()), "TimeZone": zone, "Month": month, "Day": day})) // attempt to fill in a message body if the post doesn't have any text if len(strings.TrimSpace(bodyPage.Props["PostMessage"])) == 0 && len(post.Filenames) > 0 { // extract the filenames from their paths and determine what type of files are attached filenames := make([]string, len(post.Filenames)) onlyImages := true for i, filename := range post.Filenames { var err error if filenames[i], err = url.QueryUnescape(filepath.Base(filename)); err != nil { // this should never error since filepath was escaped using url.QueryEscape filenames[i] = filepath.Base(filename) } ext := filepath.Ext(filename) onlyImages = onlyImages && model.IsFileExtImage(ext) } filenamesString := strings.Join(filenames, ", ") var attachmentPrefix string if onlyImages { attachmentPrefix = "Image" } else { attachmentPrefix = "File" } if len(post.Filenames) > 1 { attachmentPrefix += "s" } bodyPage.Props["PostMessage"] = userLocale("api.post.send_notifications_and_forget.sent", map[string]interface{}{"Prefix": attachmentPrefix, "Filenames": filenamesString}) } if err := utils.SendMail(user.Email, subjectPage.Render(), bodyPage.Render()); err != nil { l4g.Error(utils.T("api.post.send_notifications_and_forget.send.error"), user.Email, err) } }
func sendNotificationEmail(c *Context, post *model.Post, user *model.User, channel *model.Channel, team *model.Team, senderName string, sender *model.User) { // skip if inactive if user.DeleteAt > 0 { return } if *utils.Cfg.EmailSettings.EnableEmailBatching { if err := AddNotificationEmailToBatch(user, post, team); err == nil { return } // fall back to sending a single email if we can't batch it for some reason } var channelName string var bodyText string var subjectText string var mailTemplate string var mailParameters map[string]interface{} teamURL := c.GetSiteURL() + "/" + team.Name tm := time.Unix(post.CreateAt/1000, 0) userLocale := utils.GetUserTranslations(user.Locale) month := userLocale(tm.Month().String()) day := fmt.Sprintf("%d", tm.Day()) year := fmt.Sprintf("%d", tm.Year()) zone, _ := tm.Zone() if channel.Type == model.CHANNEL_DIRECT { bodyText = userLocale("api.post.send_notifications_and_forget.message_body") subjectText = userLocale("api.post.send_notifications_and_forget.message_subject") senderDisplayName := senderName if sender != nil { if result := <-Srv.Store.Preference().Get(user.Id, model.PREFERENCE_CATEGORY_DISPLAY_SETTINGS, "name_format"); result.Err != nil { // Show default sender's name if user doesn't set display settings. senderDisplayName = senderName } else { senderDisplayName = sender.GetDisplayNameForPreference(result.Data.(model.Preference).Value) } } mailTemplate = "api.templates.post_subject_in_direct_message" mailParameters = map[string]interface{}{"SubjectText": subjectText, "TeamDisplayName": team.DisplayName, "SenderDisplayName": senderDisplayName, "Month": month, "Day": day, "Year": year} } else { bodyText = userLocale("api.post.send_notifications_and_forget.mention_body") subjectText = userLocale("api.post.send_notifications_and_forget.mention_subject") channelName = channel.DisplayName mailTemplate = "api.templates.post_subject_in_channel" mailParameters = map[string]interface{}{"SubjectText": subjectText, "TeamDisplayName": team.DisplayName, "ChannelName": channelName, "Month": month, "Day": day, "Year": year} } subjectPage := utils.NewHTMLTemplate("post_subject", user.Locale) subjectPage.Props["Subject"] = userLocale(mailTemplate, mailParameters) subjectPage.Props["SiteName"] = utils.Cfg.TeamSettings.SiteName bodyPage := utils.NewHTMLTemplate("post_body", user.Locale) bodyPage.Props["SiteURL"] = c.GetSiteURL() bodyPage.Props["PostMessage"] = getMessageForNotification(post, userLocale) bodyPage.Props["TeamLink"] = teamURL + "/pl/" + post.Id bodyPage.Props["BodyText"] = bodyText bodyPage.Props["Button"] = userLocale("api.templates.post_body.button") bodyPage.Html["Info"] = template.HTML(userLocale("api.templates.post_body.info", map[string]interface{}{"ChannelName": channelName, "SenderName": senderName, "Hour": fmt.Sprintf("%02d", tm.Hour()), "Minute": fmt.Sprintf("%02d", tm.Minute()), "TimeZone": zone, "Month": month, "Day": day})) if err := utils.SendMail(user.Email, subjectPage.Render(), bodyPage.Render()); err != nil { l4g.Error(utils.T("api.post.send_notifications_and_forget.send.error"), user.Email, err) } }