I will go about this differently. Create a non-global flag on the message (ie for each user) and only give flag action (not unflag). Do not auto display this flag.
Then in your view you add the flag action as a field on the row and test whether it works by clicking on it (to test you could give temporary unflag permission). When it works to you satisfaction hide the flag link via css, and add some javascript to click the flag if the row is hovered (or whatever) over. And set the Javascript up so that it can only activate the link once as one can sometimes fire off multiple events when on the border of an element.
And then just add you rule to fire when the message is actually viewed to cover that angle as well as the user may go to that path from somewhere else but your view.
EDIT: jQuery example code:
This code is for a flag called 'test', and a view called 'all', jQuery version 1.7+
(function ($, Drupal, window, document, undefined) {
Drupal.behaviors.MYMODULE = {
attach: function(context, settings) {
$('.view-all .views-row').once().on('mouseover', function(){
// unbind this event handler so it only fires once
$(this).off('mouseover');
// get the flag and click it.
$(this).find('.flag-test a.flag').trigger('click');
});
window.alert = function(text) {
// Prevent unwanted ajax errors when navigation away
return true;
};
}
};
})(jQuery, Drupal, this, this.document);
One other little issue is that views does not seem to respect the flag unflag permissions per role. I circumvented that by adding a field 'Flags: Flagged (A boolean field to show whether the flag is set or not.) and setting its output to 0/1. I then hid this new field as well as the flag link, and added a Global PHP field with this Output Code, and it worked like a charm:
<?php
if (!$row->flagged) print $row->ops;
?>
There is a possible patch for this behaviour at Flags: Flag link views field should respect permissions, but I have not tested it.