summaryrefslogtreecommitdiff
path: root/usr.sbin/smtpd
diff options
context:
space:
mode:
authorGilles Chehade <gilles@cvs.openbsd.org>2018-04-28 10:33:42 +0000
committerGilles Chehade <gilles@cvs.openbsd.org>2018-04-28 10:33:42 +0000
commit3ca74bad86b3d380e109922e0819add3e13bd849 (patch)
treeb084fdabdd1f4e45d8c3bf6b1bd144eb5e6e3fcb /usr.sbin/smtpd
parenteeb76458825f7dcec612be4876c7639e74042680 (diff)
handle subaddresses
ok eric@
Diffstat (limited to 'usr.sbin/smtpd')
-rw-r--r--usr.sbin/smtpd/mail.maildir.814
-rw-r--r--usr.sbin/smtpd/mail.maildir.c69
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);