]> code.citadel.org Git - citadel.git/blobdiff - citadel/serv_smtp.c
* Coded up some more of the SMTP-sender (still not done)
[citadel.git] / citadel / serv_smtp.c
index 5dacdabb38891bbc3041c8d4f5585dfdc982cd76..4c694c342b534ed86c117365256898483682ebdc 100644 (file)
@@ -58,6 +58,13 @@ enum {                               /* Delivery modes */
 long SYM_SMTP;
 long SYM_SMTP_RECP;
 
+
+
+/*****************************************************************************/
+/*                      SMTP SERVER (INBOUND) STUFF                          */
+/*****************************************************************************/
+
+
 /*
  * Here's where our SMTP session begins its happy day.
  */
@@ -143,7 +150,7 @@ void smtp_get_pass(char *argbuf) {
        lprintf(9, "Trying <%s>\n", password);
        if (CtdlTryPassword(password) == pass_ok) {
                cprintf("235 Authentication successful.\r\n");
-               lprintf(9, "SMTP auth login successful\n");
+               lprintf(9, "SMTP authenticated login successful\n");
                CC->internal_pgm = 0;
                CC->cs_flags &= ~CS_STEALTH;
        }
@@ -376,7 +383,7 @@ void smtp_rcpt(char *argbuf) {
                                strlen(SMTP_RECP) + 1024 );
                        strcat(SMTP_RECP, "room|");
                        strcat(SMTP_RECP, user);
-                       strcat(SMTP_RECP, "|0\n");
+                       strcat(SMTP_RECP, "|0|\n");
                        return;
 
                case rfc822_no_such_user:
@@ -394,7 +401,7 @@ void smtp_rcpt(char *argbuf) {
                                        strlen(SMTP_RECP) + 1024 );
                                strcat(SMTP_RECP, "remote|");
                                strcat(SMTP_RECP, recp);
-                               strcat(SMTP_RECP, "|0\n");
+                               strcat(SMTP_RECP, "|0|\n");
                                return;
                        }
                        return;
@@ -444,8 +451,8 @@ int smtp_message_delivery(struct CtdlMessage *msg) {
        ++successful_saves;
 
        instr = mallok(1024);
-       sprintf(instr, "Content-type: %s\n\nmsgid|%ld\n",
-               SPOOLMIME, msgid);
+       sprintf(instr, "Content-type: %s\n\nmsgid|%ld\nsubmitted|%ld\n",
+               SPOOLMIME, msgid, time(NULL) );
 
        for (i=0; i<SMTP->number_of_recipients; ++i) {
                extract_token(buf, SMTP_RECP, i, '\n');
@@ -654,6 +661,163 @@ void smtp_command_loop(void) {
 }
 
 
+
+
+/*****************************************************************************/
+/*               SMTP CLIENT (OUTBOUND PROCESSING) STUFF                     */
+/*****************************************************************************/
+
+
+
+/*
+ * smtp_try()
+ *
+ * Called by smtp_do_procmsg() to attempt delivery to one SMTP host
+ *
+ */
+void smtp_try(char *key, char *addr, int *status, char *dsn) {
+
+       *status = 3;
+       strcpy(dsn, "smtp_try() is not finished yet");
+}
+
+
+
+/*
+ * smtp_do_procmsg()
+ *
+ * Called by smtp_do_queue() to handle an individual message.
+ */
+void smtp_do_procmsg(long msgnum) {
+       struct CtdlMessage *msg;
+       char *instr = NULL;
+       char *results = NULL;
+       int i;
+       int lines;
+       int status;
+       char buf[1024];
+       char key[1024];
+       char addr[1024];
+       char dsn[1024];
+       long text_msgid = (-1);
+
+       msg = CtdlFetchMessage(msgnum);
+       if (msg == NULL) {
+               lprintf(3, "SMTP: tried %ld but no such message!\n", msgnum);
+               return;
+       }
+
+       instr = strdoop(msg->cm_fields['M']);
+       CtdlFreeMessage(msg);
+
+       /* Strip out the headers amd any other non-instruction line */
+       lines = num_tokens(instr, '\n');
+       for (i=0; i<lines; ++i) {
+               extract_token(buf, instr, i, '\n');
+               if (num_tokens(buf, '|') < 2) {
+                       lprintf(9, "removing <%s>\n", buf);
+                       remove_token(instr, i, '|');
+                       --lines;
+                       --i;
+               }
+       }
+
+       /* Learn the message ID */
+       lines = num_tokens(instr, '\n');
+       for (i=0; i<lines; ++i) {
+               extract_token(buf, instr, i, '\n');
+               extract(key, buf, 0);
+               if (!strcasecmp(key, "msgid")) {
+                       text_msgid = extract_long(buf, 1);
+               }
+       }
+
+       if (text_msgid < 0L) {
+               lprintf(3, "SMTP: no 'msgid' directive found!\n", msgnum);
+               phree(instr);
+               return;
+       }
+
+       /* Plow through the instructions looking for 'remote' directives and
+        * a status of 0 (no delivery yet attempted) or 3 (transient errors
+        * were experienced and it's time to try again)
+        */
+       lines = num_tokens(instr, '\n');
+       for (i=0; i<lines; ++i) {
+               extract_token(buf, instr, i, '\n');
+               extract(key, buf, 0);
+               extract(addr, buf, 1);
+               status = extract_int(buf, 2);
+               extract(dsn, buf, 3);
+               if ( (!strcasecmp(key, "remote"))
+                  && ((status==0)||(status==3)) ) {
+                       remove_token(instr, i, '\n');
+                       --i;
+                       --lines;
+                       lprintf(9, "SMTP: Trying <%s>\n", addr);
+                       smtp_try(key, addr, &status, dsn);
+                       if (status != 2) {
+                               if (results == NULL) {
+                                       results = mallok(1024);
+                                       memset(results, 0, 1024);
+                               }
+                               else {
+                                       results = reallok(results,
+                                               strlen(results) + 1024);
+                               }
+                               sprintf(&results[strlen(results)],
+                                       "%s|%s|%d|%s\n",
+                                       key, addr, status, dsn);
+                       }
+               }
+       }
+
+       if (results != NULL) {
+               instr = reallok(instr, strlen(instr) + strlen(results) + 2);
+               strcat(instr, results);
+               phree(results);
+       }
+
+       /* Delete the instructions and replace with the updated ones */
+       CtdlDeleteMessages(SMTP_SPOOLOUT_ROOM, msgnum, NULL);    
+        msg = mallok(sizeof(struct CtdlMessage));
+       memset(msg, 0, sizeof(struct CtdlMessage));
+       msg->cm_magic = CTDLMESSAGE_MAGIC;
+       msg->cm_anon_type = MES_NORMAL;
+       msg->cm_format_type = FMT_RFC822;
+       msg->cm_fields['M'] = instr;
+       CtdlSaveMsg(msg, "", SMTP_SPOOLOUT_ROOM, MES_LOCAL, 1);
+       CtdlFreeMessage(msg);
+}
+
+
+
+/*
+ * smtp_do_queue()
+ * 
+ * Run through the queue sending out messages.
+ */
+void smtp_do_queue(void) {
+       lprintf(5, "SMTP: processing outbound queue\n");
+
+       if (getroom(&CC->quickroom, SMTP_SPOOLOUT_ROOM) != 0) {
+               lprintf(3, "Cannot find room <%s>\n", SMTP_SPOOLOUT_ROOM);
+               return;
+       }
+       CtdlForEachMessage(MSGS_ALL, 0L, SPOOLMIME, NULL, smtp_do_procmsg);
+
+       lprintf(5, "SMTP: queue run completed\n");
+}
+
+
+
+
+
+/*****************************************************************************/
+/*                      MODULE INITIALIZATION STUFF                          */
+/*****************************************************************************/
+
+
 char *Dynamic_Module_Init(void)
 {
        SYM_SMTP = CtdlGetDynamicSymbol();