Okay, I have written something that may be of help. Its not finished as don't have time today. It gets all accounts and if the zimbraMaxPasswordAge > 0 (never expire) then it will query when the password on the account was last changed, add the max password age, and show when the password will need to be changed

Code:
#!/usr/bin/perl
use Time::Local;
open(ZCSGAA, "zmprov gaa |");
while ($account = <ZCSGAA>) {
chomp($account);
$zmprov = "zmprov ga " . $account . " zimbraPasswordModifiedTime zimbraPasswordMaxAge";
open(ZCSGA, "$zmprov |");
while (<ZCSGA>) {
s/#.*//; next if /^(\s)*$/;
chomp($_);
if (!defined($zpmt)) { ($zpmt) = $_ =~ /zimbraPasswordModifiedTime: (.*)Z/g; }
if (!defined($zpma)) { ($zpma) = $_ =~ /zimbraPasswordMaxAge: (.*)/g; }
}
close(ZCSGA);
if ($zpma gt 0) {
($year, $mon, $day, $hour, $min, $sec) = $zpmt =~ /(\d{4})(\d{2})(\d{2})(\d{2})(\d{2})(\d{2}).*/;
$epoch = timelocal($sec,$min,$hour,$day,$mon,$year);
$changepass = $epoch + ($zpma * 24 * 60 * 60);
($sec,$min,$hour,$day,$mon,$year) = localtime($changepass); $year = 1900 + $year; $mon++;
printf "$account password will need to change on %02d/%02d/%04d %02d:%02d:%02d\n", $day, $mon, $year, $hour, $min, $sec;
}
}
close(ZCSGAA);