]> code.citadel.org Git - citadel.git/blobdiff - citadel/serv_smtp.c
centralized filename calculation
[citadel.git] / citadel / serv_smtp.c
index 770a254c55058743b523e20a2ca5509ffe7d9c60..b16d7804f4ce67c7eb5c712ea5cfba63789410e5 100644 (file)
@@ -31,6 +31,7 @@
 #include <pwd.h>
 #include <errno.h>
 #include <sys/types.h>
+#include <syslog.h>
 
 #if TIME_WITH_SYS_TIME
 # include <sys/time.h>
@@ -69,6 +70,7 @@
 #include "domain.h"
 #include "clientsocket.h"
 #include "locate_host.h"
+#include "citadel_dirs.h"
 
 #ifdef HAVE_OPENSSL
 #include "serv_crypto.h"
@@ -92,6 +94,7 @@ struct citsmtp {              /* Information about the current session */
        int delivery_mode;
        int message_originated_locally;
        int is_lmtp;
+       int is_unfiltered;
        int is_msa;
 };
 
@@ -168,6 +171,16 @@ void lmtp_greeting(void) {
 }
 
 
+/*
+ * We also have an unfiltered LMTP socket that bypasses spam filters.
+ */
+void lmtp_unfiltered_greeting(void) {
+       smtp_greeting();
+       SMTP->is_lmtp = 1;
+       SMTP->is_unfiltered = 1;
+}
+
+
 /*
  * Login greeting common to all auth methods
  */
@@ -276,7 +289,7 @@ void smtp_get_user(char *argbuf) {
        char username[SIZ];
 
        CtdlDecodeBase64(username, argbuf, SIZ);
-       lprintf(CTDL_DEBUG, "Trying <%s>\n", username);
+       /* lprintf(CTDL_DEBUG, "Trying <%s>\n", username); */
        if (CtdlLoginExistingUser(username) == login_ok) {
                CtdlEncodeBase64(buf, "Password:", 9);
                cprintf("334 %s\r\n", buf);
@@ -296,7 +309,7 @@ void smtp_get_pass(char *argbuf) {
        char password[SIZ];
 
        CtdlDecodeBase64(password, argbuf, SIZ);
-       lprintf(CTDL_DEBUG, "Trying <%s>\n", password);
+       /* lprintf(CTDL_DEBUG, "Trying <%s>\n", password); */
        if (CtdlTryPassword(password) == pass_ok) {
                smtp_auth_greeting();
        }
@@ -454,6 +467,7 @@ void smtp_expn(char *argbuf) {
  */
 void smtp_rset(int do_response) {
        int is_lmtp;
+       int is_unfiltered;
 
        /*
         * Our entire SMTP state is discarded when a RSET command is issued,
@@ -461,6 +475,7 @@ void smtp_rset(int do_response) {
         * we save it for later.
         */
        is_lmtp = SMTP->is_lmtp;
+       is_unfiltered = SMTP->is_unfiltered;
 
        memset(SMTP, 0, sizeof(struct citsmtp));
 
@@ -479,6 +494,7 @@ void smtp_rset(int do_response) {
         * Reinstate this little piece of information we saved (see above).
         */
        SMTP->is_lmtp = is_lmtp;
+       SMTP->is_unfiltered = is_unfiltered;
 
        if (do_response) {
                cprintf("250 2.0.0 Zap!\r\n");
@@ -548,9 +564,9 @@ void smtp_mail(char *argbuf) {
        }
 
        /* Otherwise, make sure outsiders aren't trying to forge mail from
-        * this system.
+        * this system (unless, of course, c_allow_spoofing is enabled)
         */
-       else {
+       else if (config.c_allow_spoofing == 0) {
                process_rfc822_addr(SMTP->from, user, node, name);
                if (CtdlHostAlias(node) != hostalias_nomatch) {
                        cprintf("550 5.1.8 "
@@ -611,7 +627,7 @@ void smtp_rcpt(char *argbuf) {
        }
 
        valid = validate_recipients(recp);
-       if (valid->num_error > 0) {
+       if (valid->num_error != 0) {
                cprintf("599 5.1.1 Error: %s\r\n", valid->errormsg);
                free(valid);
                return;
@@ -653,7 +669,7 @@ void smtp_rcpt(char *argbuf) {
 void smtp_data(void) {
        char *body;
        struct CtdlMessage *msg;
-       long msgnum;
+       long msgnum = (-1L);
        char nowstamp[SIZ];
        struct recptypes *valid;
        int scan_errors;
@@ -724,7 +740,12 @@ void smtp_data(void) {
         * submission (such as virus checkers or spam filters), call them now
         * and give them an opportunity to reject the message.
         */
-       scan_errors = PerformMessageHooks(msg, EVT_SMTPSCAN);
+       if (SMTP->is_unfiltered) {
+               scan_errors = 0;
+       }
+       else {
+               scan_errors = PerformMessageHooks(msg, EVT_SMTPSCAN);
+       }
 
        if (scan_errors > 0) {  /* We don't want this message! */
 
@@ -761,6 +782,22 @@ void smtp_data(void) {
                cprintf("%s", result);
        }
 
+       /* Write something to the syslog (which may or may not be where the
+        * rest of the Citadel logs are going; some sysadmins want LOG_MAIL).
+        */
+       if (enable_syslog) {
+               syslog((LOG_MAIL | LOG_INFO),
+                       "%ld: from=<%s>, nrcpts=%d, relay=%s [%s], stat=%s",
+                       msgnum,
+                       SMTP->from,
+                       SMTP->number_of_recipients,
+                       CC->cs_host,
+                       CC->cs_addr,
+                       result
+               );
+       }
+
+       /* Clean up */
        CtdlFreeMessage(msg);
        free(valid);
        smtp_data_clear();      /* clear out the buffers now */
@@ -799,7 +836,7 @@ void smtp_command_loop(void) {
        time(&CC->lastcmd);
        memset(cmdbuf, 0, sizeof cmdbuf); /* Clear it, just in case */
        if (client_getln(cmdbuf, sizeof cmdbuf) < 1) {
-               lprintf(CTDL_CRIT, "SMTP socket is broken.  Ending session.\n");
+               lprintf(CTDL_CRIT, "Client disconnected: ending session.\n");
                CC->kill_me = 1;
                return;
        }
@@ -902,9 +939,11 @@ void smtp_try(const char *key, const char *addr, int *status,
        int num_mxhosts;
        int mx;
        int i;
-       char user[SIZ], node[SIZ], name[SIZ];
+       char user[1024], node[1024], name[1024];
        char buf[1024];
        char mailfrom[1024];
+       char mx_host[256];
+       char mx_port[256];
        int lp, rp;
        char *msgtext;
        char *ptr;
@@ -921,7 +960,7 @@ void smtp_try(const char *key, const char *addr, int *status,
        CC->redirect_buffer = malloc(SIZ);
        CC->redirect_len = 0;
        CC->redirect_alloc = SIZ;
-       CtdlOutputMsg(msgnum, MT_RFC822, HEADERS_ALL, 0, 1);
+       CtdlOutputMsg(msgnum, MT_RFC822, HEADERS_ALL, 0, 1, NULL);
        msgtext = CC->redirect_buffer;
        msg_size = CC->redirect_len;
        CC->redirect_buffer = NULL;
@@ -987,8 +1026,13 @@ void smtp_try(const char *key, const char *addr, int *status,
        sock = (-1);
        for (mx=0; (mx<num_mxhosts && sock < 0); ++mx) {
                extract_token(buf, mxhosts, mx, '|', sizeof buf);
-               lprintf(CTDL_DEBUG, "Trying <%s>\n", buf);
-               sock = sock_connect(buf, "25", "tcp");
+               extract_token(mx_host, buf, 0, ':', sizeof mx_host);
+               extract_token(mx_port, buf, 1, ':', sizeof mx_port);
+               if (!mx_port[0]) {
+                       strcpy(mx_port, "25");
+               }
+               lprintf(CTDL_DEBUG, "Trying %s : %s ...\n", mx_host, mx_port);
+               sock = sock_connect(mx_host, mx_port, "tcp");
                snprintf(dsn, SIZ, "Could not connect: %s", strerror(errno));
                if (sock >= 0) lprintf(CTDL_DEBUG, "Connected!\n");
                if (sock < 0) snprintf(dsn, SIZ, "%s", strerror(errno));
@@ -1068,7 +1112,7 @@ void smtp_try(const char *key, const char *addr, int *status,
        }
 
        /* MAIL succeeded, now try the RCPT To: command */
-       snprintf(buf, sizeof buf, "RCPT To: <%s>\r\n", addr);
+       snprintf(buf, sizeof buf, "RCPT To: <%s@%s>\r\n", user, node);
        lprintf(CTDL_DEBUG, ">%s", buf);
        sock_write(sock, buf, strlen(buf));
        if (ml_sock_gets(sock, buf) < 0) {
@@ -1153,6 +1197,20 @@ void smtp_try(const char *key, const char *addr, int *status,
 
 bail:  free(msgtext);
        sock_close(sock);
+
+       /* Write something to the syslog (which may or may not be where the
+        * rest of the Citadel logs are going; some sysadmins want LOG_MAIL).
+        */
+       if (enable_syslog) {
+               syslog((LOG_MAIL | LOG_INFO),
+                       "%ld: to=<%s>, relay=%s, stat=%s",
+                       msgnum,
+                       addr,
+                       mx_host,
+                       dsn
+               );
+       }
+
        return;
 }
 
@@ -1508,8 +1566,8 @@ void smtp_do_procmsg(long msgnum, void *userdata) {
         * message and the message message.
         */
        if (incomplete_deliveries_remaining <= 0) {
-               CtdlDeleteMessages(SMTP_SPOOLOUT_ROOM, msgnum, "");
-               CtdlDeleteMessages(SMTP_SPOOLOUT_ROOM, text_msgid, "");
+               CtdlDeleteMessages(SMTP_SPOOLOUT_ROOM, msgnum, "", 0);
+               CtdlDeleteMessages(SMTP_SPOOLOUT_ROOM, text_msgid, "", 0);
        }
 
 
@@ -1518,7 +1576,7 @@ void smtp_do_procmsg(long msgnum, void *userdata) {
         * instructions and replace with the updated ones.
         */
        if (incomplete_deliveries_remaining > 0) {
-               CtdlDeleteMessages(SMTP_SPOOLOUT_ROOM, msgnum, "");
+               CtdlDeleteMessages(SMTP_SPOOLOUT_ROOM, msgnum, "", 0);
                msg = malloc(sizeof(struct CtdlMessage));
                memset(msg, 0, sizeof(struct CtdlMessage));
                msg->cm_magic = CTDLMESSAGE_MAGIC;
@@ -1666,6 +1724,7 @@ void smtp_cleanup_function(void) {
 
 char *serv_smtp_init(void)
 {
+
        CtdlRegisterServiceHook(config.c_smtp_port,     /* SMTP MTA */
                                NULL,
                                smtp_greeting,
@@ -1687,10 +1746,16 @@ char *serv_smtp_init(void)
                                NULL);
 
        CtdlRegisterServiceHook(0,                      /* local LMTP */
-                               "lmtp.socket",
-                               lmtp_greeting,
-                               smtp_command_loop,
-                               NULL);
+                                                       file_lmtp_socket,
+                                                       lmtp_greeting,
+                                                       smtp_command_loop,
+                                                       NULL);
+
+       CtdlRegisterServiceHook(0,                      /* local LMTP */
+                                                       file_lmtp_unfiltered_socket,
+                                                       lmtp_unfiltered_greeting,
+                                                       smtp_command_loop,
+                                                       NULL);
 
        smtp_init_spoolout();
        CtdlRegisterSessionHook(smtp_do_queue, EVT_TIMER);