/*
run Lint
Test it with multiple emails.
Handle reloading config file
Check for memory leaks bugs.

In getmail.conf
  get pop=nnn@x.y.com user="fred" pass="abc" group=rec.humor  

  int getmail_update(void)

  Additions:
	header="x-news-gateway:" dash_to_dot prepend="pdx."


	char *prepend;
	int dashtodot;

*/

#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <ctype.h>
#include "emsg.h"
#include "str.h"
#include "cmd.h"
#include "sary.h"
#include "group.h"
#include "dnews.h"
#include "lib.h"
#include "item.h"
#include "chan.h"
#include "hist.h"
#include "expire.h"
#include "feed.h"
#include "post.h"
#include "suck.h"
#include "chan_dmy.h"
#include "db.h"

#undef mymalloc
#undef myfree
#define mymalloc(x) mymalloc2(x,M_GETMAIL)
#define myfree(x) myfree2(x,M_GETMAIL)

#ifdef OS2
#define vsnprintf _vbprintf
#endif



typedef struct LINK {
	int chan,state;
	time_t lastdata;
	String *xin;
	int tisok;
	int upto;
	int inhead,inref,gotref,indrop,dropit;
	char to[BFSZ];
	char mid[BFSZ];
	char ref[BFSZ];
	char realref[BFSZ];
	char subject[BFSZ];
	char from[BFSZ];
	char togroup[BFSZ];
	int gotfrom;
} Link;
typedef struct GETRULES {
	char *user;
	char *pass;
	char *gname;
	char *pophost;
	char *header;
	char *prepend;
	char *recipient;
	int todot;
	struct GETRULES *next;
} Getrules;

void getmail_init(void);
void getmail_read_config(void);
void getmail_config_line(char *xin);
void getmail_rule_add(char *gname, char *pop, char *user, char *pass, char *header, char *prepend, int todot, char *recip);
void getmail_idle(void);
int getmail_close_link(Link *l, char *reason);
int getmail_start(void);
char *email_trim(char *s);

int getmail_data_chan(int chan, char *data, int len);
char *getmail_from(void);
void getmail_data(Link *l, char *line);
int getmail_write(Link *l,char *arg_list, ...);
void hdrs_clear(void);
int hdrs_isdup(char *hdr);
int getmail_store(Link *l, Getrules *g, char *line);
static int cur_date;

static int status_nrules,status_nupdates,status_nok,status_nbad;

static Link lnk;
static Getrules *rules;

enum {P_CLOSED,P_OPENING, P_USER, P_PASS, P_RETR_STATUS, P_RETR, P_QUIT, P_DELE,P_DATA,P_QUIT_STATUS};

void getmail_free(void);
void getmail_init(void)
{
	if (is_readonly()) return;
	getmail_free();
	lnk.chan = -1;
	lnk.state = 0;
	getmail_read_config();
}
void getmail_free(void)
{
	Getrules *g,*gnext;
	getmail_close_link(&lnk,"reloading getmail.conf file");
	for (g=rules;g!=NULL;g=gnext) {
		mystrfree(g->user,SD_GETMAIL);
		mystrfree(g->pass,SD_GETMAIL);
		mystrfree(g->prepend,SD_GETMAIL);
		mystrfree(g->header,SD_GETMAIL);
		mystrfree(g->gname,SD_GETMAIL);
		mystrfree(g->pophost,SD_GETMAIL);
		gnext = g->next;
		myfree(g);
	}
	rules = NULL;	
	status_nrules = 0;
}
void getmail_read_config(void)
{
	FILE *f;
	char *s;
	char bf[BFSZ];

	if (is_readonly()) return;
	cur_date = lib_cdate(file_config("getmail.conf"));

	f = fopen(file_config("getmail.conf"),"r");
	if (f==NULL) {
		imsg("No getmail.conf file, this is ok (%s)\n",file_config("getmail.conf"));
		return;
	}
	for (;!feof(f);) {
		if (fgets(bf,BFSZ-1,f)==NULL) break;
		s = strchr(bf,'\n'); if (s!=NULL) *s = 0;
		getmail_config_line(bf);
	}
	fclosep(f);
}
void getmail_config_line(char *xin)
{
	char *p[100];
	int n;
	int i;
	char gname[BFSZ],user[BFSZ],pass[BFSZ],pop[BFSZ],recipient[BFSZ];
	int todot = FALSE;
	char prepend[BFSZ];
	char header[BFSZ];
/*	header="x-news-gateway:" dash_to_dot prepend="pdx."*/

	strcpy(recipient,"");
	strcpy(prepend,"");
	strcpy(header,"");
	strcpy(gname,"");
	strcpy(pop,"");
	strcpy(user,"");
	strcpy(pass,"");
	n = token_quote(xin,p,99);
	if (n<=0) return;
	if (strncmp(p[0],"#",1)==0) return;
	if (strcmp(p[0],"")==0) return;
	for (i=0; i<n; i++) {
		if (i==0) {
			if (strcmp(p[i],"get")!=0) {
				emsg("First word on getmail.conf line must be 'get' \n");	
				return;
			}
			continue;
		} else if (strcmp(p[i],"group")==0) {
			if (i+2>=n) {emsg("Parameters missing in getmail.conf %s\n",p[i]); return;}
			i++;
			ncpy(gname,p[++i],BFSZ-1); 
		} else if (strcmp(p[i],"header")==0) {
			if (i+2>=n) {emsg("Parameters missing in getmail.conf %s\n",p[i]); return;}
			i++;
			ncpy(header,p[++i],BFSZ-1); 
		} else if (strcmp(p[i],"recipient")==0) {
			if (i+2>=n) {emsg("Parameters missing in getmail.conf %s\n",p[i]); return;}
			i++;
			ncpy(recipient,p[++i],BFSZ-1); 
		} else if (strcmp(p[i],"prepend")==0) {
			if (i+2>=n) {emsg("Parameters missing in getmail.conf %s\n",p[i]); return;}
			i++;
			ncpy(prepend,p[++i],BFSZ-1); 
		} else if (strcmp(p[i],"todot")==0) {
			todot = TRUE;
		} else if (strcmp(p[i],"todots")==0) { /* Added to avoid confusion */
			todot = TRUE;
		} else if (strcmp(p[i],"pop")==0) {
			if (i+2>=n) {emsg("Parameters missing in getmail.conf %s\n",p[i]); return;}
			i++;
			ncpy(pop,p[++i],BFSZ-1); 
		} else if (strcmp(p[i],"user")==0) {
			if (i+2>=n) {emsg("Parameters missing in getmail.conf %s\n",p[i]); return;}
			i++;
			ncpy(user,p[++i],BFSZ-1); 
		} else if (strcmp(p[i],"pass")==0) {
			if (i+2>=n) {emsg("Parameters missing in getmail.conf %s\n",p[i]); return;}
			i++;
			ncpy(pass,p[++i],BFSZ-1); 
		} else {
			emsg("Unknown setting in getmail.conf (%s)\n",p[i]);
		}
	}
	strlwr(header); 
	if (strlen(header)>0) {
		if (strchr(header,':')==NULL) strcat(header,":");
	}
	if (strlen(pop)==0) {emsg("You must define a pop host for each getmail.conf rule\n"); return;}
	if (strlen(pass)==0) {emsg("You must define a password for each getmail.conf rule\n"); return;}
	if (strlen(user)==0) {emsg("You must define a user for each getmail.conf rule\n"); return;}
	if (strlen(header)==0) if (strlen(gname)==0) {emsg("You must define a group for each getmail.conf rule\n"); return;}

	getmail_rule_add(gname,pop,user,pass,header,prepend,todot,recipient);
}
void getmail_rule_add(char *gname, char *pop, char *user, char *pass, char *header, char *prepend, int todot, char *recipient)
{
	Getrules *g = mymalloc(sizeof(Getrules));
	memset(g,0,sizeof(Getrules));
	imsg("getmail: Get %s@%s --> %s\n",user,pop,gname);
	g->gname = mystrdup(gname,SD_GETMAIL);
	g->pophost =  mystrdup(pop,SD_GETMAIL);
	g->user = mystrdup(user,SD_GETMAIL);
	g->pass = mystrdup(pass,SD_GETMAIL);
	g->header = mystrdup(header,SD_GETMAIL);
	g->prepend = mystrdup(prepend,SD_GETMAIL);
	g->recipient = mystrdup(recipient,SD_GETMAIL);
	g->todot = todot;
	g->next = rules;
	status_nrules++;
	rules = g;
}
void getmail_idle(void)
{
	Link *l=&lnk;
	static int last;
	static int lastday;
	int t = lib_gmtime();
	int xnow;

	if (is_readonly()) return;


	if (l->state==P_CLOSED) {
		if (config_true(C_DISKIO_MIN)) return;
		xnow = lib_cdate(file_config("getmail.conf"));
		if (xnow!=cur_date) {
			imsg("getmail: Reload as getmail.conf date changed\n");
			getmail_init();
		}
		return;
	}
	if (t - l->lastdata>300) {
		getmail_close_link(l,"No data received on connection for 5 minutes");
	}
}
static Getrules *cur_rule;
int getmail_update(void)
{
	static int lastt;

	if (lib_gmtime()-lastt<60) return TRUE;
	lastt = lib_gmtime();

	if (is_readonly()) return TRUE;
	if (cur_rule!=NULL) return TRUE;
	cur_rule = rules;
	if (cur_rule!=NULL) {
		getmail_start();
		status_nupdates++;
	}
	return TRUE;
}
int getmail_next(void)
{
	if (cur_rule==NULL) return FALSE;
	imsg("getmail: getmail_next %p (%s)\n",cur_rule,cur_rule->user);
	cur_rule = cur_rule->next;
	if (cur_rule==NULL) return FALSE;
	imsg("getmail: getmail_next2 %p (%s)\n",cur_rule,cur_rule->user);
	getmail_start();
	return TRUE;
}

int getmail_close_link(Link *l, char *reason)
{
	imsg("getmail: Closing link- (%s)\n",reason);
	if (l->chan>=0) chan_close(l->chan);
	if (l->xin!=NULL) str_free(l->xin);
	l->xin = NULL;
	l->chan = -1;
	l->state = P_CLOSED;
	getmail_next();
	return TRUE;
}
int getmail_start(void)
{
	Link *l=&lnk;
	Getrules *g;
	char bf[BFSZ];

	if (cur_rule==NULL) return TRUE;
	g = cur_rule;
	if (g==NULL) return TRUE;

	imsg("getmail_start %s@%s\n",g->user,g->pophost);
	if (l->state==P_CLOSED) {
		lprintf(bf,BFSZ-1,"%s:110",g->pophost);
		l->chan = chan_open(bf);
		imsg("getmail: Opening connection to (%s)\n",bf);
		if (l->chan>=0) {
			chan_setfn(l->chan,getmail_data_chan);
			l->state = P_OPENING;
		} else imsg("getmail: Cannot open POP3 link to %s\n",bf);
	} else {
		emsg("getmail: unknown state for start call %d\n",l->state);
	}

	return TRUE;
}

int getmail_data_chan(int chan, char *data, int len)
{
	Link *l=&lnk;
	static int in;
	if ((chan<0)||(chan>=MAX_CHAN)) return TRUE;
	l->lastdata = lib_gmtime();
	if (len<0) {
		if (in>0) return TRUE;
		in=1;
		wmsg("getmail: Channel closed s=%d\n",l->state);
		if (chan==l->chan)  {
			getmail_close_link(l,"Channel closed");
		} else imsg("getmail: Old channel %d closed\n",chan);
		in = 0;
		return TRUE;
	}
	l->lastdata = lib_gmtime();
	data[len] = 0;
	for (;len>0;len--) {
		if (data[len-1]!='\n') if (data[len-1]!='\r') break;
		len--;
		data[len] = 0;
	}
	if (len>200) data[len] = 0;
	getmail_data(l,data);
	return TRUE;
}
char *getmail_from(void)
{
	static char bf[BFSZ];
	strcpy(bf,config_get(C_GETMAIL_FROM));
	if (strlen(bf)==0) lprintf(bf,BFSZ-1,"dnews-gateway@%s",config_get(C_MYNAME));
	return bf;
}
#define matches(a,b) (strncmpnc(a,b,strlen(b))==0) 
void getmail_data(Link *l, char *line)
{
	int isok=FALSE;
	char *s;
	Getrules *g=cur_rule;
	if (line[0]=='+') isok = TRUE;
	l->lastdata = lib_gmtime();
	if (g==NULL) {
		emsg("No current rule, thats odd\n");
		return;
	}
	s = strchr(line,'\r'); if (s!=NULL) *s = 0;
	s = strchr(line,'\n'); if (s!=NULL) *s = 0;
	if (l->state!=P_DATA) imsg("getmail: <--[%d] %s\n",l->state,line);
again:
	switch (l->state) {
	case P_OPENING:
		if (!isok) {
			emsg("getmail: Open responded (%s)\n",line);
			getmail_close_link(l,line);
			return;
		}
		l->state = P_USER;
		getmail_write(l,"USER %s\r\n",g->user);
		break;
	case P_USER:
		if (!isok) {
			emsg("getmail: user response (%s)\n",line);
			getmail_close_link(l,line);
			return;
		}
		l->state = P_PASS;
		getmail_write(l,"PASS %s\r\n",g->pass);
		break;
	case P_PASS:
		if (!isok) {
			emsg("getmail: PASS response (%s)\n",line);
			getmail_close_link(l,line);
			return;
		}
		l->state = P_RETR;
		l->upto = 1;
		goto again;
	case P_RETR:
		strcpy(l->togroup,"");
		getmail_write(l,"RETR %d\r\n",l->upto);
		l->state = P_RETR_STATUS;
		l->tisok = FALSE;
		break;
	case P_RETR_STATUS:
		if (!isok) {
			imsg("getmail: Retrieved %d messages from %s@%s\n",l->upto-1,g->user,g->pophost);
			l->state = P_QUIT;
			goto again;
		}
		l->state = P_DATA;
		break;
	case P_DATA: 
		if (!getmail_store(l,g,line)) break; /* Processing message still */ 
		l->state = P_DELE;
		getmail_write(l,"DELE %d\r\n",l->upto);
		break;
	case P_DELE: /* 211 3892 170808 174699 rec.humor selected*/
		if (!isok) {
			emsg("getmail: FATAL ERROR, COULD NOT DELETE ITEM, THIS COULD MAKE A LOOP %s@%s %s\n",g->user,g->pophost,line); 
			getmail_close_link(l,"Couldn't delete item"); 
			return;
		}
		l->upto++;
		l->state = P_RETR;
		goto again;
	case P_QUIT:
		getmail_write(l,"QUIT\r\n");
		l->state = P_QUIT_STATUS;
		break;
	case P_QUIT_STATUS:
		getmail_close_link(l,"Normal Close");
		return;
	}
}
#ifdef WIN32
#define vsnprintf _vsnprintf
#endif
int getmail_write(Link *l,char *arg_list, ...)
{
        va_list arg_ptr;
        char *format;
        int len;
	char output[4000];
	char *s;
        va_start(arg_ptr, arg_list);
        format = arg_list;
        len = vsnprintf(output,900, format, arg_ptr);
	if (len>400) {
		emsg("Wrote too much data to getmail_write %.80s\n",output);
	}
	if (l->chan<0) return -1;
	chan_write_s(l->chan,output);
	s = strchr(output,'\r'); if (s!=NULL) *s = 0;
	if (strncmp(output,"PASS",4)!=0) 
	  dmsg("getmail: -> %.200s\n",output);
	/*imsg("getmail: -> %s\n",output);*/
	return TRUE;
}
static char *hdrs[1000];
static int nhdrs = 0;
void hdrs_clear(void)
{
	int i;
	for (i=0; i<nhdrs; i++) mystrfree(hdrs[i],SD_GETMAIL);
	nhdrs = 0;
}
char *getmail_unspace(char *tmp)
{
	char *s;
	char *out=tmp;
	for (s=tmp; *s!=0; s++) {
		if (*s==' ') continue;
		if (*s=='\t') continue;
		*out++ = *s;
	}
	*out++ = 0;
	return tmp;

}
int hdrs_isdup(char *hdr)
{
	int i;
	char bf[BFSZ];
	char *s;
	strncpy(bf,hdr,BFSZ-1); bf[200] = 0;
	strlwr(bf);
	s = strchr(bf,':'); if (s!=NULL) *s = 0; else return FALSE;
	for (i=0; i<nhdrs; i++) {
		if (strcmp(bf,hdrs[i])==0) {
			emsg("Dropping duplicate header (%s)\n",bf);
			return TRUE;
		}
	}
	if (nhdrs>200) return TRUE;
	hdrs[nhdrs++] = mystrdup(bf,SD_GETMAIL);
	return FALSE;
}
char *post_geterr(void);
int getmail_store(Link *l, Getrules *g, char *line)
{
	char tmp[BFSZ];
	char add[BFSZ];
	char tmp2[BFSZ];
	char *v;
	static char last_group[BFSZ];
	char bf[BFSZ];
	static int checkr = FALSE;
	static int failn=1;
	static char *last;
	char *s;
	char *s2;
	int keepn;
	FILE *f;
	if (l->xin==NULL) {
		l->xin = str_new();
		l->inhead = TRUE;
		l->inref = FALSE;
		l->gotref = FALSE;
		strcpy(l->subject,"");
		l->indrop = FALSE;
		strcpy(l->mid,"");
		strcpy(l->from,"");
		strcpy(l->ref,"");
		strcpy(l->realref,"");
		hdrs_clear();
		l->dropit = FALSE;
		l->gotfrom = FALSE;
	}
	if (strcmp(line,".")==0) {
		if (strlen(g->recipient)==0) l->tisok = TRUE;
		if (!l->tisok) {
			imsg("getmail: Rejecting bad recipient=(%.100s) wanted=(%.100s)\n",l->to,g->recipient);
			l->dropit = TRUE;
		} else {
			dmsg("getmail: Recipient ok (%.100s) wanted=(%.100s)\n",l->to,g->recipient);
		}
		if (!l->dropit) {
			feed_setpost(TRUE);
			str_write(l->xin,file_work("getmail.dat"));
			if (item_suck(l->xin)) {
				feed_setpost(FALSE);
				status_nok++;
			} else {
				feed_setpost(FALSE);
				status_nbad++;
				emsg("getmail: Local store failed, %s@%s %.180s, %.180s, %.180s\n",g->user,g->pophost,l->mid,l->subject,post_geterr());
				if(keepn=atoi(config_get(C_GETMAIL_FAIL_KEEPN))) {
					lprintf(tmp,BFSZ-1,"getmailf_%d.tmp",failn);
					f=fopen(file_work(tmp),"w");
					if(!f) emsg("getmail_store error, store as (%s) failed\n",file_work(tmp));
					else {
						str_write(l->xin,file_work(tmp));
						imsg("getmail_store error, stored as (%s)\n",file_work(tmp));
						if(failn==keepn) failn=1;
						else failn++;
					}
				}
			}
		} else {
			emsg("getmail: Dropping message %s@%s %.180s, %.180s\n",g->user,g->pophost,l->mid,l->subject);
		}
		str_free(l->xin);
		l->xin = NULL;
		l->dropit = FALSE;
		return TRUE;
	}
	if (l->inhead) {
		if ((line[0]==' ') || (line[0]=='\t')) {
			if (checkr) {
				if (mystrstrnc(line,g->recipient)!=NULL) l->tisok = TRUE;
			}
			if (last!=NULL) {
				ncpy(tmp2,last,200);
				ncpy(tmp2+strlen(tmp2),line+1,200);
				ncpy(last,tmp2,200);
				return FALSE;
			} else {
				if (l->indrop) return FALSE;
				if (l->inref) {
					if (strlen(l->realref)+strlen(line)<500) strcat(l->realref,line+1);
				} else {
					str_addsn(l->xin,line);
					str_addsn(l->xin,"\r\n");
					return FALSE;
				}
			}
			return FALSE;
		}
		checkr = FALSE;
		last = NULL;
		l->indrop = FALSE;
		l->inref = FALSE;
		/* Things to store about the message */
		if (strlen(g->header)>0) {
			if (matches(line,g->header)) {ncpy(l->togroup,line+strlen(g->header)+1,200); }
		}
		if (matches(line,"Newsgroups:")) {l->indrop = TRUE; return FALSE;}
		if (matches(line,"Subject:")) {ncpy(l->subject,line+8,200); last = l->subject; return FALSE; }
		if (matches(line,"From:")) {ncpy(l->from,line+5,200); l->gotfrom = TRUE; last = l->from;}



		/* Reasons to reject the message */
		if (matches(line,"Control:")) {emsg("getmail: Rejecting control message from email\n"); l->dropit = TRUE;}

		if (matches(line,"To: ")) {
			checkr = TRUE;
			ncpy(l->to,line+4,100);
			if (mystrstrnc(line+3,g->recipient)!=NULL) l->tisok = TRUE;
		}
		if (matches(line,"Cc: ")) {
			checkr = TRUE;
			if (mystrstrnc(line+3,g->recipient)!=NULL) l->tisok = TRUE;
		}


		/* Headers to drop */
		if (matches(line,"Newsgroups:")) {l->indrop = TRUE; return FALSE;}
		if (matches(line,"Posting-Version:")) {l->indrop = TRUE; return FALSE;}
		if (matches(line,"Relay-Version:")) {l->indrop = TRUE; return FALSE;}
		if (matches(line,"Posted:")) {l->indrop = TRUE; return FALSE;}
		if (matches(line,"Received:")) {l->indrop = TRUE; return FALSE;}
		if (matches(line,"Date-Received:")) {l->indrop = TRUE; return FALSE;}
		if (matches(line,"To:")) {l->indrop = TRUE; return FALSE;}
/*		if (matches(line,"Date:")) {l->indrop = TRUE; return FALSE;}*/
		if (matches(line,"Cc:")) {l->indrop = TRUE; return FALSE;}
		if (matches(line,"From ")) {l->indrop = TRUE; return FALSE;}
		if (matches(line,">From ")) {l->indrop = TRUE; return FALSE;}
		if (hdrs_isdup(line)) {l->indrop = TRUE; return FALSE;}

		/* Store Message ID  */
		if (strlen(line)>12) if (matches(line,"Message-ID:")) 	{
			ncpy(tmp,line+12,200);
			getmail_unspace(tmp);
			imsg("getmail: Incoming MID (%s)\n",tmp);
			ncpy(l->mid,tmp,200);
			if ((strchr(tmp,'<')==NULL) || (strchr(tmp,'@')==NULL)) {
				v = strtok(tmp," <>\r\n\t\"");
				if (v==NULL) return FALSE;
				lprintf(l->mid,BFSZ-1,"<%.200s>",v);
				if (strchr(l->mid,'@')==NULL) lprintf(l->mid,BFSZ-1,"<%s@getmail.com>",v);
			}

			if (config_true(C_GETMAIL_CROSSPOSTS)) {
				lprintf(add,BFSZ-1,"_%s>",g->gname);
				if (strstr(l->mid,add)==NULL) {
					/* First check if original exists, if it does then
					don't do this */
					if (!hist_exists(l->mid)) {
					 ncpy(tmp,l->mid,200);
					 v = strtok(tmp," <>\r\n\t\"");
					 if (v==NULL) return FALSE;
					 lprintf(l->mid,BFSZ-1,"<%.100s%.100s",v,add);
					 if (strlen(l->mid)>95) {
						ncpy(tmp,l->mid,90);
						strcat(tmp,">");
						ncpy(l->mid,tmp,100);
						imsg("Truncating MID to (%.200s)\n",l->mid);
					 }
					} else {
						imsg("Not adding groupname to mid as mid already exists (%.100s)\n",l->mid);
					}
				} else {
					imsg("Not adding groupname to mid as already added (%.100s)\n",l->mid);
				}
			}
			return FALSE;
		}
		/* References processing, this makes threading work on a good day */ 
		if (matches(line,"In-Reply-To:")) {ncpy(l->ref,line+13,BFSZ-1);}
		if (matches(line,"References:")) {
			ncpy(l->realref,line+12,BFSZ-1);
			l->inref = TRUE;
			l->gotref = TRUE;
			return FALSE;
		}

		if (matches(line,"X-Gateway-From:")) {
			if (strstr(line,config_get(C_MYNAME))!=NULL) {
				imsg("getmail: found gateway_from matched so dropping %s\n",line);
				l->dropit = TRUE; 
				return FALSE;
			}
		}
		{ char tmp[BFSZ];
		 lprintf(tmp,BFSZ-1,"X-Gateway-From: %.90s",getmail_from());
		 if (strstr(line,tmp)!=NULL) {l->dropit = TRUE; return FALSE;}
		}
		/* Add any headers now */
		if (strlen(line)==0) {
			l->inhead = FALSE;
	
			if (strlen(l->mid)>0) {

				if (config_true(C_GETMAIL_CROSSPOSTS)) {
					if (strstr(l->mid,"_>")!=NULL) {
						ncpy(tmp,l->mid,BFSZ-1);
						v = strtok(tmp," <>\r\n\t\"");
						if (v!=NULL) {
							lprintf(l->mid,BFSZ-1,"<%.100s_%.100s>",v,(strlen(g->gname)==0) ? last_group : g->gname);
							if (strlen(l->mid)>95) {
								ncpy(tmp,l->mid,90);
								strcat(tmp,">");
								ncpy(l->mid,tmp,100);
								imsg("Truncating MID to (%.200s)\n",l->mid);
							}	
						}
					}
				}
				str_printf(l->xin,"Message-ID: %.110s\r\n",l->mid);
			} else {
				imsg("Adding messageid as it didn't have one\n");
				str_printf(l->xin,"Message-ID: %s\r\n",lib_messageid());
			}
			if (!l->gotfrom) str_printf(l->xin,"From: %.80s\r\n",getmail_from());
			if (strlen(g->header)>0) {
				if (strlen(l->togroup)==0) {
					emsg("No header (%s) found\n",g->header);
				} else {
					if (strchr(l->togroup,'@')==NULL) s2 = l->togroup;
					else s2 = email_trim(l->togroup);
					s = strchr(s2,'@'); if (s!=NULL) *s = 0;

					if (strlen(config_get(C_GETMAIL_STRIP))>0) {
						if (strncmpnc(s2,config_get(C_GETMAIL_STRIP),strlen(config_get(C_GETMAIL_STRIP)))==0) {
							s2 += strlen(config_get(C_GETMAIL_STRIP));
						}
					}
					lprintf(bf,BFSZ-1,"%.200s%.200s",g->prepend,s2);
					if (g->todot) str_todot(bf);

					str_printf(l->xin,"Newsgroups: %s\r\n",bf);
					ncpy(last_group,bf,BFSZ-1);
					imsg("getmail: Posting to newsgroup: %s\n",bf);
				}
			} else {				
				str_printf(l->xin,"Newsgroups: %s\r\n",g->gname);
			}
			if (strlen(l->subject)==0) strcpy(l->subject,"(No Subject)");
			str_printf(l->xin,"Subject: %s\r\n",l->subject);
			str_printf(l->xin,"X-Gateway-Administrator: %s\r\n",config_get(C_MANAGER));
			if (strlen(config_get(C_GETMAIL_HEADER))>0) {
    	    	    	    str_printf(l->xin,"%s\r\n",config_get(C_GETMAIL_HEADER));
			}
			str_printf(l->xin,"X-Gateway-From: %.90s\r\n",getmail_from());
			if (!l->gotref) {
				if (strlen(l->ref)>0) str_printf(l->xin,"References: %.400s\r\n",l->ref);
			} else {
				if (strlen(l->realref)+strlen(l->ref)<500) {
					if (strstr(l->realref,l->ref)==NULL) {
						strcat(l->realref," ");
						strcat(l->realref,l->ref);
					}
				}
				if (strlen(l->realref)>400) {
					s = strchr(l->realref+399,' ');
					if (s!=NULL) *s = 0;
				}
				str_printf(l->xin,"References: %.500s\r\n",l->realref);  
			}
			str_printf(l->xin,"\r\n");
			return FALSE;
		}
		str_addsn(l->xin,line);
		str_addsn(l->xin,"\r\n");
		return FALSE;
	}
	last = NULL;
	str_addsn(l->xin,line);
	str_addsn(l->xin,"\r\n");
	return FALSE;
}


char *getmail_status(void)
{
	static char bf[BFSZ];
	if (status_nrules==0) return "";
	lprintf(bf,BFSZ-1,"Getmail: %d rules, %d updates, %d stored ok, %d rejected\r\n",
		status_nrules,	status_nupdates, status_nok, status_nbad);
	return bf;
}
char *email_trim(char *s)
{
	static char bf[BFSZ];
	static char bf2[BFSZ];
	char *ss=s;
	ncpy(bf,s,BFSZ-1);

	s = strtok(bf," \t\n");
	for (;s!=NULL;) {
	 	if (*s=='<') goto found;
		if (strchr(s,'@')!=NULL) goto found;
		s = strtok(NULL," \t\n");
	}
	return "";
found:
	if (*s=='<') {
		ncpy(bf2,s+1,BFSZ-1);
		s = strchr(bf2,'>'); if (s!=NULL) *s = 0;
		return bf2;
	}
       	lprintf(bf2,BFSZ-1,"%s",s);
	return bf2;
}
