Download raw body.
What I had left.
On Sat, Aug 24, 2024 at 08:41:30AM +0200, Christian Schulte wrote:
> > +
> > + for (p = info; p != NULL; p = p->ai_next)
> > + fqdn = p->ai_canonname;
>
> I am not sure this is correct. The manpage of getaddrinfo has this:
>
> If the AI_CANONNAME bit is set, a successful call to getaddrinfo() will
> return a NUL-terminated string containing the canonical name of the
> specified host name in the ai_canonname element of the *first* addrinfo
> structure returned.
>
> I would take that "first" seriously. Maybe someone familiar with the asr
> code implementing getaddrinfo can comment on that. Also this is lacking
> NULL checks as well.
Below I pasted a little program to test the function (even easier that
patching mail(1)), there I added a NULL check in the loop and a break.
I'm still not sure if that's really necessary but it doesn't hurt.
> Re-reading <https://datatracker.ietf.org/doc/html/rfc2822#section-3.6.4>
> I think there is no value in just blindly adding a message id header.
> You cannot tell if the user intentionally did not add that header, so
> this could be rated a regression for some users.
>
> For example:
>
> for i in `cat /etc/lots_of_recipients`;do echo "Hell of a message." |
> mail $i;done
>
> If mail would silently add a different message-id header to all of those
> messages, it would certainly behave incorrectly, as that is the same
> instance of a message sent to multiple recipients from e.g. a script.
>
As I see it, the fact that the body of your message is the same doesn't
change that what you're doing in your example with your loop is sending
multiple messages, mail(1) doesn't have to know about this.
I don't remember if GNU mailutils version is able to read headers
included in the same file you feed with the body (perhaps Mutt?) In
this case you should be able to use a loop like this:
for i in `cat /etc/lots_of_recipients`; do
mail $i < body_including_headers.txt
done
But, so far, with the OpenBSD version of mail you can't do that. You
cannot pass other headers than From, To, Cc, Bcc and Subject, and only
in the ways explained in the man page.
/*
* Little program to test the generate Message-ID function (portable
* version, or rather the one that also works on Linux.)
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <err.h>
#include <ctype.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netdb.h>
char* genmsgid(void);
int
main()
{
printf("Message-ID: %s\n", genmsgid());
return 0;
}
/* Generate Message-ID */
char*
genmsgid(void)
{
size_t n = 0;
char c;
static char r[24];
struct addrinfo *info = NULL;
struct addrinfo *p = NULL;
struct addrinfo hints;
char *fqdn = NULL;
static char hostname[NI_MAXHOST];
static char buf[sizeof(r) + sizeof(hostname) + 4];
int error = 0;
while (n < sizeof(r) - 1) {
c = arc4random_uniform(173);
if (isalnum(c) && snprintf(&r[n++], 2, "%c", c) != 1)
errx(1, "genmsgid: snprintf");
}
if (gethostname(hostname, sizeof(hostname)))
errx(1, "genmsgid: gethostname");
memset(&hints, 0, sizeof hints);
hints.ai_family = AF_UNSPEC;
hints.ai_socktype = SOCK_STREAM;
hints.ai_flags = AI_CANONNAME;
if (getaddrinfo(hostname, NULL, &hints, &info) != 0)
errx(1, "genmsgid: getaddrinfo");
for (p = info; p != NULL; p = p->ai_next) {
if (p->ai_canonname == NULL)
errx(1, "genmsgid: ai_canonname");
fqdn = p->ai_canonname;
break;
}
error = snprintf(buf, sizeof(buf), "<%s@%s>", r, fqdn);
if (error < 0 || error >= sizeof(buf))
errx(1, "genmsgid: snprintf");
freeaddrinfo(info);
return(buf);
}
--
Walter