A semaphore does not manage the number of keys; it only manages handing out of keys that it has.
Think of a bank with a set of coins. When you construct the bank, the new() constructor deposits an initial set of coins. Then people stand in line waiting to get() a certain number of coins, while other people come to put() coins in the bank. There are many different ways to use a semaphore, but all of them require the user to manage the number of keys that are get() or put().
A mailbox, on the other hand is constructed with a maximum size.