From a13464f3046d1203b8c0fd04536cfe233a46a2e0 Mon Sep 17 00:00:00 2001 From: Daniel Fomin Date: Mon, 6 Nov 2023 21:22:23 +0100 Subject: [PATCH 1/4] Keep Mail unseen --- imap-common.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/imap-common.c b/imap-common.c index a086992..2f6cdd5 100644 --- a/imap-common.c +++ b/imap-common.c @@ -956,7 +956,7 @@ imap_state_next(struct account *a, struct fetch_ctx *fctx) * GMail is broken and does not set the \Seen flag after mail * is fetched, so set it explicitly for kept mail. */ - if (imap_putln(a, "%u UID STORE %u +FLAGS.SILENT (\\Seen)", + if (imap_putln(a, "%u UID STORE %u +FLAGS.SILENT ()", ++data->tag, ARRAY_FIRST(&data->kept)) != 0) return (FETCH_ERROR); ARRAY_REMOVE(&data->kept, 0); @@ -1001,7 +1001,7 @@ imap_state_next(struct account *a, struct fetch_ctx *fctx) /* Fetch the next mail. */ if (imap_putln(a, "%u " - "UID FETCH %u BODY[]",++data->tag, ARRAY_FIRST(&data->wanted)) != 0) + "UID FETCH %u BODY.PEEK[]",++data->tag, ARRAY_FIRST(&data->wanted)) != 0) return (FETCH_ERROR); fctx->state = imap_state_body; return (FETCH_BLOCK); From 62cdd3cbfb0351db69ad267d970da5e65c194087 Mon Sep 17 00:00:00 2001 From: Daniel Fomin Date: Tue, 7 Nov 2023 22:29:59 +0100 Subject: [PATCH 2/4] Adding account flag 'unseen' --- fdm.h | 1 + imap-common.c | 27 ++++++++++++++++++++------- lex.c | 1 + parse.y | 15 +++++++++++++-- 4 files changed, 35 insertions(+), 9 deletions(-) diff --git a/fdm.h b/fdm.h index 0d63e34..02f1310 100644 --- a/fdm.h +++ b/fdm.h @@ -507,6 +507,7 @@ struct account { int disabled; int keep; + int remain_unseen; struct fetch *fetch; void *data; diff --git a/imap-common.c b/imap-common.c index 2f6cdd5..52d2a18 100644 --- a/imap-common.c +++ b/imap-common.c @@ -956,9 +956,16 @@ imap_state_next(struct account *a, struct fetch_ctx *fctx) * GMail is broken and does not set the \Seen flag after mail * is fetched, so set it explicitly for kept mail. */ - if (imap_putln(a, "%u UID STORE %u +FLAGS.SILENT ()", - ++data->tag, ARRAY_FIRST(&data->kept)) != 0) - return (FETCH_ERROR); + if (a->remain_unseen) { + if (imap_putln(a, "%u UID STORE %u +FLAGS.SILENT ()", + ++data->tag, ARRAY_FIRST(&data->kept)) != 0) + return (FETCH_ERROR); + else { + if (imap_putln(a, "%u UID STORE %u +FLAGS.SILENT (\\Seen)", + ++data->tag, ARRAY_FIRST(&data->kept)) != 0) + return (FETCH_ERROR); + + } ARRAY_REMOVE(&data->kept, 0); fctx->state = imap_state_commit; return (FETCH_BLOCK); @@ -999,10 +1006,16 @@ imap_state_next(struct account *a, struct fetch_ctx *fctx) return (FETCH_BLOCK); } - /* Fetch the next mail. */ - if (imap_putln(a, "%u " - "UID FETCH %u BODY.PEEK[]",++data->tag, ARRAY_FIRST(&data->wanted)) != 0) - return (FETCH_ERROR); + if (a->remain_unseen) { + /* Fetch the next mail. */ + if (imap_putln(a, "%u " + "UID FETCH %u BODY.PEEK[]",++data->tag, ARRAY_FIRST(&data->wanted)) != 0) + return (FETCH_ERROR); + } else { + if (imap_putln(a, "%u " + "UID FETCH %u BODY[]",++data->tag, ARRAY_FIRST(&data->wanted)) != 0) + return (FETCH_ERROR); + } fctx->state = imap_state_body; return (FETCH_BLOCK); } diff --git a/lex.c b/lex.c index 87d4202..ca95e83 100644 --- a/lex.c +++ b/lex.c @@ -197,6 +197,7 @@ static const struct token tokens[] = { { "total-size", TOKTOTALSIZE }, { "unmatched", TOKUNMATCHED }, { "unmatched-mail", TOKIMPLACT }, + { "unseen", TOKUNSEEN }, { "user", TOKUSER }, { "users", TOKUSERS }, { "value", TOKVALUE }, diff --git a/parse.y b/parse.y index 6fab6c2..730afbc 100644 --- a/parse.y +++ b/parse.y @@ -176,6 +176,7 @@ yyerror(const char *fmt, ...) %token TOKINSECURE %token TOKINVALID %token TOKKEEP +%token TOKUNSEEN %token TOKKEY %token TOKKILOBYTES %token TOKLMTP @@ -309,7 +310,7 @@ yyerror(const char *fmt, ...) %type expritem %type exprop %type fetchtype -%type cont not disabled keep execpipe writeappend compress verify +%type cont not disabled keep unseen execpipe writeappend compress verify %type apop poptype imaptype nntptype nocrammd5 noplain nologin uidl %type starttls insecure oauthbearer xoauth2 %type localgid @@ -1046,6 +1047,15 @@ keep: TOKKEEP $$ = 0; } +unseen: TOKUNSEEN + { + $$ = 1; + } + | /* empty */ + { + $$ = 0; + } + disabled: TOKDISABLED { $$ = 1; @@ -2458,7 +2468,7 @@ fetchtype: poptype server userpassnetrc poponly apop verify uidl starttls data->server.ai = NULL; } -account: TOKACCOUNT replstrv disabled users fetchtype keep +account: TOKACCOUNT replstrv disabled users fetchtype keep unseen { struct account *a; char *su, desc[DESCBUFSIZE]; @@ -2473,6 +2483,7 @@ account: TOKACCOUNT replstrv disabled users fetchtype keep a = xcalloc(1, sizeof *a); strlcpy(a->name, $2, sizeof a->name); a->keep = $6; + a->remain_unseen = $7; a->disabled = $3; a->users = $4; a->fetch = $5.fetch; From 7ef295c595fe392df82ca09ddb9f14d20c044749 Mon Sep 17 00:00:00 2001 From: Daniel Fomin Date: Wed, 8 Nov 2023 22:46:30 +0100 Subject: [PATCH 3/4] Add 'unseen' flag documentation --- MANUAL | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/MANUAL b/MANUAL index 03ab6b7..5ed4768 100644 --- a/MANUAL +++ b/MANUAL @@ -470,7 +470,7 @@ fdm fetches mail from a set of 'accounts', defined using the 'account' keyword. Each account has a name, a type, a number of account specific parameters and a couple of optional flags. The general form is: - account [] [disabled] [] [keep] + account [] [disabled] [] [keep] [unseen] The item is a string by which the account is referred in filtering rules, log output and for the '-a' and '-x' command line options. @@ -486,6 +486,10 @@ The optional 'keep' keyword instructs fdm to keep all mail from this account (not delete it from the server) regardless of the result of the filtering rules. +If the optional keyword 'unseen' is used, fdm will not mark all delivered +mails as seen. This can be useful for archiving purposes, so that the mail +status on the server is not changed, but backups can be created by fdm. + The item may be one of: 'pop3', 'pop3s', 'imap', 'imaps', 'stdin', 'maildir' or 'maildirs'. @@ -805,7 +809,8 @@ match account "news" { With POP3 and IMAP, fdm can be set up to fetch only new or old mail. For POP3 this is achieved by recording the current state of the server in a cache file, which is updated as each mail is fetched. For IMAP it makes use of the 'seen' -server flag which is updated by the server after each mail is fetched. +server flag which is updated by the server after each mail is fetched. +The 'unseen' flag is not compatible with this functionality. These options are specified as in the following examples. For POP3: @@ -1603,7 +1608,7 @@ This is because GMail is broken, see: In addition, GMail IMAP doesn't set the \Seen flag when mail is fetched with the UID FETCH BODY[] command (RFC3501 says that the "\Seen flag is implicitly set"). fdm works around this bug by setting the flag explicitly when mail is -kept. +kept (unless the 'unseen' flag is used). %%% Why doesn't fdm run as a daemon? From cbbcfe4a27b76526adf2573dbe9b31c5580ce99d Mon Sep 17 00:00:00 2001 From: Daniel Fomin Date: Wed, 8 Nov 2023 23:05:49 +0100 Subject: [PATCH 4/4] Fixing syntax error --- imap-common.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/imap-common.c b/imap-common.c index 52d2a18..5b677c9 100644 --- a/imap-common.c +++ b/imap-common.c @@ -960,11 +960,10 @@ imap_state_next(struct account *a, struct fetch_ctx *fctx) if (imap_putln(a, "%u UID STORE %u +FLAGS.SILENT ()", ++data->tag, ARRAY_FIRST(&data->kept)) != 0) return (FETCH_ERROR); - else { + } else { if (imap_putln(a, "%u UID STORE %u +FLAGS.SILENT (\\Seen)", ++data->tag, ARRAY_FIRST(&data->kept)) != 0) return (FETCH_ERROR); - } ARRAY_REMOVE(&data->kept, 0); fctx->state = imap_state_commit;