diff --git a/docsrc/imap/reference/manpages/systemcommands/smmapd.rst b/docsrc/imap/reference/manpages/systemcommands/smmapd.rst index 428dca8e75..20b432b194 100644 --- a/docsrc/imap/reference/manpages/systemcommands/smmapd.rst +++ b/docsrc/imap/reference/manpages/systemcommands/smmapd.rst @@ -8,28 +8,38 @@ **smmapd** ========== -Sendmail socket map daemon +Sendmail and Postfix socket map daemon Synopsis ======== .. parsed-literal:: - **smmapd** [ **-C** *config-file* ] [ **-U** *uses* ] [ **-T** *timeout* ] [ **-D** ] + **smmapd** [ **-C** *config-file* ] [ **-U** *uses* ] [ **-T** *timeout* ] [ **-D** ] [**-p**] Description =========== -**smmapd** is a Sendmail socket map daemon which is used to verify that -a Cyrus mailbox exists, that it is postable and it is under quota. It +**smmapd** is a Sendmail and Postfix socket map daemon which is used to verify +that a Cyrus mailbox exists, that it is postable, it is not blocked for the +smmapd service in the userdeny database, and it is under quota. It accepts commands on its standard input and responds on its standard output. It MUST be invoked by :cyrusman:`master(8)` with those -descriptors attached to a remote client connection. The service ignores -the userdeny database. The received queries contain map name followed by -mailbox, **smmapd** ignores the map name. Queries with plus addressing return -*OK* if the user has a mailbox with the name after plus, otherwise the result -is *NOTFOUND*. Match for the mailbox after plus is performed case-sensitive, -for the address before the plus - case-insensitive. +descriptors attached to a remote client connection. The received queries +contain map name followed by mailbox, **smmapd** ignores the map name. +Queries with plus addressing, when *-p* is not passed, return *OK* when +the user has a mailbox with the name after plus, otherwise the result +is *NOTFOUND*. Match for the mailbox after plus is performed +case-sensitive, for the address before the plus - depends on +`lmtp_downcase_rcpt`. + +The use case is to verify in Sendmail or Postfix if the destination exists, +before accepting an email. Then, if `autocreate_sieve_folders` is set, but +the folder does not exist yet, **smmapd** will return *NOTFOUND*, unless *-p* +is passed. Another use case is to do something in a Sieve script with emails, +based on plus addressing, without delivering them in the correspondent sub-folder. +To accept such emails, when the folder with the same name does not exist, *-p* must +be passed. **smmapd** |default-conf-text| @@ -57,6 +67,11 @@ Options Run external debugger specified in debug_command. +.. option:: -p + + Skip plus addressing: everything from `+` until `@`. When looking up the userdeny + database, plus addressing is always skipped, irrespective of this option. + Examples ======== diff --git a/imap/smmapd.c b/imap/smmapd.c index 1be389d74f..e6d4e6468f 100644 --- a/imap/smmapd.c +++ b/imap/smmapd.c @@ -75,7 +75,6 @@ */ #include - #ifdef HAVE_UNISTD_H #include #endif @@ -93,6 +92,7 @@ #include "proc.h" #include "quota.h" #include "slowio.h" +#include "userdeny.h" #include "util.h" #include "xmalloc.h" #include "xstrlcpy.h" @@ -104,7 +104,9 @@ const char *BB; static int forcedowncase; -extern int optind; +extern int optind, opterr; +extern char *optarg; +static int skipplus; static struct protstream *map_in, *map_out; static const char *smmapd_clienthost; @@ -175,7 +177,7 @@ EXPORTED void fatal(const char* s, int code) */ int service_init(int argc, char **argv, char **envp) { - int r; + int r, opt; if (geteuid() == 0) fatal("must run as the Cyrus user", EX_USAGE); proc_settitle_init(argc, argv, envp); @@ -192,6 +194,17 @@ int service_init(int argc, char **argv, char **envp) fatal(error_message(r), EX_CONFIG); } + while ((opt = getopt(argc, argv, "p")) != EOF) { + switch(opt) { + case 'p': + skipplus = 1; + break; + default: + syslog(LOG_ERR, "usage: smmapd [-C ] [-U uses] [-T timeout] [-D] [-p]"); + exit(EX_USAGE); + } + } + return 0; } @@ -242,14 +255,21 @@ static int verify_user(const char *key, struct auth_state *authstate) mbname_t *mbname = mbname_from_recipient(key, &map_namespace); + if (skipplus) mbname_set_boxes(mbname, NULL); if (forcedowncase) mbname_downcaseuser(mbname); - /* see if its a shared mailbox address */ + /* see if it is a shared mailbox address */ if (!strcmpsafe(mbname_userid(mbname), BB)) { mbname_set_localpart(mbname, NULL); mbname_set_domain(mbname, NULL); } + char msg[MAX_MAILBOX_PATH+1]; + if (userdeny(mbname_userid(mbname), config_ident, msg, sizeof(msg))) { + prot_printf(map_out, SIZE_T_FMT ":NOTFOUND %s,", 9 + strlen(msg), msg); + mbname_free(&mbname); + return -1; + } /* * check to see if mailbox exists and we can append to it: *