From: Kirill A. Korinsky Subject: Re: calendar(1): introduce RECIPIENT_EMAIL To: Vitaliy Makkoveev Cc: tech@openbsd.org Date: Mon, 03 Feb 2025 15:27:57 +0100 On Mon, 03 Feb 2025 11:53:53 +0100, Vitaliy Makkoveev wrote: > > On Sat, Feb 01, 2025 at 11:18:40PM +0100, Kirill A. Korinsky wrote: > > tech@ > > > > Here a patch which introduced a special variable RECIPIENT_EMAIL in > > calendar(1). > > > > By default it sends daily emails to a user and it can be forwarded via > > ~/.forward to desire destination. But here no way to send calendar's email > > to other email. > > > > My patch introduced a variable RECIPIENT_EMAIL which can be used to override > > the destination email in calendar file. > > > > Feedback? Ok? > > > > Do we need extra checks to be sure `recipient' contains valid email > address? > Good point, thnaks. Right now mallformed email leads to a error: sendmail: command failed: 501 5.1.3 Recipient address syntax error which won't be delivered to the user. Thus, implementing here a custom email validation smeels wrong as well. The clean solution that I see is implemeting -bv at sendmail. So, here quite trivial diff for sendmail wrapper, which is followed by updated version of the diff for calendar. Index: usr.sbin/smtpd/enqueue.c =================================================================== RCS file: /home/cvs/src/usr.sbin/smtpd/enqueue.c,v diff -u -p -r1.126 enqueue.c --- usr.sbin/smtpd/enqueue.c 21 Nov 2024 13:26:25 -0000 1.126 +++ usr.sbin/smtpd/enqueue.c 3 Feb 2025 12:41:22 -0000 @@ -172,7 +172,7 @@ qp_encoded_write(FILE *fp, char *buf) int enqueue(int argc, char *argv[], FILE *ofp) { - int i, ch, tflag = 0; + int i, ch, tflag = 0, validate_rcpt = 0; char *fake_from = NULL, *buf = NULL; struct passwd *pw; FILE *fp = NULL, *fout; @@ -220,10 +220,13 @@ enqueue(int argc, char *argv[], FILE *of case 'V': msg.dsn_envid = optarg; break; + case 'b': + if (optarg[0] == 'v') + validate_rcpt = 1; + break; /* all remaining: ignored, sendmail compat */ case 'A': case 'B': - case 'b': case 'E': case 'e': case 'i:' @@ -340,6 +343,9 @@ enqueue(int argc, char *argv[], FILE *of if (!get_responses(fout, 1)) goto fail; } + + if (validate_rcpt) + exit(EX_OK); if (!send_line(fout, verbose, "DATA\r\n")) goto fail; Index: usr.bin/calendar/calendar.1 =================================================================== RCS file: /home/cvs/src/usr.bin/calendar/calendar.1,v diff -u -p -r1.44 calendar.1 --- usr.bin/calendar/calendar.1 29 Jan 2019 22:28:30 -0000 1.44 +++ usr.bin/calendar/calendar.1 1 Feb 2025 22:03:35 -0000 @@ -107,6 +107,10 @@ Use .Dq CALENDAR= to return to the default (Gregorian). .Pp +The +.Dq RECIPIENT_EMAIL +variable can be used to specify recipient of daily mails. +.Pp To enforce special date calculation mode for Cyrillic calendars you should specify .Dq LANG= Index: usr.bin/calendar/io.c =================================================================== RCS file: /home/cvs/src/usr.bin/calendar/io.c,v diff -u -p -r1.51 io.c --- usr.bin/calendar/io.c 7 Dec 2021 14:00:33 -0000 1.51 +++ usr.bin/calendar/io.c 3 Feb 2025 13:45:51 -0000 @@ -51,6 +51,9 @@ #include "calendar.h" +char *recipient = NULL; + + struct iovec header[] = { { "From: ", 6 }, { NULL, 0 }, @@ -66,11 +69,12 @@ struct iovec header[] = { void cal(void) { - int ch, l, i, bodun = 0, bodun_maybe = 0, var, printing; + int ch, l, i, bodun = 0, bodun_maybe = 0, var, printing, status; struct event *events, *cur_evt, *ev1, *tmp; char buf[2048 + 1], *prefix = NULL, *p; struct match *m; FILE *fp; + pid_t pid = -1; events = NULL; cur_evt = NULL; @@ -123,6 +127,29 @@ cal(void) if ((prefix = strdup(buf + 6)) == NULL) err(1, NULL); continue; + } else if (strncmp(buf, "RECIPIENT_EMAIL=", 16) == 0) { + free(recipient); + if ((recipient = strdup(buf + 16)) == NULL) + err(1, NULL); + + switch ((pid = vfork())) { + case -1: + err(1, "vfork"); + case 0: + close(STDIN_FILENO); + close(STDOUT_FILENO); + close(STDERR_FILENO); + execl(_PATH_SENDMAIL, "sendmail", + "-bv", recipient, (char *)NULL); + warn(_PATH_SENDMAIL); + _exit(1); + } + if (waitpid(pid, &status, 0) == -1 || + !WIFEXITED(status) || + WEXITSTATUS(status)) + err(1, "Mallformed recipient email: %s", + recipient); + continue; } /* User defined names for special events */ if ((p = strchr(buf, '='))) { @@ -408,7 +435,7 @@ closecal(FILE *fp) } (void)close(pdes[1]); execl(_PATH_SENDMAIL, "sendmail", "-i", "-t", "-F", - "\"Reminder Service\"", (char *)NULL); + "\"Reminder Service\"", recipient, (char *)NULL); warn(_PATH_SENDMAIL); _exit(1); } -- wbr, Kirill