On 2015-06-11 23:23, Joerg Jung wrote: > Hi, > > please find below a diff which enhances deliver to LMTP. > > Gilles suggested to bring this diff to misc@ to gain a wider audience > and hopefully receive some comments from actual LMTP users. > > tl;dr > "deliver to lmtp" delivers to (system) users only, making it hard to > be used in common virtual users setups (with single system user). > Therefore, I provide a diff which adds a parameter to > specify/expands RCPT TO within LMTP. > > This was described earlier already [1], but no solution. > > Let me explain the rationale/background of the diff below a bit: One of > my production servers runs Sendmail/Dovecot and I would like to migrate > it to OpenSMTPD/Dovecot. The server uses virtual users in a common > scenario: with all mail addresses mapped to a single system user/uid/gid > (called vmail in my case). Dovecot uses a (static) userdb to map the > IMAP maildirs and addresses. [...]
In my case, I got around this by using a shared SQL db, and have dovecot work with virtual mailboxes too: https://hugo.barrera.io/journal/2015/02/15/opensmtpd-dovecot-shared-sql-db/ (note that there are improvements to what is described here that I still need to document). A big upside is having users for SMTP and IMAP in a single place. The only downside this that mail has a header of Delivered-To: hugo_barrera.io instead of Delivered-To: [email protected] > [...] Now I have three options to bring incoming > mails from OpenSMTPD to Dovecot: > > 1. deliver to maildir > Unfortunately, not an option in my case, because I heavily use Sieve > and Quotas on the Dovecot server. Both require updates/processing on > delivery. > > 2. deliver to mda "dovecot-lda -a ${rcpt} ..." > Would work fine, and is what I have done before with Sendmail as > well. But requires me to fiddle with dovecot-lda options, poor > performance, and expansions and user permissions, as it needs > adjusting for the "single system user all virtual" setup mentioned > above... thus a bit annoying to setup. > I agree completely that this option is "fragile" and inefficient. > 3. deliver to lmtp "/var/dovecot/lmtp" > IMHO, the most easy and straight forward option, also preferred > nowadays, due to better performance [2]. Not useable in my > scenarios, as deliver_lmtp.c always uses the (system) user in > RCPT TO. > > So the diff below addresses this and makes it possible to > specify/expand the RCPT TO. > > Items for Discussion: > - In a first version of this diff and as suggested in [1], I added a > new keyword RCPT, e.g. ... deliver to lmtp "..." rcpt "${rcpt}", I > decided to leave it away as it simplifies things and does not require > to mess with rule_to_text() and A_LMTP I'd personally prefer a table for this, so I can move this out to SQL (with some fancy query) for maximum flexibility. I'm pretty sure I would need it for my current setup. > - In a second version I added an additional variable to store and > separate actual lmtp host:port/socket and expanded recipient... > (similar to r_delivery_user) but this required a lot of more changes > in several files to copy things around, and even an additional enum > expand_type might be required: EXPAND_LMTP, or something. So for the > sake of simplicity I decided against this approach. > - Another approach to solve this problem, as suggested in Dovecot > Wiki [3], is to override the RCPT TO with setting > X-Original-Recipient Header (different approach, different diff). > I do not like this idea of injecting additional header in LMTP > session, thus I went with the approach below. > On this last idea, I'd also like to add that an SMTP fiddling with custom headers is pretty ugly and should be avoided if possible. > Please: comments, suggestions, other approaches, right/wrong direction, > rants, flames,... ? > I like what your view on the problem and your idea on how to solve it. I'm not familiar enough with the code (and my C level is not up to this project), so I can't comment on the diffs themselves. > Thanks, > Regards, > Joerg > > [1] https://www.mail-archive.com/[email protected]/msg00531.html > [2] http://wiki2.dovecot.org/LDA > [3] http://wiki2.dovecot.org/LMTP > > > ---------------------------------------------------------------- > > > smtpd/delivery_lmtp.c | 10 ++++------ > smtpd/parse.y | 22 ++++++++++++++++++++++ > smtpd/smtpd.conf.5 | 13 ++++++++++++- > 3 files changed, 38 insertions(+), 7 deletions(-) > > diff --git a/smtpd/delivery_lmtp.c b/smtpd/delivery_lmtp.c > index 5080c46..6c55994 100644 > --- a/smtpd/delivery_lmtp.c > +++ b/smtpd/delivery_lmtp.c > @@ -137,16 +137,14 @@ unix_socket(char *path) { > static void > delivery_lmtp_open(struct deliver *deliver) > { > - char *buffer; > - char *lbuf; > + char *buffer, *lbuf, *rcpt = deliver->to; > char lhloname[255]; > int s; > - FILE *fp; > + FILE *fp = NULL; > enum lmtp_state state = LMTP_BANNER; > size_t len; > > - fp = NULL; > - > + strsep(&rcpt, " "); > if (deliver->to[0] == '/') > s = unix_socket(deliver->to); > else > @@ -183,7 +181,7 @@ delivery_lmtp_open(struct deliver *deliver) > case LMTP_MAIL_FROM: > if (buffer[0] != '2') > errx(1, "MAIL FROM rejected: %s\n", buffer); > - fprintf(fp, "RCPT TO:<%s>\r\n", deliver->user); > + fprintf(fp, "RCPT TO:<%s>\r\n", rcpt ? rcpt : deliver->user); > state = LMTP_RCPT_TO; > break; > > diff --git a/smtpd/parse.y b/smtpd/parse.y > index b73ed7f..8523dd4 100644 > --- a/smtpd/parse.y > +++ b/smtpd/parse.y > @@ -1161,6 +1161,28 @@ deliver_action : DELIVER TO MAILDIR { > fatal("invalid lmtp destination"); > free($4); > } > + | DELIVER TO LMTP STRING STRING deliver_as { > + rule->r_action = A_LMTP; > + if (strchr($4, ':') || $4[0] == '/') { > + if (strlcpy(rule->r_value.buffer, $4, > + sizeof(rule->r_value.buffer)) > + >= sizeof(rule->r_value.buffer)) > + fatal("lmtp destination too long"); > + } else > + fatal("invalid lmtp destination"); > + if (strchr($5, '%')) { > + if (strlcat(rule->r_value.buffer, " ", > + sizeof(rule->r_value.buffer)) > + >= sizeof(rule->r_value.buffer) || > + strlcat(rule->r_value.buffer, $5, > + sizeof(rule->r_value.buffer)) > + >= sizeof(rule->r_value.buffer)) > + fatal("lmtp recipient too long"); > + } else > + fatal("invalid lmtp recipient"); > + free($4); > + free($5); > + } > | DELIVER TO MDA STRING deliver_as { > rule->r_action = A_MDA; > if (strlcpy(rule->r_value.buffer, $4, > diff --git a/smtpd/smtpd.conf.5 b/smtpd/smtpd.conf.5 > index 72d3811..eb76ad6 100644 > --- a/smtpd/smtpd.conf.5 > +++ b/smtpd/smtpd.conf.5 > @@ -287,13 +287,22 @@ accept for domain opensmtpd.org forward-only > .Pp > Finally, the method of delivery is specified: > .Bl -tag -width Ds > -.It Ic deliver to lmtp Op Ar host : Ns Ar port | socket > +.It Xo > +.Ic deliver to lmtp > +.Op Ar host : Ns Ar port | socket > +.Op Ar rcpt > +.Xc > Mail is delivered to > .Ar host : Ns Ar port , > or to the > .Ux > .Ar socket > over LMTP. > +Optionally, > +.Ar rcpt > +might specify a recipient. > +The latter parameter may use conversion specifiers that are expanded before > use > +.Pq see Sx FORMAT SPECIFIERS . > .It Ic deliver to maildir Ar path > Mail is added to a maildir. > Its location, > @@ -911,7 +920,9 @@ descriptions. > .Ss FORMAT SPECIFIERS > Some configuration directives support expansion of their parameters at > runtime. > Such directives (for example > +.Ic deliver to lmtp , > .Ic deliver to maildir , > +and > .Ic deliver to mda ) > may use format specifiers which will be expanded before delivery or > relaying. -- Hugo Osvaldo Barrera A: Because we read from top to bottom, left to right. Q: Why should I start my reply below the quoted text?
signature.asc
Description: PGP signature
