diff --git a/app/src/main/java/de/kuschku/quasseldroid/service/QuasselNotificationBackend.kt b/app/src/main/java/de/kuschku/quasseldroid/service/QuasselNotificationBackend.kt
index c50b66fc74d98d2a413b8e80cea165f61b21478e..b175e538f0ce19790105b67c4f00ad40e0a75e2f 100644
--- a/app/src/main/java/de/kuschku/quasseldroid/service/QuasselNotificationBackend.kt
+++ b/app/src/main/java/de/kuschku/quasseldroid/service/QuasselNotificationBackend.kt
@@ -29,9 +29,9 @@ import de.kuschku.libquassel.quassel.ExtendedFeature
 import de.kuschku.libquassel.quassel.syncables.IgnoreListManager
 import de.kuschku.libquassel.session.NotificationManager
 import de.kuschku.libquassel.session.Session
-import de.kuschku.libquassel.util.IrcUserUtils
 import de.kuschku.libquassel.util.flag.hasFlag
 import de.kuschku.libquassel.util.irc.HostmaskHelper
+import de.kuschku.libquassel.util.irc.SenderColorUtil
 import de.kuschku.quasseldroid.GlideApp
 import de.kuschku.quasseldroid.GlideRequest
 import de.kuschku.quasseldroid.R
@@ -234,7 +234,7 @@ class QuasselNotificationBackend @Inject constructor(
         val content = contentFormatter.formatContent(it.content, false)
 
         val nickName = HostmaskHelper.nick(it.sender)
-        val senderColorIndex = IrcUserUtils.senderColor(nickName)
+        val senderColorIndex = SenderColorUtil.senderColor(nickName)
         val rawInitial = nickName.trimStart('-',
                                             '_',
                                             '[',
diff --git a/app/src/main/java/de/kuschku/quasseldroid/ui/chat/input/AutoCompleteHelper.kt b/app/src/main/java/de/kuschku/quasseldroid/ui/chat/input/AutoCompleteHelper.kt
index 842ec28569adc9ee3a3b35490aa2252234e18ca9..1f6419617fc930ab6a6a6e3592790a93387a1df9 100644
--- a/app/src/main/java/de/kuschku/quasseldroid/ui/chat/input/AutoCompleteHelper.kt
+++ b/app/src/main/java/de/kuschku/quasseldroid/ui/chat/input/AutoCompleteHelper.kt
@@ -30,11 +30,11 @@ import de.kuschku.libquassel.quassel.syncables.IrcChannel
 import de.kuschku.libquassel.quassel.syncables.IrcUser
 import de.kuschku.libquassel.quassel.syncables.Network
 import de.kuschku.libquassel.session.ISession
-import de.kuschku.libquassel.util.IrcUserUtils
 import de.kuschku.libquassel.util.Optional
 import de.kuschku.libquassel.util.flag.hasFlag
 import de.kuschku.libquassel.util.helpers.nullIf
 import de.kuschku.libquassel.util.helpers.value
+import de.kuschku.libquassel.util.irc.SenderColorUtil
 import de.kuschku.quasseldroid.R
 import de.kuschku.quasseldroid.settings.AutoCompleteSettings
 import de.kuschku.quasseldroid.settings.MessageSettings
@@ -89,7 +89,7 @@ class AutoCompleteHelper(
       }.map {
         if (it is AutoCompleteItem.UserItem) {
           val nickName = it.nick
-          val senderColorIndex = IrcUserUtils.senderColor(nickName)
+          val senderColorIndex = SenderColorUtil.senderColor(nickName)
           val rawInitial = nickName.trimStart(*IGNORED_CHARS).firstOrNull()
                            ?: nickName.firstOrNull()
           val initial = rawInitial?.toUpperCase().toString()
diff --git a/app/src/main/java/de/kuschku/quasseldroid/ui/chat/messages/QuasselMessageRenderer.kt b/app/src/main/java/de/kuschku/quasseldroid/ui/chat/messages/QuasselMessageRenderer.kt
index c5805a0a141524be59f3ab29723502c8971d47e2..3b5254bce009e6b2130d323ef86bc51e6a1a7577 100644
--- a/app/src/main/java/de/kuschku/quasseldroid/ui/chat/messages/QuasselMessageRenderer.kt
+++ b/app/src/main/java/de/kuschku/quasseldroid/ui/chat/messages/QuasselMessageRenderer.kt
@@ -32,9 +32,9 @@ import android.widget.LinearLayout
 import de.kuschku.libquassel.protocol.Message.MessageType.*
 import de.kuschku.libquassel.protocol.Message_Flag
 import de.kuschku.libquassel.protocol.Message_Type
-import de.kuschku.libquassel.util.IrcUserUtils
 import de.kuschku.libquassel.util.flag.hasFlag
 import de.kuschku.libquassel.util.irc.HostmaskHelper
+import de.kuschku.libquassel.util.irc.SenderColorUtil
 import de.kuschku.quasseldroid.R
 import de.kuschku.quasseldroid.persistence.QuasselDatabase
 import de.kuschku.quasseldroid.settings.MessageSettings
@@ -212,7 +212,7 @@ class QuasselMessageRenderer @Inject constructor(
         }
         val content = contentFormatter.formatContent(message.content.content, highlight)
         val nickName = HostmaskHelper.nick(message.content.sender)
-        val senderColorIndex = IrcUserUtils.senderColor(nickName)
+        val senderColorIndex = SenderColorUtil.senderColor(nickName)
         val rawInitial = nickName.trimStart('-', '_', '[', ']', '{', '}', '|', '`', '^', '.', '\\')
                            .firstOrNull() ?: nickName.firstOrNull()
         val initial = rawInitial?.toUpperCase().toString()
diff --git a/app/src/main/java/de/kuschku/quasseldroid/ui/chat/nicks/NickListFragment.kt b/app/src/main/java/de/kuschku/quasseldroid/ui/chat/nicks/NickListFragment.kt
index 6f7e0ba2af69cb13bef7c94a3ad025ad05ac3252..6b00e1e4c036e2f59443fb8bee26ae30e0642265 100644
--- a/app/src/main/java/de/kuschku/quasseldroid/ui/chat/nicks/NickListFragment.kt
+++ b/app/src/main/java/de/kuschku/quasseldroid/ui/chat/nicks/NickListFragment.kt
@@ -39,9 +39,9 @@ import com.bumptech.glide.integration.recyclerview.RecyclerViewPreloader
 import com.bumptech.glide.util.FixedPreloadSizeProvider
 import de.kuschku.libquassel.protocol.Buffer_Type
 import de.kuschku.libquassel.quassel.BufferInfo
-import de.kuschku.libquassel.util.IrcUserUtils
 import de.kuschku.libquassel.util.helpers.value
 import de.kuschku.libquassel.util.irc.IrcCaseMappers
+import de.kuschku.libquassel.util.irc.SenderColorUtil
 import de.kuschku.quasseldroid.GlideApp
 import de.kuschku.quasseldroid.R
 import de.kuschku.quasseldroid.settings.AppearanceSettings
@@ -103,7 +103,7 @@ class NickListFragment : ServiceBoundFragment() {
       runInBackground {
         it?.asSequence()?.map {
           val nickName = it.nick
-          val senderColorIndex = IrcUserUtils.senderColor(nickName)
+          val senderColorIndex = SenderColorUtil.senderColor(nickName)
           val rawInitial = nickName.trimStart('-',
                                               '_',
                                               '[',
diff --git a/app/src/main/java/de/kuschku/quasseldroid/util/irc/format/ContentFormatter.kt b/app/src/main/java/de/kuschku/quasseldroid/util/irc/format/ContentFormatter.kt
index 6259d284bbf50ac6b81276eae4150246e818adc0..92283235dd5a0a7664c68ad7860553725f2716ae 100644
--- a/app/src/main/java/de/kuschku/quasseldroid/util/irc/format/ContentFormatter.kt
+++ b/app/src/main/java/de/kuschku/quasseldroid/util/irc/format/ContentFormatter.kt
@@ -27,7 +27,8 @@ import android.text.TextPaint
 import android.text.style.ForegroundColorSpan
 import android.text.style.StyleSpan
 import android.text.style.URLSpan
-import de.kuschku.libquassel.util.IrcUserUtils
+import de.kuschku.libquassel.util.irc.HostmaskHelper
+import de.kuschku.libquassel.util.irc.SenderColorUtil
 import de.kuschku.quasseldroid.R
 import de.kuschku.quasseldroid.settings.MessageSettings
 import de.kuschku.quasseldroid.util.helper.styledAttributes
@@ -106,7 +107,7 @@ class ContentFormatter @Inject constructor(
                                  senderColors: IntArray): CharSequence {
     val spannableString = SpannableString(nick)
     if (colorize) {
-      val senderColor = IrcUserUtils.senderColor(nick)
+      val senderColor = SenderColorUtil.senderColor(nick)
       spannableString.setSpan(
         ForegroundColorSpan(senderColors[(senderColor + senderColors.size) % senderColors.size]),
         0,
@@ -125,12 +126,11 @@ class ContentFormatter @Inject constructor(
 
   private fun formatNickImpl(sender: String, colorize: Boolean, hostmask: Boolean,
                              senderColors: IntArray): CharSequence {
-    val nick = IrcUserUtils.nick(sender)
-    val mask = IrcUserUtils.mask(sender)
+    val (nick, user, host) = HostmaskHelper.split(sender)
     val formattedNick = formatNickNickImpl(nick, colorize, senderColors)
 
     return if (hostmask) {
-      SpanFormatter.format("%s (%s)", formattedNick, mask)
+      SpanFormatter.format("%s (%s@%s)", formattedNick, user, host)
     } else {
       formattedNick
     }
diff --git a/lib/src/main/java/de/kuschku/libquassel/util/IrcUserUtils.kt b/lib/src/main/java/de/kuschku/libquassel/util/IrcUserUtils.kt
deleted file mode 100644
index 87fed68d3f8eb38aeb163fd0db6e9f336275d35f..0000000000000000000000000000000000000000
--- a/lib/src/main/java/de/kuschku/libquassel/util/IrcUserUtils.kt
+++ /dev/null
@@ -1,76 +0,0 @@
-/*
- * Quasseldroid - Quassel client for Android
- *
- * Copyright (c) 2018 Janne Koschinski
- * Copyright (c) 2018 The Quassel Project
- *
- * This program is free software: you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 3 as published
- * by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program.  If not, see <http://www.gnu.org/licenses/>.
- */
-
-package de.kuschku.libquassel.util
-
-import java.util.*
-
-object IrcUserUtils {
-  fun senderColor(nick: String): Int {
-    return 0xf and CRCUtils.qChecksum(
-      nick.trimEnd('_').toLowerCase(Locale.US).toByteArray(Charsets.ISO_8859_1)
-    )
-  }
-
-  fun nick(hostmask: String): String {
-    return hostmask.substring(
-      0,
-      hostmask.lastIndex('!', hostmask.lastIndex('@')) ?: hostmask.length
-    )
-  }
-
-  fun user(hostmask: String): String {
-    return hostmask.substring(
-      (hostmask.lastIndex('!', hostmask.lastIndex('@')) ?: -1) + 1,
-      hostmask.lastIndex('@') ?: hostmask.length
-    )
-  }
-
-  fun host(hostmask: String): String {
-    return hostmask.substring(
-      (hostmask.lastIndex('@') ?: -1) + 1
-    )
-  }
-
-  fun mask(hostmask: String): String {
-    return hostmask.substring(
-      (hostmask.lastIndex('!', hostmask.lastIndex('@')) ?: -1) + 1
-    )
-  }
-
-  private fun String.firstIndex(char: Char,
-                                startIndex: Int? = null,
-                                ignoreCase: Boolean = false): Int? {
-    val lastIndex = indexOf(char, startIndex ?: 0, ignoreCase)
-    return if (lastIndex < 0)
-      null
-    else
-      lastIndex
-  }
-
-  private fun String.lastIndex(char: Char,
-                               startIndex: Int? = null,
-                               ignoreCase: Boolean = false): Int? =
-    lastIndexOf(char, startIndex ?: lastIndex, ignoreCase).let { lastIndex ->
-      if (lastIndex < 0)
-        null
-      else
-        lastIndex
-    }
-}
diff --git a/lib/src/main/java/de/kuschku/libquassel/util/irc/SenderColorUtil.kt b/lib/src/main/java/de/kuschku/libquassel/util/irc/SenderColorUtil.kt
new file mode 100644
index 0000000000000000000000000000000000000000..6c5da692ee6abda14a542590d2ecb25dd3b173c8
--- /dev/null
+++ b/lib/src/main/java/de/kuschku/libquassel/util/irc/SenderColorUtil.kt
@@ -0,0 +1,31 @@
+/*
+ * Quasseldroid - Quassel client for Android
+ *
+ * Copyright (c) 2018 Janne Koschinski
+ * Copyright (c) 2018 The Quassel Project
+ *
+ * This program is free software: you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 3 as published
+ * by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+package de.kuschku.libquassel.util.irc
+
+import de.kuschku.libquassel.util.CRCUtils
+import java.util.*
+
+object SenderColorUtil {
+  fun senderColor(nick: String): Int {
+    return 0xf and CRCUtils.qChecksum(
+      nick.trimEnd('_').toLowerCase(Locale.US).toByteArray(Charsets.ISO_8859_1)
+    )
+  }
+}
diff --git a/lib/src/test/java/de/kuschku/libquassel/util/irc/HostmaskHelperTest.kt b/lib/src/test/java/de/kuschku/libquassel/util/irc/HostmaskHelperTest.kt
new file mode 100644
index 0000000000000000000000000000000000000000..51c406e0b9402670e6d63365b1103bd7ce0092c5
--- /dev/null
+++ b/lib/src/test/java/de/kuschku/libquassel/util/irc/HostmaskHelperTest.kt
@@ -0,0 +1,39 @@
+package de.kuschku.libquassel.util.irc
+
+import org.junit.Assert.assertEquals
+import org.junit.Test
+
+class HostmaskHelperTest {
+  @Test
+  fun testNormal() {
+    assertEquals("justJanne", HostmaskHelper.nick("justJanne!kuschku@lithium.kuschku.de"))
+    assertEquals("kuschku", HostmaskHelper.user("justJanne!kuschku@lithium.kuschku.de"))
+    assertEquals("lithium.kuschku.de", HostmaskHelper.host("justJanne!kuschku@lithium.kuschku.de"))
+  }
+
+  @Test
+  fun testUnvalidatedIdent() {
+    assertEquals("justJanne", HostmaskHelper.nick("justJanne!~kuschku@lithium.kuschku.de"))
+    assertEquals("~kuschku", HostmaskHelper.user("justJanne!~kuschku@lithium.kuschku.de"))
+    assertEquals("lithium.kuschku.de", HostmaskHelper.host("justJanne!~kuschku@lithium.kuschku.de"))
+  }
+
+  @Test
+  fun testUnicode() {
+    assertEquals("bärlauch", HostmaskHelper.nick("bärlauch!maße@flüge.de"))
+    assertEquals("maße", HostmaskHelper.user("bärlauch!maße@flüge.de"))
+    assertEquals("flüge.de", HostmaskHelper.host("bärlauch!maße@flüge.de"))
+  }
+
+  @Test
+  fun testServer() {
+    assertEquals("irc.freenode.org", HostmaskHelper.nick("irc.freenode.org"))
+  }
+
+  @Test
+  fun testDiscord() {
+    assertEquals("Gin_", HostmaskHelper.nick("Gin_!Gin_!♡♅ƸӜƷ♅♡!@discord"))
+    assertEquals("Gin_!♡♅ƸӜƷ♅♡!", HostmaskHelper.user("Gin_!Gin_!♡♅ƸӜƷ♅♡!@discord"))
+    assertEquals("discord", HostmaskHelper.host("Gin_!Gin_!♡♅ƸӜƷ♅♡!@discord"))
+  }
+}