How does the actual blocking put/get happens inside the mailbox or the uvm blocking ports etc?

for mailbox kind of functionality you can use following code.

class channel #(type T = int, depth = 5);
T fifo[$]

task put(T tr);
wait(fifo.size() < depth);
fifo.push_back(tr) ;
endtask

task get(output T tr);
wait(fifo.size()>0);
tr = fifo.pop_front();
endtask

endclass