require "spec_helper" describe Gitlab::Email::Receiver, lib: true do before do stub_incoming_email_setting(enabled: true, address: "reply+%{key}@appmail.adventuretime.ooo") stub_config_setting(host: 'localhost') end let(:reply_key) { "59d8df8370b7e95c5a49fbf86aeb2c93" } let(:email_raw) { fixture_file('emails/valid_reply.eml') } let(:project) { create(:project, :public) } let(:noteable) { create(:issue, project: project) } let(:user) { create(:user) } let!(:sent_notification) { SentNotification.record(noteable, user.id, reply_key) } let(:receiver) { described_class.new(email_raw) } let(:markdown) { "![image](uploads/image.png)" } def setup_attachment allow_any_instance_of(Gitlab::Email::AttachmentUploader).to receive(:execute).and_return( [ { url: "uploads/image.png", is_image: true, alt: "image", markdown: markdown } ] ) end context "when the recipient address doesn't include a reply key" do let(:email_raw) { fixture_file('emails/valid_reply.eml').gsub(reply_key, "") } it "raises a SentNotificationNotFoundError" do expect { receiver.execute }.to raise_error(Gitlab::Email::Receiver::SentNotificationNotFoundError) end end context "when no sent notification for the reply key could be found" do let(:email_raw) { fixture_file('emails/wrong_reply_key.eml') } it "raises a SentNotificationNotFoundError" do expect { receiver.execute }.to raise_error(Gitlab::Email::Receiver::SentNotificationNotFoundError) end end context "when the email is blank" do let(:email_raw) { "" } it "raises an EmptyEmailError" do expect { receiver.execute }.to raise_error(Gitlab::Email::Receiver::EmptyEmailError) end end context "when the email was auto generated" do let!(:reply_key) { '636ca428858779856c226bb145ef4fad' } let!(:email_raw) { fixture_file("emails/auto_reply.eml") } it "raises an AutoGeneratedEmailError" do expect { receiver.execute }.to raise_error(Gitlab::Email::Receiver::AutoGeneratedEmailError) end end context "when the user could not be found" do before do user.destroy end it "raises a UserNotFoundError" do expect { receiver.execute }.to raise_error(Gitlab::Email::Receiver::UserNotFoundError) end end context "when the user has been blocked" do before do user.block end it "raises a UserBlockedError" do expect { receiver.execute }.to raise_error(Gitlab::Email::Receiver::UserBlockedError) end end context "when the user is not authorized to create a note" do before do project.update_attribute(:visibility_level, Project::PRIVATE) end it "raises a UserNotAuthorizedError" do expect { receiver.execute }.to raise_error(Gitlab::Email::Receiver::UserNotAuthorizedError) end end context "when the noteable could not be found" do before do noteable.destroy end it "raises a NoteableNotFoundError" do expect { receiver.execute }.to raise_error(Gitlab::Email::Receiver::NoteableNotFoundError) end end context "when the reply is blank" do let!(:email_raw) { fixture_file("emails/no_content_reply.eml") } it "raises an EmptyEmailError" do expect { receiver.execute }.to raise_error(Gitlab::Email::Receiver::EmptyEmailError) end end context "when the note could not be saved" do before do allow_any_instance_of(Note).to receive(:persisted?).and_return(false) end it "raises an InvalidNoteError" do expect { receiver.execute }.to raise_error(Gitlab::Email::Receiver::InvalidNoteError) end end context "when everything is fine" do before do setup_attachment end it "creates a comment" do expect { receiver.execute }.to change { noteable.notes.count }.by(1) note = noteable.notes.last expect(note.author).to eq(sent_notification.recipient) expect(note.note).to include("I could not disagree more.") end it "adds all attachments" do receiver.execute note = noteable.notes.last expect(note.note).to include(markdown) end context 'when sub-addressing is not supported' do before do stub_incoming_email_setting(enabled: true, address: nil) end shared_examples 'an email that contains a reply key' do |header| it "fetches the reply key from the #{header} header and creates a comment" do expect { receiver.execute }.to change { noteable.notes.count }.by(1) note = noteable.notes.last expect(note.author).to eq(sent_notification.recipient) expect(note.note).to include('I could not disagree more.') end end context 'reply key is in the References header' do let(:email_raw) { fixture_file('emails/reply_without_subaddressing_and_key_inside_references.eml') } it_behaves_like 'an email that contains a reply key', 'References' end end end context "when it's trying to create a new issue" do before do setup_attachment stub_incoming_email_setting(enabled: true, address: "incoming+%{key}@appmail.adventuretime.ooo") end let(:sent_notification) {} let!(:user) { create(:user, email: 'jake@adventuretime.ooo') } let(:namespace) { create(:namespace, path: 'gitlabhq') } let(:project) { create(:project, :public, namespace: namespace) } let(:email_raw) { fixture_file('emails/valid_new_issue.eml') } context "when everything is fine" do it "creates a new issue" do expect { receiver.execute }.to change { project.issues.count }.by(1) issue = project.issues.last expect(issue.author).to eq(user) expect(issue.title).to eq('New Issue by email') expect(issue.description).to include('reply by email') expect(issue.description).to include(markdown) end end context "something is wrong" do context "when the issue could not be saved" do before do project allow_any_instance_of(Issue).to receive(:persisted?).and_return(false) end it "raises an InvalidIssueError" do expect { receiver.execute }.to raise_error(Gitlab::Email::Receiver::InvalidIssueError) end end end end end