diff --git a/docs/config.c b/docs/config.c index 77d9232a8..c03b9bc93 100644 --- a/docs/config.c +++ b/docs/config.c @@ -1636,7 +1636,9 @@ /* ** .pp ** When \fIset\fP, NeoMutt will skip the host name part of $$hostname variable -** when adding the domain part to addresses. +** when adding the domain part to addresses. This variable does not +** affect the generation of Message-IDs, and it will not lead to the +** cut-off of first-level domains. */ { "hidden_tags", DT_SLIST, "unread,draft,flagged,passed,replied,attachment,signed,encrypted" }, @@ -1753,7 +1755,8 @@ ** .pp ** Specifies the fully-qualified hostname of the system NeoMutt is running on ** containing the host's name and the DNS domain it belongs to. It is used -** as the domain part (after "@") for local email addresses. +** as the domain part (after "@") for local email addresses as well as +** Message-Id headers. ** .pp ** If not specified in a config file, then NeoMutt will try to determine the hostname itself. ** .pp diff --git a/docs/manual.xml.head b/docs/manual.xml.head index 0a42a6846..09e4d5266 100644 --- a/docs/manual.xml.head +++ b/docs/manual.xml.head @@ -19309,8 +19309,18 @@ set use_threads=threads sort=last-date sort_aux=date Message-Id: headers - Since 2023-02-18 NeoMutt generates random Message-Id: headers, which - do not leak any information beyond their randomness. + Message-Id: headers contain a local part that is to be created in + a unique fashion. In order to do so, NeoMutt will leak + some information to the outside world when sending messages: the + generation of this header includes a step counter which is increased + (and rotated) with every message sent. Other parts include the date, + time, PID of NeoMutt, and $hostname. + In a longer running NeoMutt session, others can + make assumptions about your mailing habits + depending on the number of messages sent. If this is not desired, the + header can be manually provided using + $edit_headers (though not + recommended). diff --git a/send/sendlib.c b/send/sendlib.c index 849e50661..68ab3adab 100644 --- a/send/sendlib.c +++ b/send/sendlib.c @@ -726,42 +726,25 @@ const char *mutt_fqdn(bool may_hide_host, const struct ConfigSubset *sub) } /** - * gen_msgid - Generate a random Message ID + * gen_msgid - Generate a unique Message ID * @retval ptr Message ID * - * The length of the message id is chosen such that it is maximal and fits in - * the recommended 78 character line length for the headers Message-ID:, - * References:, and In-Reply-To:, this leads to 62 available characters - * (excluding `@` and `>`). Since we choose from 32 letters, we have 32^62 - * = 2^310 different message ids. - * - * Examples: - * ``` - * Message-ID: <12345678901111111111222222222233333333334444444444@123456789011> - * In-Reply-To: <12345678901111111111222222222233333333334444444444@123456789011> - * References: <12345678901111111111222222222233333333334444444444@123456789011> - * ``` - * - * The distribution of the characters to left-of-@ and right-of-@ was arbitrary. - * The choice was made to put more into the left-id and shorten the right-id to - * slightly mimic a common length domain name. - * * @note The caller should free the string */ -static char *gen_msgid(void) +static char *gen_msgid(struct ConfigSubset *sub) { - const int ID_LEFT_LEN = 50; - const int ID_RIGHT_LEN = 12; - char rnd_id_left[ID_LEFT_LEN + 1]; - char rnd_id_right[ID_RIGHT_LEN + 1]; char buf[128] = { 0 }; + char rndid[MUTT_RANDTAG_LEN + 1]; - mutt_rand_base32(rnd_id_left, sizeof(rnd_id_left) - 1); - mutt_rand_base32(rnd_id_right, sizeof(rnd_id_right) - 1); - rnd_id_left[ID_LEFT_LEN] = 0; - rnd_id_right[ID_RIGHT_LEN] = 0; + mutt_rand_base32(rndid, sizeof(rndid) - 1); + rndid[MUTT_RANDTAG_LEN] = 0; + const char *fqdn = mutt_fqdn(false, sub); + if (!fqdn) + fqdn = NONULL(ShortHostname); - snprintf(buf, sizeof(buf), "<%s@%s>", rnd_id_left, rnd_id_right); + struct tm tm = mutt_date_gmtime(mutt_date_now()); + snprintf(buf, sizeof(buf), "<%d%02d%02d%02d%02d%02d.%s@%s>", tm.tm_year + 1900, + tm.tm_mon + 1, tm.tm_mday, tm.tm_hour, tm.tm_min, tm.tm_sec, rndid, fqdn); return mutt_str_dup(buf); } @@ -799,7 +782,7 @@ void mutt_prepare_envelope(struct Envelope *env, bool final, struct ConfigSubset mutt_set_followup_to(env, sub); if (!env->message_id) - env->message_id = gen_msgid(); + env->message_id = gen_msgid(sub); } /* Take care of 8-bit => 7-bit conversion. */ @@ -872,7 +855,7 @@ static int bounce_message(FILE *fp, struct Mailbox *m, struct Email *e, fprintf(fp_tmp, "Resent-Date: %s\n", buf_string(date)); buf_pool_release(&date); - char *msgid_str = gen_msgid(); + char *msgid_str = gen_msgid(sub); fprintf(fp_tmp, "Resent-Message-ID: %s\n", msgid_str); FREE(&msgid_str); mutt_addrlist_write_file(to, fp_tmp, "Resent-To");