about summary refs log tree commit diff
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--imbox.112
-rw-r--r--imbox.c27
2 files changed, 32 insertions, 7 deletions
diff --git a/imbox.1 b/imbox.1
index 22e2df3..bd66a80 100644
--- a/imbox.1
+++ b/imbox.1
@@ -1,4 +1,4 @@
-.Dd February 16, 2021
+.Dd February 24, 2021
 .Dt IMBOX 1
 .Os
 .
@@ -8,7 +8,7 @@
 .
 .Sh SYNOPSIS
 .Nm
-.Op Fl ivw
+.Op Fl Uisvw
 .Op Fl C Ar cc
 .Op Fl F Ar from
 .Op Fl M Ar mailbox
@@ -25,7 +25,7 @@ The
 utility exports messages from an IMAP mailbox
 to the mboxrd format on standard output.
 Messages matching the criteria set by
-.Fl CFST
+.Fl CFSTU
 are exported.
 The default criterion is
 .Fl S Cm '[PATCH' .
@@ -68,6 +68,9 @@ Export messages with matching
 .Cm To
 headers.
 .
+.It Fl U
+Export only unseen messages.
+.
 .It Fl h Ar host
 Connect to IMAP on
 .Ar host .
@@ -98,6 +101,9 @@ the default port is
 Otherwise,
 the port is determined in the same fashion as the host.
 .
+.It Fl s
+Mark exported messages as seen.
+.
 .It Fl v
 Log IMAP protocol to standard error.
 .
diff --git a/imbox.c b/imbox.c
index b385366..70b1270 100644
--- a/imbox.c
+++ b/imbox.c
@@ -68,29 +68,35 @@ static void mboxrd(char *header, char *body) {
 }
 
 int main(int argc, char *argv[]) {
+	int rppFlags = 0;
 	const char *host = NULL;
 	const char *port = "imaps";
 	const char *mailbox = "INBOX";
+
 	const char *subject = "[PATCH";
 	const char *from = NULL;
 	const char *to = NULL;
 	const char *cc = NULL;
-	const char *move = NULL;
+	bool unseen = false;
 	bool idle = false;
-	int rppFlags = 0;
+
+	const char *move = NULL;
+	bool seen = false;
 
 	int opt;
-	while (0 < (opt = getopt(argc, argv, "C:F:M:S:T:h:im:p:vw"))) {
+	while (0 < (opt = getopt(argc, argv, "C:F:M:S:T:Uh:im:p:svw"))) {
 		switch (opt) {
 			break; case 'C': cc = optarg;
 			break; case 'F': from = optarg;
 			break; case 'M': move = optarg;
 			break; case 'S': subject = optarg;
 			break; case 'T': to = optarg;
+			break; case 'U': unseen = true;
 			break; case 'h': host = optarg;
 			break; case 'i': idle = true;
 			break; case 'm': mailbox = optarg;
 			break; case 'p': port = optarg;
+			break; case 's': seen = true;
 			break; case 'v': imapVerbose = true;
 			break; case 'w': rppFlags |= RPP_STDIN;
 			break; default:  return EX_USAGE;
@@ -125,7 +131,7 @@ int main(int argc, char *argv[]) {
 	enum Atom examine = atom("examine");
 	fprintf(
 		imap.w, "%s %s \"%s\"\r\n",
-		Atoms[examine], (move ? "SELECT" : "EXAMINE"), mailbox
+		Atoms[examine], (move || seen ? "SELECT" : "EXAMINE"), mailbox
 	);
 	for (; resp = respOk(imapResp(&imap)), resp.tag != examine; respFree(resp));
 	respFree(resp);
@@ -138,6 +144,7 @@ search:;
 	if (from) fprintf(imap.w, " FROM \"%s\"", from);
 	if (to) fprintf(imap.w, " TO \"%s\"", to);
 	if (cc) fprintf(imap.w, " CC \"%s\"", cc);
+	if (unseen) fprintf(imap.w, " UNSEEN");
 	fprintf(imap.w, "\r\n");
 	for (; resp = respOk(imapResp(&imap)), resp.tag != search; respFree(resp)) {
 		if (resp.resp != AtomSearch) continue;
@@ -185,6 +192,18 @@ search:;
 	}
 	respFree(resp);
 
+	if (seen) {
+		enum Atom sto = atom("store");
+		fprintf(imap.w, "%s STORE ", Atoms[sto]);
+		for (size_t i = 0; i < nums.len; ++i) {
+			uint32_t num = dataCheck(nums.ptr[i], Number).number;
+			fprintf(imap.w, "%s%" PRIu32, (i ? "," : ""), num);
+		}
+		fprintf(imap.w, " +FLAGS.SILENT (\\Seen)\r\n");
+		for (; resp = respOk(imapResp(&imap)), resp.tag != sto; respFree(resp));
+		respFree(resp);
+	}
+
 	if (move) {
 		enum Atom mov = atom("move");
 		fprintf(imap.w, "%s MOVE ", Atoms[mov]);