diff --git a/lib/exirc/utils.ex b/lib/exirc/utils.ex
index a5f18b5..d3f903c 100644
--- a/lib/exirc/utils.ex
+++ b/lib/exirc/utils.ex
@@ -1,181 +1,181 @@
 defmodule ExIrc.Utils do
 
   ######################
   # IRC Message Parsing
   ######################
 
   @doc """
   Parse an IRC message
 
   Example:
 
       data    = ':irc.example.org 005 nick NETWORK=Freenode PREFIX=(ov)@+ CHANTYPES=#&'
       message = ExIrc.Utils.parse data
       assert "irc.example.org" = message.server
   """
   @spec parse(raw_data :: char_list) :: IrcMessage.t
   def parse(raw_data) do
     data = :string.substr(raw_data, 1, length(raw_data))
     case data do
       [?:|_] ->
           [[?:|from]|rest] = :string.tokens(data, ' ')
           get_cmd(rest, parse_from(from, %IrcMessage{ctcp: false}))
       data ->
           get_cmd(:string.tokens(data, ' '), %IrcMessage{ctcp: false})
     end
   end
 
-  @prefix_pattern ~r/^(?<nick>[^!]+)(?:(?:!(?<user>[^@ ]+))?(?:@(?<host>[\w.:-]+)))?$/
+  @prefix_pattern ~r/^(?<nick>[^!]+)(?:!(?:(?<user>[^@ ]+)@)?(?:(?<host>[\w.:-]+)))?$/
   defp parse_from(from, msg) do
     from_str = IO.iodata_to_binary(from)
     parts    = Regex.run(@prefix_pattern, from_str, capture: :all_but_first)
     case parts do
       [nick, user, host] ->
         %{msg | nick: nick, user: user, host: host}
       [nick, host] ->
         %{msg | nick: nick, host: host}
       [nick] ->
         if String.contains?(nick, ".") do
           %{msg | server: nick}
         else
           %{msg | nick: nick}
         end
     end
   end
 
   # Parse command from message
   defp get_cmd([cmd, arg1, [?:, 1 | ctcp_trail] | restargs], msg) when cmd == 'PRIVMSG' or cmd == 'NOTICE' do
     get_cmd([cmd, arg1, [1 | ctcp_trail] | restargs], msg)
   end
 
   defp get_cmd([cmd, target, [1 | ctcp_cmd] | cmd_args], msg) when cmd == 'PRIVMSG' or cmd == 'NOTICE' do
     args = cmd_args
       |> Enum.map(&Enum.take_while(&1, fn c -> c != 0o001 end))
       |> Enum.map(&List.to_string/1)
     case args do
       args when args != [] ->
         %{msg | 
           cmd:  to_string(ctcp_cmd),
           args: [to_string(target), args |> Enum.join(" ")],
           ctcp: true
         }
       _ ->
         %{msg | cmd: to_string(cmd), ctcp: :invalid}
     end
   end
 
   defp get_cmd([cmd | rest], msg) do
     get_args(rest, %{msg | cmd: to_string(cmd)})
   end
 
 
   # Parse command args from message
   defp get_args([], msg) do
     args = msg.args
       |> Enum.reverse
       |> Enum.filter(fn arg -> arg != [] end)
       |> Enum.map(&trim_crlf/1)
       |> Enum.map(&List.to_string/1)
     post_process(%{msg | args: args})
   end
 
   defp get_args([[?: | first_arg] | rest], msg) do
     args = (for arg <- [first_arg | rest], do: ' ' ++ trim_crlf(arg)) |> List.flatten
     case args do
       [_] ->
           get_args([], %{msg | args: msg.args})
       [_ | full_trail] ->
           get_args([], %{msg | args: [full_trail | msg.args]})
     end
   end
 
   defp get_args([arg | rest], msg) do
     get_args(rest, %{msg | args: [arg | msg.args]})
   end
 
   # This function allows us to handle special case messages which are not RFC
   # compliant, before passing it to the client.
   defp post_process(%IrcMessage{cmd: "332", args: [nick, channel]} = msg) do
     # Handle malformed RPL_TOPIC messages which contain no topic
     %{msg | :cmd => "331", :args => [channel, "No topic is set"], :nick => nick}
   end
   defp post_process(msg), do: msg
 
   ############################
   # Parse RPL_ISUPPORT (005)
   ############################
 
   @doc """
   Parse RPL_ISUPPORT message.
 
   If an empty list is provided, do nothing, otherwise parse CHANTYPES,
   NETWORK, and PREFIX parameters for relevant data.
   """
   @spec isup(parameters :: list(binary), state :: ExIrc.Client.ClientState.t) :: ExIrc.Client.ClientState.t
   def isup([], state), do: state
   def isup([param | rest], state) do
     try do
       isup(rest, isup_param(param, state))
     rescue
       _ -> isup(rest, state)
     end
   end
 
   defp isup_param("CHANTYPES=" <> channel_prefixes, state) do
     prefixes = channel_prefixes |> String.split("", trim: true)
     %{state | channel_prefixes: prefixes}
   end
   defp isup_param("NETWORK=" <> network, state) do
     %{state | network: network}
   end
   defp isup_param("PREFIX=" <> user_prefixes, state) do
     prefixes = Regex.run(~r/\((.*)\)(.*)/, user_prefixes, capture: :all_but_first)
                |> Enum.map(&String.to_char_list/1)
                |> List.zip
     %{state | user_prefixes: prefixes}
   end
   defp isup_param(_, state) do
     state
   end
 
   ###################
   # Helper Functions
   ###################
 
   @days_of_week   ['Mon','Tue','Wed','Thu','Fri','Sat','Sun']
   @months_of_year ['Jan','Feb','Mar','Apr','May','Jun','Jul','Aug','Sep','Oct','Nov','Dec']
   @doc """
   Get CTCP formatted time from a tuple representing the current calendar time:
 
   Example:
 
       iex> local_time = {{2013,12,6},{14,5,0}}
       {{2013,12,6},{14,5,0}}
       iex> ExIrc.Utils.ctcp_time local_time
       "Fri Dec 06 14:05:00 2013"
   """
   @spec ctcp_time(datetime :: {{integer, integer, integer}, {integer, integer, integer}}) :: binary
   def ctcp_time({{y, m, d}, {h, n, s}} = _datetime) do
     [:lists.nth(:calendar.day_of_the_week(y,m,d), @days_of_week),
      ' ',
      :lists.nth(m, @months_of_year),
      ' ',
      :io_lib.format("~2..0s", [Integer.to_char_list(d)]),
      ' ',
      :io_lib.format("~2..0s", [Integer.to_char_list(h)]),
      ':',
      :io_lib.format("~2..0s", [Integer.to_char_list(n)]),
      ':',
      :io_lib.format("~2..0s", [Integer.to_char_list(s)]),
      ' ',
      Integer.to_char_list(y)] |> List.flatten |> List.to_string
   end
 
   defp trim_crlf(charlist) do
     case Enum.reverse(charlist) do
       [?\n, ?\r | text] -> Enum.reverse(text)
       _ -> charlist
     end
   end
 
 end
diff --git a/test/utils_test.exs b/test/utils_test.exs
index 31dac37..38e343b 100644
--- a/test/utils_test.exs
+++ b/test/utils_test.exs
@@ -1,123 +1,130 @@
 defmodule ExIrc.UtilsTest do
   use ExUnit.Case, async: true
 
   use Irc.Commands
 
   alias ExIrc.Utils, as: Utils
   alias ExIrc.Client.ClientState, as: ClientState
 
   doctest ExIrc.Utils
 
   test "Given a local date/time as a tuple, can retrieve get the CTCP formatted time" do
   	local_time = {{2013,12,6},{14,5,0}} # Mimics output of :calendar.local_time()
   	assert Utils.ctcp_time(local_time) == "Fri Dec 06 14:05:00 2013"
   end
 
   test "Can parse a CTCP command" do
     message = ':pschoenf NOTICE #testchan :' ++ '#{<<0o001>>}' ++ 'ACTION mind explodes!!' ++ '#{<<0o001>>}'
   	expected = %IrcMessage{
       nick: "pschoenf",
       cmd:  "ACTION",
       ctcp: true,
       args: ["#testchan", "mind explodes!!"]
     }
     result = Utils.parse(message)
     assert expected == result
   end
 
   test "Parse INVITE message" do
     message = ':pschoenf INVITE testuser #awesomechan'
     assert %IrcMessage{
       :nick => "pschoenf",
       :cmd =>  "INVITE",
       :args => ["testuser", "#awesomechan"]
     } = Utils.parse(message)
   end
 
   test "Parse KICK message" do
     message = ':pschoenf KICK #testchan lameuser'
     assert %IrcMessage{
       :nick => "pschoenf",
       :cmd =>  "KICK",
       :args => ["#testchan", "lameuser"]
     } = Utils.parse(message)
   end
 
   test "Can parse RPL_ISUPPORT commands" do
     message = ':irc.example.org 005 nick NETWORK=Freenode PREFIX=(ov)@+ CHANTYPES=#&'
     parsed  = Utils.parse(message)
     state   = %ClientState{}
     assert %ClientState{
       :channel_prefixes => ["#", "&"],
       :user_prefixes =>    [{?o, ?@}, {?v, ?+}],
       :network =>          "Freenode"
     } = Utils.isup(parsed.args, state)
   end
 
   test "Can parse full prefix in messages" do
     assert %IrcMessage{
       nick: "WiZ",
       user: "jto",
       host: "tolsun.oulu.fi",
     } = Utils.parse(':WiZ!jto@tolsun.oulu.fi NICK Kilroy')
   end
 
+  test "Can parse prefix with only hostname in messages" do
+    assert %IrcMessage{
+      nick: "WiZ",
+      host: "tolsun.oulu.fi",
+    } = Utils.parse(':WiZ!tolsun.oulu.fi NICK Kilroy')
+  end
+
   test "Can parse reduced prefix in messages" do
     assert %IrcMessage{
       nick: "Trillian",
     } = Utils.parse(':Trillian SQUIT cm22.eng.umd.edu :Server out of control')
   end
 
   test "Can parse server-only prefix in messages" do
     assert %IrcMessage{
       server: "ircd.stealth.net"
     } = Utils.parse(':ircd.stealth.net 302 yournick :syrk=+syrk@millennium.stealth.net')
   end
 
   test "Can parse FULL STOP in username in prefixes" do
     assert %IrcMessage{
       nick: "nick",
       user: "user.name",
       host: "irc.example.org"
     } = Utils.parse(':nick!user.name@irc.example.org PART #channel')
   end
 
   test "Can parse EXCLAMATION MARK in username in prefixes" do
     assert %IrcMessage{
       nick: "nick",
       user: "user!name",
       host: "irc.example.org"
     } = Utils.parse(':nick!user!name@irc.example.org PART #channel')
   end
 
   test "parse join message" do
     message = ':pschoenf JOIN #elixir-lang'
     assert %IrcMessage{
       :nick => "pschoenf",
       :cmd => "JOIN",
       :args => ["#elixir-lang"]
     } = Utils.parse(message)
   end
 
   test "Parse Slack's inappropriate RPL_TOPIC message as if it were an RPL_NOTOPIC" do
     # NOTE: This is not a valid message per the RFC.  If there's no topic
     # (which is the case for Slack in this instance), they should instead send
     # us a RPL_NOTOPIC (331).
     #
     # Two things:
     #
     # 1) Bad slack!  Read your RFCs! (because my code has never had bugs yup obv)
     # 2) Don't care, still want to talk to them without falling over dead!
     #
     # Parsing this as if it were actually an RPL_NOTOPIC (331) seems especially like
     # a good idea when I realized that there's nothing in ExIRc that does anything
     # with 331 at all - they just fall on the floor, no crashes to be seen (ideally)
     message = ':irc.tinyspeck.com 332 jadams #elm-playground-news :'
     assert %IrcMessage{
       :nick => "jadams",
       :cmd =>  "331",
       :args => ["#elm-playground-news", "No topic is set"]
     } = Utils.parse(message)
   end
 
 end