Clients which are NOT in an IDLE state still need to be
notified of message existence. Unlike the EXPUNGE response,
untagged EXISTS responses seem to be allowed at any time
according to RFC 3501.
We'll also perform uo2m_extend on the NOOP command, since
NOOP is the recommended command for message polling.
'* '.capa($self)."\r\n$tag OK Capability done\r\n";
}
'* '.capa($self)."\r\n$tag OK Capability done\r\n";
}
-sub cmd_noop ($$) { "$_[1] OK Noop done\r\n" }
-
# uo2m: UID Offset to MSN, this is an arrayref by default,
# but uo2m_hibernate can compact and deduplicate it
sub uo2m_ary_new ($) {
# uo2m: UID Offset to MSN, this is an arrayref by default,
# but uo2m_hibernate can compact and deduplicate it
sub uo2m_ary_new ($) {
# extend {uo2m} to account for new messages which arrived since
# {uo2m} was created.
# extend {uo2m} to account for new messages which arrived since
# {uo2m} was created.
+sub uo2m_extend ($$;$) {
my ($self, $new_uid_max) = @_;
defined(my $uo2m = $self->{uo2m}) or
return($self->{uo2m} = uo2m_ary_new($self));
my ($self, $new_uid_max) = @_;
defined(my $uo2m = $self->{uo2m}) or
return($self->{uo2m} = uo2m_ary_new($self));
++$beg;
my $uids = $self->{ibx}->over->uid_range($beg, $base + UID_SLICE);
my @tmp; # [$UID_OFFSET] => $MSN
++$beg;
my $uids = $self->{ibx}->over->uid_range($beg, $base + UID_SLICE);
my @tmp; # [$UID_OFFSET] => $MSN
+ my $write_method = $_[2] // 'msg_more';
if (ref($uo2m)) {
my $msn = $uo2m->[-1];
$tmp[$_ - $beg] = ++$msn for @$uids;
if (ref($uo2m)) {
my $msn = $uo2m->[-1];
$tmp[$_ - $beg] = ++$msn for @$uids;
+ $self->$write_method("* $msn EXISTS\r\n");
push @$uo2m, @tmp;
$uo2m;
} else {
my $msn = unpack('S', substr($uo2m, -2, 2));
$tmp[$_ - $beg] = ++$msn for @$uids;
push @$uo2m, @tmp;
$uo2m;
} else {
my $msn = unpack('S', substr($uo2m, -2, 2));
$tmp[$_ - $beg] = ++$msn for @$uids;
+ $self->$write_method("* $msn EXISTS\r\n");
$uo2m .= uo2m_pack(\@tmp);
my %dedupe = ($uo2m => undef);
$self->{uo2m} = (keys %dedupe)[0];
}
}
$uo2m .= uo2m_pack(\@tmp);
my %dedupe = ($uo2m => undef);
$self->{uo2m} = (keys %dedupe)[0];
}
}
+sub cmd_noop ($$) {
+ my ($self, $tag) = @_;
+ defined($self->{uid_base}) and
+ uo2m_extend($self, $self->{uid_base} + UID_SLICE);
+ \"$tag OK Noop done\r\n";
+}
+
# the flexible version which works on scalars and array refs.
# Must call uo2m_extend before this
sub uid2msn ($$) {
# the flexible version which works on scalars and array refs.
# Must call uo2m_extend before this
sub uid2msn ($$) {
# called by PublicInbox::InboxIdle
sub on_inbox_unlock {
my ($self, $ibx) = @_;
# called by PublicInbox::InboxIdle
sub on_inbox_unlock {
my ($self, $ibx) = @_;
- my $old = uo2m_last_uid($self);
my $uid_end = $self->{uid_base} + UID_SLICE;
my $uid_end = $self->{uid_base} + UID_SLICE;
- uo2m_extend($self, $uid_end);
+ uo2m_extend($self, $uid_end, 'write');
my $new = uo2m_last_uid($self);
my $new = uo2m_last_uid($self);
- if ($new > $old) {
- my $msn = uid2msn($self, $new);
- $self->write(\"* $msn EXISTS\r\n");
- } elsif ($new == $uid_end) { # max exceeded $uid_end
+ if ($new == $uid_end) { # max exceeded $uid_end
# continue idling w/o inotify
my $sock = $self->{sock} or return;
$ibx->unsubscribe_unlock(fileno($sock));
# continue idling w/o inotify
my $sock = $self->{sock} or return;
$ibx->unsubscribe_unlock(fileno($sock));
my ($self, $tag) = @_;
# IDLE seems allowed by dovecot w/o a mailbox selected *shrug*
my $ibx = $self->{ibx} or return "$tag BAD no mailbox selected\r\n";
my ($self, $tag) = @_;
# IDLE seems allowed by dovecot w/o a mailbox selected *shrug*
my $ibx = $self->{ibx} or return "$tag BAD no mailbox selected\r\n";
- $self->{-idle_tag} = $tag;
- my $max = $ibx->over->max;
my $uid_end = $self->{uid_base} + UID_SLICE;
my $uid_end = $self->{uid_base} + UID_SLICE;
+ uo2m_extend($self, $uid_end);
my $sock = $self->{sock} or return;
my $fd = fileno($sock);
my $sock = $self->{sock} or return;
my $fd = fileno($sock);
+ $self->{-idle_tag} = $tag;
# only do inotify on most recent slice
# only do inotify on most recent slice
- if ($max < $uid_end) {
- uo2m_extend($self, $uid_end);
+ if ($ibx->over->max < $uid_end) {
$ibx->subscribe_unlock($fd, $self);
$self->{imapd}->idler_start;
}
$ibx->subscribe_unlock($fd, $self);
$self->{imapd}->idler_start;
}