[opendmarc-users] Bug in opendmarc-expire script
Todd Lyons
tlyons at ivenue.com
Thu Aug 9 22:19:20 PDT 2012
Murray, I started running opendmarc about 2 days ago, so it should not
expire request data b/c there shouldn't have been anything that age.
CentOS58[root at lunar ~]# opendmarc-expire --verbose --dbhost=ivwm52
--dbname=dmarc --dbpasswd=DMARCopendmarc --dbuser=dmarc
opendmarc-expire: started at Thu Aug 9 21:40:10 2012
opendmarc-expire: connected to database
opendmarc-expire: expiring messages older than 180 day(s)
opendmarc-expire: no rows deleted
opendmarc-expire: expiring signatures on expired messages (id < 1)
opendmarc-expire: no rows deleted
opendmarc-expire: expiring request data older than 180 days
opendmarc-expire: 371 row(s) deleted
opendmarc-expire: terminating at Thu Aug 9 21:40:10 2012
I ran this expire script and it did the above, now my system has no
domains that it wants to send out information for. All my data is in
a mysql database, so maybe this issue is specific to mysql. Basically
I'm doing in crontab:
@hourly opendkim-import < $statsfile
@hourly opendkim-reports
# @daily opendkim-expire
But the expire action is deleting the data from the requests table, so
it has no reports to send. I ran the query from the script and I
figured it out. This is what it's doing:
mysql> SELECT * FROM requests WHERE lastsent <=
DATE_SUB(CURRENT_TIMESTAMP(), INTERVAL 180 DAY);
+-----+--------+--------+-------+------+--------+---------+-----+---------------------+---------------------+
| id | domain | repuri | adkim | aspf | policy | spolicy | pct |
firstseen | lastsent |
+-----+--------+--------+-------+------+--------+---------+-----+---------------------+---------------------+
| 372 | 489 | | 0 | 0 | 0 | 0 | 0 |
2012-08-10 05:00:02 | 0000-00-00 00:00:00 |
| 373 | 490 | | 0 | 0 | 0 | 0 | 0 |
2012-08-10 05:00:02 | 0000-00-00 00:00:00 |
| 374 | 233 | | 0 | 0 | 0 | 0 | 0 |
2012-08-10 05:00:02 | 0000-00-00 00:00:00 |
| 375 | 12 | | 0 | 0 | 0 | 0 | 0 |
2012-08-10 05:00:02 | 0000-00-00 00:00:00 |
| 376 | 201 | | 114 | 114 | 114 | 0 | 100 |
2012-08-10 05:00:02 | 0000-00-00 00:00:00 |
| 377 | 133 | | 0 | 0 | 0 | 0 | 0 |
2012-08-10 05:00:02 | 0000-00-00 00:00:00 |
| 378 | 492 | | 0 | 0 | 0 | 0 | 0 |
2012-08-10 05:00:02 | 0000-00-00 00:00:00 |
| 379 | 485 | | 0 | 0 | 0 | 0 | 0 |
2012-08-10 05:00:02 | 0000-00-00 00:00:00 |
| 380 | 493 | | 0 | 0 | 0 | 0 | 0 |
2012-08-10 05:00:02 | 0000-00-00 00:00:00 |
+-----+--------+--------+-------+------+--------+---------+-----+---------------------+---------------------+
9 rows in set (0.00 sec)
Since lastsent starts at zero, it always matches it. Changing the
query to exclude values of 0 fixes it:
mysql> SELECT * FROM requests WHERE lastsent <=
DATE_SUB(CURRENT_TIMESTAMP(), INTERVAL 180 DAY) AND lastsent > 0;
Empty set (0.00 sec)
Second, looking at indexes, an EXPLAIN shows that it's doing a full table scan:
mysql> explain SELECT * FROM requests WHERE lastsent <=
DATE_SUB(CURRENT_TIMESTAMP(), INTERVAL 180 DAY) AND lastsent > 0 \G
*************************** 1. row ***************************
id: 1
select_type: SIMPLE
table: requests
type: ALL
possible_keys: NULL
key: NULL
key_len: NULL
ref: NULL
rows: 9
Extra: Using where
1 row in set (0.00 sec)
There should be an index on the field that is being used in the WHERE:
ALTER TABLE `requests` ADD KEY `lastsent_idx` (`lastsent`);
Now it uses that index instead of a full table scan:
mysql> explain SELECT * FROM requests WHERE lastsent <=
DATE_SUB(CURRENT_TIMESTAMP(), INTERVAL 180 DAY) AND lastsent > 0 \G
*************************** 1. row ***************************
id: 1
select_type: SIMPLE
table: requests
type: range
possible_keys: lastsent_idx
key: lastsent_idx
key_len: 4
ref: NULL
rows: 1
Extra: Using where
1 row in set (0.00 sec)
...Todd
--
The total budget at all receivers for solving senders' problems is $0.
If you want them to accept your mail and manage it the way you want,
send it the way the spec says to. --John Levine
More information about the opendmarc-users
mailing list