You can use :erlang.process_info
E.g.:
iex(1)> shell_process = self
iex(2)> spawn(fn ->
...(2)> send(shell_process, :foobar)
...(2)> :erlang.process_info(shell_process, :messages) |> IO.inspect
...(2)> end)
{:messages, [:foobar]}
You can have a GUI interface via observer application. Just start it from the shell with :observer.start, head to Processes tab, find the target process, double click it, and in messages you should see a snapshot of the message queue.
It is also possible to use Erlang's tracing via :sys, :dbg module, and :erlang.trace/3 function to dynamically start traces for various events. Among other things, you can trace messages sent to or from particular process(es).