user/dev discussion of public-inbox itself
 help / color / mirror / code / Atom feed
Search results ordered by [date|relevance]  view[summary|nested|Atom feed]
thread overview below | download mbox.gz: |
* [PATCH 8/8] lei import: store IMAP user+auth in mail_sync folder URI
  2021-05-21 10:28  7% [PATCH 0/8] lei: export-kw, IMAP import incompatibility Eric Wong
@ 2021-05-21 10:28  5% ` Eric Wong
  0 siblings, 0 replies; 2+ results
From: Eric Wong @ 2021-05-21 10:28 UTC (permalink / raw)
  To: meta

Just having UIDVALIDITY in the URI isn't enough, since a single
lei user may have multiple IMAP logins on the same server.

This leads to compatibility problems and forces a reimport for
the few users already using this lei functionality, but it's not
stable nor released, yet.
---
 lib/PublicInbox/NetReader.pm | 42 ++++++++++++++++++++++--------------
 t/lei-import-imap.t          |  9 +++++---
 2 files changed, 32 insertions(+), 19 deletions(-)

diff --git a/lib/PublicInbox/NetReader.pm b/lib/PublicInbox/NetReader.pm
index fd0d1682..a532b218 100644
--- a/lib/PublicInbox/NetReader.pm
+++ b/lib/PublicInbox/NetReader.pm
@@ -58,12 +58,10 @@ sub auth_anon_cb { '' }; # for Mail::IMAPClient::Authcallback
 
 # mic_for may prompt the user and store auth info, prepares mic_get
 sub mic_for ($$$$) { # mic = Mail::IMAPClient
-	my ($self, $url, $mic_args, $lei) = @_;
-	require PublicInbox::URIimap;
-	my $uri = PublicInbox::URIimap->new($url);
+	my ($self, $uri, $mic_args, $lei) = @_;
 	require PublicInbox::GitCredential;
 	my $cred = bless {
-		url => $url,
+		url => "$uri",
 		protocol => $uri->scheme,
 		host => $uri->host,
 		username => $uri->user,
@@ -83,13 +81,13 @@ sub mic_for ($$$$) { # mic = Mail::IMAPClient
 	};
 	require PublicInbox::IMAPClient;
 	my $mic = mic_new($self, $mic_arg, $sec, $uri) or
-			die "E: <$url> new: $@\n";
+			die "E: <$uri> new: $@\n";
 	# default to using STARTTLS if it's available, but allow
 	# it to be disabled since I usually connect to localhost
 	if (!$mic_arg->{Ssl} && !defined($mic_arg->{Starttls}) &&
 			$mic->has_capability('STARTTLS') &&
 			$mic->can('starttls')) {
-		$mic->starttls or die "E: <$url> STARTTLS: $@\n";
+		$mic->starttls or die "E: <$uri> STARTTLS: $@\n";
 	}
 
 	# do we even need credentials?
@@ -111,8 +109,13 @@ sub mic_for ($$$$) { # mic = Mail::IMAPClient
 	if ($mic->login && $mic->IsAuthenticated) {
 		# success! keep IMAPClient->new arg in case we get disconnected
 		$self->{mic_arg}->{$sec} = $mic_arg;
+		if ($cred) {
+			$uri->user($cred->{username}) if !defined($uri->user);
+		} elsif ($mic_arg->{Authmechanism} eq 'ANONYMOUS') {
+			$uri->auth('ANONYMOUS') if !defined($uri->auth);
+		}
 	} else {
-		$err = "E: <$url> LOGIN: $@\n";
+		$err = "E: <$uri> LOGIN: $@\n";
 		if ($cred && defined($cred->{password})) {
 			$err =~ s/\Q$cred->{password}\E/*******/g;
 		}
@@ -304,15 +307,16 @@ sub imap_common_init ($;$) {
 	# make sure we can connect and cache the credentials in memory
 	$self->{mic_arg} = {}; # schema://authority => IMAPClient->new args
 	my $mics = {}; # schema://authority => IMAPClient obj
-	for my $uri (@{$self->{imap_order}}) {
-		my $sec = uri_section($uri);
+	for my $orig_uri (@{$self->{imap_order}}) {
+		my $sec = uri_section($orig_uri);
+		my $uri = PublicInbox::URIimap->new("$sec/");
 		my $mic = $mics->{$sec} //=
-				mic_for($self, "$sec/", $mic_args, $lei) //
+				mic_for($self, $uri, $mic_args, $lei) //
 				die "Unable to continue\n";
 		next unless $self->isa('PublicInbox::NetWriter');
-		my $dst = $uri->mailbox // next;
+		my $dst = $orig_uri->mailbox // next;
 		next if $mic->exists($dst); # already exists
-		$mic->create($dst) or die "CREATE $dst failed <$uri>: $@";
+		$mic->create($dst) or die "CREATE $dst failed <$orig_uri>: $@";
 	}
 	$mics;
 }
@@ -419,12 +423,18 @@ sub run_commit_cb ($) {
 	$cb->(@args);
 }
 
-sub _itrk_last ($$;$) {
-	my ($self, $uri, $r_uidval) = @_;
+sub itrk_last ($$;$$) {
+	my ($self, $uri, $r_uidval, $mic) = @_;
 	return (undef, undef, $r_uidval) unless $self->{incremental};
 	my ($itrk, $l_uid, $l_uidval);
 	if (defined(my $lms = $self->{-lms_ro})) { # LeiMailSync or 0
 		$uri->uidvalidity($r_uidval) if defined $r_uidval;
+		if ($mic) {
+			my $auth = $mic->Authmechanism // '';
+			$uri->auth($auth) if $auth eq 'ANONYMOUS';
+			my $user = $mic->User;
+			$uri->user($user) if defined($user);
+		}
 		my $x;
 		$l_uid = ($lms && ($x = $lms->location_stats($$uri))) ?
 				$x->{'uid.max'} : undef;
@@ -459,7 +469,7 @@ E: $orig_uri UIDVALIDITY mismatch (got $r_uidval)
 EOF
 
 	my $uri = $orig_uri->clone;
-	my ($itrk, $l_uid, $l_uidval) = _itrk_last($self, $uri, $r_uidval);
+	my ($itrk, $l_uid, $l_uidval) = itrk_last($self, $uri, $r_uidval, $mic);
 	return <<EOF if $l_uidval != $r_uidval;
 E: $uri UIDVALIDITY mismatch
 E: local=$l_uidval != remote=$r_uidval
@@ -612,7 +622,7 @@ sub _nntp_fetch_all ($$$) {
 	# IMAPTracker is also used for tracking NNTP, UID == article number
 	# LIST.ACTIVE can get the equivalent of UIDVALIDITY, but that's
 	# expensive.  So we assume newsgroups don't change:
-	my ($itrk, $l_art) = _itrk_last($self, $uri);
+	my ($itrk, $l_art) = itrk_last($self, $uri);
 
 	# allow users to specify articles to refetch
 	# cf. https://tools.ietf.org/id/draft-gilman-news-url-01.txt
diff --git a/t/lei-import-imap.t b/t/lei-import-imap.t
index fd15ef4f..d424ebb1 100644
--- a/t/lei-import-imap.t
+++ b/t/lei-import-imap.t
@@ -23,9 +23,11 @@ test_lei({ tmpdir => $tmpdir }, sub {
 
 	lei_ok('import', $url);
 	lei_ok 'ls-mail-sync';
-	like($lei_out, qr!\A\Q$url\E;UIDVALIDITY=\d+\n\z!, 'ls-mail-sync');
+	like($lei_out, qr!\Aimap://;AUTH=ANONYMOUS\@\Q$host_port\E
+			/t\.v2\.0;UIDVALIDITY=\d+\n\z!x, 'ls-mail-sync');
 	chomp(my $u = $lei_out);
 	lei_ok('import', $u, \'UIDVALIDITY match in URL');
+	$url = $u;
 	$u =~ s/;UIDVALIDITY=(\d+)\s*/;UIDVALIDITY=9$1/s;
 	ok(!lei('import', $u), 'UIDVALIDITY mismatch in URL rejected');
 
@@ -33,7 +35,7 @@ test_lei({ tmpdir => $tmpdir }, sub {
 	my $inspect = json_utf8->decode($lei_out);
 	my @k = keys %$inspect;
 	is(scalar(@k), 1, 'one URL resolved');
-	like($k[0], qr!\A\Q$url\E;UIDVALIDITY=\d+\z!, 'inspect URL matches');
+	is($k[0], $url, 'inspect URL matches');
 	my $stats = $inspect->{$k[0]};
 	is_deeply([ sort keys %$stats ],
 		[ qw(uid.count uid.max uid.min) ], 'keys match');
@@ -55,7 +57,8 @@ test_lei({ tmpdir => $tmpdir }, sub {
 	my $x = json_utf8->decode($lei_out);
 	is(ref($x->{'lei/store'}), 'ARRAY', 'lei/store in inspect');
 	is(ref($x->{'mail-sync'}), 'HASH', 'sync in inspect');
-	is(ref($x->{'mail-sync'}->{$k[0]}), 'ARRAY', 'UID arrays in inspect');
+	is(ref($x->{'mail-sync'}->{$k[0]}), 'ARRAY', 'UID arrays in inspect')
+		or diag explain($x);
 
 	my $psgi_attach = 'cfa3622cbeffc9bd6b0fc66c4d60d420ba74f60d';
 	lei_ok('blob', $psgi_attach);

^ permalink raw reply related	[relevance 5%]

* [PATCH 0/8] lei: export-kw, IMAP import incompatibility
@ 2021-05-21 10:28  7% Eric Wong
  2021-05-21 10:28  5% ` [PATCH 8/8] lei import: store IMAP user+auth in mail_sync folder URI Eric Wong
  0 siblings, 1 reply; 2+ results
From: Eric Wong @ 2021-05-21 10:28 UTC (permalink / raw)
  To: meta

"lei export-kw" is a new command.  I'm not sure exactly how
it'll be used but it's probably more of a plumbing command,
for now.  My brain hurts thinking about synchronization
and merge/conflict resolution when it comes to propagating
keywords assignments/clearing.

(I frequently mark messages as Unread in my MUA so I know to
reread them in the future, and I suspect it's a common thing).

mail_sync.sqlite3 now tracks AUTH=ANONYMOUS or username in the
folder name to account for lei(Unix) users having multiple IMAP
accounts on the same host with the same folders+UIDVALIDITY.

"lei import imap(s)://" users will waste a bit of bandwidth
resyncing as a result.

Eric Wong (8):
  treewide: favor open(..., '+<&=', $fd)
  lei: drop EOFpipe in favor of PktOp
  lei tag: support tagging index-only messages
  lei_input: fix canonicalization of Maildirs for sync
  lei index: support command-line options
  lei export-kw: new command to export keywords to Maildirs
  uri_imap: support uid/auth/user as full accessors
  lei import: store IMAP user+auth in mail_sync folder URI

 MANIFEST                       |   2 +
 examples/unsubscribe.milter    |   3 +-
 lib/PublicInbox/DS.pm          |   3 +-
 lib/PublicInbox/Daemon.pm      |   2 +-
 lib/PublicInbox/LEI.pm         |  18 +++-
 lib/PublicInbox/LeiExportKw.pm | 180 +++++++++++++++++++++++++++++++++
 lib/PublicInbox/LeiInput.pm    |   3 +-
 lib/PublicInbox/LeiMailSync.pm |  10 ++
 lib/PublicInbox/LeiOverview.pm |   2 +-
 lib/PublicInbox/LeiSearch.pm   |  22 +++-
 lib/PublicInbox/LeiTag.pm      |  10 +-
 lib/PublicInbox/LeiToMail.pm   |  12 ++-
 lib/PublicInbox/MdirReader.pm  |  14 +++
 lib/PublicInbox/NetReader.pm   |  42 +++++---
 lib/PublicInbox/Sigfd.pm       |   3 +-
 lib/PublicInbox/URIimap.pm     |  82 +++++++++++----
 t/epoll.t                      |   7 +-
 t/lei-export-kw.t              |  35 +++++++
 t/lei-import-imap.t            |   9 +-
 t/lei-index.t                  |  12 ++-
 t/mdir_reader.t                |   5 +
 t/uri_imap.t                   |  60 ++++++++---
 22 files changed, 461 insertions(+), 75 deletions(-)
 create mode 100644 lib/PublicInbox/LeiExportKw.pm
 create mode 100644 t/lei-export-kw.t


^ permalink raw reply	[relevance 7%]

Results 1-2 of 2 | reverse | options above
-- pct% links below jump to the message on this page, permalinks otherwise --
2021-05-21 10:28  7% [PATCH 0/8] lei: export-kw, IMAP import incompatibility Eric Wong
2021-05-21 10:28  5% ` [PATCH 8/8] lei import: store IMAP user+auth in mail_sync folder URI Eric Wong

Code repositories for project(s) associated with this public inbox

	https://80x24.org/public-inbox.git

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).