# frozen_string_literal: true

RSpec.describe Jobs::UserEmail do
  before do
    SiteSetting.email_time_window_mins = 10
  end

  fab!(:user) { Fabricate(:user, last_seen_at: 11.minutes.ago) }
  fab!(:staged) { Fabricate(:user, staged: true, last_seen_at: 11.minutes.ago) }
  fab!(:suspended) { Fabricate(:user, last_seen_at: 10.minutes.ago, suspended_at: 5.minutes.ago, suspended_till: 7.days.from_now) }
  fab!(:anonymous) { Fabricate(:anonymous, last_seen_at: 11.minutes.ago) }

  it "raises an error when there is no user" do
    expect { Jobs::UserEmail.new.execute(type: :digest) }.to raise_error(Discourse::InvalidParameters)
  end

  it "raises an error when there is no type" do
    expect { Jobs::UserEmail.new.execute(user_id: user.id) }.to raise_error(Discourse::InvalidParameters)
  end

  it "raises an error when the type doesn't exist" do
    expect { Jobs::UserEmail.new.execute(type: :no_method, user_id: user.id) }.to raise_error(Discourse::InvalidParameters)
  end

  context 'when digest can be generated' do
    fab!(:user) { Fabricate(:user, last_seen_at: 8.days.ago, last_emailed_at: 8.days.ago) }
    fab!(:popular_topic) { Fabricate(:topic, user: Fabricate(:admin), created_at: 1.hour.ago) }

    it "doesn't call the mailer when the user is missing" do
      Jobs::UserEmail.new.execute(type: :digest, user_id: User.last.id + 10000)
      expect(ActionMailer::Base.deliveries).to eq([])
    end

    it "doesn't call the mailer when the user is staged" do
      staged.update!(last_seen_at: 8.days.ago, last_emailed_at: 8.days.ago)
      Jobs::UserEmail.new.execute(type: :digest, user_id: staged.id)
      expect(ActionMailer::Base.deliveries).to eq([])
    end

    context 'when not emailed recently' do
      before do
        freeze_time
        user.update!(last_emailed_at: 8.days.ago)
      end

      it "calls the mailer when the user exists" do
        Jobs::UserEmail.new.execute(type: :digest, user_id: user.id)
        expect(ActionMailer::Base.deliveries).to_not be_empty
        expect(user.user_stat.reload.digest_attempted_at).to eq_time(Time.zone.now)
      end
    end

    context 'when recently emailed' do
      before do
        freeze_time
        user.update!(last_emailed_at: 2.hours.ago)
        user.user_option.update!(digest_after_minutes: 1.day.to_i / 60)
      end

      it 'skips sending digest email' do
        Jobs::UserEmail.new.execute(type: :digest, user_id: user.id)
        expect(ActionMailer::Base.deliveries).to eq([])
        expect(user.user_stat.reload.digest_attempted_at).to eq_time(Time.zone.now)
      end
    end
  end

  context "with bounce score" do
    it "always sends critical emails when bounce score threshold has been reached" do
      email_token = Fabricate(:email_token)
      user.user_stat.update(bounce_score: SiteSetting.bounce_score_threshold + 1)

      Jobs::CriticalUserEmail.new.execute(type: "signup", user_id: user.id, email_token: email_token.token)

      email_log = EmailLog.where(user_id: user.id).last
      expect(email_log.email_type).to eq("signup")

      expect(ActionMailer::Base.deliveries.first.to).to contain_exactly(
        user.email
      )
    end
  end

  context 'with to_address' do
    it 'overwrites a to_address when present' do
      Jobs::UserEmail.new.execute(type: :confirm_new_email, user_id: user.id, to_address: 'jake@adventuretime.ooo')

      expect(ActionMailer::Base.deliveries.first.to).to contain_exactly(
        'jake@adventuretime.ooo'
      )
    end
  end

  context "with disable_emails setting" do
    it "sends when no" do
      SiteSetting.disable_emails = 'no'
      Jobs::UserEmail.new.execute(type: :confirm_new_email, user_id: user.id)

      expect(ActionMailer::Base.deliveries.first.to).to contain_exactly(
        user.email
      )
    end

    it "does not send an email when yes" do
      SiteSetting.disable_emails = 'yes'
      Jobs::UserEmail.new.execute(type: :confirm_new_email, user_id: user.id)

      expect(ActionMailer::Base.deliveries).to eq([])
    end
  end

  context "when recently seen" do
    fab!(:post) { Fabricate(:post, user: user) }
    fab!(:notification) { Fabricate(
        :notification,
        user: user,
        topic: post.topic,
        post_number: post.post_number,
        data: { original_post_id: post.id }.to_json
      )
    }
    before do
      user.update_column(:last_seen_at, 9.minutes.ago)
    end

    it "doesn't send an email to a user that's been recently seen" do
      Jobs::UserEmail.new.execute(type: :user_replied, user_id: user.id, post_id: post.id)
      expect(ActionMailer::Base.deliveries).to eq([])
    end

    it "does send an email to a user that's been recently seen but has email_level set to always" do
      user.user_option.update(email_level: UserOption.email_level_types[:always])
      PostTiming.create!(topic_id: post.topic_id, post_number: post.post_number, user_id: user.id, msecs: 100)

      Jobs::UserEmail.new.execute(
        type: :user_replied,
        user_id: user.id,
        post_id: post.id,
        notification_id: notification.id
      )

      expect(ActionMailer::Base.deliveries.first.to).to contain_exactly(
        user.email
      )
    end

    it "doesn't send an email even if email_level is set to always if `force_respect_seen_recently` arg is true" do
      user.user_option.update(email_level: UserOption.email_level_types[:always])
      PostTiming.create!(topic_id: post.topic_id, post_number: post.post_number, user_id: user.id, msecs: 100)

      Jobs::UserEmail.new.execute(
        type: :user_replied,
        user_id: user.id,
        post_id: post.id,
        notification_id: notification.id,
        force_respect_seen_recently: true
      )
      expect(ActionMailer::Base.deliveries).to eq([])
    end

    it "sends an email with no gsub substitution bugs" do
      upload = Fabricate(:upload)

      post.update!(raw: <<~RAW)
      This is a test post

      With a \\0 \\1 \\2 in it
      RAW
      Jobs::UserEmail.new.execute(
        type: :user_private_message,
        user_id: user.id,
        post_id: post.id,
        notification_id: notification.id
      )

      email = ActionMailer::Base.deliveries.first

      expect(email.to).to contain_exactly(user.email)

      html_part = email.parts.find { |x| x.content_type.include? "html" }
      expect(html_part.body.to_s).to_not include('%{email_content}')
      expect(html_part.body.to_s).to include('\0')
    end

    it "sends an email by default for a PM to a user that's been recently seen" do
      upload = Fabricate(:upload)

      post.update!(raw: <<~RAW)
      This is a test post

      <a class="attachment" href="#{upload.url}">test</a>
      <img src="#{upload.url}"/>
      RAW

      Jobs::UserEmail.new.execute(
        type: :user_private_message,
        user_id: user.id,
        post_id: post.id,
        notification_id: notification.id
      )

      email = ActionMailer::Base.deliveries.first

      expect(email.to).to contain_exactly(user.email)

      expect(email.parts[0].body.to_s).to include(<<~MD)
      This is a test post

      [test|attachment](#{Discourse.base_url}#{upload.url})
      ![](#{Discourse.base_url}#{upload.url})
      MD
    end

    it "sends a PM email to a user that's been recently seen and has email_messages_level set to always" do
      user.user_option.update(email_messages_level: UserOption.email_level_types[:always])
      user.user_option.update(email_level: UserOption.email_level_types[:never])
      Jobs::UserEmail.new.execute(
        type: :user_private_message,
        user_id: user.id,
        post_id: post.id,
        notification_id: notification.id
      )

      expect(ActionMailer::Base.deliveries.first.to).to contain_exactly(
        user.email
      )
    end

    it "doesn't send a PM email to a user that's been recently seen and has email_messages_level set to never" do
      user.user_option.update(email_messages_level: UserOption.email_level_types[:never])
      user.user_option.update(email_level: UserOption.email_level_types[:always])
      Jobs::UserEmail.new.execute(type: :user_private_message, user_id: user.id, post_id: post.id)

      expect(ActionMailer::Base.deliveries).to eq([])
    end

    it "doesn't send a regular post email to a user that's been recently seen and has email_level set to never" do
      user.user_option.update(email_messages_level: UserOption.email_level_types[:always])
      user.user_option.update(email_level: UserOption.email_level_types[:never])
      Jobs::UserEmail.new.execute(type: :user_replied, user_id: user.id, post_id: post.id)

      expect(ActionMailer::Base.deliveries).to eq([])
    end
  end

  context "with email_log" do
    fab!(:post) { Fabricate(:post, created_at: 30.seconds.ago) }

    before do
      SiteSetting.editing_grace_period = 0
    end

    it "creates an email log when the mail is sent (via Email::Sender)" do
      freeze_time

      last_emailed_at = 7.days.ago
      user.update!(last_emailed_at: last_emailed_at)
      Topic.last.update(created_at: 1.minute.ago)

      expect do
        Jobs::UserEmail.new.execute(type: :digest, user_id: user.id)
      end.to change { EmailLog.count }.by(1)

      email_log = EmailLog.last

      expect(email_log.user).to eq(user)
      expect(email_log.post).to eq(nil)
      # last_emailed_at should have changed
      expect(email_log.user.last_emailed_at).to_not eq_time(last_emailed_at)
    end

    it "creates a skipped email log when the mail is skipped" do
      freeze_time

      last_emailed_at = 7.days.ago
      user.update!(
        last_emailed_at: last_emailed_at,
        suspended_till: 1.year.from_now
      )

      expect do
        Jobs::UserEmail.new.execute(type: :digest, user_id: user.id)
      end.to change { SkippedEmailLog.count }.by(1)

      expect(SkippedEmailLog.exists?(
        email_type: "digest",
        user: user,
        post: nil,
        to_address: user.email,
        reason_type: SkippedEmailLog.reason_types[:user_email_user_suspended_not_pm]
      )).to eq(true)

      # last_emailed_at doesn't change
      expect(user.last_emailed_at).to eq_time(last_emailed_at)
    end

    it "creates a skipped email log when the user isn't allowed to see the post" do
      user.user_option.update(email_level: UserOption.email_level_types[:always])
      post.topic.convert_to_private_message(Discourse.system_user)

      expect do
        Jobs::UserEmail.new.execute(type: :user_posted, user_id: user.id, post_id: post.id)
      end.to change { SkippedEmailLog.count }.by(1)

      expect(SkippedEmailLog.exists?(
        email_type: "user_posted",
        user: user,
        post: post,
        to_address: user.email,
        reason_type: SkippedEmailLog.reason_types[:user_email_access_denied]
      )).to eq(true)

      expect(ActionMailer::Base.deliveries).to eq([])
    end
  end

  context 'with args' do
    it 'passes a token as an argument when a token is present' do
      Jobs::UserEmail.new.execute(type: :forgot_password, user_id: user.id, email_token: 'asdfasdf')

      mail = ActionMailer::Base.deliveries.first

      expect(mail.to).to contain_exactly(user.email)
      expect(mail.body).to include("asdfasdf")
    end

    context "with confirm_new_email" do
      let(:email_token) { Fabricate(:email_token, user: user) }
      before do
        EmailChangeRequest.create!(
          user: user,
          requested_by: requested_by,
          new_email_token: email_token,
          new_email: "testnew@test.com",
          change_state: EmailChangeRequest.states[:authorizing_new]
        )
      end

      context "when the change was requested by admin" do
        let(:requested_by) { Fabricate(:admin) }
        it "passes along true for the requested_by_admin param which changes the wording in the email" do
          Jobs::UserEmail.new.execute(type: :confirm_new_email, user_id: user.id, email_token: email_token.token)
          mail = ActionMailer::Base.deliveries.first
          expect(mail.body).to include("This email change was requested by a site admin.")
        end
      end

      context "when the change was requested by the user" do
        let(:requested_by) { user }
        it "passes along false for the requested_by_admin param which changes the wording in the email" do
          Jobs::UserEmail.new.execute(type: :confirm_new_email, user_id: user.id, email_token: email_token.token)
          mail = ActionMailer::Base.deliveries.first
          expect(mail.body).not_to include("This email change was requested by a site admin.")
        end
      end

      context "when requested_by record is not present" do
        let(:requested_by) { nil }
        it "passes along false for the requested_by_admin param which changes the wording in the email" do
          Jobs::UserEmail.new.execute(type: :confirm_new_email, user_id: user.id, email_token: email_token.token)
          mail = ActionMailer::Base.deliveries.first
          expect(mail.body).not_to include("This email change was requested by a site admin.")
        end
      end
    end

    context "with post" do
      fab!(:post) { Fabricate(:post, user: user) }

      it "doesn't send the email if you've seen the post" do
        PostTiming.record_timing(topic_id: post.topic_id, user_id: user.id, post_number: post.post_number, msecs: 6666)
        Jobs::UserEmail.new.execute(type: :user_private_message, user_id: user.id, post_id: post.id)

        expect(ActionMailer::Base.deliveries).to eq([])
      end

      it "doesn't send the email if the user deleted the post" do
        post.update_column(:user_deleted, true)
        Jobs::UserEmail.new.execute(type: :user_private_message, user_id: user.id, post_id: post.id)

        expect(ActionMailer::Base.deliveries).to eq([])
      end

      it "doesn't send the email if user of the post has been deleted" do
        post.update!(user_id: nil)
        Jobs::UserEmail.new.execute(type: :user_replied, user_id: user.id, post_id: post.id)

        expect(ActionMailer::Base.deliveries).to eq([])
      end

      context 'when user is suspended' do
        it "doesn't send email for a pm from a regular user" do
          Jobs::UserEmail.new.execute(type: :user_private_message, user_id: suspended.id, post_id: post.id)

          expect(ActionMailer::Base.deliveries).to eq([])
        end

        it "does send an email for a pm from a staff user" do
          pm_from_staff = Fabricate(:post, user: Fabricate(:moderator))
          pm_from_staff.topic.topic_allowed_users.create!(user_id: suspended.id)

          pm_notification = Fabricate(:notification,
            user: suspended,
            topic: pm_from_staff.topic,
            post_number: pm_from_staff.post_number,
            data: { original_post_id: pm_from_staff.id }.to_json
          )

          Jobs::UserEmail.new.execute(
            type: :user_private_message,
            user_id: suspended.id,
            post_id: pm_from_staff.id,
            notification_id: pm_notification.id
          )

          expect(ActionMailer::Base.deliveries.first.to).to contain_exactly(
            suspended.email
          )
        end

        it "doesn't send PM from system user" do
          pm_from_system = SystemMessage.create(suspended, :unsilenced)

          system_pm_notification = Fabricate(:notification,
            user: suspended,
            topic: pm_from_system.topic,
            post_number: pm_from_system.post_number,
            data: { original_post_id: pm_from_system.id }.to_json
          )

          Jobs::UserEmail.new.execute(
            type: :user_private_message,
            user_id: suspended.id,
            post_id: pm_from_system.id,
            notification_id: system_pm_notification.id
          )

          expect(ActionMailer::Base.deliveries).to eq([])
        end
      end

      context 'when user is anonymous' do
        before { SiteSetting.allow_anonymous_posting = true }

        it "doesn't send email for a pm from a regular user" do
          Jobs::UserEmail.new.execute(type: :user_private_message, user_id: anonymous.id, post_id: post.id)

          expect(ActionMailer::Base.deliveries).to eq([])
        end

        it "doesn't send email for a pm from a staff user" do
          pm_from_staff = Fabricate(:post, user: Fabricate(:moderator))
          pm_from_staff.topic.topic_allowed_users.create!(user_id: anonymous.id)
          Jobs::UserEmail.new.execute(type: :user_private_message, user_id: anonymous.id, post_id: pm_from_staff.id)

          expect(ActionMailer::Base.deliveries).to eq([])
        end
      end
    end

    context 'with notification' do
      fab!(:post) { Fabricate(:post, user: user) }
      fab!(:notification) {
        Fabricate(:notification,
                    user: user,
                    topic: post.topic,
                    post_number: post.post_number,
                    data: {
                      original_post_id: post.id
                    }.to_json
                 )
      }

      it "doesn't send the email if the notification has been seen" do
        notification.update_column(:read, true)
        message, err = Jobs::UserEmail.new.message_for_email(
          user,
          post,
          :user_mentioned,
          notification,
          notification_type: notification.notification_type,
          notification_data_hash: notification.data_hash
        )

        expect(message).to eq(nil)

        expect(SkippedEmailLog.exists?(
          email_type: "user_mentioned",
          user: user,
          post: post,
          to_address: user.email,
          reason_type: SkippedEmailLog.reason_types[:user_email_notification_already_read]
        )).to eq(true)
      end

      it "does send the email if the notification has been seen but user has email_level set to always" do
        notification.update_column(:read, true)
        user.user_option.update_column(:email_level, UserOption.email_level_types[:always])

        Jobs::UserEmail.new.execute(
          type: :user_mentioned,
          user_id: user.id,
          post_id: post.id,
          notification_id: notification.id
        )

        expect(ActionMailer::Base.deliveries.first.to).to contain_exactly(
          user.email
        )
      end

      it "does send the email if the user is using daily mailing list mode" do
        user.user_option.update(mailing_list_mode: true, mailing_list_mode_frequency: 0)

        Jobs::UserEmail.new.execute(
          type: :user_mentioned,
          user_id: user.id,
          post_id: post.id,
          notification_id: notification.id
        )

        expect(ActionMailer::Base.deliveries.first.to).to contain_exactly(
          user.email
        )
      end

      it "sends the mail if the user enabled mailing list mode, but mailing list mode is disabled globally" do
        user.user_option.update(mailing_list_mode: true, mailing_list_mode_frequency: 1)

        Jobs::UserEmail.new.execute(
          type: :user_mentioned,
          user_id: user.id,
          post_id: post.id,
          notification_id: notification.id
        )

        expect(ActionMailer::Base.deliveries.first.to).to contain_exactly(user.email)
      end

      context "when recently seen" do
        it "doesn't send an email to a user that's been recently seen" do
          user.update!(last_seen_at: 9.minutes.ago)

          Jobs::UserEmail.new.execute(
            type: :user_replied,
            user_id: user.id,
            post_id: post.id,
            notification_id: notification.id
          )

          expect(ActionMailer::Base.deliveries).to eq([])
        end

        it "does send an email to a user that's been recently seen but has email_level set to always" do
          user.update!(last_seen_at: 9.minutes.ago)
          user.user_option.update!(email_level: UserOption.email_level_types[:always])

          Jobs::UserEmail.new.execute(
            type: :user_replied,
            user_id: user.id,
            post_id: post.id,
            notification_id: notification.id
          )

          expect(ActionMailer::Base.deliveries.first.to).to contain_exactly(
            user.email
          )
        end
      end

      context 'when max_emails_per_day_per_user limit is reached' do
        before do
          SiteSetting.max_emails_per_day_per_user = 2
          2.times { Fabricate(:email_log, user: user, email_type: 'blah', to_address: user.email) }
        end

        it "does not send notification if limit is reached" do
          expect do
            2.times do
              Jobs::UserEmail.new.execute(
                type: :user_mentioned,
                user_id: user.id,
                notification_id: notification.id,
                post_id: post.id
              )
            end
          end.to change { SkippedEmailLog.count }.by(1)

          expect(SkippedEmailLog.exists?(
            email_type: "user_mentioned",
            user: user,
            post: post,
            to_address: user.email,
            reason_type: SkippedEmailLog.reason_types[:exceeded_emails_limit]
          )).to eq(true)

          freeze_time(Time.zone.now.tomorrow + 1.second)

          expect do
            Jobs::UserEmail.new.execute(
              type: :user_mentioned,
              user_id: user.id,
              notification_id: notification.id,
              post_id: post.id
            )
          end.not_to change { SkippedEmailLog.count }
        end

        it "sends critical email" do
          expect do
            Jobs::UserEmail.new.execute(
              type: :forgot_password,
              user_id: user.id,
              notification_id: notification.id,
            )
          end.to change { EmailLog.count }.by(1)

          expect(EmailLog.exists?(
            email_type: "forgot_password",
            user: user,
          )).to eq(true)
        end
      end

      it "erodes bounce score each time an email is sent" do
        SiteSetting.bounce_score_erode_on_send = 0.2

        user.user_stat.update(bounce_score: 2.7)

        Jobs::UserEmail.new.execute(
          type: :user_mentioned,
          user_id: user.id,
          notification_id: notification.id,
          post_id: post.id
        )

        user.user_stat.reload
        expect(user.user_stat.bounce_score).to eq(2.5)

        user.user_stat.update(bounce_score: 0)

        Jobs::UserEmail.new.execute(
          type: :user_mentioned,
          user_id: user.id,
          notification_id: notification.id,
          post_id: post.id
        )

        user.user_stat.reload
        expect(user.user_stat.bounce_score).to eq(0)
      end

      it "does not send notification if bounce threshold is reached" do
        user.user_stat.update(bounce_score: SiteSetting.bounce_score_threshold)

        expect do
          Jobs::UserEmail.new.execute(
            type: :user_mentioned,
            user_id: user.id,
            notification_id: notification.id,
            post_id: post.id
          )
        end.to change { SkippedEmailLog.count }.by(1)

        expect(SkippedEmailLog.exists?(
          email_type: "user_mentioned",
          user: user,
          post: post,
          to_address: user.email,
          reason_type: SkippedEmailLog.reason_types[:exceeded_bounces_limit]
        )).to eq(true)
      end

      it "doesn't send the mail if the user is using individual mailing list mode" do
        SiteSetting.disable_mailing_list_mode = false

        user.user_option.update(mailing_list_mode: true, mailing_list_mode_frequency: 1)
        # sometimes, we pass the notification_id
        Jobs::UserEmail.new.execute(type: :user_mentioned, user_id: user.id, notification_id: notification.id, post_id: post.id)
        # other times, we only pass the type of notification
        Jobs::UserEmail.new.execute(type: :user_mentioned, user_id: user.id, notification_type: "posted", post_id: post.id)
        # When post is nil
        Jobs::UserEmail.new.execute(type: :user_mentioned, user_id: user.id, notification_type: "posted")
        # When post does not have a topic
        post = Fabricate(:post)
        post.topic.destroy
        Jobs::UserEmail.new.execute(type: :user_mentioned, user_id: user.id, notification_type: "posted", post_id: post.id)

        expect(ActionMailer::Base.deliveries).to eq([])
      end

      it "doesn't send the mail if the user is using individual mailing list mode with no echo" do
        SiteSetting.disable_mailing_list_mode = false

        user.user_option.update(mailing_list_mode: true, mailing_list_mode_frequency: 2)
        # sometimes, we pass the notification_id
        Jobs::UserEmail.new.execute(type: :user_mentioned, user_id: user.id, notification_id: notification.id, post_id: post.id)
        # other times, we only pass the type of notification
        Jobs::UserEmail.new.execute(type: :user_mentioned, user_id: user.id, notification_type: "posted", post_id: post.id)
        # When post is nil
        Jobs::UserEmail.new.execute(type: :user_mentioned, user_id: user.id, notification_type: "posted")
        # When post does not have a topic
        post = Fabricate(:post)
        post.topic.destroy
        Jobs::UserEmail.new.execute(type: :user_mentioned, user_id: user.id, notification_type: "posted", post_id: post.id)

        expect(ActionMailer::Base.deliveries).to eq([])
      end

      it "doesn't send the email if the post has been user deleted" do
        post.update_column(:user_deleted, true)
        Jobs::UserEmail.new.execute(type: :user_mentioned, user_id: user.id, notification_id: notification.id, post_id: post.id)

        expect(ActionMailer::Base.deliveries).to eq([])
      end

      context 'when user is suspended' do
        it "doesn't send email for a pm from a regular user" do
          msg, err = Jobs::UserEmail.new.message_for_email(
              suspended,
              Fabricate.build(:post),
              :user_private_message,
              notification
          )

          expect(msg).to eq(nil)
          expect(err).not_to eq(nil)
        end

        context 'with pm from staff' do
          before do
            @pm_from_staff = Fabricate(:post, user: Fabricate(:moderator))
            @pm_from_staff.topic.topic_allowed_users.create!(user_id: suspended.id)
            @pm_notification = Fabricate(:notification,
                                            user: suspended,
                                            topic: @pm_from_staff.topic,
                                            post_number: @pm_from_staff.post_number,
                                            data: { original_post_id: @pm_from_staff.id }.to_json
                                        )
          end

          let :sent_message do
            Jobs::UserEmail.new.message_for_email(
                suspended,
                @pm_from_staff,
                :user_private_message,
                @pm_notification
            )
          end

          it "sends an email" do
            msg, err = sent_message
            expect(msg).not_to be(nil)
            expect(err).to be(nil)
          end

          it "sends an email even if user was last seen recently" do
            suspended.update_column(:last_seen_at, 1.minute.ago)

            msg, err = sent_message
            expect(msg).not_to be(nil)
            expect(err).to be(nil)
          end
        end
      end

      context 'when user is anonymous' do
        before { SiteSetting.allow_anonymous_posting = true }

        it "doesn't send email for a pm from a regular user" do
          Jobs::UserEmail.new.execute(
            type: :user_private_message,
            user_id: anonymous.id,
            post_id: post.id,
            notification_id: notification.id
          )

          expect(ActionMailer::Base.deliveries).to eq([])
        end

        it "doesn't send email for a pm from staff" do
          pm_from_staff = Fabricate(:post, user: Fabricate(:moderator))
          pm_from_staff.topic.topic_allowed_users.create!(user_id: anonymous.id)
          pm_notification = Fabricate(:notification,
                                          user: anonymous,
                                          topic: pm_from_staff.topic,
                                          post_number: pm_from_staff.post_number,
                                          data: { original_post_id: pm_from_staff.id }.to_json
                                      )
          Jobs::UserEmail.new.execute(
            type: :user_private_message,
            user_id: anonymous.id,
            post_id: pm_from_staff.id,
            notification_id: pm_notification.id
          )

          expect(ActionMailer::Base.deliveries).to eq([])
        end
      end
    end
  end
end