Re: Partial restore of seen state

Andy Bennett <[email protected]> Thu, 14 Aug 2025 16:05:43 +0100
Newsgroups gmane.mail.imap.cyrus
Message-ID <[email protected]>
Hi,

> Next I'll work on merging the .SEEN files produced by my 
> mbexamine-seenstate script. I'm currently thinking that I'll 
> then write a script that logs in via IMAP and tweaks the seen 
> state on the individual messages.
> I'd welcome thoughts from people with more experience at this 
> kind of thing tho'.

Attached is the script I used to apply my seen state from my backups to my 
mailbox.

I anyone else finds it useful they'll need to provide your own hostname, 
username and password in the script and your seen state on stdin.


I'm pretty happy that I've solved my problem now but if anyone else wants a 
hand then let me know.



Best wishes,
@ndy

-- 
[email protected]
http://www.ashurst.eu.org/
0x7EBA75FF
------------------------------------------
Cyrus: Info
Permalink: https://cyrus.topicbox.com/groups/info/Tb45482804665ba7a-M99e4f9cfdb42f44adc4d95e5
Delivery options: https://cyrus.topicbox.com/groups/info/subscription
apply-seen-state.pl (application/x-perl, 1.5 KB)
#!/usr/bin/perl

#
# Apply SEEN state to messages via IMAP.
#
# ./apply-seen-state.pl < state.SEEN
#
# Supply lines containing "<UID>: UNSEEN" or "<UID>: FLAG_SEEN" on stdin.
# For example:
#
# -----
# 00000005: FLAG_SEEN
# 00001670: UNSEEN
# -----
#
# Andy Bennett <[email protected]>, 2025/08/12 17:50.
#

use Net::IMAP::Client;  # https://metacpan.org/pod/Net::IMAP::Client


my $imap = Net::IMAP::Client->new(
	server => '',
	user   => '',
	pass   => '',
	ssl    => 1,
	ssl_verify_peer => 1,
	port   => 993
) or die "Could not connect to IMAP server";

$imap->login or die('Login failed: ' . $imap->last_error);

# my @folders = $imap->folders;

$imap->select('INBOX');

# Read batches from stdin.
# Add UIDs to an array for seen or unseen.
# Send arrays to server with the appropriate call.

my @seen_uids   = ();
my @unseen_uids = ();
my $line_no     = 0;

sub flush_seen_uids {
	$imap->add_flags(\@seen_uids, "\\Seen");
	@seen_uids = ();
}

sub flush_unseen_uids {
	$imap->del_flags(\@unseen_uids, "\\Seen");
	@unseen_uids = ();
}

while ($line = <STDIN>) {
	chomp $line;
	$line_no += 1;

	if ($line =~ /^([0-9]+): ((FLAG_SEEN)|(UNSEEN))$/) {

		$uid   = $1;
		$state = $2;

		if ($state eq "FLAG_SEEN") {
			push @seen_uids, int($uid);

		} elsif ($state eq "UNSEEN") {
			push @unseen_uids, int($uid);
		}

		if (@seen_uids >= 10) {
			flush_seen_uids;
		}
		if (@unseen_uids >= 10) {
			flush_unseen_uids;
		}

	} else {
		die("Syntax error on $line_no! Got: <$line>\n");
	}
}

if (@seen_uids > 0) {
	flush_seen_uids;
}
if (@unseen_uids > 0) {
	flush_unseen_uids;
}