Gilles Chehade <[email protected]> writes:

> On Fri, Jan 06, 2017 at 08:20:05AM +0100, Antoine Jacoutot wrote:
>> On Fri, Jan 06, 2017 at 02:35:46PM +1100, Damian McGuckin wrote:
>> >
>> > Does the FAQ need a section of tweaks for email clients?
>> >
>> > I tried to use 'alpine' on OpenBSD 6.0 with the standard SMTPD therein.
>> >
>> > A pkg_add'ed 'alpine' just sits there trying and trying until you go into
>> >
>> >    Main-Menu -> Setup -> Config
>> >
>> > and change the SMTP server to 'localhost'. I have never had to do that
>> > in my life with 'alpine' on any other system that has used sendmail or
>> > postfix.
>> >
>> > How many other email clients need tweaking for OpenSMTPD?
>>
>> It's probably due to the default sendmail flags used by alpine :
>> smtp_msa_flags="-bs -odb -oem"
>>
>
> ok, it is indeed due to these flags, OP should open a bug report on our
> tracker and one of us will add compat to the enqueuer so it doesn't
> choke on these.
>
>
>> I'll have a look at the port today, there's a configure option to change the
>> defaults.
>>
>
> that would make it work out of the box on openbsd but still, we should
> have the compat getopt() imo

Turns out it's a bit more than compat getopt(), we do accept and ignore
those flags however.

With 'sendmail -bs' MUA expects STMP dialog over stdin/stdout, which
means, MUA will wait for the greeting on stdout while smtpctl waits for
text on stdin and they are now deadlocked.

The following diff bridges the enqueuer fd and stdout/stdin by writing
output from fd to stdout and commands from stdin to fd.

I can send mails with apline now without any config modifications and
also enqueue via plain 'sendmail -bs'.

Tests and comments welcome.

diff --git a/smtpd/enqueue.c b/smtpd/enqueue.c
index 3fd7fbd6..d0748cfd 100644
--- a/smtpd/enqueue.c
+++ b/smtpd/enqueue.c
@@ -31,6 +31,7 @@
 #include <grp.h>
 #include <imsg.h>
 #include <inttypes.h>
+#include <poll.h>
 #include <pwd.h>
 #include <stdarg.h>
 #include <stdio.h>
@@ -46,6 +47,7 @@ extern struct imsgbuf *ibuf;

 void usage(void);
 static void build_from(char *, struct passwd *);
+static void handle_bs(void);
 static int parse_message(FILE *, int, int, FILE *);
 static void parse_addr(char *, size_t, int);
 static void parse_addr_terminal(int);
@@ -171,6 +173,7 @@ enqueue(int argc, char *argv[], FILE *ofp)
        FILE                    *fp = NULL, *fout;
        size_t                   sz = 0, envid_sz = 0;
        ssize_t                  len;
+       int                      bs_flag = 0;
        int                      fd;
        char                     sfn[] = "/tmp/smtpd.XXXXXXXXXX";
        char                    *line;
@@ -216,10 +219,14 @@ enqueue(int argc, char *argv[], FILE *ofp)
                case 'V':
                        msg.dsn_envid = optarg;
                        break;
+               case 'b':
+                       if (strcmp(optarg, "s") != 0)
+                               return (EX_SOFTWARE);
+                       bs_flag = 1;
+                       break;
                /* all remaining: ignored, sendmail compat */
                case 'A':
                case 'B':
-               case 'b':
                case 'E':
                case 'e':
                case 'i':
@@ -240,6 +247,9 @@ enqueue(int argc, char *argv[], FILE *ofp)
        argc -= optind;
        argv += optind;

+       if (bs_flag)
+               handle_bs();
+
        if (getmailname(host, sizeof(host)) == -1)
                errx(EX_NOHOST, "getmailname");
        if (no_getlogin) {
@@ -458,6 +468,57 @@ fail:
        exit(EX_SOFTWARE);
 }

+/*
+ * sendmail -bs requires STMP dialog over stdin/stdout.
+ * Bridge stdin/stdout with enqueuer fd.
+ */
+static void
+handle_bs(void)
+{
+       char            buf[LINE_MAX];
+       struct pollfd   pfd[2];
+       nfds_t          nfds;
+       size_t          i;
+       ssize_t         nr;
+       int             fd, nready, outfd;
+
+       if (!srv_connected())
+               errx(EX_UNAVAILABLE, "Server offline");
+
+       if ((fd = open_connection()) == -1)
+               errx(EX_UNAVAILABLE, "server too busy");
+
+       pfd[0].fd = STDIN_FILENO;
+       pfd[1].fd = fd;
+       pfd[0].events = pfd[1].events = POLLIN;
+       nfds = 2;
+       while ((nready = poll(pfd, nfds, INFTIM))) {
+               if (nready == -1)
+                       err(1, "poll");
+
+               for (i = 0; i < nfds; i++) {
+                       if (pfd[i].revents & (POLLERR|POLLNVAL))
+                               errx(1, "bsd fd %d", pfd[i].fd);
+
+                       if ((pfd[i].revents & (POLLIN|POLLHUP))) {
+                               nr = read(pfd[i].fd, buf, sizeof buf);
+                               if (nr == -1)
+                                       err(1, "read");
+                               else if (nr == 0)
+                                       goto done;
+
+                               outfd = pfd[i].fd == STDIN_FILENO ?
+                                   fd : STDOUT_FILENO;
+                               if (write(outfd, buf, nr) == -1)
+                                       err(1, "write");
+                       }
+               }
+       }
+
+ done:
+       exit(EX_OK);
+}
+
 static int
 get_responses(FILE *fin, int n)
 {

-- 
You received this mail because you are subscribed to [email protected]
To unsubscribe, send a mail to: [email protected]

Reply via email to