Beispiel #1
0
void retr_msg(int msgnum)
{
    char	    *p, *q, temp[PATH_MAX], *base;
    int		    Header;
    unsigned int    crc = -1;

    snprintf(temp, 81, "RETR %d\r\n", msgnum);
    if (pop3_cmd(temp) == 0) {
	Msg_New();
	Header = TRUE;
	snprintf(temp, PATH_MAX, "%s/%s/mailbox", CFG.bbs_usersdir, exitinfo.Name);
	base = xstrcpy(temp);
	Open_Msgbase(base, 'w');
	Msg.Arrived = time(NULL) - (gmt_offset((time_t)0) * 60);
	Msg.Private = TRUE;
	while (TRUE) {
	    p = pop3_receive();
	    if ((p[0] == '.') && (strlen(p) == 1)) {
		break;
	    } else {
		if (Header) {
		    /*
		     *  Check the primary message header lines.
		     */
		    if (strncmp(p, "To: ", 4) == 0) {
			if (strlen(p) > 104)
			    p[104] = '\0';
			snprintf(Msg.To, 101, "%s", p+4);
		    }
		    if (strncmp(p, "From: ", 6) == 0) {
		        if (strlen(p) > 106)
			    p[106] = '\0';
			snprintf(Msg.From, 101, "%s", p+6);
		    }
		    if (strncmp(p, "Subject: ", 9) == 0) {
			if (strlen(p) > 109)
			    p[109] = '\0';
			snprintf(Msg.Subject, 101, "%s", p+9);
			mbse_CleanSubject(Msg.Subject);
		    }
		    if (strncmp(p, "Date: ", 6) == 0)
			Msg.Written = parsedate(p+6, NULL) - (gmt_offset((time_t)0) * 60);
		    if (strncmp(p, "Message-Id: ", 12) == 0) {
			q = xstrcpy(p+12);
			Msg.MsgIdCRC = upd_crc32(q, crc, strlen(q));
			free(q);
		    }
		    Msg.ReplyCRC = 0xffffffff;
		    if (strlen(p) == 0) {
			Header = FALSE;
		    } else {
			snprintf(temp, PATH_MAX, "\001%s", p);
			MsgText_Add2(temp);
		    }
		} else {
		    MsgText_Add2(p);
		}
	    }
	}
	Msg_AddMsg();
	Msg_UnLock();
	Close_Msgbase(base);
	free(base);
	snprintf(temp, 81, "DELE %d\r\n", msgnum);
	pop3_cmd(temp);
    } else {
	WriteError("POP3: Can't retrieve message %d", msgnum);
    }
}
Beispiel #2
0
/*
 * Kill messages according to age and max messages.
 */
void KillArea(char *Path, char *Name, int DaysOld, int MaxMsgs, int Areanr)
{
    unsigned int    Number, TotalMsgs = 0, *Active, Counter = 0;
    int		    i, DelCount = 0, DelAge = 0, Done;
    time_t	    Today, MsgDate;

    IsDoing("Killing %ld", Areanr);
    Today = time(NULL) / 86400L;

    if (Msg_Open(Path)) {

	if (!do_quiet) {
	    mbse_colour(LIGHTRED, BLACK);
	    printf(" (Killing)");
	    mbse_colour(LIGHTMAGENTA, BLACK);
	    fflush(stdout);
	}

	if (Msg_Lock(30L)) {

	    TotalMsgs = Msg_Number();

	    if (TotalMsgs) {
		if ((Active = (unsigned int *)malloc((size_t)((TotalMsgs + 100L) * sizeof(unsigned int)))) != NULL) {
		    i = 0;
		    Number = Msg_Lowest();
		    do {
			Active[i++] = Number;
		    } while (Msg_Next(&Number) == TRUE);
		}
	    } else
		Active = NULL;

	    Number  = Msg_Lowest();

	    do {
		if (CFG.slow_util && do_quiet)
		msleep(1);

		if ((!do_quiet) && ((Counter % 10L) == 0)) {
		    printf("%6u / %6u\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b", Counter, TotalMsgs);
		    fflush(stdout);
		}
		if ((Counter % 10L) == 0)
		    DoNop();

		Counter++;
		msg_tot++;

		if (Msg_ReadHeader(Number) == TRUE) {
		    Done = FALSE;
		    if (DaysOld) {
			/*
			 * GoldED doesn't fill the Msg.Arrived field, use the
			 * written date instead.
			 */
			if (Msg.Arrived == 0L)
			    MsgDate = Msg.Written / 86400L;
			else
			    MsgDate = Msg.Arrived / 86400L;

			if ((Today - MsgDate) > DaysOld) {
			    Msg_Delete(Number);
			    Done = TRUE;
			    DelAge++;
			    msg_del++;
			    if (Active != NULL) {
				for (i = 0; i < TotalMsgs; i++) {
				    if (Active[i] == Number)
					Active[i] = 0L;
				}
			    }
			}
		    }

		    if (Done == FALSE && (MaxMsgs) && Msg_Number() > MaxMsgs) {
			Msg_Delete(Number);
			DelCount++;
			msg_del++;
			if (Active != NULL) {
			    for (i = 0; i < TotalMsgs; i++) {
				if (Active[i] == Number)
				    Active[i] = 0L;
			    }
			}
		    }
		} 
	    } while (Msg_Next(&Number) == TRUE);

	    if (Active != NULL)
		free(Active);
	    Msg_UnLock();
	} else {
	    Syslog('+', "Can't lock msgbase %s", Path);
	}

	if (!do_quiet) {
	    printf("               \b\b\b\b\b\b\b\b\b\b\b\b\b\b\b");
	    fflush(stdout);
	}

	Msg_Close();
	Syslog('-', "%6d    %6d %6d   %6d %6d %s", TotalMsgs, DaysOld, DelAge, MaxMsgs, DelCount, Name);

	if (!do_quiet) {
	    printf("\b\b\b\b\b\b\b\b\b\b          \b\b\b\b\b\b\b\b\b\b");
	    fflush(stdout);
	}
    } else
	Syslog('+', "Failed to open %s", Path);
}
Beispiel #3
0
int Read_a_Email(unsigned int Num)
{
    char        *p = NULL, *fn, *charset = NULL, *charsin = NULL;
    lastread    LR;
    unsigned int	mycrc;

    LastNum = Num;
    iLineCount = 7;
    WhosDoingWhat(READ_POST, NULL);

    /*
     * The area data is already set, so we can do the next things
     */
    if (EmailBase.Total == 0) {
	Enter(1);
	/* There are no messages in this area */
	pout(WHITE, BLACK, (char *) Language(205));
	Enter(2);
	sleep(3);
	return FALSE;
    }

    if (!Msg_Open(sMailpath)) {
	WriteError("Error open JAM base %s", sMailpath);
	return FALSE;
    }

    if (!Msg_ReadHeader(Num)) {
	Enter(1);
	pout(WHITE, BLACK, (char *)Language(77));
	Enter(2);
	Msg_Close();
	sleep(3);
	return FALSE;
    }

    /*
     * Fill Quote file in case the user wants to reply. Note that line
     * wrapping is set lower then normal message read, to create room
     * for the Quote> strings at the start of each line.
     */
    fn = calloc(PATH_MAX, sizeof(char));
    snprintf(fn, PATH_MAX, "%s/%s/.quote", CFG.bbs_usersdir, exitinfo.Name);
    if ((qf = fopen(fn, "w")) != NULL) {
	if (Msg_Read(Num, 75)) {
	    if ((p = (char *)MsgText_First()) != NULL)
		do {
		    if (p[0] == '\001') {
			/*
			 * Check CHRS kludge
			 */
			if (strncmp(p, "\001CHRS: ", 7) == 0) {
			    charset = xstrcpy(p + 7);
			}
			/*
			 * While doing this, store the original Message-id in case
			 * a reply will be made.
			 */
			if (strncasecmp(p, "\001Message-id: ", 13) == 0) {
			    snprintf(Msg.Msgid, sizeof(Msg.Msgid), "%s", p+13);
			    Syslog('m', "Stored Msgid \"%s\"", Msg.Msgid);
			}
			if (Kludges) {
			    p[0] = 'a';
			    fprintf(qf, "^%s\n", p);
			}
		    } else
			fprintf(qf, "%s\n", p);
		} while ((p = (char *)MsgText_Next()) != NULL);
	}
	fclose(qf);
    } else {
	WriteError("$Can't open %s", p);
    }
    free(fn);

    if (charset == NULL) {
	charsin = xstrcpy((char *)"CP437");
    } else {
    	charsin = xstrcpy(get_ic_ftn(find_ftn_charset(charset)));
    }

    /*
     * Setup character translation
     */
    chartran_init(charsin, get_ic_ftn(exitinfo.Charset), 'b');

    ShowEmailHdr();

    /*
     * Show message text
     */
    colour(CFG.TextColourF, CFG.TextColourB);
    if (Msg_Read(Num, 79)) {
	if ((p = (char *)MsgText_First()) != NULL) {
	    do {
		if (p[0] == '\001') {
		    if (Kludges) {
			colour(LIGHTGRAY, BLACK);
			if (p[0] == '\001')
			    p[0] = 'a';
			PUTSTR(chartran(p));
			Enter(1);
			if (CheckLine(CFG.TextColourF, CFG.TextColourB, TRUE))
			    break;
		    }
		} else {
		    colour(CFG.TextColourF, CFG.TextColourB);
		    if (strchr(p, '>') != NULL)
			if ((strlen(p) - strlen(strchr(p, '>'))) < 10)
			    colour(CFG.HiliteF, CFG.HiliteB);
		    PUTSTR(chartran(p));
		    Enter(1);
		    if (CheckLine(CFG.TextColourF, CFG.TextColourB, TRUE))
			break;
		}
	    } while ((p = (char *)MsgText_Next()) != NULL);
	}
    }

    if (charset)
    	free(charset);
    if (charsin)
    	free(charsin);
    chartran_close();

    /*
     * Set the Received status on this message.
     */
    if (!Msg.Received) {
	Syslog('m', "Marking message received");
	Msg.Received = TRUE;
	Msg.Read = time(NULL) - (gmt_offset((time_t)0) * 60);
	if (Msg_Lock(30L)) {
	    Msg_WriteHeader(Num);
	    Msg_UnLock();
	}
    }

    /*
     * Update lastread pointer.
     */
    p = xstrcpy(exitinfo.sUserName);
    mycrc = StringCRC32(tl(p));
    free(p);
    if (Msg_Lock(30L)) {
        LR.UserID = grecno;
	LR.UserCRC = mycrc;
        if (Msg_GetLastRead(&LR) == TRUE) {
            LR.LastReadMsg = Num;
            if (Num > LR.HighReadMsg)
                LR.HighReadMsg = Num;
            if (LR.HighReadMsg > EmailBase.Highest)
                LR.HighReadMsg = EmailBase.Highest;
            LR.UserCRC = mycrc;
	    if (!Msg_SetLastRead(LR))
                WriteError("Error update lastread");
	} else {
            /*
             * Append new lastread pointer
             */
            LR.UserCRC = mycrc;
            LR.UserID  = grecno;
            LR.LastReadMsg = Num;
            LR.HighReadMsg = Num;
            if (!Msg_NewLastRead(LR))
                WriteError("Can't append lastread");
        }
        Msg_UnLock();
    }

    Msg_Close();
    return TRUE;
}
Beispiel #4
0
/*
 *  Save the message to disk.
 */
int Save_Email(int IsReply)
{
    int             i;
    char            *p, *temp;
    unsigned int    crc = -1;
    int		    id;
    FILE	    *fp;

    if (Line < 2)
	return TRUE;

    if (!Open_Msgbase(sMailpath, 'w')) {
	return FALSE;
    }

    Msg.Arrived = time(NULL) - (gmt_offset((time_t)0) * 60);
    Msg.Written = Msg.Arrived;
    Msg.Local = TRUE;
    Msg.Netmail = TRUE;
    temp = calloc(PATH_MAX, sizeof(char));

    /*
     * Add header lines
     */
    snprintf(temp, PATH_MAX, "\001Date: %s", rfcdate(Msg.Written));
    MsgText_Add2(temp);
    snprintf(temp, PATH_MAX, "\001From: %s", Msg.From);
    MsgText_Add2(temp);
    snprintf(temp, PATH_MAX, "\001Subject: %s", Msg.Subject);
    MsgText_Add2(temp);
    snprintf(temp, PATH_MAX, "\001Sender: %s", Msg.From);
    MsgText_Add2(temp);
    snprintf(temp, PATH_MAX, "\001To: %s", Msg.To);
    MsgText_Add2(temp);
    MsgText_Add2((char *)"\001MIME-Version: 1.0");
    if (exitinfo.Charset != FTNC_NONE) {
	snprintf(temp, PATH_MAX, "\001Content-Type: text/plain; charset=%s", getrfcchrs(exitinfo.Charset));
    } else {
	snprintf(temp, PATH_MAX, "\001Content-Type: text/plain; charset=iso8859-1");
    }
    MsgText_Add2(temp);
    MsgText_Add2((char *)"\001Content-Transfer-Encoding: 8bit");
    snprintf(temp, PATH_MAX, "\001X-Mailreader: MBSE BBS %s", VERSION);
    MsgText_Add2(temp);
    p = calloc(81, sizeof(char));
    id = sequencer();
    snprintf(p, 81, "<%08x@%s>", id, CFG.sysdomain);
    snprintf(temp, PATH_MAX, "\001Message-id: %s", p);
    MsgText_Add2(temp);
    Msg.MsgIdCRC = upd_crc32(temp, crc, strlen(temp));
    free(p);

    if (IsReply) {
	snprintf(temp, PATH_MAX, "\001In-reply-to: %s", Msg.Replyid);
	MsgText_Add2(temp);
	crc = -1;
	Msg.ReplyCRC = upd_crc32(temp, crc, strlen(temp));
    } else
	Msg.ReplyCRC = 0xffffffff;

    /*
     * Add message text
     */
    for (i = 1; i < Line; i++) {
	MsgText_Add2(Message[i]);
    }

    /*
     * Add signature.
     */
    snprintf(temp, PATH_MAX, "%s/%s/.signature", CFG.bbs_usersdir, exitinfo.Name);
    if ((fp = fopen(temp, "r"))) {
        Syslog('m', "  Add .signature");
        MsgText_Add2((char *)"");
        while (fgets(temp, 80, fp)) {
	    Striplf(temp);
	    MsgText_Add2(temp);
	}
	fclose(fp);
	MsgText_Add2((char *)"");
    }
    MsgText_Add2(TearLine());

    /*
     * Save if to disk
     */
    Msg_AddMsg();
    Msg_UnLock();

    ReadExitinfo();
    exitinfo.iPosted++;
    mib_posted++;
    WriteExitinfo();

    do_mailout = TRUE;
    LC_Wrote = TRUE;

    Syslog('+', "Email (%ld) to \"%s\", \"%s\", in mailbox", Msg.Id, Msg.To, Msg.Subject);

    Enter(1);
    /* Saving message to disk */
    snprintf(temp, 81, "%s(%d)", (char *) Language(202), Msg.Id);
    pout(CFG.HiliteF, CFG.HiliteB, temp);
    Enter(2);
    sleep(2);

    /*
     * Add quick mailscan info
     */
    snprintf(temp, PATH_MAX, "%s/tmp/netmail.jam", getenv("MBSE_ROOT"));
    if ((fp = fopen(temp, "a")) != NULL) {
	fprintf(fp, "%s/%s/mailbox %u\n", CFG.bbs_usersdir, exitinfo.Name, Msg.Id);
	fclose(fp);
    }

    free(temp);
    Close_Msgbase(sMailpath);

    return TRUE;
}
Beispiel #5
0
/*
 * Link messages in one area.
 * Returns -1 if error, else the number of linked messages.
 */
int Msg_Link(char *Path, int do_quiet, int slow_util)
{
    int             i, m, msg_link = 0;
    unsigned int    Number, Prev, Next, Crc, Total;
    char            Temp[128], *p;
    MSGLINK         *Link;
        
    if (! Msg_Open(Path)) {
	return -1;
    }

    if (!do_quiet) {
	msg_colour(LIGHTRED, BLACK);
	printf(" (linking)");
	msg_colour(LIGHTMAGENTA, BLACK);
	fflush(stdout);
    }

    if ((Total = Msg_Number()) != 0L) {
	if (Msg_Lock(30L)) {
	    if ((Link = (MSGLINK *)malloc((Total + 1) * sizeof(MSGLINK))) != NULL) {
		memset(Link, 0, (Total + 1) * sizeof(MSGLINK));
		Number = Msg_Lowest();
		i = 0;
		do {
		    Msg_ReadHeader(Number);
		    strcpy(Temp, Msg.Subject);
		    p = strupr(Temp);
		    if (!strncmp(p, "RE:", 3)) {
			p += 3;
			if (*p == ' ')
			    p++;
		    }
		    Link[i].Subject = StringCRC32(p);
		    Link[i].Number = Number;
		    i++;

		    if (((i % 10) == 0) && (!do_quiet)) {
			printf("%6d / %6u\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b", i, Total);
			fflush(stdout);
		    }
		} while(Msg_Next(&Number) == TRUE);

		if (!do_quiet) {
		    printf("%6d / %6u\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b", i, Total);
		    fflush(stdout);
		}
		Number = Msg_Lowest();
		i = 0;
		do {
		    Msg_ReadHeader(Number);
		    Prev = Next = 0;
		    Crc = Link[i].Subject;

		    for (m = 0; m < Total; m++) {
			if (m == i)
			    continue;
			if (Link[m].Subject == Crc) {
			    if (m < i)
				Prev = Link[m].Number;
			    else if (m > i) {
				Next = Link[m].Number;
				break;
			    }
			}
		    }

		    if (((i % 10) == 0) && (!do_quiet)) {
			printf("%6d / %6u\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b", i, Total);
			fflush(stdout);
		    }

		    if (Msg.Original != Prev || Msg.Reply != Next) {
			Msg.Original = Prev;
			Msg.Reply = Next;
			Msg_WriteHeader(Number);
			msg_link++;
		    }

		    i++;
	    
		} while(Msg_Next(&Number) == TRUE);

		if (!do_quiet) {
		    printf("%6d / %6u\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b", i, Total);
		    fflush(stdout);
		}

		free(Link);
	    }

	    if (!do_quiet) {
		printf("               \b\b\b\b\b\b\b\b\b\b\b\b\b\b\b");
		fflush(stdout);
	    }
	    Msg_UnLock();
	} else {
	    Syslog('+', "Can't lock %s", Path);
	    return -1;
	}
    }

    Msg_Close();

    if (!do_quiet) {
	printf("\b\b\b\b\b\b\b\b\b\b          \b\b\b\b\b\b\b\b\b\b");
	fflush(stdout);
    }
    return msg_link;
}
Beispiel #6
0
int Post(char *To, int Area, char *Subj, char *File, char *Flavor)
{
    int		    i, rc = FALSE, has_tear = FALSE, has_origin = FALSE;
    char	    *aka, *temp, *sAreas;
    FILE	    *fp, *tp;
    unsigned int    crc = -1;
    time_t	    tt;
    struct tm	    *t;

    ftnd_CleanSubject(Subj);

    if (!do_quiet) {
	ftnd_colour(CYAN, BLACK);
	printf("Post \"%s\" to \"%s\" in area %d\n", File, To, Area);
    }

    IsDoing("Posting");
    Syslog('+', "Post \"%s\" area %d to \"%s\" flavor %s", File, Area, To, Flavor);
    Syslog('+', "Subject: \"%s\"", Subj);

    if ((tp = fopen(File, "r")) == NULL) {
	WriteError("$Can't open %s", File);
	if (!do_quiet)
	    printf("Can't open \"%s\"\n", File);
	return -1;
    }

    sAreas = calloc(PATH_MAX, sizeof(char));
    snprintf(sAreas, PATH_MAX, "%s/etc/mareas.data", getenv("FTND_ROOT"));
    if ((fp = fopen(sAreas, "r")) == NULL) {
	WriteError("$Can't open %s", sAreas);
	free(sAreas);
	fclose(tp);
	return -1;
    }

    fread(&msgshdr, sizeof(msgshdr), 1, fp);
    if (fseek(fp, (msgshdr.recsize + msgshdr.syssize) * (Area - 1), SEEK_CUR) == 0) {
	if (fread(&msgs, msgshdr.recsize, 1, fp) == 1) {
	    rc = TRUE;
	} else {
	    WriteError("$Can't read area %ld", Area);
	}
    } else {
	WriteError("$Can't seek area %ld", Area);
    }

    free(sAreas);
    if (rc == FALSE) {
	fclose(fp);
	fclose(tp);
	return -1;
    }

    if (!msgs.Active) {
	WriteError("Area %s not active", msgs.Name);
	fclose(fp);
	fclose(tp);
	return -1;
    }

    /*
     * Check the proper syntax in the To parameter, in netmail areas
     * it must have a destination address, in all other areas just a
     * full name.
     */
    if (msgs.Type == NETMAIL) {
	if ((strchr(To, '@') == NULL) || (strstr(To, (char *)".n") == NULL) || (strstr(To, (char *)".z") == NULL)) {
	    WriteError("No address in \"%s\" and area is netmail", To);
	    if (!do_quiet)
		printf("No address in \"%s\" and area is netmail\n", To);
	    fclose(fp);
	    fclose(tp);
	    return -1;
	}
    } else {
	if ((strchr(To, '@')) || (strstr(To, (char *)".n")) || (strstr(To, (char *)".z"))) {
	    WriteError("Address present in \"%s\" and area is not netmail", To);
	    if (!do_quiet)
		printf("Address present in \"%s\" and area is not netmail\n", To);
	    fclose(fp);
	    fclose(tp);
	    return -1;
	}
    }

    if (!Msg_Open(msgs.Base)) {
	WriteError("Can't open %s", msgs.Base);
	fclose(fp);
	fclose(tp);
	return -1;
    }

    if (!Msg_Lock(30L)) {
	WriteError("Can't lock %s", msgs.Base);
	Msg_Close();
	fclose(fp);
	fclose(tp);
	return -1;
    }

    tt = time(NULL);
    t = localtime(&tt);
    Diw = t->tm_wday;
    Miy = t->tm_mon;
    memset(&Msg, 0, sizeof(Msg));
    Msg_New();

    /*
     * Update statistic counter for message area
     */
    fseek(fp, - msgshdr.recsize, SEEK_CUR);
    msgs.Posted.total++;
    msgs.Posted.tweek++;
    msgs.Posted.tdow[Diw]++;
    msgs.Posted.month[Miy]++;
    fwrite(&msgs, msgshdr.recsize, 1, fp);
    fclose(fp);

    /*
     * Start writing the message
     */
    snprintf(Msg.From, 101, CFG.sysop_name);
    snprintf(Msg.To, 101, To);

    /*
     * If netmail, clean the To field.
     */
    if ((msgs.Type == NETMAIL) && strchr(To, '@')) {
	for (i = 0; i < strlen(Msg.To); i++) {
	    if (Msg.To[i] == '_')
		Msg.To[i] = ' ';
	    if (Msg.To[i] == '@') {
		Msg.To[i] = '\0';
		break;
	    }
	}
    }

    snprintf(Msg.Subject, 101, "%s", Subj);
    snprintf(Msg.FromAddress, 101, "%s", aka2str(msgs.Aka));
    Msg.Written = Msg.Arrived = time(NULL) - (gmt_offset((time_t)0) * 60);
    Msg.Local = TRUE;

    if (strchr(Flavor, 'c'))
	Msg.Crash = TRUE;
    if (strchr(Flavor, 'p'))
	Msg.Private = TRUE;
    if (strchr(Flavor, 'h'))
	Msg.Hold = TRUE;

    switch (msgs.Type) {
	case LOCALMAIL:	
			Msg.Localmail = TRUE;
			break;

	case NETMAIL:
			Msg.Netmail = TRUE;
			snprintf(Msg.ToAddress, 101, "%s", ascfnode(parsefaddr(To), 0xff));
			break;

	case ECHOMAIL:
			Msg.Echomail = TRUE;
			break;

	case NEWS:
			Msg.News = TRUE;
			break;
    }

    temp = calloc(PATH_MAX, sizeof(char));
    snprintf(temp, PATH_MAX, "\001MSGID: %s %08x", aka2str(msgs.Aka), sequencer());
    MsgText_Add2(temp);
    Msg.MsgIdCRC = upd_crc32(temp, crc, strlen(temp));
    Msg.ReplyCRC = 0xffffffff;
    snprintf(temp, PATH_MAX, "\001PID: FTND-FIDO %s (%s-%s)", VERSION, OsName(), OsCPU());
    MsgText_Add2(temp);
    if (msgs.Charset != FTNC_NONE) {
	snprintf(temp, PATH_MAX, "\001CHRS: %s", getftnchrs(msgs.Charset));
    } else {
	snprintf(temp, PATH_MAX, "\001CHRS: %s", getftnchrs(FTNC_LATIN_1));
    }
    MsgText_Add2(temp);
    snprintf(temp, PATH_MAX, "\001TZUTC: %s", gmtoffset(tt));
    MsgText_Add2(temp);

    while ((Fgets(temp, PATH_MAX, tp)) != NULL) {
	if (strncmp(temp, "--- ", 4) == 0)
	    has_tear = TRUE;
	if (strncmp(temp, " * Origin: ", 11) == 0)
	    has_origin = TRUE;
    }
    rewind(tp);
    Syslog('m', "has tearline=%s, has origin=%s", has_tear?"True":"False", has_origin?"True":"False");

    /*
     * Add the file as text
     */
    Msg_Write(tp);
    fclose(tp);

    /*
     * Finish the message
     */
    if ((! has_tear) && (! has_origin)) {
	MsgText_Add2((char *)"");
	MsgText_Add2(TearLine());
    }

    if (! has_origin) {
	aka = calloc(40, sizeof(char));

	if (msgs.Aka.point)
	    snprintf(aka, 40, "(%d:%d/%d.%d)", msgs.Aka.zone, msgs.Aka.net, msgs.Aka.node, msgs.Aka.point);
	else
	    snprintf(aka, 40, "(%d:%d/%d)", msgs.Aka.zone, msgs.Aka.net, msgs.Aka.node);

	if (strlen(msgs.Origin))
	    snprintf(temp, 81, " * Origin: %s %s", msgs.Origin, aka);
	else
	    snprintf(temp, 81, " * Origin: %s %s", CFG.origin, aka);

	MsgText_Add2(temp);
	free(aka);
    }

    Msg_AddMsg();
    Msg_UnLock();
    Syslog('+', "Posted message %ld", Msg.Id);

    if (msgs.Type != LOCALMAIL) {
	snprintf(temp, PATH_MAX, "%s/tmp/%smail.jam", getenv("FTND_ROOT"), (msgs.Type == ECHOMAIL) ? "echo" : "net");
	if ((fp = fopen(temp, "a")) != NULL) {
	    fprintf(fp, "%s %u\n", msgs.Base, Msg.Id);
	    fclose(fp);
	}
	CreateSema((char *)"mailout");
    }

    free(temp);
    Msg_Close();

    return 0;
}