diff --git a/app/assets/javascripts/discourse/lib/plugin-api.js.es6 b/app/assets/javascripts/discourse/lib/plugin-api.js.es6
index c429d6b4a..789b35aa3 100644
--- a/app/assets/javascripts/discourse/lib/plugin-api.js.es6
+++ b/app/assets/javascripts/discourse/lib/plugin-api.js.es6
@@ -93,3 +93,30 @@ export function withPluginApi(version, apiCodeCallback, opts) {
     return apiCodeCallback(api);
   }
 }
+
+// This is backported so plugins in the new format will not raise errors
+//
+// To upgrade your plugin for backwards compatibility, you can add code in this
+// form:
+//
+//   function newApiCode(api) {
+//     // api.xyz();
+//   }
+//
+//   function oldCode() {
+//     // your pre-PluginAPI code goes here. You will be able to delete this
+//     // code once the `PluginAPI` has been rolled out to all versions of
+//     // Discourse you want to support.
+//   }
+//
+//   // `newApiCode` will use API version 0.1, if no API support then
+//   // `oldCode` will be called
+//   withPluginApi('0.1', newApiCode, { noApi: oldCode });
+//
+export function withPluginApi(version, apiCodeCallback, opts) {
+  console.warn(`Plugin API v${version} is not supported`);
+
+  if (opts && opts.noApi) {
+    return opts.noApi();
+  }
+}
diff --git a/app/assets/javascripts/discourse/models/user.js.es6 b/app/assets/javascripts/discourse/models/user.js.es6
index fd702adff..a26f5e10e 100644
--- a/app/assets/javascripts/discourse/models/user.js.es6
+++ b/app/assets/javascripts/discourse/models/user.js.es6
@@ -147,25 +147,29 @@ const User = RestModel.extend({
             'location',
             'name',
             'locale',
-            'email_digests',
-            'email_direct',
-            'email_always',
-            'email_private_messages',
-            'dynamic_favicon',
-            'digest_after_days',
             'new_topic_duration_minutes',
-            'external_links_in_new_tab',
-            'mailing_list_mode',
-            'enable_quoting',
-            'disable_jump_reply',
             'custom_fields',
             'user_fields',
             'muted_usernames',
             'profile_background',
-            'card_background',
-            'automatically_unpin_topics'
+            'card_background'
           );
 
+    [       'email_always',
+            'mailing_list_mode',
+            'external_links_in_new_tab',
+            'email_digests',
+            'email_direct',
+            'email_private_messages',
+            'dynamic_favicon',
+            'enable_quoting',
+            'disable_jump_reply',
+            'automatically_unpin_topics',
+            'digest_after_days'
+    ].forEach(s => {
+      data[s] = this.get(`user_option.${s}`);
+    });
+
     ['muted','watched','tracked'].forEach(s => {
       let cats = this.get(s + 'Categories').map(c => c.get('id'));
       // HACK: denote lack of categories
@@ -174,7 +178,7 @@ const User = RestModel.extend({
     });
 
     if (!Discourse.SiteSettings.edit_history_visible_to_public) {
-      data['edit_history_public'] = this.get('edit_history_public');
+      data['edit_history_public'] = this.get('user_option.edit_history_public');
     }
 
     // TODO: We can remove this when migrated fully to rest model.
@@ -184,7 +188,7 @@ const User = RestModel.extend({
       type: 'PUT'
     }).then(result => {
       this.set('bio_excerpt', result.user.bio_excerpt);
-      const userProps = this.getProperties('enable_quoting', 'external_links_in_new_tab', 'dynamic_favicon');
+      const userProps = Em.getProperties(this.get('user-option'),'enable_quoting', 'external_links_in_new_tab', 'dynamic_favicon');
       Discourse.User.current().setProperties(userProps);
     }).finally(() => {
       this.set('isSaving', false);
diff --git a/app/assets/javascripts/discourse/templates/user/preferences.hbs b/app/assets/javascripts/discourse/templates/user/preferences.hbs
index 636227b75..4c65524e8 100644
--- a/app/assets/javascripts/discourse/templates/user/preferences.hbs
+++ b/app/assets/javascripts/discourse/templates/user/preferences.hbs
@@ -169,17 +169,17 @@
     <div class="control-group pref-email-settings">
       <label class="control-label">{{i18n 'user.email_settings'}}</label>
       {{#if canReceiveDigest}}
-        {{preference-checkbox labelKey="user.email_digests.title" checked=model.email_digests}}
-        {{#if model.email_digests}}
+        {{preference-checkbox labelKey="user.email_digests.title" checked=model.user_option.email_digests}}
+        {{#if model.user_option.email_digests}}
           <div class='controls controls-dropdown'>
-            {{combo-box valueAttribute="value" content=digestFrequencies value=model.digest_after_days}}
+            {{combo-box valueAttribute="value" content=digestFrequencies value=model.user_option.digest_after_days}}
           </div>
         {{/if}}
       {{/if}}
-      {{preference-checkbox labelKey="user.email_private_messages" checked=model.email_private_messages}}
-      {{preference-checkbox labelKey="user.email_direct" checked=model.email_direct}}
-      <span class="pref-mailing-list-mode">{{preference-checkbox labelKey="user.mailing_list_mode" checked=model.mailing_list_mode}}</span>
-      {{preference-checkbox labelKey="user.email_always" checked=model.email_always}}
+      {{preference-checkbox labelKey="user.email_private_messages" checked=model.user_option.email_private_messages}}
+      {{preference-checkbox labelKey="user.email_direct" checked=model.user_option.email_direct}}
+      <span class="pref-mailing-list-mode">{{preference-checkbox labelKey="user.mailing_list_mode" checked=model.user_option.mailing_list_mode}}</span>
+      {{preference-checkbox labelKey="user.email_always" checked=model.user_option.email_always}}
 
       <div class='instructions'>
         {{#if siteSettings.email_time_window_mins}}
@@ -209,12 +209,12 @@
         {{combo-box valueAttribute="value" content=autoTrackDurations value=model.auto_track_topics_after_msecs}}
       </div>
 
-      {{preference-checkbox labelKey="user.external_links_in_new_tab" checked=model.external_links_in_new_tab}}
-      {{preference-checkbox labelKey="user.enable_quoting" checked=model.enable_quoting}}
-      {{preference-checkbox labelKey="user.dynamic_favicon" checked=model.dynamic_favicon}}
-      {{preference-checkbox labelKey="user.disable_jump_reply" checked=model.disable_jump_reply}}
+      {{preference-checkbox labelKey="user.external_links_in_new_tab" checked=model.user_option.external_links_in_new_tab}}
+      {{preference-checkbox labelKey="user.enable_quoting" checked=model.user_option.enable_quoting}}
+      {{preference-checkbox labelKey="user.dynamic_favicon" checked=model.user_option.dynamic_favicon}}
+      {{preference-checkbox labelKey="user.disable_jump_reply" checked=model.user_option.disable_jump_reply}}
       {{#unless siteSettings.edit_history_visible_to_public}}
-        {{preference-checkbox labelKey="user.edit_history_public" checked=model.edit_history_public}}
+        {{preference-checkbox labelKey="user.edit_history_public" checked=model.user_option.edit_history_public}}
       {{/unless}}
 
       {{plugin-outlet "user-custom-preferences"}}
@@ -254,7 +254,7 @@
     {{#if siteSettings.automatically_unpin_topics}}
     <div class="control-group topics">
       <label class="control-label">{{i18n 'categories.topics'}}</label>
-        {{preference-checkbox labelKey="user.automatically_unpin_topics" checked=model.automatically_unpin_topics}}
+        {{preference-checkbox labelKey="user.automatically_unpin_topics" checked=model.user_option.automatically_unpin_topics}}
     </div>
     {{/if}}
 
diff --git a/app/controllers/admin/email_templates_controller.rb b/app/controllers/admin/email_templates_controller.rb
index 9d872c998..ccbb3eaf6 100644
--- a/app/controllers/admin/email_templates_controller.rb
+++ b/app/controllers/admin/email_templates_controller.rb
@@ -26,7 +26,8 @@ class Admin::EmailTemplatesController < Admin::AdminController
                      "user_notifications.user_invited_to_private_message_pm",
                      "user_notifications.user_invited_to_topic", "user_notifications.user_mentioned",
                      "user_notifications.user_posted", "user_notifications.user_posted_pm",
-                     "user_notifications.user_quoted", "user_notifications.user_replied"]
+                     "user_notifications.user_quoted", "user_notifications.user_replied",
+                     "user_notifications.user_linked"]
   end
 
   def show
diff --git a/app/controllers/email_controller.rb b/app/controllers/email_controller.rb
index 4e0ff301a..22bbec051 100644
--- a/app/controllers/email_controller.rb
+++ b/app/controllers/email_controller.rb
@@ -25,9 +25,12 @@ class EmailController < ApplicationController
     end
 
     if params[:from_all]
-      @user.update_columns(email_digests: false, email_direct: false, email_private_messages: false, email_always: false)
+      @user.user_option.update_columns(email_always: false,
+                                       email_digests: false,
+                                       email_direct: false,
+                                       email_private_messages: false)
     else
-      @user.update_column(:email_digests, false)
+      @user.user_option.update_column(:email_digests, false)
     end
 
     @success = true
@@ -36,7 +39,7 @@ class EmailController < ApplicationController
   def resubscribe
     @user = DigestUnsubscribeKey.user_for_key(params[:key])
     raise Discourse::NotFound unless @user.present?
-    @user.update_column(:email_digests, true)
+    @user.user_option.update_column(:email_digests, true)
   end
 
 end
diff --git a/app/jobs/regular/notify_mailing_list_subscribers.rb b/app/jobs/regular/notify_mailing_list_subscribers.rb
index c78e78f3e..29436e423 100644
--- a/app/jobs/regular/notify_mailing_list_subscribers.rb
+++ b/app/jobs/regular/notify_mailing_list_subscribers.rb
@@ -11,7 +11,8 @@ module Jobs
 
       users =
           User.activated.not_blocked.not_suspended.real
-          .where(mailing_list_mode: true)
+          .joins(:user_option)
+          .where(user_options: {mailing_list_mode: true})
           .where('NOT EXISTS(
                       SELECT 1
                       FROM topic_users tu
diff --git a/app/jobs/regular/user_email.rb b/app/jobs/regular/user_email.rb
index 6830ec2e6..ff38409c1 100644
--- a/app/jobs/regular/user_email.rb
+++ b/app/jobs/regular/user_email.rb
@@ -62,7 +62,7 @@ module Jobs
       return if user.staged && type == :digest
 
       seen_recently = (user.last_seen_at.present? && user.last_seen_at > SiteSetting.email_time_window_mins.minutes.ago)
-      seen_recently = false if user.email_always || user.staged
+      seen_recently = false if user.user_option.email_always || user.staged
 
       email_args = {}
 
@@ -85,14 +85,14 @@ module Jobs
           email_args[:notification_type] = email_args[:notification_type].to_s
         end
 
-        if user.mailing_list_mode? &&
+        if user.user_option.mailing_list_mode? &&
            !post.topic.private_message? &&
            NOTIFICATIONS_SENT_BY_MAILING_LIST.include?(email_args[:notification_type])
            # no need to log a reason when the mail was already sent via the mailing list job
            return [nil, nil]
         end
 
-        unless user.email_always?
+        unless user.user_option.email_always?
           if (notification && notification.read?) || (post && post.seen?(user))
             return skip_message(I18n.t('email_log.notification_already_read'))
           end
diff --git a/app/jobs/scheduled/enqueue_digest_emails.rb b/app/jobs/scheduled/enqueue_digest_emails.rb
index 40cf0976d..ea74f98ed 100644
--- a/app/jobs/scheduled/enqueue_digest_emails.rb
+++ b/app/jobs/scheduled/enqueue_digest_emails.rb
@@ -15,8 +15,10 @@ module Jobs
     def target_user_ids
       # Users who want to receive emails and haven't been emailed in the last day
       query = User.real
-                  .where(email_digests: true, active: true, staged: false)
+                  .where(active: true, staged: false)
+                  .joins(:user_option)
                   .not_suspended
+                  .where(user_options: {email_digests: true})
                   .where("COALESCE(last_emailed_at, '2010-01-01') <= CURRENT_TIMESTAMP - ('1 DAY'::INTERVAL * digest_after_days)")
                   .where("COALESCE(last_seen_at, '2010-01-01') <= CURRENT_TIMESTAMP - ('1 DAY'::INTERVAL * digest_after_days)")
                   .where("COALESCE(last_seen_at, '2010-01-01') >= CURRENT_TIMESTAMP - ('1 DAY'::INTERVAL * #{SiteSetting.delete_digest_email_after_days})")
diff --git a/app/mailers/user_notifications.rb b/app/mailers/user_notifications.rb
index 517294278..52db55f8a 100644
--- a/app/mailers/user_notifications.rb
+++ b/app/mailers/user_notifications.rb
@@ -110,6 +110,13 @@ class UserNotifications < ActionMailer::Base
     notification_email(user, opts)
   end
 
+  def user_linked(user, opts)
+    opts[:allow_reply_by_email] = true
+    opts[:use_site_subject] = true
+    opts[:show_category_in_subject] = true
+    notification_email(user, opts)
+  end
+
   def user_mentioned(user, opts)
     opts[:allow_reply_by_email] = true
     opts[:use_site_subject] = true
@@ -314,7 +321,7 @@ class UserNotifications < ActionMailer::Base
       context: context,
       username: username,
       add_unsubscribe_link: !user.staged,
-      add_unsubscribe_via_email_link: user.mailing_list_mode,
+      add_unsubscribe_via_email_link: user.user_option.mailing_list_mode,
       unsubscribe_url: post.topic.unsubscribe_url,
       allow_reply_by_email: allow_reply_by_email,
       use_site_subject: use_site_subject,
diff --git a/app/models/user.rb b/app/models/user.rb
index a1be4c16b..5634cbeaf 100644
--- a/app/models/user.rb
+++ b/app/models/user.rb
@@ -38,6 +38,7 @@ class User < ActiveRecord::Base
   has_many :user_archived_messages, dependent: :destroy
 
 
+  has_one :user_option, dependent: :destroy
   has_one :user_avatar, dependent: :destroy
   has_one :facebook_user_info, dependent: :destroy
   has_one :twitter_user_info, dependent: :destroy
@@ -80,6 +81,7 @@ class User < ActiveRecord::Base
 
   after_create :create_email_token
   after_create :create_user_stat
+  after_create :create_user_option
   after_create :create_user_profile
   after_create :ensure_in_trust_level_group
   after_create :automatic_group_membership
@@ -123,7 +125,7 @@ class User < ActiveRecord::Base
 
   # TODO-PERF: There is no indexes on any of these
   # and NotifyMailingListSubscribers does a select-all-and-loop
-  # may want to create an index on (active, blocked, suspended_till, mailing_list_mode)?
+  # may want to create an index on (active, blocked, suspended_till)?
   scope :blocked, -> { where(blocked: true) }
   scope :not_blocked, -> { where(blocked: false) }
   scope :suspended, -> { where('suspended_till IS NOT NULL AND suspended_till > ?', Time.zone.now) }
@@ -911,6 +913,10 @@ class User < ActiveRecord::Base
     stat.save!
   end
 
+  def create_user_option
+    UserOption.create(user_id: id)
+  end
+
   def create_email_token
     email_tokens.create(email: email)
   end
@@ -965,21 +971,8 @@ class User < ActiveRecord::Base
   end
 
   def set_default_user_preferences
-    set_default_email_digest_frequency
-    set_default_email_private_messages
-    set_default_email_direct
-    set_default_email_mailing_list_mode
-    set_default_email_always
-
     set_default_other_new_topic_duration_minutes
     set_default_other_auto_track_topics_after_msecs
-    set_default_other_external_links_in_new_tab
-    set_default_other_enable_quoting
-    set_default_other_dynamic_favicon
-    set_default_other_disable_jump_reply
-    set_default_other_edit_history_public
-
-    set_default_topics_automatic_unpin
 
     # needed, otherwise the callback chain is broken...
     true
@@ -1031,26 +1024,6 @@ class User < ActiveRecord::Base
     end
   end
 
-  def set_default_email_digest_frequency
-    if has_attribute?(:email_digests)
-      if SiteSetting.default_email_digest_frequency.to_i <= 0
-        self.email_digests = false
-      else
-        self.email_digests = true
-        self.digest_after_days ||= SiteSetting.default_email_digest_frequency.to_i if has_attribute?(:digest_after_days)
-      end
-    end
-  end
-
-  def set_default_email_mailing_list_mode
-    self.mailing_list_mode = SiteSetting.default_email_mailing_list_mode if has_attribute?(:mailing_list_mode)
-  end
-
-  %w{private_messages direct always}.each do |s|
-    define_method("set_default_email_#{s}") do
-      self.send("email_#{s}=", SiteSetting.send("default_email_#{s}")) if has_attribute?("email_#{s}")
-    end
-  end
 
   %w{new_topic_duration_minutes auto_track_topics_after_msecs}.each do |s|
     define_method("set_default_other_#{s}") do
@@ -1058,16 +1031,6 @@ class User < ActiveRecord::Base
     end
   end
 
-  %w{external_links_in_new_tab enable_quoting dynamic_favicon disable_jump_reply edit_history_public}.each do |s|
-    define_method("set_default_other_#{s}") do
-      self.send("#{s}=", SiteSetting.send("default_other_#{s}")) if has_attribute?(s)
-    end
-  end
-
-  def set_default_topics_automatic_unpin
-    self.automatically_unpin_topics = SiteSetting.default_topics_automatic_unpin
-  end
-
 end
 
 # == Schema Information
@@ -1090,14 +1053,11 @@ end
 #  last_seen_at                  :datetime
 #  admin                         :boolean          default(FALSE), not null
 #  last_emailed_at               :datetime
-#  email_digests                 :boolean          not null
 #  trust_level                   :integer          not null
 #  email_private_messages        :boolean          default(TRUE)
-#  email_direct                  :boolean          default(TRUE), not null
 #  approved                      :boolean          default(FALSE), not null
 #  approved_by_id                :integer
 #  approved_at                   :datetime
-#  digest_after_days             :integer
 #  previous_visit_at             :datetime
 #  suspended_at                  :datetime
 #  suspended_till                :datetime
@@ -1107,24 +1067,16 @@ end
 #  flag_level                    :integer          default(0), not null
 #  ip_address                    :inet
 #  new_topic_duration_minutes    :integer
-#  external_links_in_new_tab     :boolean          not null
-#  enable_quoting                :boolean          default(TRUE), not null
 #  moderator                     :boolean          default(FALSE)
 #  blocked                       :boolean          default(FALSE)
-#  dynamic_favicon               :boolean          default(FALSE), not null
 #  title                         :string(255)
 #  uploaded_avatar_id            :integer
-#  email_always                  :boolean          default(FALSE), not null
-#  mailing_list_mode             :boolean          default(FALSE), not null
 #  primary_group_id              :integer
 #  locale                        :string(10)
 #  registration_ip_address       :inet
 #  last_redirected_to_top_at     :datetime
-#  disable_jump_reply            :boolean          default(FALSE), not null
-#  edit_history_public           :boolean          default(FALSE), not null
 #  trust_level_locked            :boolean          default(FALSE), not null
 #  staged                        :boolean          default(FALSE), not null
-#  automatically_unpin_topics    :boolean          default(TRUE)
 #
 # Indexes
 #
diff --git a/app/models/user_email_observer.rb b/app/models/user_email_observer.rb
index db9dbdc73..d153d01b5 100644
--- a/app/models/user_email_observer.rb
+++ b/app/models/user_email_observer.rb
@@ -28,6 +28,10 @@ class UserEmailObserver < ActiveRecord::Observer
       enqueue :user_replied
     end
 
+    def linked
+      enqueue :user_linked
+    end
+
     def private_message
       enqueue_private(:user_private_message)
     end
@@ -60,12 +64,12 @@ class UserEmailObserver < ActiveRecord::Observer
     EMAILABLE_POST_TYPES ||= Set.new [Post.types[:regular], Post.types[:whisper]]
 
     def enqueue(type, delay=default_delay)
-      return unless notification.user.email_direct?
+      return unless notification.user.user_option.email_direct?
       perform_enqueue(type, delay)
     end
 
     def enqueue_private(type, delay=private_delay)
-      return unless notification.user.email_private_messages?
+      return unless notification.user.user_option.email_private_messages?
       perform_enqueue(type, delay)
     end
 
diff --git a/app/models/user_option.rb b/app/models/user_option.rb
new file mode 100644
index 000000000..3dac2ded9
--- /dev/null
+++ b/app/models/user_option.rb
@@ -0,0 +1,29 @@
+class UserOption < ActiveRecord::Base
+  self.primary_key = :user_id
+  belongs_to :user
+  before_create :set_defaults
+
+  def set_defaults
+    self.email_always = SiteSetting.default_email_always
+    self.mailing_list_mode = SiteSetting.default_email_mailing_list_mode
+    self.email_direct = SiteSetting.default_email_direct
+    self.automatically_unpin_topics = SiteSetting.default_topics_automatic_unpin
+    self.email_private_messages = SiteSetting.default_email_private_messages
+
+    self.enable_quoting = SiteSetting.default_other_enable_quoting
+    self.external_links_in_new_tab = SiteSetting.default_other_external_links_in_new_tab
+    self.dynamic_favicon = SiteSetting.default_other_dynamic_favicon
+    self.disable_jump_reply = SiteSetting.default_other_disable_jump_reply
+    self.edit_history_public = SiteSetting.default_other_edit_history_public
+
+
+    if SiteSetting.default_email_digest_frequency.to_i <= 0
+      self.email_digests = false
+    else
+      self.email_digests = true
+      self.digest_after_days ||= SiteSetting.default_email_digest_frequency.to_i
+    end
+
+    true
+  end
+end
diff --git a/app/serializers/current_user_serializer.rb b/app/serializers/current_user_serializer.rb
index c576025cd..5cf912d47 100644
--- a/app/serializers/current_user_serializer.rb
+++ b/app/serializers/current_user_serializer.rb
@@ -31,7 +31,8 @@ class CurrentUserSerializer < BasicUserSerializer
              :is_anonymous,
              :post_queue_new_count,
              :show_queued_posts,
-             :read_faq
+             :read_faq,
+             :automatically_unpin_topics
 
   def include_site_flagged_posts_count?
     object.staff?
@@ -49,6 +50,26 @@ class CurrentUserSerializer < BasicUserSerializer
     object.user_stat.topic_reply_count
   end
 
+  def enable_quoting
+    object.user_option.enable_quoting
+  end
+
+  def disable_jump_reply
+    object.user_option.disable_jump_reply
+  end
+
+  def external_links_in_new_tab
+    object.user_option.external_links_in_new_tab
+  end
+
+  def dynamic_favicon
+    object.user_option.dynamic_favicon
+  end
+
+  def automatically_unpin_topics
+    object.user_option.automatically_unpin_topics
+  end
+
   def site_flagged_posts_count
     PostAction.flagged_posts_count
   end
diff --git a/app/serializers/user_option_serializer.rb b/app/serializers/user_option_serializer.rb
new file mode 100644
index 000000000..77c9d6854
--- /dev/null
+++ b/app/serializers/user_option_serializer.rb
@@ -0,0 +1,20 @@
+class UserOptionSerializer < ApplicationSerializer
+  attributes :user_id,
+             :email_always,
+             :mailing_list_mode,
+             :email_digests,
+             :email_private_messages,
+             :email_direct,
+             :external_links_in_new_tab,
+             :dynamic_favicon,
+             :enable_quoting,
+             :disable_jump_reply,
+             :digest_after_days,
+             :automatically_unpin_topics,
+             :edit_history_public
+
+
+  def include_edit_history_public?
+    !SiteSetting.edit_history_visible_to_public
+  end
+end
diff --git a/app/serializers/user_serializer.rb b/app/serializers/user_serializer.rb
index 480fbd9c6..1ad96ce24 100644
--- a/app/serializers/user_serializer.rb
+++ b/app/serializers/user_serializer.rb
@@ -61,40 +61,33 @@ class UserSerializer < BasicUserSerializer
              :uploaded_avatar_id,
              :badge_count,
              :has_title_badges,
-             :edit_history_public,
              :custom_fields,
              :user_fields,
              :topic_post_count,
              :pending_count,
-             :profile_view_count,
-             :automatically_unpin_topics
+             :profile_view_count
 
   has_one :invited_by, embed: :object, serializer: BasicUserSerializer
   has_many :groups, embed: :object, serializer: BasicGroupSerializer
   has_many :featured_user_badges, embed: :ids, serializer: UserBadgeSerializer, root: :user_badges
   has_one  :card_badge, embed: :object, serializer: BadgeSerializer
+  has_one :user_option, embed: :object, serializer: UserOptionSerializer
+
+  def include_user_option?
+    can_edit
+  end
 
   staff_attributes :post_count,
                    :can_be_deleted,
                    :can_delete_all_posts
 
   private_attributes :locale,
-                     :email_digests,
-                     :email_private_messages,
-                     :email_direct,
-                     :email_always,
-                     :digest_after_days,
-                     :mailing_list_mode,
                      :auto_track_topics_after_msecs,
                      :new_topic_duration_minutes,
-                     :external_links_in_new_tab,
-                     :dynamic_favicon,
-                     :enable_quoting,
                      :muted_category_ids,
                      :tracked_category_ids,
                      :watched_category_ids,
                      :private_messages_stats,
-                     :disable_jump_reply,
                      :system_avatar_upload_id,
                      :system_avatar_template,
                      :gravatar_avatar_upload_id,
@@ -322,10 +315,6 @@ class UserSerializer < BasicUserSerializer
     object.badges.where(allow_title: true).count > 0
   end
 
-  def include_edit_history_public?
-    can_edit && !SiteSetting.edit_history_visible_to_public
-  end
-
   def user_fields
     object.user_fields
   end
diff --git a/app/services/anonymous_shadow_creator.rb b/app/services/anonymous_shadow_creator.rb
index 18b7eccea..08c1d6a33 100644
--- a/app/services/anonymous_shadow_creator.rb
+++ b/app/services/anonymous_shadow_creator.rb
@@ -40,11 +40,14 @@ class AnonymousShadowCreator
         active: true,
         trust_level: 1,
         trust_level_locked: true,
-        email_private_messages: false,
-        email_digests: false,
         created_at: 1.day.ago # bypass new user restrictions
       )
 
+      shadow.user_option.update_columns(
+        email_private_messages: false,
+        email_digests: false
+      )
+
       shadow.email_tokens.update_all(confirmed: true)
       shadow.activate
 
diff --git a/app/services/user_anonymizer.rb b/app/services/user_anonymizer.rb
index 48699b176..e9ff162db 100644
--- a/app/services/user_anonymizer.rb
+++ b/app/services/user_anonymizer.rb
@@ -23,14 +23,17 @@ class UserAnonymizer
       @user.name = nil
       @user.date_of_birth = nil
       @user.title = nil
-      @user.email_digests = false
-      @user.email_private_messages = false
-      @user.email_direct = false
-      @user.email_always = false
-      @user.mailing_list_mode = false
       @user.uploaded_avatar_id = nil
       @user.save
 
+      options = @user.user_option
+      options.email_always = false
+      options.mailing_list_mode = false
+      options.email_digests = false
+      options.email_private_messages = false
+      options.email_direct = false
+      options.save
+
       profile = @user.user_profile
       profile.destroy if profile
       @user.create_user_profile
diff --git a/app/services/user_updater.rb b/app/services/user_updater.rb
index c6f236d2b..e028a0d14 100644
--- a/app/services/user_updater.rb
+++ b/app/services/user_updater.rb
@@ -6,18 +6,19 @@ class UserUpdater
     muted_category_ids: :muted
   }
 
-  USER_ATTR = [
-    :email_digests,
+  OPTION_ATTR = [
     :email_always,
+    :mailing_list_mode,
+    :email_digests,
     :email_direct,
     :email_private_messages,
     :external_links_in_new_tab,
     :enable_quoting,
     :dynamic_favicon,
-    :mailing_list_mode,
     :disable_jump_reply,
     :edit_history_public,
     :automatically_unpin_topics,
+    :digest_after_days
   ]
 
   def initialize(actor, user)
@@ -36,7 +37,6 @@ class UserUpdater
 
     user.name = attributes.fetch(:name) { user.name }
     user.locale = attributes.fetch(:locale) { user.locale }
-    user.digest_after_days = attributes.fetch(:digest_after_days) { user.digest_after_days }
 
     if attributes[:auto_track_topics_after_msecs]
       user.auto_track_topics_after_msecs = attributes[:auto_track_topics_after_msecs].to_i
@@ -56,9 +56,19 @@ class UserUpdater
       end
     end
 
-    USER_ATTR.each do |attribute|
+
+    save_options = false
+    OPTION_ATTR.each do |attribute|
       if attributes[attribute].present?
-        user.send("#{attribute}=", attributes[attribute] == 'true')
+        save_options = true
+
+
+        if [true,false].include?(user.user_option.send(attribute))
+          val = attributes[attribute].to_s == 'true'
+          user.user_option.send("#{attribute}=", val)
+        else
+          user.user_option.send("#{attribute}=", attributes[attribute])
+        end
       end
     end
 
@@ -72,7 +82,7 @@ class UserUpdater
         update_muted_users(attributes[:muted_usernames])
       end
 
-      user_profile.save && user.save
+      (!save_options || user.user_option.save) && user_profile.save && user.save
     end
   end
 
diff --git a/config/locales/server.en.yml b/config/locales/server.en.yml
index 78d65d384..5a4011301 100644
--- a/config/locales/server.en.yml
+++ b/config/locales/server.en.yml
@@ -2092,6 +2092,18 @@ en:
         ---
         %{respond_instructions}
 
+    user_linked:
+      subject_template: "[%{site_name}] %{topic_title}"
+      text_body_template: |
+        %{header_instructions}
+
+        %{message}
+
+        %{context}
+
+        ---
+        %{respond_instructions}
+
     user_mentioned:
       subject_template: "[%{site_name}] %{topic_title}"
       text_body_template: |
diff --git a/db/fixtures/009_users.rb b/db/fixtures/009_users.rb
index 7effb7377..4c5f11875 100644
--- a/db/fixtures/009_users.rb
+++ b/db/fixtures/009_users.rb
@@ -16,14 +16,51 @@ User.seed do |u|
   u.active = true
   u.admin = true
   u.moderator = true
-  u.email_direct = false
   u.approved = true
-  u.email_private_messages = false
   u.trust_level = TrustLevel[4]
 end
 
+UserOption.where(user_id: -1).update_all(
+  email_private_messages: false,
+  email_direct: false
+)
+
 Group.user_trust_level_change!(-1, TrustLevel[4])
 
+# 60 minutes after our migration runs we need to exectue this code...
+duration = Rails.env.production? ? 60 : 0
+if User.exec_sql("SELECT 1 FROM schema_migration_details
+                  WHERE EXISTS(
+                      SELECT 1 FROM INFORMATION_SCHEMA.COLUMNS
+                      WHERE table_name = 'users' AND column_name = 'enable_quoting'
+                    ) AND
+                    name = 'AllowDefaultsOnUsersTable' AND
+                    created_at < (current_timestamp at time zone 'UTC' - interval '#{duration} minutes')
+                 ").to_a.length > 0
+
+
+  User.transaction do
+    STDERR.puts "Removing superflous user columns!"
+    %w[
+      email_always
+      mailing_list_mode
+      email_digests
+      email_direct
+      email_private_messages
+      external_links_in_new_tab
+      enable_quoting
+      dynamic_favicon
+      disable_jump_reply
+      edit_history_public
+      automatically_unpin_topics
+      digest_after_days
+    ].each do |column|
+      User.exec_sql("ALTER TABLE users DROP column #{column}")
+    end
+
+  end
+end
+
 # User for the smoke tests
 if ENV["SMOKE"] == "1"
   smoke_user = User.seed do |u|
@@ -49,3 +86,4 @@ if ENV["SMOKE"] == "1"
     et.confirmed = true
   end
 end
+
diff --git a/db/migrate/20000225050318_add_schema_migration_details.rb b/db/migrate/20000225050318_add_schema_migration_details.rb
new file mode 100644
index 000000000..dbf4959b1
--- /dev/null
+++ b/db/migrate/20000225050318_add_schema_migration_details.rb
@@ -0,0 +1,30 @@
+class AddSchemaMigrationDetails < ActiveRecord::Migration
+  def up
+    # schema_migrations table is way too thin, does not give info about
+    # duration of migration or the date it happened, this migration together with the
+    # monkey patch adds a lot of information to the migration table
+
+    create_table :schema_migration_details do |t|
+      t.string :version, null: false
+      t.string :name
+      t.string :hostname
+      t.string :git_version
+      t.string :rails_version
+      t.integer :duration
+      t.string :direction # this really should be a pg enum type but annoying to wire up for little gain
+      t.datetime :created_at, null: false
+    end
+
+    add_index :schema_migration_details, [:version]
+
+    execute("INSERT INTO schema_migration_details(version, created_at)
+             SELECT version, current_timestamp
+             FROM schema_migrations
+             ORDER BY version
+            ")
+  end
+
+  def down
+    drop_table :schema_migration_details
+  end
+end
diff --git a/db/migrate/20160225050317_add_user_options.rb b/db/migrate/20160225050317_add_user_options.rb
new file mode 100644
index 000000000..13df057cd
--- /dev/null
+++ b/db/migrate/20160225050317_add_user_options.rb
@@ -0,0 +1,76 @@
+class AddUserOptions < ActiveRecord::Migration
+  def up
+
+    create_table :user_options, id: false do |t|
+      t.integer :user_id, null: false
+      t.boolean :email_always, null: false, default: false
+      t.boolean :mailing_list_mode, null: false, default: false
+      t.boolean :email_digests
+      t.boolean :email_direct, null: false, default: true
+      t.boolean :email_private_messages, null: false, default: true
+      t.boolean :external_links_in_new_tab, null: false, default: false
+      t.boolean :enable_quoting, null: false, default: true
+      t.boolean :dynamic_favicon, null: false, default: false
+      t.boolean :disable_jump_reply, null: false, default: false
+      t.boolean :edit_history_public, null: false, default: false
+      t.boolean :automatically_unpin_topics, null: false, default: true
+      t.integer :digest_after_days
+    end
+
+    add_index :user_options, [:user_id], unique: true
+
+    execute <<SQL
+    INSERT INTO user_options (
+            user_id,
+            email_always,
+            mailing_list_mode,
+            email_digests,
+            email_direct,
+            email_private_messages,
+            external_links_in_new_tab,
+            enable_quoting,
+            dynamic_favicon,
+            disable_jump_reply,
+            edit_history_public,
+            automatically_unpin_topics,
+            digest_after_days
+    )
+    SELECT  id,
+            email_always,
+            mailing_list_mode,
+            email_digests,
+            email_direct,
+            email_private_messages,
+            external_links_in_new_tab,
+            enable_quoting,
+            dynamic_favicon,
+            disable_jump_reply,
+            edit_history_public,
+            automatically_unpin_topics,
+            digest_after_days
+    FROM users
+SQL
+
+    # these can not be removed until a bit later
+    # if we remove them now all currently running unicorns will start erroring out
+    #
+    # remove_column :users, :email_always
+    # remove_column :users, :mailing_list_mode
+    # remove_column :users, :email_digests
+    # remove_column :users, :email_direct
+    # remove_column :users, :email_private_messages
+    # remove_column :users, :external_links_in_new_tab
+    # remove_column :users, :enable_quoting
+    # remove_column :users, :dynamic_favicon
+    # remove_column :users, :disable_jump_reply
+    # remove_column :users, :edit_history_public
+    # remove_column :users, :automatically_unpin_topics
+    # remove_column :users, :digest_after_days
+  end
+
+  def down
+    # we can not move backwards here cause columns
+    # get removed an hour after the migration
+    raise ActiveRecord::IrreversibleMigration
+  end
+end
diff --git a/db/migrate/20160225050318_allow_defaults_on_users_table.rb b/db/migrate/20160225050318_allow_defaults_on_users_table.rb
new file mode 100644
index 000000000..999e275fd
--- /dev/null
+++ b/db/migrate/20160225050318_allow_defaults_on_users_table.rb
@@ -0,0 +1,10 @@
+class AllowDefaultsOnUsersTable < ActiveRecord::Migration
+  def up
+    # we need to temporarily change table a bit to ensure we can insert new records
+    change_column :users, :email_digests, :boolean, null: false, default: true
+    change_column :users, :external_links_in_new_tab, :boolean, null: false, default: false
+  end
+
+  def down
+  end
+end
diff --git a/lib/freedom_patches/schema_migration_details.rb b/lib/freedom_patches/schema_migration_details.rb
new file mode 100644
index 000000000..bbae956c1
--- /dev/null
+++ b/lib/freedom_patches/schema_migration_details.rb
@@ -0,0 +1,54 @@
+module FreedomPatches
+  module SchemaMigrationDetails
+    def exec_migration(conn, direction)
+      rval = nil
+
+      time = Benchmark.measure do
+        rval=super
+      end
+
+      sql = <<SQL
+      INSERT INTO schema_migration_details(
+        version,
+        hostname,
+        name,
+        git_version,
+        duration,
+        direction,
+        rails_version,
+        created_at
+      ) values (
+        :version,
+        :hostname,
+        :name,
+        :git_version,
+        :duration,
+        :direction,
+        :rails_version,
+        :created_at
+      )
+SQL
+
+      hostname = `hostname` rescue ""
+      sql = ActiveRecord::Base.send(:sanitize_sql_array, [sql, {
+        version: version || "",
+        duration: (time.real * 1000).to_i,
+        hostname: hostname,
+        name: name,
+        git_version: Discourse.git_version,
+        created_at: Time.zone.now,
+        direction: direction.to_s,
+        rails_version: Rails.version
+      }])
+
+      conn.execute(sql)
+
+      rval
+    end
+
+  end
+end
+
+class ActiveRecord::Migration
+  prepend FreedomPatches::SchemaMigrationDetails
+end
diff --git a/lib/guardian/post_guardian.rb b/lib/guardian/post_guardian.rb
index 722c01748..8635bc6c1 100644
--- a/lib/guardian/post_guardian.rb
+++ b/lib/guardian/post_guardian.rb
@@ -157,7 +157,7 @@ module PostGuardian
     return false unless post
 
     if !post.hidden
-      return true if post.wiki || SiteSetting.edit_history_visible_to_public || post.user.try(:edit_history_public)
+      return true if post.wiki || SiteSetting.edit_history_visible_to_public || (post.user && post.user.user_option.edit_history_public)
     end
 
     authenticated? &&
diff --git a/spec/components/freedom_patches/schema_migration_details_spec.rb b/spec/components/freedom_patches/schema_migration_details_spec.rb
new file mode 100644
index 000000000..86e960edb
--- /dev/null
+++ b/spec/components/freedom_patches/schema_migration_details_spec.rb
@@ -0,0 +1,32 @@
+require 'rails_helper'
+require_dependency "freedom_patches/schema_migration_details"
+
+describe FreedomPatches::SchemaMigrationDetails do
+
+  # we usually don't really need this model so lets not clutter up with it
+  class SchemaMigrationDetail < ActiveRecord::Base
+  end
+
+  class TestMigration < ActiveRecord::Migration
+    def up
+      sleep 0.001
+    end
+  end
+
+  it "logs information on migration" do
+    migration = TestMigration.new("awesome_migration","20160225050318")
+
+    ActiveRecord::Base.connection_pool.with_connection do |conn|
+      migration.exec_migration(conn, :up)
+    end
+
+    info = SchemaMigrationDetail.find_by(version: "20160225050318")
+
+    expect(info.duration).to be > 0
+    expect(info.git_version).to eq Discourse.git_version
+    expect(info.direction).to eq "up"
+    expect(info.rails_version).to eq Rails.version
+    expect(info.filename).to eq migration.filename
+    expect(info.name).to eq "awesome_migration"
+  end
+end
diff --git a/spec/components/guardian_spec.rb b/spec/components/guardian_spec.rb
index e71c1550a..14db91210 100644
--- a/spec/components/guardian_spec.rb
+++ b/spec/components/guardian_spec.rb
@@ -510,7 +510,7 @@ describe Guardian do
 
         it 'is true if the author has public edit history' do
           public_post_revision = Fabricate(:post_revision)
-          public_post_revision.post.user.edit_history_public = true
+          public_post_revision.post.user.user_option.edit_history_public = true
           expect(Guardian.new.can_see?(public_post_revision)).to be_truthy
         end
       end
@@ -533,7 +533,7 @@ describe Guardian do
 
         it 'is true if the author has public edit history' do
           public_post_revision = Fabricate(:post_revision)
-          public_post_revision.post.user.edit_history_public = true
+          public_post_revision.post.user.user_option.edit_history_public = true
           expect(Guardian.new.can_see?(public_post_revision)).to be_truthy
         end
       end
diff --git a/spec/controllers/email_controller_spec.rb b/spec/controllers/email_controller_spec.rb
index f5c6e9180..0376076b9 100644
--- a/spec/controllers/email_controller_spec.rb
+++ b/spec/controllers/email_controller_spec.rb
@@ -21,7 +21,11 @@ describe EmailController do
 
   context '.resubscribe' do
 
-    let(:user) { Fabricate(:user, email_digests: false) }
+    let(:user) {
+      user = Fabricate(:user)
+      user.user_option.update_columns(email_digests: false)
+      user
+    }
     let(:key) { DigestUnsubscribeKey.create_key_for(user) }
 
     context 'with a valid key' do
@@ -31,7 +35,7 @@ describe EmailController do
       end
 
       it 'subscribes the user' do
-        expect(user.email_digests).to eq(true)
+        expect(user.user_option.email_digests).to eq(true)
       end
     end
 
@@ -39,7 +43,11 @@ describe EmailController do
 
   context '.unsubscribe' do
 
-    let(:user) { Fabricate(:user, email_digests: true, email_direct: true, email_private_messages: true, email_always: true) }
+    let(:user) {
+      user = Fabricate(:user)
+      user.user_option.update_columns(email_always: true, email_digests: true, email_direct: true, email_private_messages: true)
+      user
+    }
     let(:key) { DigestUnsubscribeKey.create_key_for(user) }
 
     context 'from confirm unsubscribe email' do
@@ -49,10 +57,11 @@ describe EmailController do
       end
 
       it 'unsubscribes from all emails' do
-        expect(user.email_digests).to eq false
-        expect(user.email_direct).to eq false
-        expect(user.email_private_messages).to eq false
-        expect(user.email_always).to eq false
+        options = user.user_option
+        expect(options.email_digests).to eq false
+        expect(options.email_direct).to eq false
+        expect(options.email_private_messages).to eq false
+        expect(options.email_always).to eq false
       end
     end
 
@@ -63,7 +72,7 @@ describe EmailController do
       end
 
       it 'unsubscribes the user' do
-        expect(user.email_digests).to eq(false)
+        expect(user.user_option.email_digests).to eq(false)
       end
 
       it "sets the appropriate instance variables" do
@@ -90,7 +99,7 @@ describe EmailController do
       end
 
       it 'does not unsubscribe the user' do
-        expect(user.email_digests).to eq(true)
+        expect(user.user_option.email_digests).to eq(true)
       end
 
       it 'sets the appropriate instance variables' do
@@ -108,7 +117,7 @@ describe EmailController do
       end
 
       it 'unsubscribes the user' do
-        expect(user.email_digests).to eq(false)
+        expect(user.user_option.email_digests).to eq(false)
       end
 
       it 'sets the appropriate instance variables' do
diff --git a/spec/jobs/user_email_spec.rb b/spec/jobs/user_email_spec.rb
index c7ab345a1..5cce202fe 100644
--- a/spec/jobs/user_email_spec.rb
+++ b/spec/jobs/user_email_spec.rb
@@ -55,7 +55,8 @@ describe Jobs::UserEmail do
     end
 
     it "does send an email to a user that's been recently seen but has email_always set" do
-      user.update_attributes(last_seen_at: 9.minutes.ago, email_always: true)
+      user.update_attributes(last_seen_at: 9.minutes.ago)
+      user.user_option.update_attributes(email_always: true)
       Email::Sender.any_instance.expects(:send)
       Jobs::UserEmail.new.execute(type: :user_replied, user_id: user.id, post_id: post.id)
     end
@@ -188,13 +189,13 @@ describe Jobs::UserEmail do
       it "does send the email if the notification has been seen but the user is set for email_always" do
         Email::Sender.any_instance.expects(:send)
         notification.update_column(:read, true)
-        user.update_column(:email_always, true)
+        user.user_option.update_column(:email_always, true)
         Jobs::UserEmail.new.execute(type: :user_mentioned, user_id: user.id, notification_id: notification.id)
       end
 
       it "doesn't send the mail if the user is using mailing list mode" do
         Email::Sender.any_instance.expects(:send).never
-        user.update_column(:mailing_list_mode, true)
+        user.user_option.update_column(:mailing_list_mode, true)
         # sometimes, we pass the notification_id
         Jobs::UserEmail.new.execute(type: :user_mentioned, user_id: user.id, notification_id: notification.id, post_id: post.id)
         # other times, we only pass the type of notification
diff --git a/spec/models/user_email_observer_spec.rb b/spec/models/user_email_observer_spec.rb
index 0f1150c4d..2bd23dd8e 100644
--- a/spec/models/user_email_observer_spec.rb
+++ b/spec/models/user_email_observer_spec.rb
@@ -51,7 +51,7 @@ describe UserEmailObserver do
     include_examples "enqueue"
 
     it "doesn't enqueue a job if the user has mention emails disabled" do
-      notification.user.expects(:email_direct?).returns(false)
+      notification.user.user_option.update_columns(email_direct: false)
       Jobs.expects(:enqueue_in).with(delay, :user_email, has_entry(type: type)).never
       UserEmailObserver.process_notification(notification)
     end
@@ -61,7 +61,7 @@ describe UserEmailObserver do
     include_examples "enqueue"
 
     it "doesn't enqueue a job if the user has private message emails disabled" do
-      notification.user.expects(:email_private_messages?).returns(false)
+      notification.user.user_option.update_columns(email_private_messages: false)
       Jobs.expects(:enqueue_in).with(delay, :user_email, has_entry(type: type)).never
       UserEmailObserver.process_notification(notification)
     end
@@ -99,6 +99,14 @@ describe UserEmailObserver do
     include_examples "enqueue_public"
   end
 
+  context 'user_linked' do
+    let(:type) { :user_linked }
+    let(:delay) { SiteSetting.email_time_window_mins.minutes }
+    let!(:notification) { create_notification(11) }
+
+    include_examples "enqueue_public"
+  end
+
   context 'user_posted' do
     let(:type) { :user_posted }
     let(:delay) { SiteSetting.email_time_window_mins.minutes }
diff --git a/spec/models/user_spec.rb b/spec/models/user_spec.rb
index 792c9ef19..5acf8bfb6 100644
--- a/spec/models/user_spec.rb
+++ b/spec/models/user_spec.rb
@@ -152,15 +152,15 @@ describe User do
     it "is properly initialized" do
       expect(subject.approved_at).to be_blank
       expect(subject.approved_by_id).to be_blank
-      expect(subject.email_private_messages).to eq(true)
-      expect(subject.email_direct).to eq(true)
     end
 
     context 'after_save' do
       before { subject.save }
 
-      it "has an email token" do
+      it "has correct settings" do
         expect(subject.email_tokens).to be_present
+        expect(subject.user_option.email_private_messages).to eq(true)
+        expect(subject.user_option.email_direct).to eq(true)
       end
     end
 
@@ -1246,50 +1246,62 @@ describe User do
   context "when user preferences are overriden" do
 
     before do
-      SiteSetting.stubs(:default_email_digest_frequency).returns(1) # daily
-      SiteSetting.stubs(:default_email_private_messages).returns(false)
-      SiteSetting.stubs(:default_email_direct).returns(false)
-      SiteSetting.stubs(:default_email_mailing_list_mode).returns(true)
-      SiteSetting.stubs(:default_email_always).returns(true)
+      SiteSetting.default_email_digest_frequency = 1 # daily
+      SiteSetting.default_email_private_messages = false
+      SiteSetting.default_email_direct = false
+      SiteSetting.default_email_mailing_list_mode = true
+      SiteSetting.default_email_always = true
 
-      SiteSetting.stubs(:default_other_new_topic_duration_minutes).returns(-1) # not viewed
-      SiteSetting.stubs(:default_other_auto_track_topics_after_msecs).returns(0) # immediately
-      SiteSetting.stubs(:default_other_external_links_in_new_tab).returns(true)
-      SiteSetting.stubs(:default_other_enable_quoting).returns(false)
-      SiteSetting.stubs(:default_other_dynamic_favicon).returns(true)
-      SiteSetting.stubs(:default_other_disable_jump_reply).returns(true)
-      SiteSetting.stubs(:default_other_edit_history_public).returns(true)
+      SiteSetting.default_other_new_topic_duration_minutes = -1 # not viewed
+      SiteSetting.default_other_auto_track_topics_after_msecs = 0 # immediately
+      SiteSetting.default_other_external_links_in_new_tab = true
+      SiteSetting.default_other_enable_quoting = false
+      SiteSetting.default_other_dynamic_favicon = true
+      SiteSetting.default_other_disable_jump_reply = true
+      SiteSetting.default_other_edit_history_public = true
 
-      SiteSetting.stubs(:default_topics_automatic_unpin).returns(false)
+      SiteSetting.default_topics_automatic_unpin = false
 
-      SiteSetting.stubs(:default_categories_watching).returns("1")
-      SiteSetting.stubs(:default_categories_tracking).returns("2")
-      SiteSetting.stubs(:default_categories_muted).returns("3")
+      SiteSetting.default_categories_watching = "1"
+      SiteSetting.default_categories_tracking = "2"
+      SiteSetting.default_categories_muted = "3"
     end
 
     it "has overriden preferences" do
       user = Fabricate(:user)
-
-      expect(user.digest_after_days).to eq(1)
-      expect(user.email_private_messages).to eq(false)
-      expect(user.email_direct).to eq(false)
-      expect(user.mailing_list_mode).to eq(true)
-      expect(user.email_always).to eq(true)
+      options = user.user_option
+      expect(options.email_always).to eq(true)
+      expect(options.mailing_list_mode).to eq(true)
+      expect(options.digest_after_days).to eq(1)
+      expect(options.email_private_messages).to eq(false)
+      expect(options.external_links_in_new_tab).to eq(true)
+      expect(options.enable_quoting).to eq(false)
+      expect(options.dynamic_favicon).to eq(true)
+      expect(options.disable_jump_reply).to eq(true)
+      expect(options.edit_history_public).to eq(true)
+      expect(options.automatically_unpin_topics).to eq(false)
+      expect(options.email_direct).to eq(false)
 
       expect(user.new_topic_duration_minutes).to eq(-1)
       expect(user.auto_track_topics_after_msecs).to eq(0)
-      expect(user.external_links_in_new_tab).to eq(true)
-      expect(user.enable_quoting).to eq(false)
-      expect(user.dynamic_favicon).to eq(true)
-      expect(user.disable_jump_reply).to eq(true)
-      expect(user.edit_history_public).to eq(true)
-
-      expect(user.automatically_unpin_topics).to eq(false)
 
       expect(CategoryUser.lookup(user, :watching).pluck(:category_id)).to eq([1])
       expect(CategoryUser.lookup(user, :tracking).pluck(:category_id)).to eq([2])
       expect(CategoryUser.lookup(user, :muted).pluck(:category_id)).to eq([3])
     end
+  end
+
+  context UserOption do
+
+    it "Creates a UserOption row when a user record is created and destroys once done" do
+      user = Fabricate(:user)
+      expect(user.user_option.email_always).to eq(false)
+
+      user_id = user.id
+      user.destroy!
+      expect(UserOption.find_by(user_id: user_id)).to eq(nil)
+
+    end
 
   end
 
diff --git a/spec/serializers/user_serializer_spec.rb b/spec/serializers/user_serializer_spec.rb
index 7f16958a2..3a9db1a23 100644
--- a/spec/serializers/user_serializer_spec.rb
+++ b/spec/serializers/user_serializer_spec.rb
@@ -15,6 +15,24 @@ describe UserSerializer do
     end
   end
 
+  context "as current user" do
+    it "serializes options correctly" do
+      # so we serialize more stuff
+      SiteSetting.edit_history_visible_to_public = false
+
+      user = Fabricate.build(:user,
+                              user_profile: Fabricate.build(:user_profile),
+                              user_option: UserOption.new(edit_history_public: true),
+                              user_stat: UserStat.new
+                            )
+
+      json = UserSerializer.new(user, scope: Guardian.new(user), root: false).as_json
+
+      expect(json[:user_option][:edit_history_public]).to eq(true)
+
+    end
+  end
+
   context "with a user" do
     let(:user) { Fabricate.build(:user, user_profile: Fabricate.build(:user_profile) ) }
     let(:serializer) { UserSerializer.new(user, scope: Guardian.new, root: false) }
@@ -26,7 +44,7 @@ describe UserSerializer do
 
     context "with `enable_names` true" do
       before do
-        SiteSetting.stubs(:enable_names?).returns(true)
+        SiteSetting.enable_names = true
       end
 
       it "has a name" do
@@ -34,6 +52,7 @@ describe UserSerializer do
       end
     end
 
+
     context "with `enable_names` false" do
       before do
         SiteSetting.stubs(:enable_names?).returns(false)
diff --git a/spec/services/anonymous_shadow_creator_spec.rb b/spec/services/anonymous_shadow_creator_spec.rb
index 1483f59c7..bda16a782 100644
--- a/spec/services/anonymous_shadow_creator_spec.rb
+++ b/spec/services/anonymous_shadow_creator_spec.rb
@@ -30,6 +30,9 @@ describe AnonymousShadowCreator do
       freeze_time 4.minutes.from_now
       shadow3 = AnonymousShadowCreator.get(user)
 
+      expect(shadow3.user_option.email_digests).to eq(false)
+      expect(shadow3.user_option.email_private_messages).to eq(false)
+
       expect(shadow2.id).not_to eq(shadow3.id)
 
     end
diff --git a/spec/services/user_anonymizer_spec.rb b/spec/services/user_anonymizer_spec.rb
index b641c1c04..9cef2507f 100644
--- a/spec/services/user_anonymizer_spec.rb
+++ b/spec/services/user_anonymizer_spec.rb
@@ -19,13 +19,17 @@ describe UserAnonymizer do
     end
 
     it "turns off all notifications" do
+      user.user_option.update_columns(
+        email_always: true
+      )
+
       make_anonymous
       user.reload
-      expect(user.email_digests).to eq(false)
-      expect(user.email_private_messages).to eq(false)
-      expect(user.email_direct).to eq(false)
-      expect(user.email_always).to eq(false)
-      expect(user.mailing_list_mode).to eq(false)
+      expect(user.user_option.email_digests).to eq(false)
+      expect(user.user_option.email_private_messages).to eq(false)
+      expect(user.user_option.email_direct).to eq(false)
+      expect(user.user_option.email_always).to eq(false)
+      expect(user.user_option.mailing_list_mode).to eq(false)
     end
 
     it "resets profile to default values" do
diff --git a/spec/services/user_updater_spec.rb b/spec/services/user_updater_spec.rb
index 1f46e5eb5..f94d2bb9e 100644
--- a/spec/services/user_updater_spec.rb
+++ b/spec/services/user_updater_spec.rb
@@ -32,26 +32,33 @@ describe UserUpdater do
   describe '#update' do
     it 'saves user' do
       user = Fabricate(:user, name: 'Billy Bob')
-      updater = described_class.new(acting_user, user)
+      updater = UserUpdater.new(acting_user, user)
 
       updater.update(name: 'Jim Tom')
 
       expect(user.reload.name).to eq 'Jim Tom'
     end
 
-    it 'updates bio' do
+    it 'updates various fields' do
       user = Fabricate(:user)
-      updater = described_class.new(acting_user, user)
+      updater = UserUpdater.new(acting_user, user)
 
-      updater.update(bio_raw: 'my new bio')
+      updater.update(bio_raw: 'my new bio',
+                     email_always: 'true',
+                     mailing_list_mode: true,
+                     digest_after_days: "8")
+      user.reload
 
-      expect(user.reload.user_profile.bio_raw).to eq 'my new bio'
+      expect(user.user_profile.bio_raw).to eq 'my new bio'
+      expect(user.user_option.email_always).to eq true
+      expect(user.user_option.mailing_list_mode).to eq true
+      expect(user.user_option.digest_after_days).to eq 8
     end
 
     context 'when update succeeds' do
       it 'returns true' do
         user = Fabricate(:user)
-        updater = described_class.new(acting_user, user)
+        updater = UserUpdater.new(acting_user, user)
 
         expect(updater.update).to be_truthy
       end
@@ -61,7 +68,7 @@ describe UserUpdater do
       it 'returns false' do
         user = Fabricate(:user)
         user.stubs(save: false)
-        updater = described_class.new(acting_user, user)
+        updater = UserUpdater.new(acting_user, user)
 
         expect(updater.update).to be_falsey
       end
@@ -73,7 +80,7 @@ describe UserUpdater do
         guardian = stub
         guardian.stubs(:can_grant_title?).with(user).returns(true)
         Guardian.stubs(:new).with(acting_user).returns(guardian)
-        updater = described_class.new(acting_user, user)
+        updater = UserUpdater.new(acting_user, user)
 
         updater.update(title: 'Minion')