diff options
author | Gilles Chehade <gilles@cvs.openbsd.org> | 2018-04-28 10:33:42 +0000 |
---|---|---|
committer | Gilles Chehade <gilles@cvs.openbsd.org> | 2018-04-28 10:33:42 +0000 |
commit | 3ca74bad86b3d380e109922e0819add3e13bd849 (patch) | |
tree | b084fdabdd1f4e45d8c3bf6b1bd144eb5e6e3fcb /usr.sbin/smtpd | |
parent | eeb76458825f7dcec612be4876c7639e74042680 (diff) |
handle subaddresses
ok eric@
Diffstat (limited to 'usr.sbin/smtpd')
-rw-r--r-- | usr.sbin/smtpd/mail.maildir.8 | 14 | ||||
-rw-r--r-- | usr.sbin/smtpd/mail.maildir.c | 69 |
2 files changed, 68 insertions, 15 deletions
diff --git a/usr.sbin/smtpd/mail.maildir.8 b/usr.sbin/smtpd/mail.maildir.8 index 45f60f53ccd..629fb5ad5e4 100644 --- a/usr.sbin/smtpd/mail.maildir.8 +++ b/usr.sbin/smtpd/mail.maildir.8 @@ -1,4 +1,4 @@ -.\" $OpenBSD: mail.maildir.8,v 1.1 2017/02/14 16:48:30 gilles Exp $ +.\" $OpenBSD: mail.maildir.8,v 1.2 2018/04/28 10:33:41 gilles Exp $ .\" .\" Copyright (c) 2017 Gilles Chehade <gilles@poolp.org> .\" @@ -14,7 +14,7 @@ .\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF .\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. .\" -.Dd $Mdocdate: February 14 2017 $ +.Dd $Mdocdate: April 28 2018 $ .Dt MAIL.MAILDIR 8 .Os .Sh NAME @@ -22,7 +22,9 @@ .Nd store mail in a maildir .Sh SYNOPSIS .Nm mail.maildir -.Op Fl d Ar maildir +.Op Fl d Ar delimiter +.Op Fl p Ar pathname +.Op Fl r Ar recipient .Sh DESCRIPTION .Nm reads the standard input up to an end-of-file and adds it to the @@ -30,8 +32,12 @@ provided mail directory. .Pp The options are as follows: .Bl -tag -width Ds -.It Fl d Ar maildir +.It Fl d Ar delimiter +Specify the delimiter to use for sub-addressing. +.It Fl p Ar pathname Specify the path to user mail directory. +.It Fl r Ar recipient +Specify the recipient email address. .El .Sh EXIT STATUS .Ex -std mail.maildir diff --git a/usr.sbin/smtpd/mail.maildir.c b/usr.sbin/smtpd/mail.maildir.c index a209764d039..96bb8fa3719 100644 --- a/usr.sbin/smtpd/mail.maildir.c +++ b/usr.sbin/smtpd/mail.maildir.c @@ -28,23 +28,35 @@ #include <string.h> #include <unistd.h> -static void maildir_engine(const char *); +#define SUBADDRESSING_DELIMITER "+" +#define MAILADDR_ESCAPE "!#$%&'*/?^`{|}~" + +static int maildir_subdir(const char *, const char *, char *, size_t); +static void maildir_engine(const char *, const char *, const char *); static int mkdirs_component(const char *, mode_t); static int mkdirs(const char *, mode_t); int main(int argc, char *argv[]) { - int ch; - char *dirname = NULL; + int ch; + char *pathname = NULL; + char *recipient = NULL; + char *delim = SUBADDRESSING_DELIMITER; if (! geteuid()) errx(1, "mail.maildir: may not be executed as root"); - while ((ch = getopt(argc, argv, "d:")) != -1) { + while ((ch = getopt(argc, argv, "d:p:r:")) != -1) { switch (ch) { case 'd': - dirname = optarg; + delim = optarg; + break; + case 'p': + pathname = optarg; + break; + case 'r': + recipient = optarg; break; default: break; @@ -53,25 +65,60 @@ main(int argc, char *argv[]) argc -= optind; argv += optind; - if (dirname == NULL) { - exit(1); - } + if (pathname == NULL) + errx(1, "no maildir pathname specified"); + + maildir_engine(pathname, recipient, delim); - maildir_engine(dirname); - return (0); } +static int +maildir_subdir(const char *recipient, const char *delim, char *dest, size_t len) +{ + char *tag; + char *sanitized; + + if ((tag = strchr(recipient, *delim))) { + 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 -maildir_engine(const char *dirname) +maildir_engine(const char *dirname, const char *recipient, const char *delim) { char tmp[PATH_MAX]; char new[PATH_MAX]; + char subdir[PATH_MAX]; int fd; FILE *fp; char *line = NULL; size_t linesize = 0; ssize_t linelen; + struct stat sb; + + if (recipient) { + memset(subdir, 0, sizeof subdir); + if (! maildir_subdir(recipient, delim, subdir, sizeof(subdir))) + err(1, NULL); + + if (subdir[0]) { + (void)snprintf(tmp, sizeof tmp, "%s/.%s", dirname, subdir); + if (stat(tmp, &sb) != -1) + dirname = tmp; + } + } if (mkdirs(dirname, 0700) < 0 && errno != EEXIST) err(1, NULL); |