From:	SMTP%"MX-List%WKUVX1.BITNET@uu7.psi.com" 19-MAY-1993 08:30:42.23
To:	EVERHART
CC:	
Subj:	Re: Missing Message-ID tags

X-Listname: Message Exchange Discussion List <MX-List@WKUVX1.BITNET>
Warnings-To: <>
Errors-To: list-mgr%WKUVX1.BITNET@uu7.psi.com
Sender: list-mgr%WKUVX1.BITNET@uu7.psi.com
X-Newsgroups: vmsnet.mail.mx
Subject: Re: Missing Message-ID tags
Message-Id: <1993May19.132707.755@hhcs.gov.au>
From: Carl Makin <makinc%hhcs.gov.au@ULKYVM.LOUISVILLE.EDU>
Reply-To: MX-List%WKUVX1.BITNET@uu7.psi.com
Date: 19 May 93 13:27:07 +1000
Distribution: world
Organization: Government mouthful incorporated
Nntp-Posting-Host: 163.127.2.21
X-Useragent: Nuntius v1.1.1d17X-XXDate: Wed, 19 May 93 21:26:20 GMTLines: 246
Lines: 246
To: MX-List@WKUVX1.BITNET
X-Gateway-Source-Info: USENET

In article <1993May17.180612.182@kenyon.edu> , oursler@kenyon.edu writes:

>       Recently, while gatewaying several mailing-lists into
>       local newsgroups for my convenience, I encountered a problem.
>
>        It seems that messages from one of the lists (PMAIL) do
>        not have message-id tags associated with them.  This
>        causes ANU News to be very unhappy and the messages
>        cannot be posted.

I had the same problem a coupel of weeks ago.

>        All of my other mailing list messages have message-ids
>        tags. In fact, all my other Internet mail messages seem
>        to have message-ids tags.  I assume that it must be
>        something the mailer at the other end does or doesn't do.

Message IDs are generated by the mailer.  MX generates them for mail
entering from VMS MAIL and the majority of Internet mailers generate them
as well, however, I'm using Eudora on a Mac and it doesn't. :-(

To fix it I changed the gatemail.c file so that if the message didn't
have a message id it created one.

I used a logical MX_GATE_ID to define the psuedo news node the ID
comes from and I make it different to the ANU News node name to make
sure it is unique.


Here is the complete GATEMAIL.C file with the update;

/*
 *    Gatemail - a program to convert Mail messages from a mailing list into
 *               News articles suitable for input to the ANU-NEWS ADD FILE
 *               command.
 *
 *    Copyright 1989 by Robert R. Sloane <sloane@kuhub.cc.ukans.edu>.
 *               Permission is granted to anyone to make or distribute copies
 *               of this program, provided that this copyright notice is
 *               preserved.
 *
 *      Updated to support MX by Ted Nieland <nieland_t@asd-yf.wpafb.af.mil>
 *      March 1991
 *
 *  Updated May 1993 to generate Message-ID's for messages that don't
 *  have them.  Carl Makin <makinc@hhcs.gov.au>
 *
 */
#include <stdio.h>
#include <ssdef.h>
#include time
#include unixlib

FILE *mfd;      /* MAIL file */
FILE *bfd;      /* NEWS Batch file */

static unsigned mpid;

main(int argc, char **argv) {
    char line[1024];
    int i;
/*
 *    make sure user gave us both file names and the newsgroup name.
 */
    if (argc < 2) {
        printf("Usage: gtmail <input> <output> <list-address> <newsgroup>\n");
        exit(SS$_NORMAL);
    }
    if (argc < 5)
        exit(SS$_INSFARG);
/*
 *    now open the input file
 */
    if ( !(mfd=fopen(argv[1],"r")) ) {
        perror("can't open input file:");
        exit(SS$_ABORT);
    }
/*
 *    and the output file
 */
    if ( !(bfd=fopen(argv[2],"a")) ) {
        perror("can't open output file:");
        exit(SS$_ABORT);
    }
/*
 *    now Start processing the mail message
 */
    while ( get_head(line) ) {
/*
 *    check to see if this is the start of a new mail message
 *    and if it is, process it.  MX will Start the message with the
 *    "Received: " part of the header
 */
        if ( strncmp(line,"Received: ",10) == 0 ) {
/*
 *    now output the headers we want to keep
 */
            fputs("#! rnews ???\n",bfd);        /* output batch separator */
            fputs("Path: ",bfd); fputs(argv[3],bfd); fputs("\n",bfd);
            fputs("Newsgroups: ",bfd); fputs(argv[4],bfd); fputs("\n",bfd);
/*
 *    go through the rest of the header of the message
 *    drop any Path headers, received headers, and such that will
 *    confuse NEWS.  Any others just copy into the output file.
 */
            mpid = 0;
            while (get_head(line)) {            /* look for first null line */
                if (strncmp(line,"Return-path: ",13) == 0 )continue;
                if (strncmp(line,"Newsgroups: ", 12) == 0 )continue;
                if (strncmp(line,"Message-ID: ", 12) == 0 ) {
                        fputs(line,bfd);
                        mpid = 1;
                        continue; }
                if (strncmp(line,"Received: ",   10) == 0 )continue;
                if (strncmp(line,"X-To: ",        6) == 0 )continue;
                if (strncmp(line,"Path: ",        6) == 0 )continue;
                if (strncmp(line,"To: ",          4) == 0 )continue;
                fputs(line,bfd);
            }
            if (!mpid)
                fprintf(bfd,
                     "Message-ID: <%x@%s>\n",time(NULL),getenv("MX_GATE_ID"));

            fputs("\n",bfd);                    /* mark end of headers */
        }
/*
 *    if we get here, the headers are done, so copy each line of the text
 */
        else {
/*
 *    Check each line, and if it looks like and NEWS Batch file separator,
 *    put a > in front of is, so NEWS won't get confused.
 */
            if (!strncmp(line,"#! rnews ",9))
                fputs(">",bfd);
            fputs(line,bfd);
        }
    }
    while (get_line(line)) {            /* look for first null line */
        fputs(line,bfd);
    }
}
/*
 *    get_line: get one line of text from the input file, exit on EOF.
 *              If the line consists of just a form feed, concatenate the
 *              next line on the end.  Makes looking for \f\nFrom:\t that
 *              separates mail messages easier to find.
 */
get_line( char *line ) {
    int status;
    extern char *mygets();
/*
 *    read the next line from the file
 */
    if ( !mygets(line,1024,mfd) ) {
        fclose(bfd);
        exit(SS$_NORMAL);
    }
/*
 *    if this line is just a FORMFEED, Combine it with the next line
 */
    if ( line[0] == '\f' && line[1] == '\n' ) {
        if ( !mygets(line+2,1022,mfd) ) {  /* get the next line */
            fclose(bfd);                  /* trailing formfeeds ignored */
            exit(SS$_NORMAL);
        }
    }
    return 1;
}
/*
 *    get_head: routine to get a single header line from the input file.
 *              RFC822 standard continuation lines are concatenated together
 *              to make processing easier.  I assume that no header line will
 *              be longer than 1024 characters.
 */
get_head( char *line ) {
    int ch;
    extern char *mygets();
/*
 *    read the header line
 */
    if ( !mygets(line,1024,mfd) ) {
        fclose(bfd);                        /* close off the output file */
        exit(SS$_ENDOFFILE);                /* error in header, exit */
    }
/*
 *    if this line is just a newline, then we have reached the end of the
 *    headers.
 */
    if ( *line == '\n' ) return 0;
/*
 *    if the next line begins with a blank, then it is a continuation
 *    of this line. Append it to the end of the current line.
 */
    while ( ungetc(getc(mfd),mfd) == ' ' )
        if ( !mygets(line+strlen(line),1024-strlen(line),mfd) ) {
            fclose(bfd);
            exit(SS$_ENDOFFILE);
        }
    return 1;
}
/*
 *    You may have been wondering why I used mygets rather than the standard
 *    C library routine gets.  I started out that way, but there seems to be
 *    a problem in the C library when using ungetc, getc, and gets together
 *    on the same file.  It was easier to just write my own than try to find
 *    out what the problem was with DEC's routine.
 */
char *mygets( char *line, int max, FILE *fd ) {
    int i,ch;
/*
 *    read up to max characters from the input file
 */
    for ( i=0; i<max-1; ++i ) {
/*
 *    if there are no more characters, exit
 */
        if ( (ch=getc(fd)) == EOF ) {
            line[i] = '\0';
            return 0;
        }
/*
 *    stuff the current character in the users line buffer
 */
        line[i] = ch;
/*
 *    if this is a newline, then we are done for now, so return.
 */
        if ( ch == '\n' ) {
            line[i+1] = '\0';          /* put EOS on the end of the string */
            return line;
        }
    }
/*
 *    if we get here, the line was longer than the users buffer.
 *    put and EOS on the string, and return.
 */
    line[max] = '\0';
    return line;
}
--
Carl Makin (VK1KCM)
Internet:     makinc@hhcs.gov.au
Amprnet:      vk1kcm@vk1kcm.act.aus.oc
"Life is something to do when you can't get to sleep."
                          - Fran Lebowitz
