mirror of
https://github.com/discourse/discourse.git
synced 2024-12-02 18:43:44 +08:00
ab3a032b4b
When sending emails out via group SMTP, if we are sending them to non-staged users we want to mask those emails with BCC, just so we don't expose them to anyone we shouldn't. Staged users are ones that have likely only interacted with support via email, and will likely include other people who were CC'd on the original email to the group. Co-authored-by: Martin Brennan <martin@discourse.org>
302 lines
13 KiB
Ruby
302 lines
13 KiB
Ruby
# frozen_string_literal: true
|
|
|
|
RSpec.describe Jobs::GroupSmtpEmail do
|
|
fab!(:topic) { Fabricate(:private_message_topic, title: "Help I need support") }
|
|
fab!(:post) do
|
|
Fabricate(:post, topic: topic, raw: "some first post content")
|
|
Fabricate(:post, topic: topic, raw: "some intermediate content")
|
|
Fabricate(:post, topic: topic, raw: "this is the second post reply")
|
|
end
|
|
fab!(:group) { Fabricate(:smtp_group, name: "support-group", full_name: "Support Group") }
|
|
fab!(:recipient_user) { Fabricate(:user, email: "test@test.com") }
|
|
let(:post_id) { post.id }
|
|
let(:args) do
|
|
{
|
|
group_id: group.id,
|
|
post_id: post_id,
|
|
email: "test@test.com",
|
|
cc_emails: ["otherguy@test.com", "cormac@lit.com"]
|
|
}
|
|
end
|
|
let(:staged1) { Fabricate(:staged, email: "otherguy@test.com") }
|
|
let(:staged2) { Fabricate(:staged, email: "cormac@lit.com") }
|
|
let(:normaluser) { Fabricate(:user, email: "justanormalguy@test.com", username: "normaluser") }
|
|
|
|
before do
|
|
SiteSetting.enable_smtp = true
|
|
SiteSetting.manual_polling_enabled = true
|
|
SiteSetting.reply_by_email_address = "test+%{reply_key}@test.com"
|
|
SiteSetting.reply_by_email_enabled = true
|
|
TopicAllowedGroup.create(group: group, topic: topic)
|
|
TopicAllowedUser.create(user: recipient_user, topic: topic)
|
|
TopicAllowedUser.create(user: staged1, topic: topic)
|
|
TopicAllowedUser.create(user: staged2, topic: topic)
|
|
TopicAllowedUser.create(user: normaluser, topic: topic)
|
|
end
|
|
|
|
it "sends an email using the GroupSmtpMailer and Email::Sender" do
|
|
message = Mail::Message.new(body: "hello", to: "myemail@example.invalid")
|
|
GroupSmtpMailer
|
|
.expects(:send_mail)
|
|
.with(
|
|
group,
|
|
"test@test.com",
|
|
post,
|
|
cc_addresses: %w[otherguy@test.com cormac@lit.com],
|
|
bcc_addresses: [],
|
|
)
|
|
.returns(message)
|
|
subject.execute(args)
|
|
end
|
|
|
|
it "includes a 'reply above this line' message" do
|
|
subject.execute(args)
|
|
email_log = EmailLog.find_by(post_id: post.id, topic_id: post.topic_id, user_id: recipient_user.id)
|
|
expect(email_log.as_mail_message.html_part.to_s).to include(I18n.t("user_notifications.reply_above_line"))
|
|
end
|
|
|
|
it "does not include context posts" do
|
|
subject.execute(args)
|
|
email_log = EmailLog.find_by(post_id: post.id, topic_id: post.topic_id, user_id: recipient_user.id)
|
|
expect(email_log.as_mail_message.text_part.to_s).not_to include(I18n.t("user_notifications.previous_discussion"))
|
|
expect(email_log.as_mail_message.text_part.to_s).not_to include("some first post content")
|
|
end
|
|
|
|
it "does not include in reply to post in email but still has the header" do
|
|
second_post = topic.posts.find_by(post_number: 2)
|
|
post.update!(reply_to_post_number: 1, reply_to_user: second_post.user)
|
|
PostReply.create(post: second_post, reply: post)
|
|
subject.execute(args)
|
|
email_log = EmailLog.find_by(post_id: post.id, topic_id: post.topic_id, user_id: recipient_user.id)
|
|
expect(email_log.raw_headers).to include("In-Reply-To: <discourse/post/#{second_post.id}@#{Email::Sender.host_for(Discourse.base_url)}>")
|
|
expect(email_log.as_mail_message.html_part.to_s).not_to include(I18n.t("user_notifications.in_reply_to"))
|
|
end
|
|
|
|
it "includes the participants in the correct format (but not the recipient user), and does not have links for the staged users" do
|
|
subject.execute(args)
|
|
email_log = EmailLog.find_by(post_id: post.id, topic_id: post.topic_id, user_id: recipient_user.id)
|
|
email_text = email_log.as_mail_message.text_part.to_s
|
|
expect(email_text).to include("Support Group")
|
|
expect(email_text).to include("otherguy@test.com")
|
|
expect(email_text).not_to include("[otherguy@test.com]")
|
|
expect(email_text).to include("cormac@lit.com")
|
|
expect(email_text).not_to include("[cormac@lit.com]")
|
|
expect(email_text).to include("normaluser")
|
|
expect(email_text).not_to include(recipient_user.username)
|
|
end
|
|
|
|
it "creates an EmailLog record with the correct details" do
|
|
subject.execute(args)
|
|
email_log = EmailLog.find_by(post_id: post.id, topic_id: post.topic_id, user_id: recipient_user.id)
|
|
expect(email_log).not_to eq(nil)
|
|
expect(email_log.message_id).to eq("discourse/post/#{post.id}@test.localhost")
|
|
end
|
|
|
|
it "creates an IncomingEmail record with the correct details to avoid double processing IMAP" do
|
|
subject.execute(args)
|
|
expect(ActionMailer::Base.deliveries.count).to eq(1)
|
|
expect(ActionMailer::Base.deliveries.last.subject).to eq("Re: Help I need support")
|
|
incoming_email = IncomingEmail.find_by(post_id: post.id, topic_id: post.topic_id, user_id: post.user.id)
|
|
expect(incoming_email).not_to eq(nil)
|
|
expect(incoming_email.message_id).to eq("discourse/post/#{post.id}@test.localhost")
|
|
expect(incoming_email.created_via).to eq(IncomingEmail.created_via_types[:group_smtp])
|
|
expect(incoming_email.to_addresses).to eq("test@test.com")
|
|
expect(incoming_email.cc_addresses).to eq("otherguy@test.com;cormac@lit.com")
|
|
expect(incoming_email.subject).to eq("Re: Help I need support")
|
|
end
|
|
|
|
it "does not create a post reply key, it always replies to the group email_username" do
|
|
subject.execute(args)
|
|
expect(ActionMailer::Base.deliveries.count).to eq(1)
|
|
expect(ActionMailer::Base.deliveries.last.subject).to eq("Re: Help I need support")
|
|
email_log = EmailLog.find_by(post_id: post.id, topic_id: post.topic_id, user_id: recipient_user.id)
|
|
post_reply_key = PostReplyKey.where(user_id: recipient_user, post_id: post.id).first
|
|
expect(post_reply_key).to eq(nil)
|
|
expect(email_log.raw_headers).not_to include("Reply-To: Support Group <#{group.email_username}")
|
|
expect(email_log.raw_headers).to include("From: Support Group <#{group.email_username}")
|
|
end
|
|
|
|
it "creates an EmailLog record with the correct details" do
|
|
subject.execute(args)
|
|
expect(ActionMailer::Base.deliveries.count).to eq(1)
|
|
expect(ActionMailer::Base.deliveries.last.subject).to eq("Re: Help I need support")
|
|
email_log = EmailLog.find_by(post_id: post.id, topic_id: post.topic_id, user_id: recipient_user.id)
|
|
expect(email_log).not_to eq(nil)
|
|
expect(email_log.message_id).to eq("discourse/post/#{post.id}@test.localhost")
|
|
end
|
|
|
|
it "creates an IncomingEmail record with the correct details to avoid double processing IMAP" do
|
|
subject.execute(args)
|
|
expect(ActionMailer::Base.deliveries.count).to eq(1)
|
|
expect(ActionMailer::Base.deliveries.last.subject).to eq("Re: Help I need support")
|
|
incoming_email = IncomingEmail.find_by(post_id: post.id, topic_id: post.topic_id, user_id: post.user.id)
|
|
expect(incoming_email).not_to eq(nil)
|
|
expect(incoming_email.message_id).to eq("discourse/post/#{post.id}@test.localhost")
|
|
expect(incoming_email.created_via).to eq(IncomingEmail.created_via_types[:group_smtp])
|
|
expect(incoming_email.to_addresses).to eq("test@test.com")
|
|
expect(incoming_email.cc_addresses).to eq("otherguy@test.com;cormac@lit.com")
|
|
expect(incoming_email.subject).to eq("Re: Help I need support")
|
|
end
|
|
|
|
it "does not create a post reply key, it always replies to the group email_username" do
|
|
subject.execute(args)
|
|
expect(ActionMailer::Base.deliveries.count).to eq(1)
|
|
expect(ActionMailer::Base.deliveries.last.subject).to eq("Re: Help I need support")
|
|
email_log = EmailLog.find_by(post_id: post.id, topic_id: post.topic_id, user_id: recipient_user.id)
|
|
post_reply_key = PostReplyKey.where(user_id: recipient_user, post_id: post.id).first
|
|
expect(post_reply_key).to eq(nil)
|
|
expect(email_log.raw).not_to include("Reply-To: Support Group <#{group.email_username}")
|
|
expect(email_log.raw).to include("From: Support Group <#{group.email_username}")
|
|
end
|
|
|
|
it "falls back to the group name if full name is blank" do
|
|
group.update(full_name: "")
|
|
subject.execute(args)
|
|
expect(ActionMailer::Base.deliveries.count).to eq(1)
|
|
expect(ActionMailer::Base.deliveries.last.subject).to eq("Re: Help I need support")
|
|
email_log = EmailLog.find_by(post_id: post.id, topic_id: post.topic_id, user_id: recipient_user.id)
|
|
expect(email_log.raw_headers).to include("From: support-group <#{group.email_username}")
|
|
end
|
|
|
|
it "has the group_smtp_id and the to_address filled in correctly" do
|
|
subject.execute(args)
|
|
expect(ActionMailer::Base.deliveries.count).to eq(1)
|
|
expect(ActionMailer::Base.deliveries.last.subject).to eq("Re: Help I need support")
|
|
email_log = EmailLog.find_by(post_id: post.id, topic_id: post.topic_id, user_id: recipient_user.id)
|
|
expect(email_log.to_address).to eq("test@test.com")
|
|
expect(email_log.smtp_group_id).to eq(group.id)
|
|
end
|
|
|
|
it "drops malformed cc addresses when sending the email" do
|
|
args2 = args.clone
|
|
args2[:cc_emails] << "somebadccemail@test.com<mailto:somebadccemail@test.com"
|
|
subject.execute(args2)
|
|
expect(ActionMailer::Base.deliveries.count).to eq(1)
|
|
last_email = ActionMailer::Base.deliveries.last
|
|
expect(last_email.subject).to eq("Re: Help I need support")
|
|
expect(last_email.cc).to match_array(["otherguy@test.com", "cormac@lit.com"])
|
|
end
|
|
|
|
context "when there are cc_addresses" do
|
|
it "has the cc_addresses and cc_user_ids filled in correctly" do
|
|
subject.execute(args)
|
|
expect(ActionMailer::Base.deliveries.count).to eq(1)
|
|
sent_mail = ActionMailer::Base.deliveries.last
|
|
expect(sent_mail.subject).to eq("Re: Help I need support")
|
|
expect(sent_mail.cc).to eq(["otherguy@test.com", "cormac@lit.com"])
|
|
email_log = EmailLog.find_by(post_id: post.id, topic_id: post.topic_id, user_id: recipient_user.id)
|
|
expect(email_log.cc_addresses).to eq("otherguy@test.com;cormac@lit.com")
|
|
expect(email_log.cc_user_ids).to match_array([staged1.id, staged2.id])
|
|
end
|
|
|
|
it "where cc_addresses match non-staged users, convert to bcc_addresses" do
|
|
staged2.update!(staged: false, active: true)
|
|
subject.execute(args)
|
|
expect(ActionMailer::Base.deliveries.count).to eq(1)
|
|
sent_mail = ActionMailer::Base.deliveries.last
|
|
expect(sent_mail.subject).to eq("Re: Help I need support")
|
|
expect(sent_mail.cc).to eq(["otherguy@test.com"])
|
|
expect(sent_mail.bcc).to eq(["cormac@lit.com"])
|
|
email_log = EmailLog.find_by(post_id: post.id, topic_id: post.topic_id, user_id: recipient_user.id)
|
|
expect(email_log.cc_addresses).to eq("otherguy@test.com")
|
|
expect(email_log.bcc_addresses).to eq("cormac@lit.com")
|
|
expect(email_log.cc_user_ids).to match_array([staged1.id])
|
|
end
|
|
end
|
|
|
|
context "when the post in the argument is the OP" do
|
|
let(:post_id) { post.topic.posts.first.id }
|
|
|
|
context "when the group has imap enabled" do
|
|
before do
|
|
group.update!(imap_enabled: true)
|
|
end
|
|
|
|
it "aborts and does not send a group SMTP email; the OP is the one that sent the email in the first place" do
|
|
expect { subject.execute(args) }.not_to(change { EmailLog.count })
|
|
expect(ActionMailer::Base.deliveries.count).to eq(0)
|
|
end
|
|
end
|
|
|
|
context "when the group does not have imap enabled" do
|
|
before do
|
|
group.update!(imap_enabled: false)
|
|
end
|
|
|
|
it "sends the email as expected" do
|
|
subject.execute(args)
|
|
expect(ActionMailer::Base.deliveries.count).to eq(1)
|
|
end
|
|
end
|
|
end
|
|
|
|
context "when the post is deleted" do
|
|
it "aborts and adds a skipped email log" do
|
|
post.trash!
|
|
subject.execute(args)
|
|
expect(ActionMailer::Base.deliveries.count).to eq(0)
|
|
expect(SkippedEmailLog.exists?(
|
|
email_type: "group_smtp",
|
|
user: recipient_user,
|
|
post: nil,
|
|
to_address: recipient_user.email,
|
|
reason_type: SkippedEmailLog.reason_types[:group_smtp_post_deleted]
|
|
)).to eq(true)
|
|
end
|
|
end
|
|
|
|
context "when the topic is deleted" do
|
|
it "aborts and adds a skipped email log" do
|
|
post.topic.trash!
|
|
subject.execute(args)
|
|
expect(ActionMailer::Base.deliveries.count).to eq(0)
|
|
expect(SkippedEmailLog.exists?(
|
|
email_type: "group_smtp",
|
|
user: recipient_user,
|
|
post: post,
|
|
to_address: recipient_user.email,
|
|
reason_type: SkippedEmailLog.reason_types[:group_smtp_topic_deleted]
|
|
)).to eq(true)
|
|
end
|
|
end
|
|
|
|
context "when smtp is not enabled" do
|
|
it "returns without sending email" do
|
|
SiteSetting.enable_smtp = false
|
|
subject.execute(args)
|
|
expect(ActionMailer::Base.deliveries.count).to eq(0)
|
|
end
|
|
end
|
|
|
|
context "when disable_emails is yes" do
|
|
it "returns without sending email" do
|
|
SiteSetting.disable_emails = "yes"
|
|
subject.execute(args)
|
|
expect(ActionMailer::Base.deliveries.count).to eq(0)
|
|
end
|
|
end
|
|
|
|
context "when group is deleted" do
|
|
it "returns without sending email" do
|
|
group.destroy
|
|
subject.execute(args)
|
|
expect(ActionMailer::Base.deliveries.count).to eq(0)
|
|
end
|
|
end
|
|
|
|
context "when smtp is not enabled for the group" do
|
|
it "returns without sending email" do
|
|
group.update!(smtp_enabled: false)
|
|
subject.execute(args)
|
|
expect(ActionMailer::Base.deliveries.count).to eq(0)
|
|
expect(SkippedEmailLog.exists?(
|
|
email_type: "group_smtp",
|
|
user: recipient_user,
|
|
post: post,
|
|
to_address: recipient_user.email,
|
|
reason_type: SkippedEmailLog.reason_types[:group_smtp_disabled_for_group]
|
|
)).to eq(true)
|
|
end
|
|
end
|
|
end
|