diff --git a/app/controllers/profiles/emails_controller.rb b/app/controllers/profiles/emails_controller.rb
new file mode 100644
index 0000000000000000000000000000000000000000..9996b67a8a4e297dcb5d54574672c1725688951f
--- /dev/null
+++ b/app/controllers/profiles/emails_controller.rb
@@ -0,0 +1,26 @@
+class Profiles::EmailsController < ApplicationController
+  layout "profile"
+
+  def index
+    @primary = current_user.email
+    @emails = current_user.emails
+  end
+
+  def create
+    @email = current_user.emails.new(params[:email])
+    
+    flash[:alert] = @email.errors.full_messages.first unless @email.save
+
+    redirect_to profile_emails_url
+  end
+
+  def destroy
+    @email = current_user.emails.find(params[:id])
+    @email.destroy
+
+    respond_to do |format|
+      format.html { redirect_to profile_emails_url }
+      format.js { render nothing: true }
+    end
+  end
+end
diff --git a/app/helpers/commits_helper.rb b/app/helpers/commits_helper.rb
index 663369e45840443129ebab1d294be060043fe2a1..5e5f3f77a21dec545646dd23a46150f3c9eccd06 100644
--- a/app/helpers/commits_helper.rb
+++ b/app/helpers/commits_helper.rb
@@ -122,17 +122,18 @@ module CommitsHelper
   def commit_person_link(commit, options = {})
     source_name = commit.send "#{options[:source]}_name".to_sym
     source_email = commit.send "#{options[:source]}_email".to_sym
+    
+    user = User.find_for_commit(source_email, source_name)
+    person_name = user.nil? ? source_name : user.name
+    person_email = user.nil? ? source_email : user.email
+    
     text = if options[:avatar]
-            avatar = image_tag(avatar_icon(source_email, options[:size]), class: "avatar #{"s#{options[:size]}" if options[:size]}", width: options[:size], alt: "")
-            %Q{#{avatar} <span class="commit-#{options[:source]}-name">#{source_name}</span>}
+            avatar = image_tag(avatar_icon(person_email, options[:size]), class: "avatar #{"s#{options[:size]}" if options[:size]}", width: options[:size], alt: "")
+            %Q{#{avatar} <span class="commit-#{options[:source]}-name">#{person_name}</span>}
           else
-            source_name
+            person_name
           end
 
-    # Prefer email match over name match
-    user = User.where(email: source_email).first
-    user ||= User.where(name: source_name).first
-
     options = {
       class: "commit-#{options[:source]}-link has_tooltip",
       data: { :'original-title' => sanitize(source_email) }
diff --git a/app/mailers/emails/profile.rb b/app/mailers/emails/profile.rb
index bcd44f9476c2150ead37af7c0aa81f3743110b1e..c91660a02b5a9deb63ae9ef4d9b1d1ecd21645bc 100644
--- a/app/mailers/emails/profile.rb
+++ b/app/mailers/emails/profile.rb
@@ -6,6 +6,12 @@ module Emails
       mail(to: @user.email, subject: subject("Account was created for you"))
     end
 
+    def new_email_email(email_id)
+      @email = Email.find(email_id)
+      @user = @email.user
+      mail(to: @user.email, subject: subject("Email was added to your account"))
+    end
+
     def new_ssh_key_email(key_id)
       @key = Key.find(key_id)
       @user = @key.user
diff --git a/app/models/email.rb b/app/models/email.rb
new file mode 100644
index 0000000000000000000000000000000000000000..22e71e4f10741713623df0eabcd766fc126339ae
--- /dev/null
+++ b/app/models/email.rb
@@ -0,0 +1,33 @@
+# == Schema Information
+#
+# Table name: emails
+#
+#  id          :integer          not null, primary key
+#  user_id     :integer          not null
+#  email       :string           not null
+#  created_at  :datetime         not null
+class Email < ActiveRecord::Base
+  attr_accessible :email, :user_id
+
+  #
+  # Relations
+  #
+  belongs_to :user
+  
+  #
+  # Validations
+  #
+  validates :user_id, presence: true
+  validates :email, presence: true, email: { strict_mode: true }, uniqueness: true
+  validate :unique_email, if: ->(email) { email.email_changed? }
+  
+  before_validation :cleanup_email
+
+  def cleanup_email
+    self.email = self.email.downcase.strip
+  end
+
+  def unique_email
+    self.errors.add(:email, 'has already been taken') if User.exists?(email: self.email)
+  end
+end
\ No newline at end of file
diff --git a/app/models/user.rb b/app/models/user.rb
index 10f21d23506bc34fcbbf42aafa82cb14e04d06a5..dd59f67ea3d1c7e4d1c83ec47b890ecf58b789e4 100644
--- a/app/models/user.rb
+++ b/app/models/user.rb
@@ -78,6 +78,7 @@ class User < ActiveRecord::Base
 
   # Profile
   has_many :keys, dependent: :destroy
+  has_many :emails, dependent: :destroy
 
   # Groups
   has_many :users_groups, dependent: :destroy
@@ -116,6 +117,7 @@ class User < ActiveRecord::Base
   validates :notification_level, inclusion: { in: Notification.notification_levels }, presence: true
   validate :namespace_uniq, if: ->(user) { user.username_changed? }
   validate :avatar_type, if: ->(user) { user.avatar_changed? }
+  validate :unique_email, if: ->(user) { user.email_changed? }
   validates :avatar, file_size: { maximum: 100.kilobytes.to_i }
 
   before_validation :generate_password, on: :create
@@ -183,6 +185,13 @@ class User < ActiveRecord::Base
         where(conditions).first
       end
     end
+    
+    def find_for_commit(email, name)
+      # Prefer email match over name match
+      User.where(email: email).first ||
+        User.joins(:emails).where(emails: { email: email }).first ||
+        User.where(name: name).first
+    end
 
     def filter filter_name
       case filter_name
@@ -250,6 +259,10 @@ class User < ActiveRecord::Base
     end
   end
 
+  def unique_email
+    self.errors.add(:email, 'has already been taken') if Email.exists?(email: self.email)
+  end
+
   # Groups user has access to
   def authorized_groups
     @authorized_groups ||= begin
diff --git a/app/observers/email_observer.rb b/app/observers/email_observer.rb
new file mode 100644
index 0000000000000000000000000000000000000000..026ad8b1d9af0eb282be88571390d197123aec36
--- /dev/null
+++ b/app/observers/email_observer.rb
@@ -0,0 +1,5 @@
+class EmailObserver < BaseObserver
+  def after_create(email)
+    notification.new_email(email)
+  end
+end
diff --git a/app/services/git_push_service.rb b/app/services/git_push_service.rb
index e54f88e42de58102dce63ac8f1cf6331317155d2..fcc03c3e4b8e0db076152bdb894658a590cdfe95 100644
--- a/app/services/git_push_service.rb
+++ b/app/services/git_push_service.rb
@@ -188,8 +188,6 @@ class GitPushService
   end
 
   def commit_user commit
-    User.where(email: commit.author_email).first ||
-      User.where(name: commit.author_name).first ||
-      user
+    User.find_for_commit(commit.author_email, commit.author_name) || user
   end
 end
diff --git a/app/services/notification_service.rb b/app/services/notification_service.rb
index 7c02777e9141363312977c601aa792a3e03e3d71..9d7bb9639ac1353eb1ec94db2edf965401ebf660 100644
--- a/app/services/notification_service.rb
+++ b/app/services/notification_service.rb
@@ -17,6 +17,13 @@ class NotificationService
     end
   end
 
+  # Always notify user about email added to profile
+  def new_email(email)
+    if email.user
+      mailer.new_email_email(email.id)
+    end
+  end
+
   # When create an issue we should send next emails:
   #
   #  * issue assignee if their notification level is not Disabled
diff --git a/app/views/layouts/nav/_profile.html.haml b/app/views/layouts/nav/_profile.html.haml
index d44cb975ea59adea34d1a735f252876d931534a9..35d0d417502a7b7318ba9b7cc3222d82cd100ef9 100644
--- a/app/views/layouts/nav/_profile.html.haml
+++ b/app/views/layouts/nav/_profile.html.haml
@@ -4,6 +4,10 @@
       %i.icon-home
   = nav_link(controller: :accounts) do
     = link_to "Account", profile_account_path
+  = nav_link(controller: :emails) do
+    = link_to profile_emails_path do
+      Emails
+      %span.count= current_user.emails.count + 1
   - unless current_user.ldap_user?
     = nav_link(controller: :passwords) do
       = link_to "Password", edit_profile_password_path
diff --git a/app/views/notify/new_email_email.html.haml b/app/views/notify/new_email_email.html.haml
new file mode 100644
index 0000000000000000000000000000000000000000..4a0448a573ccd2f9387174404e4301a84d0473da
--- /dev/null
+++ b/app/views/notify/new_email_email.html.haml
@@ -0,0 +1,10 @@
+%p
+  Hi #{@user.name}!
+%p
+  A new email was added to your account:
+%p
+  email:
+  %code= @email.email
+%p
+  If this email was added in error, you can remove it here:
+  = link_to "Emails", profile_emails_url
diff --git a/app/views/notify/new_email_email.text.erb b/app/views/notify/new_email_email.text.erb
new file mode 100644
index 0000000000000000000000000000000000000000..51cba99ad0d695ed9ff107f7ebaf6b6d86a3a4a1
--- /dev/null
+++ b/app/views/notify/new_email_email.text.erb
@@ -0,0 +1,7 @@
+Hi <%= @user.name %>!
+
+A new email was added to your account:
+
+email.................. <%= @email.email %>
+
+If this email was added in error, you can remove it here: <%= profile_emails_url %>
diff --git a/app/views/profiles/emails/index.html.haml b/app/views/profiles/emails/index.html.haml
new file mode 100644
index 0000000000000000000000000000000000000000..dc45ab2de791b7ab28055b6b9a8b3e13b41fdadd
--- /dev/null
+++ b/app/views/profiles/emails/index.html.haml
@@ -0,0 +1,29 @@
+%h3.page-title
+  My Email Addresses
+%p.light
+  Your
+  %b Primary Email
+  will be used for account notifications, avatar detection and web based operations, such as edits and merges. All email addresses will be used to identify your commits.
+
+.ui-box
+  .title
+    Emails (#{@emails.count + 1})
+  %ul.well-list#emails-table
+    %li
+      %strong= @primary
+      %span.label.label-success Primary Email
+    - @emails.each do |email|
+      %li
+        %strong= email.email
+        %span.cgray
+          added #{time_ago_with_tooltip(email.created_at)}
+        = link_to 'Remove', profile_email_path(email), data: { confirm: 'Are you sure?'}, method: :delete, class: 'btn btn-small btn-remove pull-right'
+
+%h3.page-title Add Email Address
+= form_for 'email', url: profile_emails_path, html: { class: 'form-horizontal' } do |f|
+  .form-group
+    = f.label :email, class: 'control-label'
+    .col-sm-10
+      = f.text_field :email, class: 'form-control'
+  .form-actions
+    = f.submit 'Add', class: 'btn btn-create'
\ No newline at end of file
diff --git a/config/routes.rb b/config/routes.rb
index 8c66ad741f9622c309eca62b905a80763e836222..fdca1e62661a87506fe63ff84efa6467757838a3 100644
--- a/config/routes.rb
+++ b/config/routes.rb
@@ -124,6 +124,7 @@ Gitlab::Application.routes.draw do
         end
       end
       resources :keys
+      resources :emails, only: [:index, :create, :destroy]
       resources :groups, only: [:index] do
         member do
           delete :leave
diff --git a/db/migrate/20140209025651_create_emails.rb b/db/migrate/20140209025651_create_emails.rb
new file mode 100644
index 0000000000000000000000000000000000000000..cb78c4af11b25b59533c2d15a33292c01920eb3d
--- /dev/null
+++ b/db/migrate/20140209025651_create_emails.rb
@@ -0,0 +1,13 @@
+class CreateEmails < ActiveRecord::Migration
+  def change
+    create_table :emails do |t|
+      t.integer  :user_id, null: false
+      t.string   :email, null: false
+      
+      t.timestamps
+    end
+
+    add_index :emails, :user_id
+    add_index :emails, :email, unique: true
+  end
+end
diff --git a/db/schema.rb b/db/schema.rb
index acbb793bbe8daab9522909eb299826ddbff6f836..65f79fb7e051f12b8312baf543309d8120fc03ce 100644
--- a/db/schema.rb
+++ b/db/schema.rb
@@ -11,7 +11,7 @@
 #
 # It's strongly recommended that you check this file into your version control system.
 
-ActiveRecord::Schema.define(version: 20140127170938) do
+ActiveRecord::Schema.define(version: 20140209025651) do
 
   create_table "broadcast_messages", force: true do |t|
     t.text     "message",    null: false
@@ -33,6 +33,16 @@ ActiveRecord::Schema.define(version: 20140127170938) do
 
   add_index "deploy_keys_projects", ["project_id"], name: "index_deploy_keys_projects_on_project_id", using: :btree
 
+  create_table "emails", force: true do |t|
+    t.integer  "user_id",    null: false
+    t.string   "email",      null: false
+    t.datetime "created_at"
+    t.datetime "updated_at"
+  end
+
+  add_index "emails", ["email"], name: "index_emails_on_email", unique: true, using: :btree
+  add_index "emails", ["user_id"], name: "index_emails_on_user_id", using: :btree
+
   create_table "events", force: true do |t|
     t.string   "target_type"
     t.integer  "target_id"
@@ -66,8 +76,8 @@ ActiveRecord::Schema.define(version: 20140127170938) do
     t.integer  "assignee_id"
     t.integer  "author_id"
     t.integer  "project_id"
-    t.datetime "created_at"
-    t.datetime "updated_at"
+    t.datetime "created_at",               null: false
+    t.datetime "updated_at",               null: false
     t.integer  "position",     default: 0
     t.string   "branch_name"
     t.text     "description"
@@ -85,8 +95,8 @@ ActiveRecord::Schema.define(version: 20140127170938) do
 
   create_table "keys", force: true do |t|
     t.integer  "user_id"
-    t.datetime "created_at"
-    t.datetime "updated_at"
+    t.datetime "created_at",  null: false
+    t.datetime "updated_at",  null: false
     t.text     "key"
     t.string   "title"
     t.string   "type"
@@ -111,8 +121,8 @@ ActiveRecord::Schema.define(version: 20140127170938) do
     t.integer  "author_id"
     t.integer  "assignee_id"
     t.string   "title"
-    t.datetime "created_at"
-    t.datetime "updated_at"
+    t.datetime "created_at",        null: false
+    t.datetime "updated_at",        null: false
     t.integer  "milestone_id"
     t.string   "state"
     t.string   "merge_status"
@@ -164,8 +174,8 @@ ActiveRecord::Schema.define(version: 20140127170938) do
     t.text     "note"
     t.string   "noteable_type"
     t.integer  "author_id"
-    t.datetime "created_at"
-    t.datetime "updated_at"
+    t.datetime "created_at",                    null: false
+    t.datetime "updated_at",                    null: false
     t.integer  "project_id"
     t.string   "attachment"
     t.string   "line_code"
@@ -187,8 +197,8 @@ ActiveRecord::Schema.define(version: 20140127170938) do
     t.string   "name"
     t.string   "path"
     t.text     "description"
-    t.datetime "created_at"
-    t.datetime "updated_at"
+    t.datetime "created_at",                                null: false
+    t.datetime "updated_at",                                null: false
     t.integer  "creator_id"
     t.boolean  "issues_enabled",         default: true,     null: false
     t.boolean  "wall_enabled",           default: true,     null: false
@@ -239,8 +249,8 @@ ActiveRecord::Schema.define(version: 20140127170938) do
     t.text     "content",    limit: 2147483647
     t.integer  "author_id",                                    null: false
     t.integer  "project_id"
-    t.datetime "created_at"
-    t.datetime "updated_at"
+    t.datetime "created_at",                                   null: false
+    t.datetime "updated_at",                                   null: false
     t.string   "file_name"
     t.datetime "expires_at"
     t.boolean  "private",                       default: true, null: false
@@ -262,42 +272,45 @@ ActiveRecord::Schema.define(version: 20140127170938) do
     t.datetime "created_at"
   end
 
+  add_index "taggings", ["tag_id"], name: "index_taggings_on_tag_id", using: :btree
+  add_index "taggings", ["taggable_id", "taggable_type", "context"], name: "index_taggings_on_taggable_id_and_taggable_type_and_context", using: :btree
+
   create_table "tags", force: true do |t|
     t.string "name"
   end
 
   create_table "users", force: true do |t|
-    t.string   "email",                              default: "",    null: false
-    t.string   "encrypted_password",     limit: 128, default: "",    null: false
+    t.string   "email",                  default: "",    null: false
+    t.string   "encrypted_password",     default: "",    null: false
     t.string   "reset_password_token"
     t.datetime "reset_password_sent_at"
     t.datetime "remember_created_at"
-    t.integer  "sign_in_count",                      default: 0
+    t.integer  "sign_in_count",          default: 0
     t.datetime "current_sign_in_at"
     t.datetime "last_sign_in_at"
     t.string   "current_sign_in_ip"
     t.string   "last_sign_in_ip"
-    t.datetime "created_at"
-    t.datetime "updated_at"
+    t.datetime "created_at",                             null: false
+    t.datetime "updated_at",                             null: false
     t.string   "name"
-    t.boolean  "admin",                              default: false, null: false
-    t.integer  "projects_limit",                     default: 10
-    t.string   "skype",                              default: "",    null: false
-    t.string   "linkedin",                           default: "",    null: false
-    t.string   "twitter",                            default: "",    null: false
+    t.boolean  "admin",                  default: false, null: false
+    t.integer  "projects_limit",         default: 10
+    t.string   "skype",                  default: "",    null: false
+    t.string   "linkedin",               default: "",    null: false
+    t.string   "twitter",                default: "",    null: false
     t.string   "authentication_token"
-    t.integer  "theme_id",                           default: 1,     null: false
+    t.integer  "theme_id",               default: 1,     null: false
     t.string   "bio"
-    t.integer  "failed_attempts",                    default: 0
+    t.integer  "failed_attempts",        default: 0
     t.datetime "locked_at"
     t.string   "extern_uid"
     t.string   "provider"
     t.string   "username"
-    t.boolean  "can_create_group",                   default: true,  null: false
-    t.boolean  "can_create_team",                    default: true,  null: false
+    t.boolean  "can_create_group",       default: true,  null: false
+    t.boolean  "can_create_team",        default: true,  null: false
     t.string   "state"
-    t.integer  "color_scheme_id",                    default: 1,     null: false
-    t.integer  "notification_level",                 default: 1,     null: false
+    t.integer  "color_scheme_id",        default: 1,     null: false
+    t.integer  "notification_level",     default: 1,     null: false
     t.datetime "password_expires_at"
     t.integer  "created_by_id"
     t.string   "avatar"
@@ -305,14 +318,15 @@ ActiveRecord::Schema.define(version: 20140127170938) do
     t.datetime "confirmed_at"
     t.datetime "confirmation_sent_at"
     t.string   "unconfirmed_email"
-    t.boolean  "hide_no_ssh_key",                    default: false
-    t.string   "website_url",                        default: "",    null: false
+    t.boolean  "hide_no_ssh_key",        default: false
+    t.string   "website_url",            default: "",    null: false
   end
 
   add_index "users", ["admin"], name: "index_users_on_admin", using: :btree
   add_index "users", ["authentication_token"], name: "index_users_on_authentication_token", unique: true, using: :btree
   add_index "users", ["confirmation_token"], name: "index_users_on_confirmation_token", unique: true, using: :btree
   add_index "users", ["email"], name: "index_users_on_email", unique: true, using: :btree
+  add_index "users", ["extern_uid", "provider"], name: "index_users_on_extern_uid_and_provider", unique: true, using: :btree
   add_index "users", ["name"], name: "index_users_on_name", using: :btree
   add_index "users", ["reset_password_token"], name: "index_users_on_reset_password_token", unique: true, using: :btree
   add_index "users", ["username"], name: "index_users_on_username", using: :btree
@@ -331,8 +345,8 @@ ActiveRecord::Schema.define(version: 20140127170938) do
   create_table "users_projects", force: true do |t|
     t.integer  "user_id",                        null: false
     t.integer  "project_id",                     null: false
-    t.datetime "created_at"
-    t.datetime "updated_at"
+    t.datetime "created_at",                     null: false
+    t.datetime "updated_at",                     null: false
     t.integer  "project_access",     default: 0, null: false
     t.integer  "notification_level", default: 3, null: false
   end
@@ -344,8 +358,8 @@ ActiveRecord::Schema.define(version: 20140127170938) do
   create_table "web_hooks", force: true do |t|
     t.string   "url"
     t.integer  "project_id"
-    t.datetime "created_at"
-    t.datetime "updated_at"
+    t.datetime "created_at",                                    null: false
+    t.datetime "updated_at",                                    null: false
     t.string   "type",                  default: "ProjectHook"
     t.integer  "service_id"
     t.boolean  "push_events",           default: true,          null: false
diff --git a/features/profile/emails.feature b/features/profile/emails.feature
new file mode 100644
index 0000000000000000000000000000000000000000..148fc7660813ebe6696323bb7b4b2364b0dceb88
--- /dev/null
+++ b/features/profile/emails.feature
@@ -0,0 +1,25 @@
+Feature: Profile Emails
+  Background:
+    Given I sign in as a user
+    And I visit profile emails page
+
+  Scenario: I should see emails
+    Then I should see my emails
+
+  Scenario: Add new email
+    Given I submit new email "my@email.com"
+    Then I should see new email "my@email.com"
+    And I should see my emails
+
+  Scenario: Add duplicate email
+    Given I submit duplicate email @user.email
+    Then I should not have @user.email added
+    And I should see my emails
+
+  Scenario: Remove email
+    Given I submit new email "my@email.com"
+    Then I should see new email "my@email.com"
+    And I should see my emails
+    Then I click link "Remove" for "my@email.com"
+    Then I should not see email "my@email.com"
+    And I should see my emails
diff --git a/features/project/commits/commits_user_lookup.feature b/features/project/commits/commits_user_lookup.feature
new file mode 100644
index 0000000000000000000000000000000000000000..f3864c0ab389780036af3866e8ce46684e7df5c4
--- /dev/null
+++ b/features/project/commits/commits_user_lookup.feature
@@ -0,0 +1,14 @@
+Feature: Project Browse Commits User Lookup
+  Background:
+    Given I sign in as a user
+    And I own a project
+    And I have the user that authored the commits
+    And I visit my project's commits page
+
+  Scenario: I browse commit from list
+    Given I click on commit link
+    Then I see commit info
+
+  Scenario: I browse another commit from list
+    Given I click on another commit link
+    Then I see other commit info
\ No newline at end of file
diff --git a/features/steps/profile/profile_emails.rb b/features/steps/profile/profile_emails.rb
new file mode 100644
index 0000000000000000000000000000000000000000..99588c859910d8e78e63e8269702087b842c2658
--- /dev/null
+++ b/features/steps/profile/profile_emails.rb
@@ -0,0 +1,48 @@
+class ProfileEmails < Spinach::FeatureSteps
+  include SharedAuthentication
+
+  Then 'I visit profile emails page' do
+    visit profile_emails_path
+  end
+
+  Then 'I should see my emails' do
+    page.should have_content(@user.email)
+    @user.emails.each do |email|
+      page.should have_content(email.email)
+    end
+  end
+
+  And 'I submit new email "my@email.com"' do
+    fill_in "email_email", with: "my@email.com"
+    click_button "Add"
+  end
+
+  Then 'I should see new email "my@email.com"' do
+    email = @user.emails.find_by(email: "my@email.com")
+    email.should_not be_nil
+    page.should have_content("my@email.com")
+  end
+
+  Then 'I should not see email "my@email.com"' do
+    email = @user.emails.find_by(email: "my@email.com")
+    email.should be_nil
+    page.should_not have_content("my@email.com")
+  end
+  
+  Then 'I click link "Remove" for "my@email.com"' do
+    # there should only be one remove button at this time
+    click_link "Remove"
+    # force these to reload as they have been cached
+    @user.emails.reload
+  end
+
+  And 'I submit duplicate email @user.email' do
+    fill_in "email_email", with: @user.email
+    click_button "Add"
+  end
+
+  Then 'I should not have @user.email added' do
+    email = @user.emails.find_by(email: @user.email)
+    email.should be_nil
+  end
+end
diff --git a/features/steps/project/project_browse_commits_user_lookup.rb b/features/steps/project/project_browse_commits_user_lookup.rb
new file mode 100644
index 0000000000000000000000000000000000000000..328be3735532bd583a93cd6afe686eacd05fdce1
--- /dev/null
+++ b/features/steps/project/project_browse_commits_user_lookup.rb
@@ -0,0 +1,35 @@
+class ProjectBrowseCommitsUserLookup < Spinach::FeatureSteps
+  include SharedAuthentication
+  include SharedProject
+  include SharedPaths
+  
+  Given 'I have the user that authored the commits' do
+    @user = create(:user, email: 'dmitriy.zaporozhets@gmail.com')
+    create(:email, { user: @user, email: 'dzaporozhets@sphereconsultinginc.com' })
+  end
+
+  Given 'I click on commit link' do
+    visit project_commit_path(@project, ValidCommit::ID)
+  end
+
+  Given 'I click on another commit link' do
+    visit project_commit_path(@project, ValidCommitWithAltEmail::ID)
+  end
+
+  Then 'I see commit info' do
+    page.should have_content ValidCommit::MESSAGE
+    check_author_link(ValidCommit::AUTHOR_EMAIL)
+  end
+  
+  Then 'I see other commit info' do
+    page.should have_content ValidCommitWithAltEmail::MESSAGE
+    check_author_link(ValidCommitWithAltEmail::AUTHOR_EMAIL)
+  end
+
+  def check_author_link(email)
+    author_link = find('.commit-author-link')
+    author_link['href'].should == user_path(@user)
+    author_link['data-original-title'].should == email
+    find('.commit-author-name').text.should == @user.name
+  end
+end
diff --git a/features/support/env.rb b/features/support/env.rb
index 0186002c559f7929aed5410ef28a83be5bda6637..7b11f5a7c6f202c7a062b9782546e792aa6ec36e 100644
--- a/features/support/env.rb
+++ b/features/support/env.rb
@@ -15,7 +15,7 @@ require 'spinach/capybara'
 require 'sidekiq/testing/inline'
 
 
-%w(valid_commit big_commits select2_helper test_env).each do |f|
+%w(valid_commit valid_commit_with_alt_email big_commits select2_helper test_env).each do |f|
   require Rails.root.join('spec', 'support', f)
 end
 
diff --git a/spec/factories.rb b/spec/factories.rb
index e5d05a4c2ea01aa1bfbe72327c8d0ea9d59c580c..37436e53b95ad3168d3dbc718cf41598e4d81dc3 100644
--- a/spec/factories.rb
+++ b/spec/factories.rb
@@ -219,6 +219,19 @@ FactoryGirl.define do
       end
     end
   end
+  
+  factory :email do
+    user
+    email do
+      Faker::Internet.email('alias')
+    end
+
+    factory :another_email do
+      email do
+        Faker::Internet.email('another.alias')
+      end
+    end
+  end
 
   factory :milestone do
     title
diff --git a/spec/mailers/notify_spec.rb b/spec/mailers/notify_spec.rb
index d53dc17d9774d2bbacd8326b8572c0ca865ebe72..88cae0bb7560c81cd505ac920f650d4314e2c272 100644
--- a/spec/mailers/notify_spec.rb
+++ b/spec/mailers/notify_spec.rb
@@ -90,6 +90,28 @@ describe Notify do
     end
   end
 
+  describe 'user added email' do
+    let(:email) { create(:email) }
+
+    subject { Notify.new_email_email(email.id) }
+
+    it 'is sent to the new user' do
+      should deliver_to email.user.email
+    end
+
+    it 'has the correct subject' do
+      should have_subject /^gitlab \| Email was added to your account$/i
+    end
+
+    it 'contains the new email address' do
+      should have_body_text /#{email.email}/
+    end
+
+    it 'includes a link to emails page' do
+      should have_body_text /#{profile_emails_path}/
+    end
+  end
+
   context 'for a project' do
     describe 'items that are assignable, the email' do
       let(:assignee) { create(:user, email: 'assignee@example.com') }
diff --git a/spec/observers/email_observer_spec.rb b/spec/observers/email_observer_spec.rb
new file mode 100644
index 0000000000000000000000000000000000000000..599b9a6ffbabb778fc695dfa9cf481447e698523
--- /dev/null
+++ b/spec/observers/email_observer_spec.rb
@@ -0,0 +1,17 @@
+require 'spec_helper'
+
+describe EmailObserver do
+  let(:email)      { create(:email) }
+
+  before { subject.stub(notification: double('NotificationService').as_null_object) }
+
+  subject { EmailObserver.instance }
+
+  describe '#after_create' do
+    it 'trigger notification to send emails' do
+      subject.should_receive(:notification)
+
+      subject.after_create(email)
+    end
+  end
+end
diff --git a/spec/routing/routing_spec.rb b/spec/routing/routing_spec.rb
index 8929a48973dda53ecb174589b66b5229f72b3c22..9b67cd432bc1f008613f5529a7f2486c27c5eb99 100644
--- a/spec/routing/routing_spec.rb
+++ b/spec/routing/routing_spec.rb
@@ -183,6 +183,23 @@ describe Profiles::KeysController, "routing" do
   end
 end
 
+#   emails GET    /emails(.:format)        emails#index
+#          POST   /keys(.:format)          emails#create
+#          DELETE /keys/:id(.:format)      keys#destroy
+describe Profiles::EmailsController, "routing" do
+  it "to #index" do
+    get("/profile/emails").should route_to('profiles/emails#index')
+  end
+
+  it "to #create" do
+    post("/profile/emails").should route_to('profiles/emails#create')
+  end
+
+  it "to #destroy" do
+    delete("/profile/emails/1").should route_to('profiles/emails#destroy', id: '1')
+  end
+end
+
 # profile_avatar DELETE /profile/avatar(.:format) profiles/avatars#destroy
 describe Profiles::AvatarsController, "routing" do
   it "to #destroy" do
diff --git a/spec/services/notification_service_spec.rb b/spec/services/notification_service_spec.rb
index 09a5debe1dcce5f0e29fab8ea9e4dba3337bb879..e378be0425507d8f114616564b9eeb8de3f36c51 100644
--- a/spec/services/notification_service_spec.rb
+++ b/spec/services/notification_service_spec.rb
@@ -16,6 +16,19 @@ describe NotificationService do
     end
   end
 
+  describe 'Email' do
+    describe :new_email do
+      let(:email) { create(:email) }
+
+      it { notification.new_email(email).should be_true }
+
+      it 'should send email to email owner' do
+        Notify.should_receive(:new_email_email).with(email.id)
+        notification.new_email(email)
+      end
+    end
+  end
+
   describe 'Notes' do
     context 'issue note' do
       let(:issue) { create(:issue, assignee: create(:user)) }
diff --git a/spec/support/valid_commit.rb b/spec/support/valid_commit.rb
index 8094b679e991e088947cf6102d682ce987da1590..98bc59b573f9cfff7dd41fa1ea33a56f4546e926 100644
--- a/spec/support/valid_commit.rb
+++ b/spec/support/valid_commit.rb
@@ -2,6 +2,7 @@ module ValidCommit
   ID = "8470d70da67355c9c009e4401746b1d5410af2e3"
   MESSAGE = "notes controller refactored"
   AUTHOR_FULL_NAME = "Dmitriy Zaporozhets"
+  AUTHOR_EMAIL = "dmitriy.zaporozhets@gmail.com"
 
   FILES = [".foreman", ".gitignore", ".rails_footnotes", ".rspec", ".travis.yml", "CHANGELOG", "Gemfile", "Gemfile.lock", "LICENSE", "Procfile", "Procfile.production", "README.md", "Rakefile", "VERSION", "app", "config.ru", "config", "db", "doc", "lib", "log", "public", "resque.sh", "script", "spec", "vendor"]
   FILES_COUNT = 26
diff --git a/spec/support/valid_commit_with_alt_email.rb b/spec/support/valid_commit_with_alt_email.rb
new file mode 100644
index 0000000000000000000000000000000000000000..d6e364c41f1ab42f7342db59729357fb0f69d72a
--- /dev/null
+++ b/spec/support/valid_commit_with_alt_email.rb
@@ -0,0 +1,6 @@
+module ValidCommitWithAltEmail
+  ID = "1e689bfba39525ead225eaf611948cfbe8ac34cf"
+  MESSAGE = "fixed notes logic"
+  AUTHOR_FULL_NAME = "Dmitriy Zaporozhets"
+  AUTHOR_EMAIL = "dzaporozhets@sphereconsultinginc.com"
+end
\ No newline at end of file