I don't think you want a from_id and to_id, just a from_id. You'll determine the first and last message in the conversation by the date.
However, for simplicity and performance sake, I'd make a junction table that's user centric:
user_id with_user_id conversation_id last_read_id
------- ------------ --------------- --------------
1 2 1 1
1 3 2 0
2 1 1 2
3 1 2 1
Then, for the conversations:
id conversation_id from_id content created_on
-- --------------- ------- ------- ----------
1 1 1 hello 2012-06-01 12:00:00
2 1 2 hi 2012-06-01 12:10:01
3 2 3 howdy 2012-06-01 12:40:10
So, when someone wants to begin a conversation, you check the junction table to see if they're already in a conversation with that person. If they are, resume it.
If it's a new conversation, then make sure to add the record in the junction table for each user. The last_read_id column in the junction table refers to id in the conversations table.
To get all the unread messages for user 1:
SELECT c.* FROM junction j
JOIN conversation c
ON c.conversation_id = j.conversation_id
AND c.id > j.last_read_id
WHERE j.user_id = 1
ORDER BY c.created_on DESC
Results in:
id conversation_id from_id content created_on
-- --------------- ------- ------- ----------
3 2 3 howdy 2012-06-01 12:40:10
2 1 2 hi 2012-06-01 12:10:01
To get all messages between user 1 and user 2 (from user 1's point of view):
SELECT c.* FROM junction j
JOIN conversation c
ON c.conversation_id = j.conversation_id
WHERE j.user_id = 1 AND j.with_user_id = 2
ORDER BY c.created_on DESC
Results in:
id conversation_id from_id content created_on
-- --------------- ------- ------- ----------
2 1 2 hi 2012-06-01 12:10:01
1 1 1 hello 2012-06-01 12:00:00