summaryrefslogtreecommitdiff
path: root/lib/gitlab/email/receiver.rb
diff options
context:
space:
mode:
authorLin Jen-Shin <godfat@godfat.org>2016-03-23 22:20:22 +0800
committerLin Jen-Shin <godfat@godfat.org>2016-05-16 21:27:16 +0000
commit6cfd028278e7fe22c2776b9ce70a5b92223115f9 (patch)
tree4de7d86888196f30229d31bbb5c3eff3723a9e15 /lib/gitlab/email/receiver.rb
parent2375b437bd2f4287e04b11050aae011b314bcd6b (diff)
downloadgitlab-ce-6cfd028278e7fe22c2776b9ce70a5b92223115f9.tar.gz
Implement #3243 New Issue by email
So we extend Gitlab::Email::Receiver for this new behaviour, however we might want to split it into another class for better testing it. Another issue is that, currently it's using this to parse project identifier: Gitlab::IncomingEmail.key_from_address Which is using: Gitlab.config.incoming_email.address for the receiver name. This is probably `reply` because it's used for replying to a specific issue. We might want to introduce another config for this, or just use `reply` instead of `incoming`. I'll prefer to introduce a new config for this, or just change `reply` to `incoming` because it would make sense for replying to there, too. The email template used in tests were copied and modified from: `emails/valid_reply.eml` which I hope is ok.
Diffstat (limited to 'lib/gitlab/email/receiver.rb')
-rw-r--r--lib/gitlab/email/receiver.rb87
1 files changed, 70 insertions, 17 deletions
diff --git a/lib/gitlab/email/receiver.rb b/lib/gitlab/email/receiver.rb
index 97ef9851d71..2b57b3a20fc 100644
--- a/lib/gitlab/email/receiver.rb
+++ b/lib/gitlab/email/receiver.rb
@@ -12,6 +12,7 @@ module Gitlab
class UserNotAuthorizedError < ProcessingError; end
class NoteableNotFoundError < ProcessingError; end
class InvalidNoteError < ProcessingError; end
+ class InvalidIssueError < ProcessingError; end
def initialize(raw)
@raw = raw
@@ -20,29 +21,30 @@ module Gitlab
def execute
raise EmptyEmailError if @raw.blank?
- raise SentNotificationNotFoundError unless sent_notification
+ if sent_notification
+ process_reply
- raise AutoGeneratedEmailError if message.header.to_s =~ /auto-(generated|replied)/
-
- author = sent_notification.recipient
+ elsif message_project
+ process_create_issue
- raise UserNotFoundError unless author
+ else
+ # TODO: could also be project not found
+ raise SentNotificationNotFoundError
+ end
+ end
- raise UserBlockedError if author.blocked?
+ private
+ def process_reply
+ raise AutoGeneratedEmailError if message.header.to_s =~ /auto-(generated|replied)/
+ author = sent_notification.recipient
project = sent_notification.project
- raise UserNotAuthorizedError unless project && author.can?(:create_note, project)
+ check_input(author, project, :create_note)
raise NoteableNotFoundError unless sent_notification.noteable
- reply = ReplyParser.new(message).execute.strip
-
- raise EmptyEmailError if reply.blank?
-
- reply = add_attachments(reply)
-
- note = create_note(reply)
+ note = create_note(extract_reply(project))
unless note.persisted?
msg = "The comment could not be created for the following reasons:"
@@ -54,7 +56,58 @@ module Gitlab
end
end
- private
+ def process_create_issue
+ check_input(message_sender, message_project, :create_issue)
+
+ issue = Issues::CreateService.new(message_project, message_sender,
+ title: message.subject,
+ description: extract_reply(message_project)).execute
+
+ unless issue.persisted?
+ msg = "The issue could not be created for the following reasons:"
+ issue.errors.full_messages.each do |error|
+ msg << "\n\n- #{error}"
+ end
+
+ raise InvalidIssueError, msg
+ end
+ end
+
+ def check_input(author, project, permission)
+ if author
+ if author.blocked?
+ raise UserBlockedError
+ elsif project.nil? || !author.can?(permission, project)
+ # TODO: Give project not found error if author cannot read project
+ raise UserNotAuthorizedError
+ end
+ else
+ raise UserNotFoundError
+ end
+ end
+
+ # Find the first matched user in database from email From: section
+ def message_sender
+ @message_sender ||= message.from.find do |email|
+ user = User.find_by_any_email(email)
+ break user if user
+ end
+ end
+
+ def message_project
+ @message_project ||=
+ Project.find_with_namespace(reply_key) if reply_key
+ end
+
+ def extract_reply project
+ reply = ReplyParser.new(message).execute.strip
+
+ raise EmptyEmailError if reply.blank?
+
+ add_attachments(reply, project)
+
+ reply
+ end
def message
@message ||= Mail::Message.new(@raw)
@@ -93,8 +146,8 @@ module Gitlab
SentNotification.for(reply_key)
end
- def add_attachments(reply)
- attachments = Email::AttachmentUploader.new(message).execute(sent_notification.project)
+ def add_attachments(reply, project)
+ attachments = Email::AttachmentUploader.new(message).execute(project)
attachments.each do |link|
reply << "\n\n#{link[:markdown]}"