How to count rows after a specific row?
I always find views and subqueries easier to read and develop mainly as you can test and edit one section at a time. Depending on the number of messages and your system it may be a little slower though I doubt it. In this case I am going to use a union query.

I would also check first and if the limits are not exceeded then perform the insert (unless you doing millions of messages).
Create a view of the total number of sent messages

 CREATE view vwMessagesSent AS
 SELECT *
 FROM `contact`
 WHERE date_time &gt; unix_timestamp(DATE_SUB(now(), INTERVAL 1 day))


This reduces the overall complexity of

SELECT Least(4,4 - count(id)) as sendLimit
FROM `vwMessagesSent`
WHERE user_id = ?
UNION ALL
SELECT Least(2,
       IF(
          (SELECT COUNT(id) FROM `vwMessagesSent` WHERE receiver_id = ? AND  user_id = ?)=1, 4, 2)
       )  - (SELECT COUNT(id) FROM `vwMessagesSent` WHERE user_id = ? AND receiver_id = ?)
) 
FROM `vwMessagesSent`
WHERE user_id = ? AND receiver_id = ?
order by SendLimit
LIMIT 1


Note: Not tested - should be close to what you are after

We are using a few interesting SQL items out of the box. 
Least takes the lowest number of a collection of numbers. It allows us to only return the number of messages the user is allowed to send and for you to warn the user that the insert/message send was not going to be undertaken as they are over quota.

UNION allows you to merge two queries and we use the ALL to make sure we have multiple rows (rather than using the distinct key

LIMIT 1 We sort the order of the two rows returned with the minimum number available to be sent and then only return that row. 

Hope this helps. Happy to clarify or fix the main SQL and I would be looking at using at a stored procedure to improve the logic even further.