Lloyd Zusman <[EMAIL PROTECTED]> writes:
> [ ... ]
>
> And as for this patch itself, remember that it consists solely of
> putting a unique "id" field into the "Received" header. This is a minor
> change, and it mirrors what some other MTA's already do. Even if we
> don't end up using this to facilitate the methodology that I outlined in
> my Modest Proposal, it still is a useful feature in and of itself.
This patch is attached. It's for courier-0.44.2.20040207. It adds an
"id" field to the "Received" header, as in the 3rd line of this example:
Received: from speed.spamwall.net ([::ffff:66.55.26.26])
(TLS: TLSv1/SSLv3,256bits,AES256-SHA)
id 2LYK%swpAQCyOStAlKYKAGP4qUs
by asfast.net with esmtp; Thu, 12 Feb 2004 03:30:41 -0500
The majority of the code in this patch is for the algorithm for
generating the ID. The insertion of the ID itself takes just 2-3 lines
of code.
I have not yet completed the data store module that will make use of
this ID to implement my Modest Proposal. Once I complete and test this
code, I will post it, along with the results of benchmarks that I will
run, comparing it to the rejection/re-insertion methodology.
*** courier/submit.C.orig Mon Dec 15 20:51:29 2003
--- courier/submit.C Thu Feb 12 07:34:41 2004
***************
*** 12,17 ****
--- 12,18 ----
#include "rfc2045/rfc2045charset.h"
#include "rfc1035/rfc1035.h"
#include "rfc1035/rfc1035mxlist.h"
+ #include "rfc2045/rfc2045.h"
#include "numlib/numlib.h"
#include "dbobj.h"
#include "afx.h"
***************
*** 35,41 ****
--- 36,52 ----
#if HAVE_UNISTD_H
#include <unistd.h>
#endif
+ #if TIME_WITH_SYS_TIME
+ #include <sys/time.h>
#include <time.h>
+ #else
+ #if HAVE_SYS_TIME_H
+ #include <sys/time.h>
+ #else
+ #include <time.h>
+ #endif
+ #endif
+ #include <netdb.h>
#define TIMEOUT 1800
***************
*** 935,940 ****
--- 946,1076 ----
static void getrcpt(struct rw_info *rwi);
static void rcpttoerr(int, const char *, struct rw_info *);
+ struct unique_id_buffer
+ {
+ struct in_addr ip;
+ int pid;
+ struct timeval calltime;
+ unsigned int counter;
+ };
+ #define UNIQUE_BUFFER_SIZE (sizeof (unique_id_buffer))
+
+ static int write_unique_bytes(const char *p, size_t l, void *vp)
+ {
+ char **cp = (char **) vp;
+
+ while (l > 0)
+ {
+ switch (*p)
+ {
+ case '\r':
+ case '\n':
+ case '=':
+ p++;
+ l--;
+ continue;
+ case '/':
+ *p++;
+ **cp = '@';
+ break;
+ case '+':
+ *p++;
+ **cp = '%';
+ break;
+ default:
+ **cp = *p++;
+ break;
+ }
+ ++*cp;
+ l--;
+ }
+
+ return 0;
+ }
+
+ union ul_byte_overlay {
+ unsigned long ul;
+ struct {
+ unsigned char b[4];
+ } uc;
+ };
+
+ static unsigned long reverse_bytes(unsigned long item)
+ {
+ union ul_byte_overlay inp;
+ union ul_byte_overlay out;
+
+ inp.ul = item;
+ for (int i = 0; i < 4; i++) {
+ out.uc.b[i] = inp.uc.b[3 - i];
+ }
+ return (out.ul);
+ }
+
+ static char* unique_id()
+ {
+ static char result[ (UNIQUE_BUFFER_SIZE + 3) / 3 * 4 + 1 ];
+ static struct unique_id_buffer unique_id_buff = { 0 };
+
+ char* rp = result;
+ struct rfc2045_encode_info encodeInfo;
+
+ if (unique_id_buff.pid == 0)
+ {
+ char hostbuff[256];
+ struct hostent* he;
+
+ // First call only.
+ unique_id_buff.pid = getpid();
+ gethostname(hostbuff, sizeof (hostbuff) - 1);
+ he = gethostbyname(hostbuff);
+ if (he == NULL)
+ {
+ memset((char*) &unique_id_buff.ip, 0xff,
+ sizeof (unique_id_buff.ip));
+ }
+ else
+ {
+ struct in_addr hin;
+ if (he->h_addrtype != AF_INET ||
+ he->h_length < (int) sizeof (hin))
+ {
+ memset((char*) &unique_id_buff.ip, 0xff,
+ sizeof (unique_id_buff.ip));
+ }
+ else
+ {
+ memcpy((char*) &hin, he->h_addr_list[0],
+ sizeof (hin));
+ memcpy((char*) &unique_id_buff.ip,
+ (char*) &(hin.s_addr),
+ sizeof (unique_id_buff.ip));
+ }
+ }
+ srandomdev();
+ unique_id_buff.counter = (unsigned long) random();
+ }
+
+ gettimeofday(&unique_id_buff.calltime, NULL);
+
+ rfc2045_encode_start(&encodeInfo, "base64", &write_unique_bytes, &rp);
+ rfc2045_encode(&encodeInfo, (char*) &unique_id_buff,
+ UNIQUE_BUFFER_SIZE);
+ rfc2045_encode_end(&encodeInfo);
+ *rp = 0;
+
+ // It doesn't matter if the following increment overflows,
+ // because that will only be a problem if this routine is called
+ // 2**32 times within a single microsecond. By the time systems
+ // are fast enough for this to happen, we should refactor this
+ // routine.
+
+ unique_id_buff.counter =
+ reverse_bytes(reverse_bytes(unique_id_buff.counter) + 1);
+
+ return (result);
+ }
+
static void getrcpts(struct rw_info *rwi)
{
struct mailfrominfo *mf=(struct mailfrominfo *)rwi->udata;
***************
*** 1087,1092 ****
--- 1223,1232 ----
line += identinfo;
line += ')';
}
+
+ // Now, always insert a unique ID
+ line += "\n id ";
+ line += unique_id();
line += "\n by ";
line += config_me();
--
Lloyd Zusman
[EMAIL PROTECTED]