mirror of
https://github.com/codeninjasllc/discourse.git
synced 2024-11-23 23:58:31 -05:00
820a435af8
We no longer include previous replies as "context", instead we include and excerpt of the post being replied to at the bottom of notifications, this information was previously missing. Users may opt in to emailing previous replies if they wish or opt out of "in-reply-to" which makes sense in some email clients that are smarter about displaying a tree of replies.
349 lines
11 KiB
Ruby
349 lines
11 KiB
Ruby
require_dependency 'markdown_linker'
|
|
require_dependency 'email/message_builder'
|
|
require_dependency 'age_words'
|
|
|
|
class UserNotifications < ActionMailer::Base
|
|
helper :application
|
|
default charset: 'UTF-8'
|
|
|
|
include Email::BuildEmailHelper
|
|
|
|
def signup(user, opts={})
|
|
build_email(user.email,
|
|
template: "user_notifications.signup",
|
|
email_token: opts[:email_token])
|
|
end
|
|
|
|
def signup_after_approval(user, opts={})
|
|
build_email(user.email,
|
|
template: 'user_notifications.signup_after_approval',
|
|
email_token: opts[:email_token],
|
|
new_user_tips: I18n.t('system_messages.usage_tips.text_body_template', base_url: Discourse.base_url))
|
|
end
|
|
|
|
def authorize_email(user, opts={})
|
|
build_email(user.email,
|
|
template: "user_notifications.authorize_email",
|
|
email_token: opts[:email_token])
|
|
end
|
|
|
|
def forgot_password(user, opts={})
|
|
build_email(user.email,
|
|
template: user.has_password? ? "user_notifications.forgot_password" : "user_notifications.set_password",
|
|
email_token: opts[:email_token])
|
|
end
|
|
|
|
def admin_login(user, opts={})
|
|
build_email(user.email,
|
|
template: "user_notifications.admin_login",
|
|
email_token: opts[:email_token])
|
|
end
|
|
|
|
def account_created(user, opts={})
|
|
build_email(user.email,
|
|
template: "user_notifications.account_created",
|
|
email_token: opts[:email_token])
|
|
end
|
|
|
|
def short_date(dt)
|
|
if dt.year == Time.now.year
|
|
I18n.l(dt, format: :short_no_year)
|
|
else
|
|
I18n.l(dt, format: :date_only)
|
|
end
|
|
end
|
|
|
|
def digest(user, opts={})
|
|
@user = user
|
|
@base_url = Discourse.base_url
|
|
|
|
min_date = opts[:since] || @user.last_emailed_at || @user.last_seen_at || 1.month.ago
|
|
|
|
@site_name = SiteSetting.email_prefix.presence || SiteSetting.title
|
|
|
|
@header_color = ColorScheme.hex_for_name('header_background')
|
|
@anchor_color = ColorScheme.hex_for_name('tertiary')
|
|
@last_seen_at = short_date(@user.last_seen_at || @user.created_at)
|
|
|
|
# A list of topics to show the user
|
|
@featured_topics = Topic.for_digest(user, min_date, limit: SiteSetting.digest_topics, top_order: true).to_a
|
|
|
|
# Don't send email unless there is content in it
|
|
if @featured_topics.present?
|
|
featured_topic_ids = @featured_topics.map(&:id)
|
|
|
|
@new_topics_since_seen = Topic.new_since_last_seen(user, min_date, featured_topic_ids).count
|
|
if @new_topics_since_seen > SiteSetting.digest_topics
|
|
category_counts = Topic.new_since_last_seen(user, min_date, featured_topic_ids).group(:category_id).count
|
|
|
|
@new_by_category = []
|
|
if category_counts.present?
|
|
Category.where(id: category_counts.keys).each do |c|
|
|
@new_by_category << [c, category_counts[c.id]]
|
|
end
|
|
@new_by_category.sort_by! {|c| -c[1]}
|
|
end
|
|
end
|
|
|
|
@featured_topics, @new_topics = @featured_topics[0..4], @featured_topics[5..-1]
|
|
@markdown_linker = MarkdownLinker.new(Discourse.base_url)
|
|
@unsubscribe_key = DigestUnsubscribeKey.create_key_for(@user)
|
|
|
|
build_email user.email,
|
|
from_alias: I18n.t('user_notifications.digest.from', site_name: SiteSetting.title),
|
|
subject: I18n.t('user_notifications.digest.subject_template',
|
|
site_name: @site_name,
|
|
date: short_date(Time.now))
|
|
end
|
|
end
|
|
|
|
def user_replied(user, opts)
|
|
opts[:allow_reply_by_email] = true
|
|
opts[:use_site_subject] = true
|
|
opts[:show_category_in_subject] = true
|
|
notification_email(user, opts)
|
|
end
|
|
|
|
def user_quoted(user, opts)
|
|
opts[:allow_reply_by_email] = true
|
|
opts[:use_site_subject] = true
|
|
opts[:show_category_in_subject] = true
|
|
notification_email(user, opts)
|
|
end
|
|
|
|
def user_linked(user, opts)
|
|
opts[:allow_reply_by_email] = true
|
|
opts[:use_site_subject] = true
|
|
opts[:show_category_in_subject] = true
|
|
notification_email(user, opts)
|
|
end
|
|
|
|
def user_mentioned(user, opts)
|
|
opts[:allow_reply_by_email] = true
|
|
opts[:use_site_subject] = true
|
|
opts[:show_category_in_subject] = true
|
|
notification_email(user, opts)
|
|
end
|
|
|
|
def group_mentioned(user, opts)
|
|
opts[:allow_reply_by_email] = true
|
|
opts[:use_site_subject] = true
|
|
opts[:show_category_in_subject] = true
|
|
notification_email(user, opts)
|
|
end
|
|
|
|
def user_posted(user, opts)
|
|
opts[:allow_reply_by_email] = true
|
|
opts[:use_site_subject] = true
|
|
opts[:add_re_to_subject] = true
|
|
opts[:show_category_in_subject] = true
|
|
notification_email(user, opts)
|
|
end
|
|
|
|
def user_private_message(user, opts)
|
|
opts[:allow_reply_by_email] = true
|
|
opts[:use_site_subject] = true
|
|
opts[:add_re_to_subject] = true
|
|
opts[:show_category_in_subject] = false
|
|
|
|
# We use the 'user_posted' event when you are emailed a post in a PM.
|
|
opts[:notification_type] = 'posted'
|
|
|
|
notification_email(user, opts)
|
|
end
|
|
|
|
def user_invited_to_private_message(user, opts)
|
|
opts[:use_template_html] = true
|
|
notification_email(user, opts)
|
|
end
|
|
|
|
def user_invited_to_topic(user, opts)
|
|
opts[:use_template_html] = true
|
|
opts[:show_category_in_subject] = true
|
|
notification_email(user, opts)
|
|
end
|
|
|
|
def mailing_list_notify(user, post)
|
|
opts = {
|
|
post: post,
|
|
allow_reply_by_email: true,
|
|
use_site_subject: true,
|
|
add_re_to_subject: true,
|
|
show_category_in_subject: true,
|
|
notification_type: "posted",
|
|
notification_data_hash: {
|
|
original_username: post.user.username,
|
|
topic_title: post.topic.title,
|
|
},
|
|
}
|
|
notification_email(user, opts)
|
|
end
|
|
|
|
protected
|
|
|
|
def email_post_markdown(post)
|
|
result = "[email-indent]\n"
|
|
result << "#{post.raw}\n\n"
|
|
result << "#{I18n.t('user_notifications.posted_by', username: post.username, post_date: post.created_at.strftime("%m/%d/%Y"))}\n\n"
|
|
result << "[/email-indent]\n"
|
|
result
|
|
end
|
|
|
|
class UserNotificationRenderer < ActionView::Base
|
|
include UserNotificationsHelper
|
|
end
|
|
|
|
def self.get_context_posts(post, topic_user, user)
|
|
|
|
if user.user_option.email_previous_replies == UserOption.previous_replies_type[:never]
|
|
return []
|
|
end
|
|
|
|
allowed_post_types = [Post.types[:regular]]
|
|
allowed_post_types << Post.types[:whisper] if topic_user.try(:user).try(:staff?)
|
|
|
|
context_posts = Post.where(topic_id: post.topic_id)
|
|
.where("post_number < ?", post.post_number)
|
|
.where(user_deleted: false)
|
|
.where(hidden: false)
|
|
.where(post_type: allowed_post_types)
|
|
.order('created_at desc')
|
|
.limit(SiteSetting.email_posts_context)
|
|
|
|
if topic_user && topic_user.last_emailed_post_number && user.user_option.email_previous_replies == UserOption.previous_replies_type[:unless_emailed]
|
|
context_posts = context_posts.where("post_number > ?", topic_user.last_emailed_post_number)
|
|
end
|
|
|
|
context_posts
|
|
end
|
|
|
|
def notification_email(user, opts)
|
|
notification_type = opts[:notification_type]
|
|
notification_data = opts[:notification_data_hash]
|
|
post = opts[:post]
|
|
|
|
unless String === notification_type
|
|
if Numeric === notification_type
|
|
notification_type = Notification.types[notification_type]
|
|
end
|
|
notification_type = notification_type.to_s
|
|
end
|
|
|
|
user_name = notification_data[:original_username]
|
|
|
|
if post && SiteSetting.enable_names && SiteSetting.display_name_on_email_from
|
|
name = User.where(id: post.user_id).pluck(:name).first
|
|
user_name = name unless name.blank?
|
|
end
|
|
|
|
allow_reply_by_email = opts[:allow_reply_by_email] unless user.suspended?
|
|
original_username = notification_data[:original_username] || notification_data[:display_username]
|
|
|
|
send_notification_email(
|
|
title: notification_data[:topic_title],
|
|
post: post,
|
|
username: original_username,
|
|
from_alias: user_name,
|
|
allow_reply_by_email: allow_reply_by_email,
|
|
use_site_subject: opts[:use_site_subject],
|
|
add_re_to_subject: opts[:add_re_to_subject],
|
|
show_category_in_subject: opts[:show_category_in_subject],
|
|
notification_type: notification_type,
|
|
use_template_html: opts[:use_template_html],
|
|
user: user
|
|
)
|
|
end
|
|
|
|
def send_notification_email(opts)
|
|
post = opts[:post]
|
|
title = opts[:title]
|
|
allow_reply_by_email = opts[:allow_reply_by_email]
|
|
use_site_subject = opts[:use_site_subject]
|
|
add_re_to_subject = opts[:add_re_to_subject] && post.post_number > 1
|
|
username = opts[:username]
|
|
from_alias = opts[:from_alias]
|
|
notification_type = opts[:notification_type]
|
|
user = opts[:user]
|
|
|
|
# category name
|
|
category = Topic.find_by(id: post.topic_id).category
|
|
if opts[:show_category_in_subject] && post.topic_id && category && !category.uncategorized?
|
|
show_category_in_subject = category.name
|
|
|
|
# subcategory case
|
|
if !category.parent_category_id.nil?
|
|
show_category_in_subject = "#{Category.find_by(id: category.parent_category_id).name}/#{show_category_in_subject}"
|
|
end
|
|
else
|
|
show_category_in_subject = nil
|
|
end
|
|
|
|
context = ""
|
|
tu = TopicUser.get(post.topic_id, user)
|
|
context_posts = self.class.get_context_posts(post, tu, user)
|
|
|
|
# make .present? cheaper
|
|
context_posts = context_posts.to_a
|
|
|
|
if context_posts.present?
|
|
context << "-- \n*#{I18n.t('user_notifications.previous_discussion')}*\n"
|
|
context_posts.each do |cp|
|
|
context << email_post_markdown(cp)
|
|
end
|
|
end
|
|
|
|
topic_excerpt = ""
|
|
if opts[:use_template_html]
|
|
topic_excerpt = post.excerpt.gsub("\n", " ") if post.is_first_post? && post.excerpt
|
|
else
|
|
in_reply_to_post = post.reply_to_post if user.user_option.email_in_reply_to
|
|
html = UserNotificationRenderer.new(Rails.configuration.paths["app/views"]).render(
|
|
template: 'email/notification',
|
|
format: :html,
|
|
locals: { context_posts: context_posts,
|
|
post: post,
|
|
in_reply_to_post: in_reply_to_post,
|
|
classes: RTL.new(user).css_class
|
|
}
|
|
)
|
|
end
|
|
|
|
template = "user_notifications.user_#{notification_type}"
|
|
if post.topic.private_message?
|
|
template << "_pm"
|
|
template << "_staged" if user.staged?
|
|
end
|
|
|
|
email_opts = {
|
|
topic_title: title,
|
|
topic_excerpt: topic_excerpt,
|
|
message: email_post_markdown(post),
|
|
url: post.url,
|
|
post_id: post.id,
|
|
topic_id: post.topic_id,
|
|
context: context,
|
|
username: username,
|
|
add_unsubscribe_link: !user.staged,
|
|
add_unsubscribe_via_email_link: user.user_option.mailing_list_mode,
|
|
unsubscribe_url: post.topic.unsubscribe_url,
|
|
allow_reply_by_email: allow_reply_by_email,
|
|
use_site_subject: use_site_subject,
|
|
add_re_to_subject: add_re_to_subject,
|
|
show_category_in_subject: show_category_in_subject,
|
|
private_reply: post.topic.private_message?,
|
|
include_respond_instructions: !user.suspended?,
|
|
template: template,
|
|
html_override: html,
|
|
site_description: SiteSetting.site_description,
|
|
site_title: SiteSetting.title,
|
|
style: :notification
|
|
}
|
|
|
|
# If we have a display name, change the from address
|
|
email_opts[:from_alias] = from_alias if from_alias.present?
|
|
|
|
TopicUser.change(user.id, post.topic_id, last_emailed_post_number: post.post_number)
|
|
|
|
build_email(user.email, email_opts)
|
|
end
|
|
end
|