diff --git a/models/fixtures/repository.yml b/models/fixtures/repository.yml
index 3409ba8113..51812d3585 100644
--- a/models/fixtures/repository.yml
+++ b/models/fixtures/repository.yml
@@ -9,7 +9,7 @@
   num_pulls: 2
   num_closed_pulls: 0
   num_milestones: 2
-  num_watches: 2
+  num_watches: 3
 
 -
   id: 2
diff --git a/models/fixtures/watch.yml b/models/fixtures/watch.yml
index cd6efb102e..2ff888b7c7 100644
--- a/models/fixtures/watch.yml
+++ b/models/fixtures/watch.yml
@@ -7,3 +7,8 @@
   id: 2
   user_id: 4
   repo_id: 1
+
+-
+  id: 3
+  user_id: 10
+  repo_id: 1
diff --git a/models/issue.go b/models/issue.go
index 2b71e0776d..9d081471a7 100644
--- a/models/issue.go
+++ b/models/issue.go
@@ -1204,8 +1204,11 @@ func GetParticipantsByIssueID(issueID int64) ([]*User, error) {
 func getParticipantsByIssueID(e Engine, issueID int64) ([]*User, error) {
 	userIDs := make([]int64, 0, 5)
 	if err := e.Table("comment").Cols("poster_id").
-		Where("issue_id = ?", issueID).
-		And("type = ?", CommentTypeComment).
+		Where("`comment`.issue_id = ?", issueID).
+		And("`comment`.type = ?", CommentTypeComment).
+		And("`user`.is_active = ?", true).
+		And("`user`.prohibit_login = ?", false).
+		Join("INNER", "user", "`user`.id = `comment`.poster_id").
 		Distinct("poster_id").
 		Find(&userIDs); err != nil {
 		return nil, fmt.Errorf("get poster IDs: %v", err)
diff --git a/models/issue_mail.go b/models/issue_mail.go
index 9e604a50f1..74ef660554 100644
--- a/models/issue_mail.go
+++ b/models/issue_mail.go
@@ -36,9 +36,13 @@ func mailIssueCommentToParticipants(e Engine, issue *Issue, doer *User, comment
 		return fmt.Errorf("getParticipantsByIssueID [issue_id: %d]: %v", issue.ID, err)
 	}
 
-	// In case the issue poster is not watching the repository,
+	// In case the issue poster is not watching the repository and is active,
 	// even if we have duplicated in watchers, can be safely filtered out.
-	if issue.PosterID != doer.ID {
+	poster, err := GetUserByID(issue.PosterID)
+	if err != nil {
+		return fmt.Errorf("GetUserByID [%d]: %v", issue.PosterID, err)
+	}
+	if issue.PosterID != doer.ID && poster.IsActive && !poster.ProhibitLogin {
 		participants = append(participants, issue.Poster)
 	}
 
diff --git a/models/issue_test.go b/models/issue_test.go
index 8a8ccce459..21df146b58 100644
--- a/models/issue_test.go
+++ b/models/issue_test.go
@@ -80,7 +80,8 @@ func TestGetParticipantsByIssueID(t *testing.T) {
 	// User 1 is issue1 poster (see fixtures/issue.yml)
 	// User 2 only labeled issue1 (see fixtures/comment.yml)
 	// Users 3 and 5 made actual comments (see fixtures/comment.yml)
-	checkParticipants(1, []int{3, 5})
+	// User 3 is inactive, thus not active participant
+	checkParticipants(1, []int{5})
 }
 
 func TestIssue_AddLabel(t *testing.T) {
diff --git a/models/issue_watch.go b/models/issue_watch.go
index 37511787e5..994ae5a97f 100644
--- a/models/issue_watch.go
+++ b/models/issue_watch.go
@@ -90,7 +90,10 @@ func GetIssueWatchers(issueID int64) ([]*IssueWatch, error) {
 
 func getIssueWatchers(e Engine, issueID int64) (watches []*IssueWatch, err error) {
 	err = e.
-		Where("issue_id = ?", issueID).
+		Where("`issue_watch`.issue_id = ?", issueID).
+		And("`user`.is_active = ?", true).
+		And("`user`.prohibit_login = ?", false).
+		Join("INNER", "user", "`user`.id = `issue_watch`.user_id").
 		Find(&watches)
 	return
 }
diff --git a/models/issue_watch_test.go b/models/issue_watch_test.go
index d8b456c3ae..a4819b2224 100644
--- a/models/issue_watch_test.go
+++ b/models/issue_watch_test.go
@@ -43,6 +43,11 @@ func TestGetIssueWatchers(t *testing.T) {
 
 	iws, err := GetIssueWatchers(1)
 	assert.NoError(t, err)
+	// Watcher is inactive, thus 0
+	assert.Equal(t, 0, len(iws))
+
+	iws, err = GetIssueWatchers(2)
+	assert.NoError(t, err)
 	assert.Equal(t, 1, len(iws))
 
 	iws, err = GetIssueWatchers(5)
diff --git a/models/migrations/migrations.go b/models/migrations/migrations.go
index e7542954d7..c36f6fabb7 100644
--- a/models/migrations/migrations.go
+++ b/models/migrations/migrations.go
@@ -130,6 +130,8 @@ var migrations = []Migration{
 	NewMigration("adds time tracking and stopwatches", addTimetracking),
 	// v40 -> v41
 	NewMigration("migrate protected branch struct", migrateProtectedBranchStruct),
+	// v41 -> v42
+	NewMigration("add default value to user prohibit_login", addDefaultValueToUserProhibitLogin),
 }
 
 // Migrate database to current version
diff --git a/models/migrations/v41.go b/models/migrations/v41.go
new file mode 100644
index 0000000000..89763c3afe
--- /dev/null
+++ b/models/migrations/v41.go
@@ -0,0 +1,42 @@
+// Copyright 2017 The Gitea Authors. All rights reserved.
+// Use of this source code is governed by a MIT-style
+// license that can be found in the LICENSE file.
+
+package migrations
+
+import (
+	"fmt"
+
+	"code.gitea.io/gitea/models"
+
+	"github.com/go-xorm/xorm"
+)
+
+func addDefaultValueToUserProhibitLogin(x *xorm.Engine) (err error) {
+	user := &models.User{
+		ProhibitLogin: false,
+	}
+
+	if _, err := x.Where("`prohibit_login` IS NULL").Cols("prohibit_login").Update(user); err != nil {
+		return err
+	}
+
+	dialect := x.Dialect().DriverName()
+
+	switch dialect {
+	case "mysql":
+		_, err = x.Exec("ALTER TABLE user MODIFY `prohibit_login` tinyint(1) NOT NULL DEFAULT 0")
+	case "postgres":
+		_, err = x.Exec("ALTER TABLE \"user\" ALTER COLUMN `prohibit_login` SET NOT NULL, ALTER COLUMN `prohibit_login` SET DEFAULT false")
+	case "mssql":
+		// xorm already set DEFAULT 0 for data type BIT in mssql
+		_, err = x.Exec(`ALTER TABLE [user] ALTER COLUMN "prohibit_login" BIT NOT NULL`)
+	case "sqlite3":
+	}
+
+	if err != nil {
+		return fmt.Errorf("Error changing user prohibit_login column definition: %v", err)
+	}
+
+	return err
+}
diff --git a/models/notification_test.go b/models/notification_test.go
index 2166afa2a6..c1b7d50529 100644
--- a/models/notification_test.go
+++ b/models/notification_test.go
@@ -16,9 +16,8 @@ func TestCreateOrUpdateIssueNotifications(t *testing.T) {
 
 	assert.NoError(t, CreateOrUpdateIssueNotifications(issue, 2))
 
-	notf := AssertExistsAndLoadBean(t, &Notification{UserID: 1, IssueID: issue.ID}).(*Notification)
-	assert.Equal(t, NotificationStatusUnread, notf.Status)
-	notf = AssertExistsAndLoadBean(t, &Notification{UserID: 4, IssueID: issue.ID}).(*Notification)
+	// Two watchers are inactive, thus only notification for user 10 is created
+	notf := AssertExistsAndLoadBean(t, &Notification{UserID: 10, IssueID: issue.ID}).(*Notification)
 	assert.Equal(t, NotificationStatusUnread, notf.Status)
 	CheckConsistencyFor(t, &Issue{ID: issue.ID})
 }
diff --git a/models/repo_watch.go b/models/repo_watch.go
index c3baab9d2f..cf9dba900a 100644
--- a/models/repo_watch.go
+++ b/models/repo_watch.go
@@ -51,7 +51,11 @@ func WatchRepo(userID, repoID int64, watch bool) (err error) {
 
 func getWatchers(e Engine, repoID int64) ([]*Watch, error) {
 	watches := make([]*Watch, 0, 10)
-	return watches, e.Find(&watches, &Watch{RepoID: repoID})
+	return watches, e.Where("`watch`.repo_id=?", repoID).
+		And("`user`.is_active=?", true).
+		And("`user`.prohibit_login=?", false).
+		Join("INNER", "user", "`user`.id = `watch`.user_id").
+		Find(&watches)
 }
 
 // GetWatchers returns all watchers of given repository.
diff --git a/models/repo_watch_test.go b/models/repo_watch_test.go
index a1543566c1..1277b156c5 100644
--- a/models/repo_watch_test.go
+++ b/models/repo_watch_test.go
@@ -40,7 +40,8 @@ func TestGetWatchers(t *testing.T) {
 	repo := AssertExistsAndLoadBean(t, &Repository{ID: 1}).(*Repository)
 	watches, err := GetWatchers(repo.ID)
 	assert.NoError(t, err)
-	assert.Len(t, watches, repo.NumWatches)
+	// Two watchers are inactive, thus minus 2
+	assert.Len(t, watches, repo.NumWatches-2)
 	for _, watch := range watches {
 		assert.EqualValues(t, repo.ID, watch.RepoID)
 	}
@@ -77,22 +78,17 @@ func TestNotifyWatchers(t *testing.T) {
 	}
 	assert.NoError(t, NotifyWatchers(action))
 
-	AssertExistsAndLoadBean(t, &Action{
-		ActUserID: action.ActUserID,
-		UserID:    1,
-		RepoID:    action.RepoID,
-		OpType:    action.OpType,
-	})
-	AssertExistsAndLoadBean(t, &Action{
-		ActUserID: action.ActUserID,
-		UserID:    4,
-		RepoID:    action.RepoID,
-		OpType:    action.OpType,
-	})
+	// Two watchers are inactive, thus action is only created for user 8, 10
 	AssertExistsAndLoadBean(t, &Action{
 		ActUserID: action.ActUserID,
 		UserID:    8,
 		RepoID:    action.RepoID,
 		OpType:    action.OpType,
 	})
+	AssertExistsAndLoadBean(t, &Action{
+		ActUserID: action.ActUserID,
+		UserID:    10,
+		RepoID:    action.RepoID,
+		OpType:    action.OpType,
+	})
 }
diff --git a/models/user.go b/models/user.go
index f6d7051013..9adc5bd4e1 100644
--- a/models/user.go
+++ b/models/user.go
@@ -111,7 +111,7 @@ type User struct {
 	AllowGitHook            bool
 	AllowImportLocal        bool // Allow migrate repository by local path
 	AllowCreateOrganization bool `xorm:"DEFAULT true"`
-	ProhibitLogin           bool
+	ProhibitLogin           bool `xorm:"NOT NULL DEFAULT false"`
 
 	// Avatar
 	Avatar          string `xorm:"VARCHAR(2048) NOT NULL"`