when using maildir, do not create automatically create folders to match tag
authorgilles <gilles@openbsd.org>
Wed, 30 Apr 2014 09:17:29 +0000 (09:17 +0000)
committergilles <gilles@openbsd.org>
Wed, 30 Apr 2014 09:17:29 +0000 (09:17 +0000)
in email address (ie: gilles+tag => ~/Maildir/.tag), instead use the folder
if it already exists and deliver to the mail Maildir otherwise.

ok eric@ and chl@

usr.sbin/smtpd/delivery_maildir.c
usr.sbin/smtpd/lka_session.c
usr.sbin/smtpd/mda.c
usr.sbin/smtpd/smtpd-defines.h
usr.sbin/smtpd/smtpd.h

index 132d957..7dbf219 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: delivery_maildir.c,v 1.13 2014/04/19 17:31:35 gilles Exp $    */
+/*     $OpenBSD: delivery_maildir.c,v 1.14 2014/04/30 09:17:29 gilles Exp $    */
 
 /*
  * Copyright (c) 2011 Gilles Chehade <gilles@poolp.org>
@@ -42,28 +42,70 @@ extern char **environ;
 
 /* maildir backend */
 static void delivery_maildir_open(struct deliver *);
+static int maildir_tag(const struct mailaddr *, char *, size_t);
 
 struct delivery_backend delivery_backend_maildir = {
        1, delivery_maildir_open
 };
 
+static int
+mailaddr_tag(const struct mailaddr *maddr, char *dest, size_t len)
+{
+       char            *tag;
+       char            *sanitized;
+
+       if ((tag = strchr(maddr->user, TAG_CHAR))) {
+               tag++;
+               while (*tag == '.')
+                       tag++;
+       }
+       if (tag == NULL)
+               return 1;
+
+       if (strlcpy(dest, tag, len) >= len)
+               return 0;
+       for (sanitized = dest; *sanitized; sanitized++)
+               if (strchr(MAILADDR_ESCAPE, *sanitized))
+                       *sanitized = ':';
+       return 1;
+}
 
 static void
 delivery_maildir_open(struct deliver *deliver)
 {
-       char     tmp[SMTPD_MAXPATHLEN], new[SMTPD_MAXPATHLEN];
+       char     tmp[SMTPD_MAXPATHLEN], new[SMTPD_MAXPATHLEN], tag[SMTPD_MAXPATHLEN];
        int      ch, fd;
        FILE    *fp;
        char    *msg;
        int      n;
+       const char      *chd;
+       struct mailaddr maddr;
+       struct stat     sb;
 
 #define error(m)       { msg = m; goto err; }
 #define error2(m)      { msg = m; goto err2; }
 
        setproctitle("maildir delivery");
+
+       memset(&maddr, 0, sizeof maddr);
+       if (! text_to_mailaddr(&maddr, deliver->dest))
+               error("cannot parse destination address");
+
+       memset(tag, 0, sizeof tag);
+       if (! mailaddr_tag(&maddr, tag, sizeof tag))
+               error("cannot extract tag from destination address");
+
        if (mkdirs(deliver->to, 0700) < 0 && errno != EEXIST)
                error("cannot mkdir maildir");
-       if (chdir(deliver->to) < 0)
+       chd = deliver->to;
+
+       if (tag[0]) {
+               (void)snprintf(tmp, sizeof tmp, "%s/.%s", deliver->to, tag);
+               if (stat(tmp, &sb) != -1)
+                       chd = tmp;
+       }
+
+       if (chdir(chd) < 0)
                error("cannot cd to maildir");
        if (mkdir("cur", 0700) < 0 && errno != EEXIST)
                error("mkdir cur failed");
index 8b73868..d3ab19e 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: lka_session.c,v 1.66 2014/04/19 12:55:23 gilles Exp $ */
+/*     $OpenBSD: lka_session.c,v 1.67 2014/04/30 09:17:29 gilles Exp $ */
 
 /*
  * Copyright (c) 2011 Gilles Chehade <gilles@poolp.org>
@@ -40,8 +40,6 @@
 #include "smtpd.h"
 #include "log.h"
 
-#define TAG_CHAR       '+'     /* gilles+tag@ */
-
 #define        EXPAND_DEPTH    10
 
 #define        F_WAITING       0x01
@@ -70,7 +68,6 @@ static void lka_resume(struct lka_session *);
 static size_t lka_expand_format(char *, size_t, const struct envelope *,
     const struct userinfo *);
 static void mailaddr_to_username(const struct mailaddr *, char *, size_t);
-static int mailaddr_tag(const struct mailaddr *, char *, size_t);
 
 static int mod_lowercase(char *, size_t);
 static int mod_uppercase(char *, size_t);
@@ -85,8 +82,6 @@ struct modifiers {
        { "strip",      mod_strip },
        { "raw",        NULL },         /* special case, must stay last */
 };
-static const char      *unsafe = MAILADDR_ESCAPE;
-
 
 static int             init;
 static struct tree     sessions;
@@ -479,7 +474,6 @@ lka_submit(struct lka_session *lks, struct rule *rule, struct expandnode *xn)
        struct envelope         *ep;
        struct expandnode       *xn2;
        int                      r;
-       char                     tag[EXPAND_BUFFER];
 
        ep = xmemdup(&lks->envelope, sizeof *ep, "lka_submit");
        ep->expire = rule->r_qexpire;
@@ -548,24 +542,6 @@ lka_submit(struct lka_session *lks, struct rule *rule, struct expandnode *xn)
                        ep->agent.mda.method = rule->r_action;
                        (void)strlcpy(ep->agent.mda.buffer, rule->r_value.buffer,
                            sizeof ep->agent.mda.buffer);
-
-                       memset(tag, 0, sizeof tag);
-                       if (! mailaddr_tag(&ep->dest, tag, sizeof tag)) {
-                               lks->error = LKA_PERMFAIL;
-                               free(ep);
-                               return;
-                       }
-                       if (rule->r_action == A_MAILDIR && tag[0]) {
-                               (void)strlcat(ep->agent.mda.buffer, "/.",
-                                   sizeof(ep->agent.mda.buffer));
-                               if (strlcat(ep->agent.mda.buffer, tag,
-                                       sizeof(ep->agent.mda.buffer))
-                                   >= sizeof(ep->agent.mda.buffer)) {
-                                       lks->error = LKA_TEMPFAIL;
-                                       free(ep);
-                                       return;
-                               }
-                       }
                }
                else
                        fatalx("lka_deliver: bad node type");
@@ -712,7 +688,7 @@ lka_expand_token(char *dest, size_t len, const char *token,
        
        if (! raw && replace)
                for (i = 0; (size_t)i < strlen(tmp); ++i)
-                       if (strchr(unsafe, tmp[i]))
+                       if (strchr(MAILADDR_ESCAPE, tmp[i]))
                                tmp[i] = ':';
 
        /* expanded string is empty */
@@ -849,28 +825,6 @@ mailaddr_to_username(const struct mailaddr *maddr, char *dst, size_t len)
                *tag++ = '\0';
 }
 
-static int
-mailaddr_tag(const struct mailaddr *maddr, char *dest, size_t len)
-{
-       char            *tag;
-       char            *sanitized;
-
-       if ((tag = strchr(maddr->user, TAG_CHAR))) {
-               tag++;
-               while (*tag == '.')
-                       tag++;
-       }
-       if (tag == NULL)
-               return 1;
-
-       if (strlcpy(dest, tag, len) >= len)
-               return 0;
-       for (sanitized = dest; *sanitized; sanitized++)
-               if (strchr(unsafe, *sanitized))
-                       *sanitized = ':';
-       return 1;
-}
-
 static int 
 mod_lowercase(char *buf, size_t len)
 {
index 5dd4bdc..0eecd87 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: mda.c,v 1.105 2014/04/19 17:42:18 gilles Exp $        */
+/*     $OpenBSD: mda.c,v 1.106 2014/04/30 09:17:29 gilles Exp $        */
 
 /*
  * Copyright (c) 2008 Gilles Chehade <gilles@poolp.org>
@@ -290,6 +290,8 @@ mda_imsg(struct mproc *p, struct imsg *imsg)
                                deliver.userinfo = *userinfo;
                                (void)strlcpy(deliver.user, userinfo->username,
                                    sizeof(deliver.user));
+                               (void)strlcpy(deliver.dest, e->dest,
+                                   sizeof(deliver.dest));
                                if (strlcpy(deliver.to, e->buffer,
                                        sizeof(deliver.to))
                                    >= sizeof(deliver.to)) {
index a3fa675..9838f91 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: smtpd-defines.h,v 1.2 2013/12/05 10:06:32 eric Exp $  */
+/*     $OpenBSD: smtpd-defines.h,v 1.3 2014/04/30 09:17:29 gilles Exp $        */
 
 /*
  * Copyright (c) 2013 Gilles Chehade <gilles@poolp.org>
@@ -32,3 +32,5 @@
 #define PATH_CHROOT            "/var/empty"
 #define SMTPD_QUEUE_USER        "_smtpq"
 #define PATH_SPOOL             "/var/spool/smtpd"
+
+#define TAG_CHAR               '+'
index 8cba920..606f62a 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: smtpd.h,v 1.458 2014/04/30 08:23:43 reyk Exp $        */
+/*     $OpenBSD: smtpd.h,v 1.459 2014/04/30 09:17:29 gilles Exp $      */
 
 /*
  * Copyright (c) 2008 Gilles Chehade <gilles@poolp.org>
@@ -621,6 +621,7 @@ struct forward_req {
 struct deliver {
        char                    to[SMTPD_MAXPATHLEN];
        char                    from[SMTPD_MAXPATHLEN];
+       char                    dest[SMTPD_MAXLINESIZE];
        char                    user[SMTPD_MAXLOGNAME];
        short                   mode;