OSSP CVS Repository

ossp - Check-in [1010]
Not logged in
[Honeypot]  [Browse]  [Home]  [Login]  [Reports
[Search]  [Ticket]  [Timeline
  [Patchset]  [Tagging/Branching

Check-in Number: 1010
Date: 2001-Sep-14 14:55:20 (local)
2001-Sep-14 12:55:20 (UTC)
User:rse
Branch:
Comment: Finish and enhance the SMTP channel implementation. - use 4KB buffers, because a single SMTP line is already allowed to be up to 1KB in size. - use the cleanup macros to get rid of the deep if-cascade. - add support for correct RFC2821/RFC2822 dot escaping - add RFC2822-compliant Date header - reduce User-Agent header to just "L2/V.R.L"
Tickets:
Inspections:
Files:
ossp-pkg/l2/l2_ch_smtp.c      1.2 -> 1.3     108 inserted, 59 deleted

ossp-pkg/l2/l2_ch_smtp.c 1.2 -> 1.3

--- l2_ch_smtp.c 2001/09/12 09:42:34     1.2
+++ l2_ch_smtp.c 2001/09/14 12:55:20     1.3
@@ -34,6 +34,7 @@
 #include <sys/utsname.h>
 #include <sys/types.h>
 #include <pwd.h>
+#include <time.h>
 
 /* declare private channel configuration */
 typedef struct {
@@ -129,7 +130,7 @@
 
     /* configure socket parameters */
     sa_timeout(cfg->saServer, cfg->nTimeout, 0);
-    sa_buffers(cfg->saServer, 1024, 1024);
+    sa_buffers(cfg->saServer, 4096, 4096);
 
     return L2_OK;
 }
@@ -140,18 +141,18 @@
 {
     l2_ch_smtp_t *cfg = (l2_ch_smtp_t *)ctx->vp;
     char caLine[1024];
-    int bSent;
     sa_t *sa;
     sa_addr_t *saa;
-    sa_rc_t rc;
+    l2_result_t rv = L2_OK;
+    sa_rc_t sa_rv;
     size_t n;
+    const char *cpB;
+    const char *cpE;
+    const char *cpL;
+    struct tm *tm;
+    time_t t;
+    char caDate[80];
     
-    /* establish connection to server */
-    saa = cfg->saaServer;
-    sa  = cfg->saServer;
-    if ((rc = sa_connect(sa, saa)) != SA_OK)
-        return (rc == SA_ERR_SYS ? L2_ERR_SYS : L2_ERR_INT);
-
     /* 
      * Sample SMTP transaction for reference:
      *
@@ -164,70 +165,118 @@
      * | 250 2.1.5 <rse@engelschall.com>... Recipient ok
      * | DATA
      * | 354 Enter mail, end with "." on a line by itself
-     * | From: l2@localhost
+     * | Date: Fri, 14 Sep 2001 14:50:51 CEST
+     * | From: rse@en1.engelschall.com
      * | To: rse@engelschall.com
-     * | Subject: [L2] SMTP channel output
+     * | Subject: [L2] log channel output on en1.engelschall.com
+     * | User-Agent: L2/0.1.0                                                                              
      * |
-     * | test log entry
+     * | A program of user rse on host en1.engelschall.com logged:
+     * | [2001-09-10/01:02:03] <notice> sample logging message
      * | .
      * | 250 2.0.0 f88Aev847031 Message accepted for delivery
      * | QUIT
      * | 221 2.0.0 en1.engelschall.com closing connection
      *
-     * For more details about SMTP, see RFC 2821: 
-     * Simple Mail Transfer Protocol; J. Klensin; April 2001.
+     * For more details read:
+     * RFC 2821: Simple Mail Transfer Protocol; J. Klensin; April 2001.
+     * RFC 2822: Internet Message Format; P. Resnick; April 2001.
      */
 
-    bSent = FALSE;
-    if (sa_readline(sa, caLine, sizeof(caLine), &n) == SA_OK
-        && n > 3 && atoi(caLine) == 220) {
-        sa_printf(sa, "HELO %s\r\n", cfg->cpLocalHost);
-        if (sa_readline(sa, caLine, sizeof(caLine), &n) == SA_OK
-            && n > 3 && atoi(caLine) == 250) {
-            sa_printf(sa, "MAIL FROM:<%s>\r\n", cfg->cpFrom);
-            if (sa_readline(sa, caLine, sizeof(caLine), &n) == SA_OK
-                && n > 3 && atoi(caLine) == 250) {
-                sa_printf(sa, "RCPT TO:<%s>\r\n", cfg->cpRcpt);
-                if (sa_readline(sa, caLine, sizeof(caLine), &n) == SA_OK
-                    && n > 3 && atoi(caLine) == 250) {
-                    sa_printf(sa, "DATA\r\n");
-                    if (sa_readline(sa, caLine, sizeof(caLine), &n) == SA_OK
-                        && n > 3 && atoi(caLine) == 354) {
-                        sa_printf(sa, "From: %s\r\n", cfg->cpFrom);
-                        sa_printf(sa, "To: %s\r\n", cfg->cpRcpt);
-                        sa_printf(sa, "Subject: %s\r\n", cfg->cpSubject);
-                        if (cfg->cpLocalProg != NULL)
-                            sa_printf(sa, "User-Agent: %s, %s\r\n", 
-                                       cfg->cpLocalProg, l2_version.v_gnu);
-                        else
-                            sa_printf(sa, "User-Agent: %s\r\n", l2_version.v_gnu);
-                        sa_printf(sa, "\r\n");
-                        if (cfg->cpLocalProg != NULL)
-                            sa_printf(sa, "Program %s of user %s on host %s logged:\r\n", 
-                                       cfg->cpLocalProg, cfg->cpLocalUser, cfg->cpLocalHost);
-                        else
-                            sa_printf(sa, "A program of user %s on host %s logged:\r\n", 
-                                       cfg->cpLocalUser, cfg->cpLocalHost);
-                        /* FIXME: dot-escaping and remove doubled newline */
-                        sa_write(sa, buf, buf_size, &n);
-                        sa_printf(sa, "\r\n");
-                        sa_printf(sa, ".\r\n");
-                        if (sa_readline(sa, caLine, sizeof(caLine), &n) == SA_OK
-                            && n > 3 && atoi(caLine) == 250) {
-                            sa_printf(sa, "QUIT\r\n");
-                            sa_readline(sa, caLine, sizeof(caLine), &n);
-                            bSent = TRUE;
-                        }
-                    }
-                }
-            }
-        }
+    /* establish connection to server */
+    saa = cfg->saaServer;
+    sa  = cfg->saServer;
+    if ((sa_rv = sa_connect(sa, saa)) != SA_OK)
+        cu(sa_rv == SA_ERR_SYS ? L2_ERR_SYS : L2_ERR_INT);
+
+    /* | 220 en1.engelschall.com ESMTP SMTP Sendmail 8.11.0+ ready */
+    sa_rv = sa_readline(sa, caLine, sizeof(caLine), &n);
+    cu_on(!(sa_rv == SA_OK && n > 3 && atoi(caLine) == 220), L2_ERR_IO);
+    
+    /* | HELO l2
+     * | 250 en1.engelschall.com Hello en1.engelschall.com [141.1.129.1], pleased to meet you */
+    sa_printf(sa, "HELO %s\r\n", cfg->cpLocalHost);
+    sa_rv = sa_readline(sa, caLine, sizeof(caLine), &n);
+    cu_on(!(sa_rv == SA_OK && n > 3 && atoi(caLine) == 250), L2_ERR_IO);
+
+    /* | MAIL From: <l2@localhost>
+     * | 250 2.1.0 <l2@localhost>... Sender ok */
+    sa_printf(sa, "MAIL FROM:<%s>\r\n", cfg->cpFrom);
+    sa_rv = sa_readline(sa, caLine, sizeof(caLine), &n);
+    cu_on(!(sa_rv == SA_OK && n > 3 && atoi(caLine) == 250), L2_ERR_IO);
+
+    /* | RCPT To: <rse@engelschall.com>
+     * | 250 2.1.5 <rse@engelschall.com>... Recipient ok */
+    sa_printf(sa, "RCPT TO:<%s>\r\n", cfg->cpRcpt);
+    sa_rv = sa_readline(sa, caLine, sizeof(caLine), &n);
+    cu_on(!(sa_rv == SA_OK && n > 3 && atoi(caLine) == 250), L2_ERR_IO);
+
+    /* | DATA
+     * | 354 Enter mail, end with "." on a line by itself */
+    sa_printf(sa, "DATA\r\n");
+    sa_rv = sa_readline(sa, caLine, sizeof(caLine), &n);
+    cu_on(!(sa_rv == SA_OK && n > 3 && atoi(caLine) == 354), L2_ERR_IO);
+
+    /* | Date: Fri, 14 Sep 2001 14:50:51 CEST
+     * | From: rse@en1.engelschall.com
+     * | To: rse@engelschall.com
+     * | Subject: [L2] log channel output on en1.engelschall.com
+     * | User-Agent: L2/0.1.0                                                                              
+     * |                                                             */
+    t = time(NULL);
+    tm = localtime(&t);
+    strftime(caDate, sizeof(caDate), "%a, %d %b %Y %H:%M:%S %Z", tm);
+    sa_printf(sa, "Date: %s\r\n", caDate);
+    sa_printf(sa, "From: %s\r\n", cfg->cpFrom);
+    sa_printf(sa, "To: %s\r\n", cfg->cpRcpt);
+    sa_printf(sa, "Subject: %s\r\n", cfg->cpSubject);
+    if (cfg->cpLocalProg != NULL)
+        sa_printf(sa, "User-Agent: %s (%s)\r\n", 
+                  l2_version.v_web, cfg->cpLocalProg);
+    else
+        sa_printf(sa, "User-Agent: %s\r\n", l2_version.v_web);
+    sa_write(sa, "\r\n", 2, NULL);
+
+    /* | A program of user rse on host en1.engelschall.com logged:
+     * | [2001-09-10/01:02:03] <notice> sample logging message      */
+    if (cfg->cpLocalProg != NULL)
+        sa_printf(sa, "Program %s of user %s on host %s logged:\r\n", 
+                   cfg->cpLocalProg, cfg->cpLocalUser, cfg->cpLocalHost);
+    else
+        sa_printf(sa, "A program of user %s on host %s logged:\r\n", 
+                   cfg->cpLocalUser, cfg->cpLocalHost);
+    cpB = buf;
+    cpE = buf;
+    cpL = buf+buf_size;
+    while (cpB < cpL) {
+        for (cpE = cpB; cpE < cpL && (*cpE != '\r' && *cpE != '\n'); cpE++)
+            ;
+        if (*cpB == '.')
+            sa_write(sa, ".", 1, NULL);
+        sa_write(sa, cpB, cpE-cpB, NULL);
+        sa_write(sa, "\r\n", 2, NULL);
+        for (; cpE < cpL && (*cpE == '\r' || *cpE == '\n'); cpE++)
+            ;
+        cpB = cpE;
     }
 
+    /* | .
+     * | 250 2.0.0 f88Aev847031 Message accepted for delivery */
+    sa_write(sa, ".\r\n", 3, NULL);
+    sa_readline(sa, caLine, sizeof(caLine), &n);
+    cu_on(!(sa_rv == SA_OK && n > 3 && atoi(caLine) == 250), L2_ERR_IO);
+
+    /* | QUIT
+     * | 221 2.0.0 en1.engelschall.com closing connection */
+    sa_printf(sa, "QUIT\r\n");
+    sa_readline(sa, caLine, sizeof(caLine), &n);
+
+    cus:
+
     /* shutdown connection to server */
     sa_shutdown(sa, "rw");
 
-    return (bSent ? L2_OK : L2_ERR_IO);
+    return rv;
 }
 
 /* close channel */

CVSTrac 2.0.1