diff --git a/mo/db.py b/mo/db.py
index 429a930264c8bebe47786fad93eb0185a1671cb6..bb45a9d863246107868e7c43d61741717dc66936 100644
--- a/mo/db.py
+++ b/mo/db.py
@@ -303,6 +303,9 @@ class User(Base):
     def name_sort_key(self) -> Tuple[str, str]:
         return (locale.strxfrm(self.last_name), locale.strxfrm(self.first_name))
 
+    def is_inactive(self) -> bool:
+        return self.password_hash is None
+
 
 class Contest(Base):
     __tablename__ = 'contests'
diff --git a/mo/web/jinja.py b/mo/web/jinja.py
index 59c744f19a92619545a76d29fb25d10af96c189d..503283165a419441381f12753fa4137640c72ae4 100644
--- a/mo/web/jinja.py
+++ b/mo/web/jinja.py
@@ -13,6 +13,7 @@ import mo.util_format as util_format
 from mo.web import app
 from mo.web.org_contest import contest_breadcrumbs
 from mo.web.org_place import place_breadcrumbs
+from mo.web.util import user_html_flags
 
 # Konfigurace Jinjy
 
@@ -100,3 +101,7 @@ def json_pretty(js: Any) -> str:
 @app.template_global()
 def log_url(typ: str, id: int) -> str:
     return url_for('org_log', typ=typ, id=id)
+
+@app.template_filter()
+def user_flags(u: db.User) -> Markup:
+    return user_html_flags(u)
diff --git a/mo/web/org_contest.py b/mo/web/org_contest.py
index fdebce5c5e6dd8e9629a809fa11ceeddcc9b2876..1d72081dedca35c262c95e284a454ca2cadc074e 100644
--- a/mo/web/org_contest.py
+++ b/mo/web/org_contest.py
@@ -25,7 +25,7 @@ from mo.util_format import inflect_number, inflect_by_number
 from mo.web import app
 import mo.web.util
 from mo.web.util import MODecimalField, PagerForm
-from mo.web.table import CellCheckbox, Table, Row, Column, cell_pion_link, cell_place_link, cell_email_link
+from mo.web.table import CellCheckbox, Table, Row, Column, cell_pion_link, cell_place_link, cell_email_link, cell_email_link_flags, CellMarkup
 import wtforms.validators as validators
 from wtforms.widgets.html5 import NumberInput
 
@@ -551,16 +551,13 @@ def make_contestant_table(query: Query, round: db.Round, add_checkbox: bool = Fa
         html_attr = {
             'class': 'state-' + pion.state.name
         }
-        if u.is_test:
-            html_attr['class'] += ' testuser'
-            html_attr['title'] = 'Testovací uživatel'
         rows.append(Row(
             keys={
                 'sort_key': u.sort_key(),
                 'user_id': u.user_id,
                 'first_name': cell_pion_link(u, pion.contest_id, u.first_name),
                 'last_name': cell_pion_link(u, pion.contest_id, u.last_name),
-                'email': cell_email_link(u),
+                'email': cell_email_link_flags(u),
                 'school': pant.school_place.name,
                 'school_code': cell_place_link(pant.school_place, pant.school_place.get_code()),
                 'grade': pant.grade,
diff --git a/mo/web/table.py b/mo/web/table.py
index 13429bfad2bbd0b45cc7d0523532f67dfe5c59cc..72cbbcd14fdf0c7c501ccdb610dcbc6d52ec3543 100644
--- a/mo/web/table.py
+++ b/mo/web/table.py
@@ -11,6 +11,7 @@ import werkzeug.exceptions
 from mo.csv import FileFormat
 import mo.db as db
 from mo.web import app
+from mo.web.util import user_html_flags
 
 
 @dataclass
@@ -55,17 +56,19 @@ class Row:
 class CellLink(Cell):
     url: str
     hint: Optional[str]
+    html_suffix: Markup
 
-    def __init__(self, text: str, url: str, hint: Optional[str] = None):
+    def __init__(self, text: str, url: str, hint: Optional[str] = None, html_suffix: Markup = Markup("")):
         Cell.__init__(self, text)
         self.url = url
         self.hint = hint
+        self.html_suffix = html_suffix
 
     def to_html(self) -> str:
         a = '<td><a href="' + escape(self.url) + '"'
         if self.hint:
             a += ' title="' + escape(self.hint) + '"'
-        return a + '>' + escape(self.text) + '</a>'
+        return a + '>' + escape(self.text) + '</a>' + str(self.html_suffix)
 
 
 class CellCheckbox(Cell):
@@ -85,6 +88,20 @@ class CellCheckbox(Cell):
             ch += ' checked'
         return ch + '>'
 
+class CellMarkup(Cell):
+    text: str
+    html: str
+
+    def __init__(self, text: str, html: Union[str, Markup]):
+        self.text = text
+        self.html = str(html)
+
+    def __str__(self) -> str:
+        return self.text
+
+    def to_html(self) -> str:
+        return self.html
+
 
 class Table:
     columns: Sequence[Column]
@@ -184,6 +201,9 @@ class Table:
 def cell_email_link(user: db.User) -> CellLink:
     return CellLink(user.email, 'mailto:' + urllib.parse.quote(user.email, safe='@'))
 
+def cell_email_link_flags(user: db.User) -> CellLink:
+    return CellLink(user.email, 'mailto:' + urllib.parse.quote(user.email, safe='@'), html_suffix=user_html_flags(user))
+
 
 def cell_user_link(user: db.User, text: str) -> CellLink:
     return CellLink(text, url_for('org_user', id=user.user_id))
diff --git a/mo/web/templates/org_contest_solutions.html b/mo/web/templates/org_contest_solutions.html
index 7bda4f7c3466e544f126108be2883da21fed8a1c..7df83f66e70e2cf897b4b8c8fd0e841f129dbb05 100644
--- a/mo/web/templates/org_contest_solutions.html
+++ b/mo/web/templates/org_contest_solutions.html
@@ -61,7 +61,7 @@ konkrétní úlohu. Symbol <span class="icon">🗐</span> značí, že existuje
 	</thead>
 	{% for pion in pions %}
 	{% set u = pion.user %}
-	<tr class="state-{{ pion.state.name }}{% if u.is_test %} testuser{% endif %}" {% if u.is_test %}title="Testovací uživatel"{% endif %}>
+	<tr class="state-{{ pion.state.name }}>
 		<th>{{ u|pion_link(contest.contest_id) }}
 		<td>{{ pion.state.friendly_name() }}
 		{% set sum_points = [] %}
diff --git a/mo/web/templates/org_contest_user.html b/mo/web/templates/org_contest_user.html
index c6e8e4708b63e80fed734f3da89a82db61b0e151..d37540fb4adf55594f1b70a185cfd2171da08811 100644
--- a/mo/web/templates/org_contest_user.html
+++ b/mo/web/templates/org_contest_user.html
@@ -32,7 +32,7 @@
 	</thead>
 	<tr><td>Jméno:<td>{{ user.first_name }}
 	<tr><td>Příjmení:<td>{{ user.last_name }}
-	<tr><td>E-mail:<td>{{ user.email|mailto }}
+	<tr><td>E-mail:<td>{{ user.email|mailto }}{{ user|user_flags }}
 	<tr><td>Škola:<td><a href='{{ url_for('org_place', id=pant.school) }}'>{{ pant.school_place.name }}</a>
 	<tr><td>Třída:<td>{{ pant.grade }}
 	<tr><td>Rok narození:<td>{{ pant.birth_year }}
diff --git a/mo/web/templates/org_orgs.html b/mo/web/templates/org_orgs.html
index 52d30633852c2aae12252ec7e3e1667c8b00de6a..dbd6cc7e52c2f7550237dd434fd46e35a19e1605 100644
--- a/mo/web/templates/org_orgs.html
+++ b/mo/web/templates/org_orgs.html
@@ -51,7 +51,7 @@
 {% for user in users %}
 	<tr>
 		<td>{{ user.first_name }}</td><td>{{ user.last_name }}</td>
-		<td>{{ user.email|mailto }}{% if user.password_hash == None %}<span class="user-inactive" title='Účet dosud nebyl aktivován'> *</span>{% endif %}</td>
+		<td>{{ user.email|mailto }}{{ user|user_flags }}</td>
 		<td>{% if user.is_admin %}správce{% elif user.roles|count == 0 %}<i>žádná role</i>{% else %}
 			<ul>
 			{% for role in user.roles %}
diff --git a/mo/web/templates/org_submit_list.html b/mo/web/templates/org_submit_list.html
index de2b4e61978bcfa29e4a95b554faf75390612d1d..ff445d3ee105f6eeae8c395321ade119702729ed 100644
--- a/mo/web/templates/org_submit_list.html
+++ b/mo/web/templates/org_submit_list.html
@@ -9,7 +9,7 @@
 {% set site_id = sc.site.place_id if sc.site else None %}
 
 <table class="data">
-	<tr><th>Účastník<td>{{ sc.user|pion_link(sc.contest.contest_id) }}
+	<tr><th>Účastník<td>{{ sc.user|pion_link(sc.contest.contest_id) }}{{ sc.user|user_flags }}
 	<tr><th>Úloha<td><a href='{{ url_for('org_contest_task', contest_id=sc.contest.contest_id, site_id=site_id, task_id=sc.task.task_id) }}'>{{ sc.task.code }} {{ sc.task.name }}</a>
 	{% if solution %}
 	<tr><th>Body<td>
diff --git a/mo/web/templates/org_users.html b/mo/web/templates/org_users.html
index df46553b9fd9b0e76fca60cbba515cf236c8c9bf..e1b2b2f6e54997fd51082177402df64b0d4fb752 100644
--- a/mo/web/templates/org_users.html
+++ b/mo/web/templates/org_users.html
@@ -73,9 +73,9 @@
 		</tr>
 	</thead>
 {% for user in users %}
-	<tr{% if user.is_test %} class="testuser" title="Testovací uživatel"{% endif %}>
+	<tr>
 		<td>{{ user.first_name }}</td><td>{{ user.last_name }}</td>
-		<td>{{ user.email|mailto }}{% if user.password_hash == None %}<span class="user-inactive" title='Účet dosud nebyl aktivován'> *</span>{% endif %}</td>
+		<td>{{ user.email|mailto }}{{ user|user_flags }}</td>
 		<td>{% if user.participants|count == 0 %}<i>v žádném ročníku</i>{% else %}
 			<ul>
 			{% for participant in user.participants %}
diff --git a/mo/web/templates/parts/org_solution_table.html b/mo/web/templates/parts/org_solution_table.html
index 6223a92c5a84f2968b5c654c19302788949d248d..c8a85be235225cd49e2808b69129e8d1d39e77c4 100644
--- a/mo/web/templates/parts/org_solution_table.html
+++ b/mo/web/templates/parts/org_solution_table.html
@@ -35,14 +35,14 @@ finální (ve výchozím stavu poslední nahrané).{% elif sc.allow_upload_solut
 	{% set u = for_user or obj.user %}
 	{% set task = for_task or obj %}
 	{% if for_task %}
-	<tr class="state-{{ obj.state.name }}{% if u.is_test %} testuser{% endif %}" {% if u.is_test %}title="Testovací uživatel"{% endif %}>
+	<tr class="state-{{ obj.state.name }}">
 	{% else %}
 	<tr>
 	{% endif %}
 		<td>{% if for_user %}
 			<a href='{{ url_for('org_contest_task', contest_id=ct_id, task_id=task.task_id) }}'>{{ task.code }} {{ task.name }}</a>
 		    {% else %}
-			{{ u|pion_link(contest.contest_id) }}</a>
+			{{ u|pion_link(contest.contest_id) }}{{ u|user_flags }}</a>
 		    {% endif %}
 		{% if for_task %}<td>{{ obj.state.friendly_name() }}{% endif %}
 		{% if sol %}
diff --git a/mo/web/util.py b/mo/web/util.py
index 4f10a68d52fc20246453ea9ddf7b88a9f8a88ba5..11e5541e8a10d4afd064b5c1f51c9c75264914ba 100644
--- a/mo/web/util.py
+++ b/mo/web/util.py
@@ -9,6 +9,7 @@ import werkzeug.exceptions
 import werkzeug.utils
 import wtforms
 from wtforms.fields.html5 import DecimalField
+from markupsafe import Markup
 
 import mo.db as db
 import mo.jobs
@@ -145,3 +146,13 @@ class MODecimalField(DecimalField):
                 d /= 10
 
         return super(MODecimalField, self)._value()
+
+def user_html_flags(u: db.User) -> Markup:
+    r = []
+    if u.is_test:
+        r.append("<span class='user-test' title='Testovací uživatel'>*</span>")
+    if u.is_inactive():
+        r.append("<span class='user-inactive' title='Účet dosud nebyl aktivován'>*</span>")
+    if len(r) == 0:
+        return Markup("")
+    return Markup(" " + "".join(r))
diff --git a/static/mo.css b/static/mo.css
index 2de94b237bc204eea24c2b1fa0dd34d39cc92880..3c5df7742a44ae139d1ac48fd4c6886280bdfc0b 100644
--- a/static/mo.css
+++ b/static/mo.css
@@ -114,16 +114,6 @@ table.data td.sol-warn {
 	background-color: #ffaaaa;
 }
 
-table tr.testuser {
-	opacity: 0.7;
-	background: repeating-linear-gradient(
-		45deg,
-		white,
-		white 10px,
-		#ddd 10px,
-		#ddd 20px
-	);
-}
 table tr.state-disqualified, table tr.state-disqualified a:not(.btn) {
 	color: red;
 }
@@ -256,6 +246,9 @@ table.data tbody tr.job-failed:hover {
 
 /* Users */
 
+.user-test {
+	color: green;
+}
 .user-inactive {
 	color: red;
 }