diff --git a/app/mailers/emails/pipelines.rb b/app/mailers/emails/pipelines.rb
index 643b947a049a6e9a3fa6537e6f2428ff3e1dea5e..e132105807ab959a0de9cc0102563f91d170c494 100644
--- a/app/mailers/emails/pipelines.rb
+++ b/app/mailers/emails/pipelines.rb
@@ -1,18 +1,18 @@
 module Emails
   module Pipelines
-    def pipeline_succeeded_email(params, to)
-      pipeline_mail(params, to, 'succeeded')
+    def pipeline_success_email(pipeline, to)
+      pipeline_mail(pipeline, to, 'succeeded')
     end
 
-    def pipeline_failed_email(params, to)
-      pipeline_mail(params, to, 'failed')
+    def pipeline_failed_email(pipeline, to)
+      pipeline_mail(pipeline, to, 'failed')
     end
 
     private
 
-    def pipeline_mail(params, to, status)
-      @project = params.project
-      @pipeline = params.pipeline
+    def pipeline_mail(pipeline, to, status)
+      @project = pipeline.project
+      @pipeline = pipeline
       add_headers
 
       mail(to: to, subject: pipeline_subject(status))
diff --git a/app/models/ci/pipeline.rb b/app/models/ci/pipeline.rb
index 0b1df9f429423b6940ff8e18257a7efa9c2601a4..b9c46202e5e3cf6b3188c606d75e9e883e4466b4 100644
--- a/app/models/ci/pipeline.rb
+++ b/app/models/ci/pipeline.rb
@@ -62,6 +62,10 @@ module Ci
       after_transition do |pipeline, transition|
         pipeline.execute_hooks unless transition.loopback?
       end
+
+      after_transition any => [:success, :failed] do |pipeline, transition|
+        SendPipelineNotificationService.new(pipeline).execute
+      end
     end
 
     # ref can't be HEAD or SHA, can only be branch/tag name
@@ -90,6 +94,11 @@ module Ci
       project.id
     end
 
+    # For now the only user who participants is the user who triggered
+    def participants(current_user = nil)
+      [user]
+    end
+
     def valid_commit_sha
       if self.sha == Gitlab::Git::BLANK_SHA
         self.errors.add(:sha, " cant be 00000000 (branch removal)")
diff --git a/app/models/notification_setting.rb b/app/models/notification_setting.rb
index 121b598b8f3839f67a9963bc31dfb3ad9b79f597..43fc218de2b5d458ab85add171d173ab8d2c0880 100644
--- a/app/models/notification_setting.rb
+++ b/app/models/notification_setting.rb
@@ -32,7 +32,9 @@ class NotificationSetting < ActiveRecord::Base
     :reopen_merge_request,
     :close_merge_request,
     :reassign_merge_request,
-    :merge_merge_request
+    :merge_merge_request,
+    :failed_pipeline,
+    :success_pipeline
   ]
 
   store :events, accessors: EMAIL_EVENTS, coder: JSON
diff --git a/app/models/project_services/pipelines_email_service.rb b/app/models/project_services/pipelines_email_service.rb
index 1f852445c1c3b711de9c048c24bd34942a2e3fcd..7ce0aa7c16e0df21e06aecdc6fa72166d4601cf0 100644
--- a/app/models/project_services/pipelines_email_service.rb
+++ b/app/models/project_services/pipelines_email_service.rb
@@ -34,7 +34,8 @@ class PipelinesEmailService < Service
 
     return unless all_recipients.any?
 
-    PipelineEmailWorker.perform_async(data, all_recipients)
+    pipeline = Ci::Pipeline.find(data[:object_attributes][:id])
+    Ci::SendPipelineNotificationService.new(pipeline).execute(all_recipients)
   end
 
   def can_test?
diff --git a/app/services/ci/send_pipeline_notification_service.rb b/app/services/ci/send_pipeline_notification_service.rb
new file mode 100644
index 0000000000000000000000000000000000000000..d330fa1a73c2324634d8de82cbbd443c7f4c222e
--- /dev/null
+++ b/app/services/ci/send_pipeline_notification_service.rb
@@ -0,0 +1,13 @@
+module Ci
+  class SendPipelineNotificationService < BaseService
+    attr_reader :pipeline
+
+    def initialize(new_pipeline)
+      @pipeline = new_pipeline
+    end
+
+    def execute(recipients = nil)
+      notification_service.pipeline_finished(pipeline, recipients)
+    end
+  end
+end
diff --git a/app/services/notification_service.rb b/app/services/notification_service.rb
index 6139ed56e25559c4f499e0fa1b162bbf97ed3e32..de60c49ba845999580f81e908972d6f50217b402 100644
--- a/app/services/notification_service.rb
+++ b/app/services/notification_service.rb
@@ -311,6 +311,22 @@ class NotificationService
     mailer.project_was_not_exported_email(current_user, project, errors).deliver_later
   end
 
+  def pipeline_finished(pipeline, recipients = nil)
+    email_template = "pipeline_#{pipeline.status}_email"
+
+    return unless mailer.respond_to?(email_template)
+
+    recipients ||= build_recipients(
+      pipeline,
+      pipeline.project,
+      pipeline.user,
+      action: pipeline.status)
+
+    recipients.each do |to|
+      Notify.public_send(email_template, pipeline, to).deliver_later
+    end
+  end
+
   protected
 
   # Get project/group users with CUSTOM notification level
@@ -613,6 +629,6 @@ class NotificationService
   # Build event key to search on custom notification level
   # Check NotificationSetting::EMAIL_EVENTS
   def build_custom_key(action, object)
-    "#{action}_#{object.class.name.underscore}".to_sym
+    "#{action}_#{object.class.model_name.name.underscore}".to_sym
   end
 end
diff --git a/app/views/notify/pipeline_succeeded_email.html.haml b/app/views/notify/pipeline_success_email.html.haml
similarity index 100%
rename from app/views/notify/pipeline_succeeded_email.html.haml
rename to app/views/notify/pipeline_success_email.html.haml
diff --git a/app/views/notify/pipeline_succeeded_email.text.erb b/app/views/notify/pipeline_success_email.text.erb
similarity index 100%
rename from app/views/notify/pipeline_succeeded_email.text.erb
rename to app/views/notify/pipeline_success_email.text.erb
diff --git a/app/workers/pipeline_email_worker.rb b/app/workers/pipeline_email_worker.rb
deleted file mode 100644
index 2160207c9014880497940b038d936589a23cf919..0000000000000000000000000000000000000000
--- a/app/workers/pipeline_email_worker.rb
+++ /dev/null
@@ -1,39 +0,0 @@
-class PipelineEmailWorker
-  include Sidekiq::Worker
-
-  ParamsStruct = Struct.new(:pipeline, :project, :email_template)
-  class Params < ParamsStruct
-    def initialize(pipeline_id)
-      self.pipeline = Ci::Pipeline.find(pipeline_id)
-      self.project = pipeline.project
-      self.email_template = case pipeline.status
-                            when 'success'
-                              :pipeline_succeeded_email
-                            when 'failed'
-                              :pipeline_failed_email
-                            end
-    end
-  end
-
-  def perform(data, recipients)
-    params = Params.new(data['object_attributes']['id'])
-
-    return unless params.email_template
-
-    recipients.each do |to|
-      deliver(params, to) do
-        Notify.public_send(params.email_template, params, to).deliver_now
-      end
-    end
-  end
-
-  private
-
-  def deliver(params, to)
-    yield
-  # These are input errors and won't be corrected even if Sidekiq retries
-  rescue Net::SMTPFatalError, Net::SMTPSyntaxError => e
-    project_name = params.project.path_with_namespace
-    logger.info("Failed to send email for #{project_name} to #{to}: #{e}")
-  end
-end