Index | Thread | Search

From:
Kirill A. Korinsky <kirill@korins.ky>
Subject:
Re: calendar(1): introduce RECIPIENT_EMAIL
To:
Vitaliy Makkoveev <mvs@openbsd.org>
Cc:
tech@openbsd.org
Date:
Mon, 03 Feb 2025 15:27:57 +0100

Download raw body.

Thread
On Mon, 03 Feb 2025 11:53:53 +0100,
Vitaliy Makkoveev <mvs@openbsd.org> 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=<local_name>
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