MSGS command can now do full text search on the room
[citadel.git] / citadel / serv_smtp.c
index 0aac60fc326b582f71c35901e1cef58c5283a885..ac12d1eaa49f69c7d586e781629e853fb42afc17 100644 (file)
@@ -102,7 +102,8 @@ struct citsmtp {            /* Information about the current session */
 enum {                         /* Command states for login authentication */
        smtp_command,
        smtp_user,
-       smtp_password
+       smtp_password,
+       smtp_plain
 };
 
 enum {                         /* Delivery modes */
@@ -322,17 +323,40 @@ void smtp_get_pass(char *argbuf) {
 
 
 /*
- *
+ * Back end for PLAIN auth method (either inline or multistate)
  */
-void smtp_auth(char *argbuf) {
-       char username_prompt[64];
-       char method[64];
-       char encoded_authstring[1024];
+void smtp_try_plain(char *encoded_authstring) {
        char decoded_authstring[1024];
        char ident[256];
        char user[256];
        char pass[256];
 
+       CtdlDecodeBase64(decoded_authstring,
+                       encoded_authstring,
+                       strlen(encoded_authstring) );
+       safestrncpy(ident, decoded_authstring, sizeof ident);
+       safestrncpy(user, &decoded_authstring[strlen(ident) + 1], sizeof user);
+       safestrncpy(pass, &decoded_authstring[strlen(ident) + strlen(user) + 2], sizeof pass);
+
+       SMTP->command_state = smtp_command;
+       if (CtdlLoginExistingUser(user) == login_ok) {
+               if (CtdlTryPassword(pass) == pass_ok) {
+                       smtp_auth_greeting();
+                       return;
+               }
+       }
+       cprintf("504 5.7.4 Authentication failed.\r\n");
+}
+
+
+/*
+ * Attempt to perform authenticated SMTP
+ */
+void smtp_auth(char *argbuf) {
+       char username_prompt[64];
+       char method[64];
+       char encoded_authstring[1024];
+
        if (CC->logged_in) {
                cprintf("504 5.7.4 Already logged in.\r\n");
                return;
@@ -353,21 +377,16 @@ void smtp_auth(char *argbuf) {
        }
 
        if (!strncasecmp(method, "plain", 5) ) {
-               extract_token(encoded_authstring, argbuf, 1, ' ', sizeof encoded_authstring);
-               CtdlDecodeBase64(decoded_authstring,
-                               encoded_authstring,
-                               strlen(encoded_authstring) );
-               safestrncpy(ident, decoded_authstring, sizeof ident);
-               safestrncpy(user, &decoded_authstring[strlen(ident) + 1], sizeof user);
-               safestrncpy(pass, &decoded_authstring[strlen(ident) + strlen(user) + 2], sizeof pass);
-
-               if (CtdlLoginExistingUser(user) == login_ok) {
-                       if (CtdlTryPassword(pass) == pass_ok) {
-                               smtp_auth_greeting();
-                               return;
-                       }
+               if (num_tokens(argbuf, ' ') < 2) {
+                       cprintf("334 \r\n");
+                       SMTP->command_state = smtp_plain;
+                       return;
                }
-               cprintf("504 5.7.4 Authentication failed.\r\n");
+
+               extract_token(encoded_authstring, argbuf, 1, ' ', sizeof encoded_authstring);
+
+               smtp_try_plain(encoded_authstring);
+               return;
        }
 
        if (strncasecmp(method, "login", 5) ) {
@@ -852,6 +871,10 @@ void smtp_command_loop(void) {
                smtp_get_pass(cmdbuf);
        }
 
+       else if (SMTP->command_state == smtp_plain) {
+               smtp_try_plain(cmdbuf);
+       }
+
        else if (!strncasecmp(cmdbuf, "AUTH", 4)) {
                smtp_auth(&cmdbuf[5]);
        }
@@ -1080,8 +1103,8 @@ void smtp_try(const char *key, const char *addr, int *status,
 
        /* At this point we know we are talking to a real SMTP server */
 
-       /* Do a HELO command */
-       snprintf(buf, sizeof buf, "HELO %s\r\n", config.c_fqdn);
+       /* Do a EHLO command.  If it fails, try the HELO command. */
+       snprintf(buf, sizeof buf, "EHLO %s\r\n", config.c_fqdn);
        lprintf(CTDL_DEBUG, ">%s", buf);
        sock_write(sock, buf, strlen(buf));
        if (ml_sock_gets(sock, buf) < 0) {
@@ -1090,6 +1113,16 @@ void smtp_try(const char *key, const char *addr, int *status,
                goto bail;
        }
        lprintf(CTDL_DEBUG, "<%s\n", buf);
+       if (buf[0] != '2') {
+               snprintf(buf, sizeof buf, "HELO %s\r\n", config.c_fqdn);
+               lprintf(CTDL_DEBUG, ">%s", buf);
+               sock_write(sock, buf, strlen(buf));
+               if (ml_sock_gets(sock, buf) < 0) {
+                       *status = 4;
+                       strcpy(dsn, "Connection broken during SMTP HELO");
+                       goto bail;
+               }
+       }
        if (buf[0] != '2') {
                if (buf[0] == '4') {
                        *status = 4;
@@ -1608,17 +1641,18 @@ void smtp_do_procmsg(long msgnum, void *userdata) {
         * message and the message message.
         */
        if (incomplete_deliveries_remaining <= 0) {
-               CtdlDeleteMessages(SMTP_SPOOLOUT_ROOM, msgnum, "", 0);
-               CtdlDeleteMessages(SMTP_SPOOLOUT_ROOM, text_msgid, "", 0);
+               long delmsgs[2];
+               delmsgs[0] = msgnum;
+               delmsgs[1] = text_msgid;
+               CtdlDeleteMessages(SMTP_SPOOLOUT_ROOM, delmsgs, 2, "", 0);
        }
 
-
        /*
         * Uncompleted delivery instructions remain, so delete the old
         * instructions and replace with the updated ones.
         */
        if (incomplete_deliveries_remaining > 0) {
-               CtdlDeleteMessages(SMTP_SPOOLOUT_ROOM, msgnum, "", 0);
+               CtdlDeleteMessages(SMTP_SPOOLOUT_ROOM, &msgnum, 1, "", 0);
                msg = malloc(sizeof(struct CtdlMessage));
                memset(msg, 0, sizeof(struct CtdlMessage));
                msg->cm_magic = CTDLMESSAGE_MAGIC;
@@ -1666,7 +1700,7 @@ void smtp_do_queue(void) {
                lprintf(CTDL_ERR, "Cannot find room <%s>\n", SMTP_SPOOLOUT_ROOM);
                return;
        }
-       CtdlForEachMessage(MSGS_ALL, 0L,
+       CtdlForEachMessage(MSGS_ALL, 0L, NULL,
                SPOOLMIME, NULL, smtp_do_procmsg, NULL);
 
        lprintf(CTDL_INFO, "SMTP: queue run completed\n");