* More SMTP implementation
authorArt Cancro <ajc@citadel.org>
Tue, 14 Dec 1999 23:20:00 +0000 (23:20 +0000)
committerArt Cancro <ajc@citadel.org>
Tue, 14 Dec 1999 23:20:00 +0000 (23:20 +0000)
citadel/internet_addressing.c
citadel/internet_addressing.h
citadel/msgbase.c
citadel/msgbase.h
citadel/parsedate.c
citadel/parsedate.y
citadel/serv_smtp.c
citadel/tools.c

index 8881214d075b09379c06eb702b302e5c53050af0..0612e77b29670d7e089599673266014bcf08b9b4 100644 (file)
@@ -59,6 +59,10 @@ void process_rfc822_addr(char *rfc822, char *user, char *node, char *name)
 {
        int a;
 
+       strcpy(user, "");
+       strcpy(node, config.c_fqdn);
+       strcpy(name, "");
+
        /* extract full name - first, it's From minus <userid> */
        strcpy(name, rfc822);
        for (a = 0; a < strlen(name); ++a) {
@@ -204,6 +208,7 @@ void try_name(struct usersupp *us) {
 }
 
 
+
 /*
  * Convert an Internet email address to a Citadel user/host combination
  */
@@ -228,7 +233,7 @@ int convert_internet_address(char *destuser, char *desthost, char *source)
         * FIX ... make this work for non-local systems
         */
        if (strcasecmp(node, config.c_nodename)) {
-               return(1);
+               return(rfc822_address_invalid);
        }
        
        /* Now try to resolve the name
@@ -240,10 +245,45 @@ int convert_internet_address(char *destuser, char *desthost, char *source)
                strcpy(CC->buffer1, user);
                strcpy(CC->buffer2, "");
                ForEachUser(try_name);
-               if (strlen(CC->buffer2) == 0) return(2);
+               if (strlen(CC->buffer2) == 0) return(rfc822_no_such_user);
                strcpy(destuser, CC->buffer2);
-               return(0);
+               return(rfc822_address_locally_validated);
+       }
+
+       return(rfc822_address_invalid); /* unknown error */
+}
+
+
+
+
+
+/*
+ * Convert an RFC822 message (headers + body) to a CtdlMessage structure.
+ */
+struct CtdlMessage *convert_internet_message(char *rfc822) {
+
+       struct CtdlMessage *msg;
+       char *buf;
+
+       msg = mallok(sizeof(struct CtdlMessage));
+       if (msg == NULL) return msg;
+
+       memset(msg, 0, sizeof(struct CtdlMessage));
+       msg->cm_magic = CTDLMESSAGE_MAGIC;      /* self check */
+       msg->cm_anon_type = 0;                  /* never anonymous */
+       msg->cm_format_type = 4;                /* always MIME */
+       msg->cm_fields['M'] = rfc822;
+
+       /* FIX   there's plenty to do here. */
+
+
+       /* Follow-up sanity check. */
+
+       /* If there's no timestamp on this message, set it to now. */
+       if (msg->cm_fields['T'] == NULL) {
+               sprintf(buf, "%ld", time(NULL));
+               msg->cm_fields['T'] = strdoop(buf);
        }
 
-       return(3);      /* unknown error */
+       return msg;
 }
index 917e227009c1cc76674973ff09ab32ac14691ced..81913878b1a60d78920633e7645831db151a3e5f 100644 (file)
@@ -1,3 +1,12 @@
 int fuzzy_match(struct usersupp *us, char *matchstring);
 void process_rfc822_addr(char *rfc822, char *user, char *node, char *name);
 int convert_internet_address(char *destuser, char *desthost, char *source);
+
+
+enum {
+       rfc822_address_locally_validated,
+       rfc822_no_such_user,
+       rfc822_address_on_citadel_network,
+       rfc822_address_invalid
+};
+
index 5b37783ff42f840e6cc93d905d19b28e602d523e..045e38e86c22bedf0f9cf586d0618a69bff3952a 100644 (file)
@@ -1590,6 +1590,64 @@ void quickie_message(char *from, char *to, char *room, char *text)
 }
 
 
+
+/*
+ * Back end function used by make_message() and similar functions
+ */
+char *CtdlReadMessageBody(char *terminator, size_t maxlen) {
+       char buf[256];
+       size_t message_len = 0;
+       size_t buffer_len = 0;
+       char *ptr, *append;
+       char *m;
+
+       m = mallok(4096);
+       if (m == NULL) {
+               while ( (client_gets(buf)>0) && strcmp(buf, terminator) ) ;;
+               return(NULL);
+       } else {
+               buffer_len = 4096;
+               m[0] = 0;
+               message_len = 0;
+       }
+       /* read in the lines of message text one by one */
+       append = NULL;
+       while ( (client_gets(buf)>0) && strcmp(buf, terminator) ) {
+
+               /* augment the buffer if we have to */
+               if ((message_len + strlen(buf) + 2) > buffer_len) {
+                       lprintf(9, "realloking\n");
+                       ptr = reallok(m, (buffer_len * 2) );
+                       if (ptr == NULL) {      /* flush if can't allocate */
+                               while ( (client_gets(buf)>0) &&
+                                       strcmp(buf, terminator)) ;;
+                               return(m);
+                       } else {
+                               buffer_len = (buffer_len * 2);
+                               m = ptr;
+                               append = NULL;
+                               lprintf(9, "buffer_len is %d\n", buffer_len);
+                       }
+               }
+
+               if (append == NULL) append = m;
+               while (strlen(append) > 0) ++append;
+               strcpy(append, buf);
+               strcat(append, "\n");
+               message_len = message_len + strlen(buf) + 1;
+
+               /* if we've hit the max msg length, flush the rest */
+               if (message_len >= maxlen) {
+                       while ( (client_gets(buf)>0) && strcmp(buf, terminator)) ;;
+                       return(m);
+               }
+       }
+       return(m);
+}
+
+
+
+
 /*
  * Build a binary message to be saved on disk.
  */
@@ -1607,9 +1665,6 @@ struct CtdlMessage *make_message(
        int a;
        char dest_node[32];
        char buf[256];
-       size_t message_len = 0;
-       size_t buffer_len = 0;
-       char *ptr, *append;
        struct CtdlMessage *msg;
 
        msg = mallok(sizeof(struct CtdlMessage));
@@ -1664,47 +1719,9 @@ struct CtdlMessage *make_message(
        if (dest_node[0] != 0)
                msg->cm_fields['D'] = strdoop(dest_node);
 
-       msg->cm_fields['M'] = mallok(4096);
-       if (msg->cm_fields['M'] == NULL) {
-               while (client_gets(buf), strcmp(buf, "000")) ;; /* flush */
-               return(msg);
-       } else {
-               buffer_len = 4096;
-               msg->cm_fields['M'][0] = 0;
-               message_len = 0;
-       }
 
-       /* read in the lines of message text one by one */
-       append = NULL;
-       while (client_gets(buf), strcmp(buf, "000")) {
+       msg->cm_fields['M'] = CtdlReadMessageBody("000", config.c_maxmsglen);
 
-               /* augment the buffer if we have to */
-               if ((message_len + strlen(buf) + 2) > buffer_len) {
-                       lprintf(9, "realloking\n");
-                       ptr = reallok(msg->cm_fields['M'], (buffer_len * 2) );
-                       if (ptr == NULL) {      /* flush if can't allocate */
-                               while (client_gets(buf), strcmp(buf, "000")) ;;
-                               return(msg);
-                       } else {
-                               buffer_len = (buffer_len * 2);
-                               msg->cm_fields['M'] = ptr;
-                               append = NULL;
-                               lprintf(9, "buffer_len is %d\n", buffer_len);
-                       }
-               }
-
-               if (append == NULL) append = msg->cm_fields['M'];
-               while (strlen(append) > 0) ++append;
-               strcpy(append, buf);
-               strcat(append, "\n");
-               message_len = message_len + strlen(buf) + 1;
-
-               /* if we've hit the max msg length, flush the rest */
-               if (message_len >= config.c_maxmsglen) {
-                       while (client_gets(buf), strcmp(buf, "000")) ;;
-                       return(msg);
-               }
-       }
 
        return(msg);
 }
index 4718851192d84bd72d0053694c54dd01b18e9d9f..8193b90d5285832381bd3eda690fa0a2d2dd734b 100644 (file)
@@ -70,3 +70,4 @@ void serialize_message(struct ser_ret *, struct CtdlMessage *);
 int is_valid_message(struct CtdlMessage *);
 int ReplicationChecks(struct CtdlMessage *);
 int CtdlSaveMsgPointerInRoom(char *roomname, long msgid, int flags);
+char *CtdlReadMessageBody(char *terminator, size_t maxlen);
index f813214de39051f768c0a594dcf4188e8122b195..e25be117359bd174e83df6578864660e02bfec35 100644 (file)
@@ -17,7 +17,8 @@ static char yysccsid[] = "@(#)yaccpar 1.9 (Berkeley) 02/21/93";
 **  <rsalz@osf.org> and Jim Berets <jberets@bbn.com> in August, 1990.
 **  Further revised (removed obsolete constructs and cleaned up timezone
 **  names) in August, 1991, by Rich.  Paul Eggert <eggert@twinsun.com>
-**  helped in September, 1992.
+**  helped in September, 1992.  Art Cancro <ajc@uncnsrd.mt-kisco.ny.us> cleaned
+**  it up for ANSI C in December, 1999.
 **
 **  This grammar has six shift/reduce conflicts.
 **
@@ -32,7 +33,7 @@ static char yysccsid[] = "@(#)yaccpar 1.9 (Berkeley) 02/21/93";
 #include <ctype.h>
 #include <time.h>
 
-int date_lex();
+int date_lex(void);
 
 #define yyparse                date_parse
 #define yylex          date_lex
@@ -102,15 +103,13 @@ static time_t     yyRelMonth;
 static time_t  yyRelSeconds;
 
 
-extern struct tm       *localtime();
-
-static void            date_error();
-#line 100 "parsedate.y"
+static void            date_error(char *);
+#line 99 "parsedate.y"
 typedef union {
     time_t             Number;
     enum _MERIDIAN     Meridian;
 } YYSTYPE;
-#line 114 "y.tab.c"
+#line 113 "y.tab.c"
 #define tDAY 257
 #define tDAYZONE 258
 #define tMERIDIAN 259
@@ -294,7 +293,7 @@ YYSTYPE yylval;
 short yyss[YYSTACKSIZE];
 YYSTYPE yyvs[YYSTACKSIZE];
 #define yystacksize YYSTACKSIZE
-#line 287 "parsedate.y"
+#line 286 "parsedate.y"
 
 /* Month and day table. */
 static TABLE   MonthDayTable[] = {
@@ -457,11 +456,7 @@ date_error(s)
 
 
 static time_t
-ToSeconds(Hours, Minutes, Seconds, Meridian)
-    time_t     Hours;
-    time_t     Minutes;
-    time_t     Seconds;
-    MERIDIAN   Meridian;
+ToSeconds(time_t Hours, time_t Minutes, time_t Seconds, MERIDIAN Meridian)
 {
     if (Minutes < 0 || Minutes > 59 || Seconds < 0 || Seconds > 61)
        return -1;
@@ -482,15 +477,9 @@ ToSeconds(Hours, Minutes, Seconds, Meridian)
 
 
 static time_t
-Convert(Month, Day, Year, Hours, Minutes, Seconds, Meridian, dst)
-    time_t     Month;
-    time_t     Day;
-    time_t     Year;
-    time_t     Hours;
-    time_t     Minutes;
-    time_t     Seconds;
-    MERIDIAN   Meridian;
-    DSTMODE    dst;
+Convert(time_t Month, time_t Day, time_t Year,
+       time_t Hours, time_t Minutes, time_t Seconds,
+       MERIDIAN Meridian, DSTMODE dst)
 {
     static int DaysNormal[13] = {
        0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31
@@ -544,9 +533,7 @@ Convert(Month, Day, Year, Hours, Minutes, Seconds, Meridian, dst)
 
 
 static time_t
-DSTcorrect(Start, Future)
-    time_t     Start;
-    time_t     Future;
+DSTcorrect(time_t Start, time_t Future)
 {
     time_t     StartDay;
     time_t     FutureDay;
@@ -558,9 +545,7 @@ DSTcorrect(Start, Future)
 
 
 static time_t
-RelativeMonth(Start, RelMonth)
-    time_t     Start;
-    time_t     RelMonth;
+RelativeMonth(time_t Start, time_t RelMonth)
 {
     struct tm  *tm;
     time_t     Month;
@@ -578,9 +563,7 @@ RelativeMonth(Start, RelMonth)
 
 
 static int
-LookupWord(buff, length)
-    char               *buff;
-    register int       length;
+LookupWord(char *buff, register int length)
 {
     register char      *p;
     register char      *q;
@@ -670,7 +653,7 @@ LookupWord(buff, length)
 
 
 int
-date_lex()
+date_lex(void)
 {
     register char      c;
     register char      *p;
@@ -733,10 +716,9 @@ date_lex()
 
 
 time_t
-parsedate(p)
-    char               *p;
+parsedate(char *p)
 {
-    extern int         date_parse();
+    extern int         date_parse(void);
     time_t             Start;
 
     yyInput = p;
@@ -786,9 +768,7 @@ extern int  yydebug;
 
 /* ARGSUSED */
 int
-main(ac, av)
-    int                ac;
-    char       *av[];
+main(int ac, char *av[])
 {
     char       buff[128];
     time_t     d;
@@ -821,7 +801,7 @@ main(ac, av)
     /* NOTREACHED */
 }
 #endif /* TEST */
-#line 825 "y.tab.c"
+#line 805 "y.tab.c"
 #define YYABORT goto yyabort
 #define YYREJECT goto yyabort
 #define YYACCEPT goto yyaccept
@@ -963,7 +943,7 @@ yyreduce:
     switch (yyn)
     {
 case 3:
-#line 118 "parsedate.y"
+#line 117 "parsedate.y"
 {
            yyHaveTime++;
 #ifdef lint
@@ -975,26 +955,26 @@ case 3:
        }
 break;
 case 4:
-#line 127 "parsedate.y"
+#line 126 "parsedate.y"
 {
            yyHaveTime++;
            yyTimezone = yyvsp[0].Number;
        }
 break;
 case 5:
-#line 131 "parsedate.y"
+#line 130 "parsedate.y"
 {
            yyHaveDate++;
        }
 break;
 case 6:
-#line 134 "parsedate.y"
+#line 133 "parsedate.y"
 {
            yyHaveRel = 1;
        }
 break;
 case 7:
-#line 139 "parsedate.y"
+#line 138 "parsedate.y"
 {
            if (yyvsp[-1].Number < 100) {
                yyHour = yyvsp[-1].Number;
@@ -1009,7 +989,7 @@ case 7:
        }
 break;
 case 8:
-#line 151 "parsedate.y"
+#line 150 "parsedate.y"
 {
            yyHour = yyvsp[-3].Number;
            yyMinutes = yyvsp[-1].Number;
@@ -1018,7 +998,7 @@ case 8:
        }
 break;
 case 9:
-#line 157 "parsedate.y"
+#line 156 "parsedate.y"
 {
            yyHour = yyvsp[-3].Number;
            yyMinutes = yyvsp[-1].Number;
@@ -1028,7 +1008,7 @@ case 9:
        }
 break;
 case 10:
-#line 164 "parsedate.y"
+#line 163 "parsedate.y"
 {
            yyHour = yyvsp[-5].Number;
            yyMinutes = yyvsp[-3].Number;
@@ -1037,7 +1017,7 @@ case 10:
        }
 break;
 case 11:
-#line 170 "parsedate.y"
+#line 169 "parsedate.y"
 {
            yyHour = yyvsp[-5].Number;
            yyMinutes = yyvsp[-3].Number;
@@ -1048,21 +1028,21 @@ case 11:
        }
 break;
 case 12:
-#line 180 "parsedate.y"
+#line 179 "parsedate.y"
 {
            yyval.Number = yyvsp[0].Number;
            yyDSTmode = DSToff;
        }
 break;
 case 13:
-#line 184 "parsedate.y"
+#line 183 "parsedate.y"
 {
            yyval.Number = yyvsp[0].Number;
            yyDSTmode = DSTon;
        }
 break;
 case 14:
-#line 188 "parsedate.y"
+#line 187 "parsedate.y"
 {
            /* Only allow "GMT+300" and "GMT-0800" */
            if (yyvsp[-1].Number != 0) {
@@ -1073,14 +1053,14 @@ case 14:
        }
 break;
 case 15:
-#line 196 "parsedate.y"
+#line 195 "parsedate.y"
 {
            yyval.Number = yyvsp[0].Number;
            yyDSTmode = DSToff;
        }
 break;
 case 16:
-#line 202 "parsedate.y"
+#line 201 "parsedate.y"
 {
            int         i;
 
@@ -1102,14 +1082,14 @@ case 16:
        }
 break;
 case 17:
-#line 223 "parsedate.y"
+#line 222 "parsedate.y"
 {
            yyMonth = yyvsp[-2].Number;
            yyDay = yyvsp[0].Number;
        }
 break;
 case 18:
-#line 227 "parsedate.y"
+#line 226 "parsedate.y"
 {
            if (yyvsp[-4].Number > 100) {
                yyYear = yyvsp[-4].Number;
@@ -1124,14 +1104,14 @@ case 18:
        }
 break;
 case 19:
-#line 239 "parsedate.y"
+#line 238 "parsedate.y"
 {
            yyMonth = yyvsp[-1].Number;
            yyDay = yyvsp[0].Number;
        }
 break;
 case 20:
-#line 243 "parsedate.y"
+#line 242 "parsedate.y"
 {
            yyMonth = yyvsp[-3].Number;
            yyDay = yyvsp[-2].Number;
@@ -1139,14 +1119,14 @@ case 20:
        }
 break;
 case 21:
-#line 248 "parsedate.y"
+#line 247 "parsedate.y"
 {
            yyDay = yyvsp[-1].Number;
            yyMonth = yyvsp[0].Number;
        }
 break;
 case 22:
-#line 252 "parsedate.y"
+#line 251 "parsedate.y"
 {
            yyDay = yyvsp[-2].Number;
            yyMonth = yyvsp[-1].Number;
@@ -1154,7 +1134,7 @@ case 22:
        }
 break;
 case 23:
-#line 257 "parsedate.y"
+#line 256 "parsedate.y"
 {
            yyDay = yyvsp[-2].Number;
            yyMonth = yyvsp[-1].Number;
@@ -1162,42 +1142,42 @@ case 23:
        }
 break;
 case 24:
-#line 264 "parsedate.y"
+#line 263 "parsedate.y"
 {
            yyRelSeconds += yyvsp[-1].Number * yyvsp[0].Number;
        }
 break;
 case 25:
-#line 267 "parsedate.y"
+#line 266 "parsedate.y"
 {
            yyRelSeconds += yyvsp[-1].Number * yyvsp[0].Number;
        }
 break;
 case 26:
-#line 270 "parsedate.y"
+#line 269 "parsedate.y"
 {
            yyRelMonth += yyvsp[-1].Number * yyvsp[0].Number;
        }
 break;
 case 27:
-#line 273 "parsedate.y"
+#line 272 "parsedate.y"
 {
            yyRelMonth += yyvsp[-1].Number * yyvsp[0].Number;
        }
 break;
 case 28:
-#line 278 "parsedate.y"
+#line 277 "parsedate.y"
 {
            yyval.Meridian = MER24;
        }
 break;
 case 29:
-#line 281 "parsedate.y"
+#line 280 "parsedate.y"
 {
            yyval.Meridian = yyvsp[0].Meridian;
        }
 break;
-#line 1201 "y.tab.c"
+#line 1181 "y.tab.c"
     }
     yyssp -= yym;
     yystate = *yyssp;
index e167f59b73ec9d93d9e5f4e60217442a41572474..5663c6d21fe285aa5573389fb64a13fc6aa82831 100644 (file)
@@ -7,7 +7,8 @@
 **  <rsalz@osf.org> and Jim Berets <jberets@bbn.com> in August, 1990.
 **  Further revised (removed obsolete constructs and cleaned up timezone
 **  names) in August, 1991, by Rich.  Paul Eggert <eggert@twinsun.com>
-**  helped in September, 1992.
+**  helped in September, 1992.  Art Cancro <ajc@uncnsrd.mt-kisco.ny.us> cleaned
+**  it up for ANSI C in December, 1999.
 **
 **  This grammar has six shift/reduce conflicts.
 **
@@ -22,7 +23,7 @@
 #include <ctype.h>
 #include <time.h>
 
-int date_lex();
+int date_lex(void);
 
 #define yyparse                date_parse
 #define yylex          date_lex
@@ -92,9 +93,7 @@ static time_t yyRelMonth;
 static time_t  yyRelSeconds;
 
 
-extern struct tm       *localtime();
-
-static void            date_error();
+static void            date_error(char *);
 %}
 
 %union {
@@ -446,11 +445,7 @@ date_error(s)
 
 
 static time_t
-ToSeconds(Hours, Minutes, Seconds, Meridian)
-    time_t     Hours;
-    time_t     Minutes;
-    time_t     Seconds;
-    MERIDIAN   Meridian;
+ToSeconds(time_t Hours, time_t Minutes, time_t Seconds, MERIDIAN Meridian)
 {
     if (Minutes < 0 || Minutes > 59 || Seconds < 0 || Seconds > 61)
        return -1;
@@ -471,15 +466,9 @@ ToSeconds(Hours, Minutes, Seconds, Meridian)
 
 
 static time_t
-Convert(Month, Day, Year, Hours, Minutes, Seconds, Meridian, dst)
-    time_t     Month;
-    time_t     Day;
-    time_t     Year;
-    time_t     Hours;
-    time_t     Minutes;
-    time_t     Seconds;
-    MERIDIAN   Meridian;
-    DSTMODE    dst;
+Convert(time_t Month, time_t Day, time_t Year,
+       time_t Hours, time_t Minutes, time_t Seconds,
+       MERIDIAN Meridian, DSTMODE dst)
 {
     static int DaysNormal[13] = {
        0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31
@@ -533,9 +522,7 @@ Convert(Month, Day, Year, Hours, Minutes, Seconds, Meridian, dst)
 
 
 static time_t
-DSTcorrect(Start, Future)
-    time_t     Start;
-    time_t     Future;
+DSTcorrect(time_t Start, time_t Future)
 {
     time_t     StartDay;
     time_t     FutureDay;
@@ -547,9 +534,7 @@ DSTcorrect(Start, Future)
 
 
 static time_t
-RelativeMonth(Start, RelMonth)
-    time_t     Start;
-    time_t     RelMonth;
+RelativeMonth(time_t Start, time_t RelMonth)
 {
     struct tm  *tm;
     time_t     Month;
@@ -567,9 +552,7 @@ RelativeMonth(Start, RelMonth)
 
 
 static int
-LookupWord(buff, length)
-    char               *buff;
-    register int       length;
+LookupWord(char *buff, register int length)
 {
     register char      *p;
     register char      *q;
@@ -659,7 +642,7 @@ LookupWord(buff, length)
 
 
 int
-date_lex()
+date_lex(void)
 {
     register char      c;
     register char      *p;
@@ -722,10 +705,9 @@ date_lex()
 
 
 time_t
-parsedate(p)
-    char               *p;
+parsedate(char *p)
 {
-    extern int         date_parse();
+    extern int         date_parse(void);
     time_t             Start;
 
     yyInput = p;
@@ -775,9 +757,7 @@ extern int  yydebug;
 
 /* ARGSUSED */
 int
-main(ac, av)
-    int                ac;
-    char       *av[];
+main(int ac, char *av[])
 {
     char       buff[128];
     time_t     d;
index 5d2136b559c19ab31a84d230091c01f047e59c7d..d370d03feedbcd69c5485dd7ab997522c388399d 100644 (file)
 #include "tools.h"
 #include "internet_addressing.h"
 
-struct citsmtp {
+
+struct citsmtp {               /* Information about the current session */
        int command_state;
        struct usersupp vrfy_buffer;
        int vrfy_count;
        char vrfy_match[256];
        char from[256];
+       char recipient[256];
+       int number_of_recipients;
 };
 
-enum {
+enum {                         /* Command states for login authentication */
        smtp_command,
        smtp_user,
        smtp_password
@@ -85,6 +88,7 @@ void smtp_hello(char *argbuf, int is_esmtp) {
  */
 void smtp_help(void) {
        cprintf("214-Here's the frequency, Kenneth:\n");
+       cprintf("214-    DATA\n");
        cprintf("214-    EHLO\n");
        cprintf("214-    EXPN\n");
        cprintf("214-    HELO\n");
@@ -305,6 +309,7 @@ void smtp_mail(char *argbuf) {
                if (!strcasecmp(node, config.c_nodename)) { /* FIX use fcn */
                        cprintf("550 You must log in to send mail from %s\n",
                                config.c_fqdn);
+                       strcpy(SMTP->from, "");
                        return;
                }
        }
@@ -318,18 +323,71 @@ void smtp_mail(char *argbuf) {
  * Implements the "RCPT To:" command
  */
 void smtp_rcpt(char *argbuf) {
+       int cvt;
+       char user[256];
+       char node[256];
 
        if (strlen(SMTP->from) == 0) {
                cprintf("503 MAIL first, then RCPT.  Duh.\n");
                return;
        }
 
+       if (strlen(SMTP->recipient) > 0) {
+               cprintf("550 Only one recipient allowed (FIX)\n");
+               return;
+       }
+
        if (strncasecmp(argbuf, "To:", 3)) {
                cprintf("501 Syntax error\n");
                return;
        }
 
-       cprintf("599 this is unfinished\n");
+       strcpy(SMTP->recipient, &argbuf[3]);
+       striplt(SMTP->recipient);
+
+       cvt = convert_internet_address(user, node, SMTP->recipient);
+       switch(cvt) {
+               case rfc822_address_locally_validated:
+                       cprintf("250 %s is a valid recipient.\n", user);
+                       return;
+               case rfc822_no_such_user:
+                       cprintf("550 %s: no such user\n", SMTP->recipient);
+                       strcpy(SMTP->recipient, "");
+                       return;
+       }
+
+       strcpy(SMTP->recipient, "");
+       cprintf("599 Unknown error (FIX)\n");
+}
+
+
+
+
+/*
+ * Implements the DATA command
+ */
+void smtp_data(void) {
+       char *body;
+
+       if (strlen(SMTP->from) == 0) {
+               cprintf("503 Need MAIL command first.\n");
+               return;
+       }
+
+       if (SMTP->number_of_recipients < 1) {
+               cprintf("503 Need RCPT command first.\n");
+               return;
+       }
+
+       cprintf("354 Transmit message now; terminate with '.' by itself\n");
+       body = CtdlReadMessageBody(".", config.c_maxmsglen);
+       if (body == NULL) {
+               cprintf("550 Unable to save message text: internal error.\n");
+               return;
+       }
+
+       phree(body);
+       cprintf("599 command unfinished\n");
 }
 
 
@@ -363,6 +421,10 @@ void smtp_command_loop(void) {
                smtp_auth(&cmdbuf[5]);
        }
 
+       else if (!strncasecmp(cmdbuf, "DATA", 4)) {
+               smtp_data();
+       }
+
        else if (!strncasecmp(cmdbuf, "EHLO", 4)) {
                smtp_hello(&cmdbuf[5], 1);
        }
index 8117cf1d26fce9ce9f18c8d8d06c8a65db49e105..052122e6607d1461ff14bd5e616fbe7bb5701646 100644 (file)
@@ -260,13 +260,13 @@ int collapsed_strcmp(char *s1, char *s2) {
        c2 = strdup(s2);
 
        for (i=0; i<strlen(c1); ++i) {
-               if (isupper(c1[i])) c1[i]=tolower(c1[i]);
                while (!isalnum(c1[i])) strcpy(&c1[i], &c1[i+1]);
+               if (isupper(c1[i])) c1[i]=tolower(c1[i]);
        }
 
        for (i=0; i<strlen(c2); ++i) {
-               if (isupper(c2[i])) c2[i]=tolower(c2[i]);
                while (!isalnum(c2[i])) strcpy(&c2[i], &c2[i+1]);
+               if (isupper(c2[i])) c2[i]=tolower(c2[i]);
        }
 
        ret = strcmp(c1, c2);