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(:mail_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, mail_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 mail key" do let(:email_raw) { fixture_file('emails/valid_reply.eml').gsub(mail_key, "") } it "raises a SentNotificationNotFoundError" do expect { receiver.execute }.to raise_error(Gitlab::Email::SentNotificationNotFoundError) end end context "when no sent notification for the mail key could be found" do let(:email_raw) { fixture_file('emails/wrong_mail_key.eml') } it "raises a SentNotificationNotFoundError" do expect { receiver.execute }.to raise_error(Gitlab::Email::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::EmptyEmailError) end end context "when the email was auto generated" do let!(:mail_key) { '636ca428858779856c226bb145ef4fad' } let!(:email_raw) { fixture_file("emails/auto_reply.eml") } it "raises an AutoGeneratedEmailError" do expect { receiver.execute }.to raise_error(Gitlab::Email::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::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::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 ProjectNotFound" do expect { receiver.execute }.to raise_error(Gitlab::Email::ProjectNotFound) 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::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::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::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 mail key' do |header| it "fetches the mail 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 'mail 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 mail key', 'References' end end end context "when it's trying to create a new issue" do before do stub_incoming_email_setting(enabled: true, address: "incoming+%{key}@appmail.adventuretime.ooo") end let(:sent_notification) {} let!(:user) do create( :user, email: 'jake@adventuretime.ooo', authentication_token: 'auth_token' ) end 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 setup_attachment 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 context "when the reply is blank" do let!(:email_raw) { fixture_file("emails/valid_new_issue_empty.eml") } 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 eq('') end end end context "something is wrong" do before do project end context "when the issue could not be saved" do before do 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::InvalidIssueError) end end context "when the authentication_token token didn't match" do let!(:email_raw) { fixture_file("emails/wrong_authentication_token.eml") } it "raises an UserNotAuthorizedError" do expect { receiver.execute }.to raise_error(Gitlab::Email::UserNotAuthorizedError) end end context "when project is private" do let(:project) { create(:project, :private, namespace: namespace) } it "raises a ProjectNotFound if the user is not a member" do expect { receiver.execute }.to raise_error(Gitlab::Email::ProjectNotFound) end end end end end