This is your query:
SELECT campaign_id, date_time
FROM or_mail
GROUP BY campaign_id
HAVING date_time = MAX(date_time);
You are aggregating by campaign_id.  That means that the results will have one row per campaign_id.  What date_time goes on the row?  Well, an arbitrary value from one of the matching rows.  Just one value, an arbitrary one.  The same is true of the having clause.  In other words, the query does not do what you expect it to do.
Whether you know it or not, you are using a group by extension that is particular to MySQL (you can read the documentation here).  The documentation specifically warns against using the extension this say.  (There would be no problem if date_time were the same on all rows with the same campaign_id, but that is not the case.)
The following is the query that you actually want:
SELECT campaign_id, date_time
FROM or_mail om
WHERE not exists (select 1
                  from or_mail om2
                  where om2.campaign_id = om.campaign_id and
                        om2.date_time > date_time
                 );
What this says is:  Return results from all rows in or_mail with the property that there is no larger date_time with the same campaign_id.
    HAVING date_time = MAX(date_time);