/* $Id: mail.c,v 1.1 2002/03/07 15:13:48 in2 Exp $ */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <string.h>
#include "config.h"
#include "pttstruct.h"
#include "common.h"
#include "perm.h"
#include "modes.h"
#include "proto.h"

extern int TagNum;
extern int b_lines;               /* Screen bottom line number: t_lines-1 */
extern char save_title[];         /* used by editor when inserting */
extern int curredit;
extern char *err_uid;
extern char *msg_cancel;
extern char *msg_uid;
extern char *fn_overrides;
extern char quote_file[80];
extern char quote_user[80];
extern char *fn_notes;
extern char *msg_mailer;
extern char *msg_sure_ny;
extern char *BBSName;
extern char currtitle[44];
extern unsigned char currfmode;               /* current file mode */
extern char *msg_del_ny;
extern char currfile[FNLEN];
extern int currmode;
extern char currboard[];        /* name of currently selected board */
extern char *str_space;
extern char *str_author1;
extern char *str_author2;
extern userinfo_t *currutmp;
extern unsigned int currstat;
extern pid_t currpid;
extern int usernum;
extern char *str_mail_address;
extern userec_t cuser;

char currmaildir[32];
static char msg_cc[] = "\033[32m[�s�զW��]\033[m\n";
static char listfile[] = "list.0";
static int mailkeep = 0, mailsum = 0;
static int mailsumlimit = 0,mailmaxkeep = 0;

int setforward() {
    char buf[80], ip[50] = "", yn[4];
    FILE *fp;
    
    sethomepath(buf, cuser.userid);
    strcat(buf,"/.forward");
    if((fp = fopen(buf,"r"))) {
	fscanf(fp,"%s",ip);
	fclose(fp);
    }
    getdata_buf(b_lines - 1, 0, "�п�J�H�c�۰���H��email�a�}:",
		ip, 41, DOECHO);
    if(ip[0] && ip[0] != ' ') {
	getdata(b_lines, 0, "�T�w�}�Ҧ۰���H�\\��?(Y/n)", yn, 3,
		LCECHO);
	if(yn[0] != 'n' && (fp = fopen(buf, "w"))) {
	    move(b_lines,0);
	    clrtoeol();
	    fprintf(fp,"%s",ip);
	    fclose(fp);
	    outs("�]�w����!");
	    refresh();
	    return 0;
	}
    }
    move(b_lines,0);
    clrtoeol();
    outs("�����۰���H!");
    unlink(buf);
    refresh();
    return 0;
}

int built_mail_index() {
    char genbuf[128];
    
    getdata(b_lines, 0,
	    "���ثH�c?(ĵ�i:�нT�w�H�c�����D�ɤ~�ϥ�)(y/N)", genbuf, 3,
            LCECHO);
    if(genbuf[0] != 'y') return 0;  

    sprintf(genbuf, BBSHOME "/bin/buildir " BBSHOME "/home/%c/%s",
	    cuser.userid[0], cuser.userid);
    move(22,0);
    prints("\033[1;31m�w�g�B�z����!! �Ѧh���K �q�Э��~\033[m");pressanykey();
    system(genbuf);
    return 0;
}

int mailalert(char *userid)
{
    userinfo_t *uentp=NULL;
    int n,tuid,i;     

    if((tuid=searchuser(userid))==0) return -1;

    n=count_logins(tuid, 0);
    for(i=1;i<=n;i++)
       if((uentp = (userinfo_t *)search_ulistn(tuid, i)))
         uentp->mailalert=1;
    return 0;
}

int mail_muser(userec_t muser, char *title, char *filename) {
    return mail_id(muser.userid, title, filename, cuser.userid);
}

/* Heat: ��id�ӱH�H,���e�hlink�dzƦn���ɮ� */
int mail_id(char* id, char *title, char *filename, char *owner) {
    fileheader_t mhdr;
    char genbuf[128];
    sethomepath(genbuf, id);
    if(stampfile(genbuf, &mhdr))
        return 0;
    strcpy(mhdr.owner, owner);
    strncpy(mhdr.title, title, TTLEN);
    mhdr.savemode = 0;
    mhdr.filemode = 0;
    Link(filename, genbuf);
    sethomedir(genbuf,id);
    append_record(genbuf, &mhdr, sizeof(mhdr));
    mailalert(id);
    return 0;
}    
          
int invalidaddr(char *addr) {
    if(*addr == '\0')
	return 1;                   /* blank */
    while(*addr) {
	if(not_alnum(*addr) && !strchr("[].%!@:-_;", *addr))
	    return 1;
	addr++;
    }
    return 0;
}

int m_internet() {
    char receiver[60];
    
    getdata(20, 0, "���H�H�G", receiver, 60, DOECHO);
    if(strchr(receiver, '@') && !invalidaddr(receiver) &&
       getdata(21, 0, "�D  �D�G", save_title, TTLEN, DOECHO))
	do_send(receiver, save_title);
    else {
	move(22, 0);
	outs("���H�H�ΥD�D�����T, �Э��s������O");
	pressanykey();
    }
    return 0;
}

void m_init() {
    sethomedir(currmaildir, cuser.userid);
}

int chkmailbox() {
    if(!HAVE_PERM(PERM_SYSOP) && !HAVE_PERM(PERM_MAILLIMIT)) {
        int max_keepmail = MAX_KEEPMAIL;
        if ( HAS_PERM(PERM_SYSSUBOP) || HAS_PERM(PERM_SMG) ||
           HAS_PERM(PERM_PRG) || HAS_PERM(PERM_ACTION) || HAS_PERM(PERM_PAINT))
          {
            mailsumlimit = 700;
            max_keepmail = 500;
          }
	else if(HAS_PERM(PERM_BM))
          {
	    mailsumlimit = 500;
            max_keepmail = 300;
	  }
	else if(HAS_PERM(PERM_LOGINOK))
	    mailsumlimit = 200;
	else
	    mailsumlimit = 50;
	mailsumlimit += cuser.exmailbox * 10;
	mailmaxkeep = max_keepmail + cuser.exmailbox;
	m_init();
	if((mailkeep = get_num_records(currmaildir, sizeof(fileheader_t))) >
	   mailmaxkeep) {
	    move(b_lines, 0);
	    clrtoeol();
	    bell();
	    prints("�z�O�s�H��ƥ� %d �W�X�W�� %d, �о�z",
		   mailkeep, mailmaxkeep);
	    bell();
	    refresh();
	    igetch();
	    return mailkeep;
	}
	if((mailsum = get_sum_records(currmaildir, sizeof(fileheader_t))) >
	   mailsumlimit) {
	    move(b_lines, 0);
	    clrtoeol();
	    bell();
	    prints("�z�O�s�H��e�q %d(k)�W�X�W�� %d(k), �о�z",
		   mailsum, mailsumlimit);
	    bell();
	    refresh();
	    igetch();
	    return mailkeep;
	}
    }
    return 0;
}

static void do_hold_mail(char *fpath, char *receiver, char *holder) {
    char buf[80], title[128];
    
    fileheader_t mymail;
    
    sethomepath(buf, holder);
    stampfile(buf, &mymail);
    
    mymail.savemode = 'H';        /* hold-mail flag */
    mymail.filemode = FILE_READ;
    strcpy(mymail.owner, "[��.��.��]");
    if(receiver) {
	sprintf(title, "(%s) %s", receiver, save_title);
	strncpy(mymail.title, title, TTLEN);
    } else
	strcpy(mymail.title, save_title);
    
    sethomedir(title, holder);
    
    unlink(buf);
    Link(fpath, buf);
    /* Ptt: append_record->do_append */
    do_append(title, &mymail, sizeof(mymail));
}

extern userec_t xuser;

void hold_mail(char *fpath, char *receiver) {
    char buf[4];
    
    getdata(b_lines - 1, 0, "�w���Q�H�X�A�O�_�ۦs���Z(Y/N)�H[N] ",
	    buf, 4, LCECHO);
    
    if(buf[0] == 'y')
	do_hold_mail(fpath, receiver, cuser.userid);
}

int do_send(char *userid, char *title) {
    fileheader_t mhdr;
    char fpath[STRLEN];
    char receiver[IDLEN];
    char genbuf[200];
    int internet_mail, i;
    
    if(strchr(userid, '@'))
	internet_mail = 1;
    else {
	internet_mail = 0;
	if(!getuser(userid))
	    return -1;
	if(!(xuser.userlevel & PERM_READMAIL))
	    return -3;
	
	if(!title)
	    getdata(2, 0, "�D�D�G", save_title, TTLEN, DOECHO);
	curredit |= EDIT_MAIL;
	curredit &= ~EDIT_ITEM;
    }
    
    setutmpmode(SMAIL);
    
    fpath[0] = '\0';
    
    if(internet_mail) {
	int res, ch;

	if(vedit(fpath, NA, NULL) == -1) {
	    unlink(fpath);
	    clear();
	    return -2;
	}
	clear();
	prints("�H��Y�N�H�� %s\n���D���G%s\n�T�w�n�H�X��? (Y/N) [Y]",
	       userid, title);
	ch = igetch();
	switch(ch) {
	case 'N':
	case 'n':
	    outs("N\n�H��w����");
	    res = -2;
	    break;
	default:
	    outs("Y\n�еy��, �H��ǻ���...\n");
	    res =
#ifndef USE_BSMTP
		bbs_sendmail(fpath, title, userid);
#else
            bsmtp(fpath, title, userid,0);
#endif
	    hold_mail(fpath, userid);
	}
	unlink(fpath);
	return res;
    } else {
	strcpy(receiver, userid);
	sethomepath(genbuf, userid);
	stampfile(genbuf, &mhdr);
	strcpy(mhdr.owner, cuser.userid);
	strncpy(mhdr.title, save_title, TTLEN);
	mhdr.savemode = '\0';
	if(vedit(genbuf, YEA, NULL) == -1) {
	    unlink(genbuf);
	    clear();
	    return -2;
	}
	clear();
	sethomefile(fpath, userid, FN_OVERRIDES);
        i=belong(fpath, cuser.userid);
        sethomefile(fpath, userid, FN_REJECT);

        if(i || !belong(fpath, cuser.userid)) //Ptt:��belong���I�Q�� 
           {
	    sethomedir(fpath, userid);
     	    if(append_record(fpath, &mhdr, sizeof(mhdr)) == -1)
	        return -1;
            mailalert(userid);
	   }
	hold_mail(genbuf, userid);
	return 0;
    }
}

void my_send(char *uident) {
    switch(do_send(uident, NULL)) {
    case -1:
	outs(err_uid);
	break;
    case -2:
	outs(msg_cancel);
	break;
    case -3:
	prints("�ϥΪ� [%s] �L�k���H", uident);
	break;
    }
    pressanykey();
}

int m_send() {
    char uident[40];

    stand_title("�Bť������");
    usercomplete(msg_uid, uident);
    showplans(uident);
    if(uident[0])
	my_send(uident);
    return 0;
}

/* �s�ձH�H�B�^�H : multi_send, multi_reply */
extern struct word_t *toplev;

static void multi_list(int *reciper) {
    char uid[16];
    char genbuf[200];

    while(1) {
	stand_title("�s�ձH�H�W��");
	ShowNameList(3, 0, msg_cc);
	getdata(1, 0,
		"(I)�ޤJ�n�� (O)�ޤJ�W�u�q�� (N)�ޤJ�s�峹�q�� "
		"(0-9)�ޤJ��L�S�O�W��\n"
		"(A)�W�[     (D)�R��         (M)�T�{�H�H�W��   (Q)���� �H[M]",
		genbuf, 4, LCECHO);
	switch(genbuf[0]) {
	case 'a':
	    while(1) {
		move(1, 0);
		usercomplete("�п�J�n�W�[���N��(�u�� ENTER �����s�W): ", uid);
		if(uid[0] == '\0')
		    break;
		
		move(2, 0);
		clrtoeol();
		
		if(!searchuser(uid))
		    outs(err_uid);
		else if(!InNameList(uid)) {
		    AddNameList(uid);
		    (*reciper)++;
		}
		ShowNameList(3, 0, msg_cc);
	    }
	    break;
	case 'd':
	    while(*reciper) {
		move(1, 0);
		namecomplete("�п�J�n�R�����N��(�u�� ENTER �����R��): ", uid);
		if(uid[0] == '\0')
		    break;
		if(RemoveNameList(uid))
		    (*reciper)--;
		ShowNameList(3, 0, msg_cc);
	    }
	    break;
	case '0':
	case '1':
	case '2':
	case '3':
	case '4':
	case '5':
	case '6':
	case '7':
	case '8':
	case '9':
	    listfile[5] = genbuf[0];
	    genbuf[0] = '1';
	case 'i':
	    setuserfile(genbuf, genbuf[0] == '1' ? listfile : fn_overrides);
	    ToggleNameList(reciper, genbuf, msg_cc);
	    break;
	case 'o':
	    setuserfile(genbuf, "alohaed");
	    ToggleNameList(reciper, genbuf, msg_cc);
	    break;
	case 'n':
	    setuserfile(genbuf, "postlist");
	    ToggleNameList(reciper, genbuf, msg_cc);
	    break;
	case 'q':
	    *reciper = 0;
	    return;
	default:
	    return;
	}
    }
}

static void multi_send(char *title) {
    FILE *fp;
    struct word_t *p;
    fileheader_t mymail;
    char fpath[TTLEN], *ptr;
    int reciper, listing;
    char genbuf[256];
    
    CreateNameList();
    listing = reciper = 0;
    if(*quote_file) {
	AddNameList(quote_user);
	reciper = 1;
	fp = fopen(quote_file, "r");
	while(fgets(genbuf, 256, fp)) {
	    if(strncmp(genbuf, "�� ", 3)) {
		if(listing)
		    break;
	    } else {
		if(listing) {
		    strtok(ptr = genbuf + 3, " \n\r");
		    do {
			if(searchuser(ptr) && !InNameList(ptr) &&
			   strcmp(cuser.userid, ptr)) {
			    AddNameList(ptr);
			    reciper++;
			}
		    } while((ptr = (char *)strtok(NULL, " \n\r")));
		} else if(!strncmp(genbuf + 3, "[�q�i]", 6))
		    listing = 1;
	    }
	}
	ShowNameList(3, 0, msg_cc);
    }
    
    multi_list(&reciper);
    move(1, 0);
    clrtobot();
    
    if(reciper) {
	setutmpmode(SMAIL);
	if(title)
	    do_reply_title(2, title);
	else {
	    getdata(2, 0, "�D�D�G", fpath, 64, DOECHO);
	    sprintf(save_title, "[�q�i] %s", fpath);
	}
	
	setuserfile(fpath, fn_notes);
	
	if((fp = fopen(fpath, "w"))) {
	    fprintf(fp, "�� [�q�i] �@ %d �H����", reciper);
	    listing = 80;

	    for(p = toplev; p; p = p->next) {
		reciper = strlen(p->word) + 1;
		if(listing + reciper > 75) {
		    listing = reciper;
		    fprintf(fp, "\n��");
		} else
		    listing += reciper;
		
		fprintf(fp, " %s", p->word);
	    }
	    memset(genbuf, '-', 75);
	    genbuf[75] = '\0';
	    fprintf(fp, "\n%s\n\n", genbuf);
	    fclose(fp);
	}
	
	curredit |= EDIT_LIST;

	if(vedit(fpath, YEA, NULL) == -1) {
	    unlink(fpath);
	    curredit = 0;
	    outs(msg_cancel);
	    pressanykey();
	    return;
	}
	
	stand_title("�H�H��...");
	refresh();
	
	listing = 80;
	
	for(p = toplev; p; p = p->next) {
	    reciper = strlen(p->word) + 1;
	    if(listing + reciper > 75) {
		listing = reciper;
		outc('\n');
	    } else {
		listing += reciper;
		outc(' ');
	    }
	    outs(p->word);
	    if(searchuser(p->word) && strcmp(STR_GUEST, p->word) )
		sethomepath(genbuf, p->word);
	    else
		continue;
	    stampfile(genbuf, &mymail);
	    unlink(genbuf);
	    Link(fpath, genbuf);
	    
	    strcpy(mymail.owner, cuser.userid);
	    strcpy(mymail.title, save_title);
	    mymail.savemode = 'M';    /* multi-send flag */
	    sethomedir(genbuf, p->word);
	    if(append_record(genbuf, &mymail, sizeof(mymail)) == -1)
		outs(err_uid);
	    mailalert(p->word);
	}
	hold_mail(fpath, NULL);
	unlink(fpath);
	curredit = 0;
    } else
	outs(msg_cancel);
    pressanykey();
}

static int multi_reply(int ent, fileheader_t *fhdr, char *direct) {
    if(fhdr->savemode != 'M')
	return mail_reply(ent, fhdr, direct);

    stand_title("�s�զ^�H");
    strcpy(quote_user, fhdr->owner);
    setuserfile(quote_file, fhdr->filename);
    multi_send(fhdr->title);
    return 0;
}

int mail_list() {
    stand_title("�s�է@�~");
    multi_send(NULL);
    return 0;
}

int mail_all() {
    FILE *fp;
    fileheader_t mymail;
    char fpath[TTLEN];
    char genbuf[200];
    extern struct uhash_t *uhash;
    int i, unum;
    char *userid;
    
    stand_title("���Ҧ��ϥΪ̪��t�γq�i");
    setutmpmode(SMAIL);
    getdata(2, 0, "�D�D�G", fpath, 64, DOECHO);
    sprintf(save_title, "[�t�γq�i]\033[1;32m %s\033[m", fpath);
    
    setuserfile(fpath, fn_notes);
    
    if((fp = fopen(fpath, "w"))) {
	fprintf(fp, "�� [\033[1m�t�γq�i\033[m] �o�O�ʵ��Ҧ��ϥΪ̪��H\n");
	fprintf(fp, "-----------------------------------------------------"
		"----------------------\n");
	fclose(fp);
    }
    
    *quote_file = 0;
    
    curredit |= EDIT_MAIL;
    curredit &= ~EDIT_ITEM;
    if(vedit(fpath, YEA, NULL) == -1) {
	curredit = 0;
	unlink(fpath);
	outs(msg_cancel);
	pressanykey();
	return 0;
    }
    curredit = 0;
    
    setutmpmode(MAILALL);
    stand_title("�H�H��...");
    
    sethomepath(genbuf, cuser.userid);
    stampfile(genbuf, &mymail);
    unlink(genbuf);
    Link(fpath, genbuf);
    unlink(fpath);
    strcpy(fpath, genbuf);
    
    strcpy(mymail.owner, cuser.userid);  /*���� ID*/
    strcpy(mymail.title, save_title);
    mymail.savemode = 0;
    
    sethomedir(genbuf, cuser.userid);
    if(append_record(genbuf, &mymail, sizeof(mymail)) == -1)
	outs(err_uid);
    
    for(unum = uhash->number, i = 0; i < unum; i++) {
	if(bad_user_id(uhash->userid[i]))
	    continue; /* Ptt */
	
	userid = uhash->userid[i];
	if(strcmp(userid,STR_GUEST) && strcmp(userid, "new") &&
	   strcmp(userid, cuser.userid)) {
	    sethomepath(genbuf, userid);
	    stampfile(genbuf, &mymail);
	    unlink(genbuf);
	    Link(fpath, genbuf);
	    
	    strcpy(mymail.owner, cuser.userid);
	    strcpy(mymail.title, save_title);
	    mymail.savemode = 0;
	    /* mymail.filemode |= FILE_MARKED; Ptt ���i�令���|mark */
	    sethomedir(genbuf, userid);
	    if(append_record(genbuf, &mymail, sizeof(mymail)) == -1)
		outs(err_uid);
	    sprintf(genbuf, "%*s %5d / %5d", IDLEN + 1, userid, i + 1, unum);
	    outmsg(genbuf);
	    refresh();
	}
    }
    return 0;
}

int mail_mbox() {
    char cmd[100];
    fileheader_t fhdr;

    sprintf(cmd, "/tmp/%s.uu", cuser.userid);
    sprintf(fhdr.title, "%s �p�H���", cuser.userid);
    doforward(cmd, &fhdr, 'Z');
    return 0;
}

static int m_forward(int ent, fileheader_t *fhdr, char *direct) {
    char uid[STRLEN];

    stand_title("��F�H��");
    usercomplete(msg_uid, uid);
    if(uid[0] == '\0')
	return FULLUPDATE;

    strcpy(quote_user, fhdr->owner);
    setuserfile(quote_file, fhdr->filename);
    sprintf(save_title, "%.64s (fwd)", fhdr->title);
    move(1, 0);
    clrtobot();
    prints("��H��: %s\n��  �D: %s\n", uid, save_title);

    switch(do_send(uid, save_title)) {
    case -1:
	outs(err_uid);
	break;
    case -2:
	outs(msg_cancel);
	break;
    case -3:
	prints("�ϥΪ� [%s] �L�k���H", uid);
	break;
    }
    pressanykey();
    return FULLUPDATE;
}

static int delmsgs[128];
static int delcnt;
static int mrd;

static int read_new_mail(fileheader_t *fptr) {
    static int idc;
    char done = NA, delete_it;
    char fname[256];
    char genbuf[4];
    
    if(fptr == NULL) {
	delcnt = 0;
	idc = 0;
	return 0;
    }
    idc++;
    if(fptr->filemode)
	return 0;
    clear();
    move(10, 0);
    prints("�z�nŪ�Ӧ�[%s]���T��(%s)�ܡH", fptr->owner, fptr->title);
    getdata(11, 0, "�бz�T�w(Y/N/Q)?[Y] ", genbuf, 3, DOECHO);
    if(genbuf[0] == 'q')
	return QUIT;
    if(genbuf[0] == 'n')
	return 0;
    
    setuserfile(fname, fptr->filename);
    fptr->filemode |= FILE_READ;
    if(substitute_record(currmaildir, fptr, sizeof(*fptr), idc))
	return -1;
    
    mrd = 1;
    delete_it = NA;
    while(!done) {
	int more_result = more(fname, YEA);

	switch(more_result) {
	case 1:
	    return READ_PREV;
	case 2:
	    return RELATE_PREV;
	case 3:
	    return READ_NEXT;
	case 4:
	    return RELATE_NEXT;
	case 5:
	    return RELATE_FIRST;
	case 6:
	    return 0;
	case 7:
	    mail_reply(idc, fptr, currmaildir);
	    return FULLUPDATE;
	case 8:
	    multi_reply(idc, fptr, currmaildir);
	    return FULLUPDATE;
	}
	move(b_lines, 0);
	clrtoeol();
	outs(msg_mailer);
	refresh();
	
	switch(egetch()) {
	case 'r':
	case 'R':
	    mail_reply(idc, fptr, currmaildir);
	    break;
	case 'x':
	    m_forward(idc, fptr, currmaildir);
	    break;
	case 'y':
	    multi_reply(idc, fptr, currmaildir);
	    break;
	case 'd':
	case 'D':
	    delete_it = YEA;
	default:
	    done = YEA;
	}
    }
    if(delete_it) {
	clear();
	prints("�R���H��m%s�n", fptr->title);
	getdata(1, 0, msg_sure_ny, genbuf, 2, LCECHO);
	if(genbuf[0] == 'y') {
	    unlink(fname);
	    delmsgs[delcnt++] = idc;
	}
    }
    clear();
    return 0;
}

int m_new() {
    clear();
    mrd = 0;
    setutmpmode(RMAIL);
    read_new_mail(NULL);
    clear();
    curredit |= EDIT_MAIL;
    curredit &= ~EDIT_ITEM;
    if(apply_record(currmaildir, read_new_mail, sizeof(fileheader_t)) == -1) {
	outs("�S���s�H��F");
	pressanykey();
	return -1;
    }
    curredit = 0;
    if(delcnt) {
	while(delcnt--)
	    delete_record(currmaildir, sizeof(fileheader_t), delmsgs[delcnt]);
    }
    outs(mrd ? "�H�w�\\��" : "�S���s�H��F");
    pressanykey();
    return -1;
}

static void mailtitle() {
    char buf[256] = "";

    showtitle("\0�l����", BBSName);
    sprintf(buf,"[��]���}[����]���[��]�\\Ū�H�� [R]�^�H [x]��F "
	 "[y]�s�զ^�H [O]���~�H:%s [h]�D�U\n\033[7m"
	 "�s��   �� ��  �@ ��          �H  ��  ��  �D     \033[32m",
	 HAS_PERM(PERM_NOOUTMAIL)? "\033[31m��\033[m":"�}");
    outs(buf);
    buf[0]=0;
    if(mailsumlimit) {
	sprintf(buf,"(�e�q:%d/%dk %d/%d�g)", mailsum, mailsumlimit,
		mailkeep, mailmaxkeep);
    }
    sprintf(buf, "%s%*s\033[m", buf, 29 - (int) strlen(buf), "");
    outs(buf);
}

static void maildoent(int num, fileheader_t *ent) {
    char *title, *mark, color, type = "+ Mm"[ent->filemode];

    if (TagNum && !Tagger(atoi(ent->filename + 2), 0, TAG_NIN))
            type = 'D';     

    title = subject(mark = ent->title);
    if(title == mark) {
	color = '1';
	mark = "��";
    } else {
	color = '3';
	mark = "R:";
    }

    if(strncmp(currtitle, title, 40))
	prints("%5d %c %-7s%-15.14s%s %.46s\n", num, type,
	       ent->date, ent->owner, mark, title);
    else
	prints("%5d %c %-7s%-15.14s\033[1;3%cm%s %.46s\033[0m\n", num, type,
	       ent->date, ent->owner, color, mark, title);
}

#ifdef POSTBUG
extern int bug_possible;
#endif


static int m_idle(int ent, fileheader_t *fhdr, char *direct) {
    t_idle();
    return FULLUPDATE;
}

static int mail_del(int ent, fileheader_t *fhdr, char *direct) {
    char genbuf[200];

    if(fhdr->filemode & FILE_MARKED)
	return DONOTHING;

    getdata(1, 0, msg_del_ny, genbuf, 3, LCECHO);
    if(genbuf[0] == 'y') {
	strcpy(currfile, fhdr->filename);
	if(!delete_file(direct, sizeof(*fhdr), ent, cmpfilename)) {
	    setdirpath(genbuf, direct, fhdr->filename);
	    unlink(genbuf);
	    if((currmode & MODE_SELECT)) {
		int now;
		
		sethomedir(genbuf, cuser.userid);
		now = getindex(genbuf, fhdr->filename, sizeof(fileheader_t));
		delete_file(genbuf, sizeof(fileheader_t), now, cmpfilename);
	    }
	    return DIRCHANGED;
	}
    }
    return FULLUPDATE;
}

static int mail_read(int ent, fileheader_t *fhdr, char *direct) {
    char buf[64];
    char done, delete_it, replied;

    clear();
    setdirpath(buf, direct, fhdr->filename);
    strncpy(currtitle, subject(fhdr->title), 40);
    done = delete_it = replied = NA;
    while(!done) {
	int more_result = more(buf, YEA);
	
	if(more_result != -1) {
	    fhdr->filemode |= FILE_READ;
	    if((currmode & MODE_SELECT)) {
		int now;
		
		now = getindex(currmaildir, fhdr->filename,
			       sizeof(fileheader_t));
		substitute_record(currmaildir, fhdr, sizeof(*fhdr), now);
		substitute_record(direct, fhdr, sizeof(*fhdr), ent);
	    }
	    else
		substitute_record(currmaildir, fhdr, sizeof(*fhdr), ent);
	}
	switch(more_result) {
	case 1:
	    return READ_PREV;
	case 2:
	    return RELATE_PREV;
	case 3:
	    return READ_NEXT;
	case 4:
	    return RELATE_NEXT;
	case 5:
	    return RELATE_FIRST;
	case 6:
	    return FULLUPDATE;
	case 7:
	    mail_reply(ent, fhdr, direct);
	    return FULLUPDATE;
	case 8:
	    multi_reply(ent, fhdr, direct);
	    return FULLUPDATE;
	}
	move(b_lines, 0);
	clrtoeol();
	refresh();
	outs(msg_mailer);
	
	switch(egetch()) {
	case 'r':
	case 'R':
	    replied = YEA;
	    mail_reply(ent, fhdr, direct);
	    break;
	case 'x':
	    m_forward(ent, fhdr, direct);
	    break;
	case 'y':
	    multi_reply(ent, fhdr, direct);
	    break;
	case 'd':
	    delete_it = YEA;
	default:
	    done = YEA;
	}
    }
    if(delete_it)
	mail_del(ent, fhdr, direct);
    else {
	fhdr->filemode |= FILE_READ;
#ifdef POSTBUG
	if(replied)
	    bug_possible = YEA;
#endif
	if((currmode & MODE_SELECT)) {
	    int now;
	    
	    now = getindex(currmaildir, fhdr->filename, sizeof(fileheader_t));
	    substitute_record(currmaildir, fhdr, sizeof(*fhdr), now);
	    substitute_record(direct, fhdr, sizeof(*fhdr), ent);
	} else
	    substitute_record(currmaildir, fhdr, sizeof(*fhdr), ent);
#ifdef POSTBUG
	bug_possible = NA;
#endif
    }
    return FULLUPDATE;
}

/* in boards/mail �^�H����@�̡A��H����i */
int mail_reply(int ent, fileheader_t *fhdr, char *direct) {
    char uid[STRLEN];
    char *t;
    FILE *fp;
    char genbuf[512];

    stand_title("�^  �H");

    /* �P�_�O boards �� mail */
    if(curredit & EDIT_MAIL)
	setuserfile(quote_file, fhdr->filename);
    else
	setbfile(quote_file, currboard, fhdr->filename);

    /* find the author */
    strcpy(quote_user, fhdr->owner);
    if(strchr(quote_user, '.')) {
	genbuf[0] = '\0';
	if((fp = fopen(quote_file, "r"))) {
	    fgets(genbuf, 512, fp);
	    fclose(fp);
	}
	
	t = strtok(genbuf, str_space);
	if(!strcmp(t, str_author1) || !strcmp(t, str_author2))
	    strcpy(uid, strtok(NULL, str_space));
	else {
	    outs("���~: �䤣��@�̡C");
	    pressanykey();
	    return FULLUPDATE;
	}
    } else
	strcpy(uid, quote_user);
    
    /* make the title */
    do_reply_title(3, fhdr->title);
    prints("\n���H�H: %s\n��  �D: %s\n", uid, save_title);
    
    /* edit, then send the mail */
    ent = curredit;
    switch(do_send(uid, save_title)) {
    case -1:
	outs(err_uid);
	break;
    case -2:
	outs(msg_cancel);
	break;
    case -3:
	prints("�ϥΪ� [%s] �L�k���H", uid);
	break;
    }
    curredit = ent;
    pressanykey();
    return FULLUPDATE;
}

static int mail_edit(int ent, fileheader_t *fhdr, char *direct) {
    char genbuf[200];

    if(!HAS_PERM(PERM_SYSOP) && 
       strcmp(cuser.userid, fhdr->owner) &&
       strcmp("[��.��.��]", fhdr->owner))
	return DONOTHING;

    setdirpath(genbuf, direct, fhdr->filename);
    vedit(genbuf, NA, NULL);
    return FULLUPDATE;
}

static int mail_nooutmail(int ent, fileheader_t *fhdr, char *direct)
{
    cuser.userlevel ^= PERM_NOOUTMAIL;
    passwd_update(usernum, &cuser);
    return FULLUPDATE;

}

static int mail_mark(int ent, fileheader_t *fhdr, char *direct) {
    fhdr->filemode ^= FILE_MARKED;
    
    if((currmode & MODE_SELECT)) {
	int now;

	now = getindex(currmaildir, fhdr->filename, sizeof(fileheader_t));
	substitute_record(currmaildir, fhdr, sizeof(*fhdr), now);
	substitute_record(direct, fhdr, sizeof(*fhdr), ent);
    } else
	substitute_record(currmaildir, fhdr, sizeof(*fhdr), ent);
    return PART_REDRAW;
}

/* help for mail reading */
static char *mail_help[] = {
    "\0�q�l�H�c�ާ@����",
    "\01�򥻩R�O",
    "(p)(��)    �e�@�g�峹",
    "(n)(��)    �U�@�g�峹",
    "(P)(PgUp)  �e�@��",
    "(N)(PgDn)  �U�@��",
    "(##)(cr)   ����� ## ��",
    "($)        ����̫�@��",
    "\01�i���R�O",
    "(r)(��)/(R)Ū�H / �^�H",
    "(O)        ����/�}�� ���~�H����J",
    "(c/z)      ���J���H��i�J�p�H�H��/�i�J�p�H�H��",
    "(x/X)      ��F�H��/����峹���L�ݪO",
    "(y)        �s�զ^�H",
    "(F)        �N�H�ǰe�^�z���q�l�H�c      (u)���y��z�H�^�H�c",
    "(d)        �������H",
    "(D)        �������w�d�򪺫H",
    "(m)        �N�H�аO�A�H���Q�M��",
    "(^G)       �ߧY���ثH�c (�H�c���l�ɥ�)",
    "(t)        �аO���R���H��",
    "(^D)       �R���w�аO�H��",
    NULL
};

static int m_help() {
    show_help(mail_help);
    return FULLUPDATE;
}

static int mail_cross_post(int ent, fileheader_t *fhdr, char *direct) {
    char xboard[20], fname[80], xfpath[80], xtitle[80], inputbuf[10];
    fileheader_t xfile;
    FILE *xptr;
    int author = 0;
    char genbuf[200];
    char genbuf2[4];
    
    make_blist();
    move(2, 0);
    clrtoeol();
    move(3, 0);
    clrtoeol();
    move(1, 0);
    namecomplete("������峹��ݪO�G", xboard);
    if(*xboard == '\0' || !haspostperm(xboard))
	return FULLUPDATE;
    
    ent = 1;
    if(HAS_PERM(PERM_SYSOP) || !strcmp(fhdr->owner, cuser.userid)) {
	getdata(2, 0, "(1)������ (2)������榡�H[1] ",
		genbuf, 3, DOECHO);
	if(genbuf[0] != '2') {
	    ent = 0;
	    getdata(2, 0, "�O�d��@�̦W�ٶ�?[Y] ", inputbuf, 3, DOECHO);
	    if(inputbuf[0] != 'n' && inputbuf[0] != 'N')
		author = 1;
	}
    }
    
    if(ent)
	sprintf(xtitle, "[���]%.66s", fhdr->title);
    else
	strcpy(xtitle, fhdr->title);
    
    sprintf(genbuf, "�ĥέ���D�m%.60s�n��?[Y] ", xtitle);
    getdata(2, 0, genbuf, genbuf2, 4, LCECHO);
    if(*genbuf2 == 'n')
	if(getdata(2, 0, "���D�G", genbuf, TTLEN, DOECHO))
	    strcpy(xtitle, genbuf);
    
    getdata(2, 0, "(S)�s�� (L)���� (Q)�����H[Q] ", genbuf, 3, LCECHO);
    if(genbuf[0] == 'l' || genbuf[0] == 's') {
	int currmode0 = currmode;

	currmode = 0;
	setbpath(xfpath, xboard);
	stampfile(xfpath, &xfile);
	if(author)
	    strcpy(xfile.owner, fhdr->owner);
	else
	    strcpy(xfile.owner, cuser.userid);
	strcpy(xfile.title, xtitle);
	if(genbuf[0] == 'l') {
	    xfile.savemode = 'L';
	    xfile.filemode = FILE_LOCAL;
	} else
	    xfile.savemode = 'S';
	
	setuserfile(fname, fhdr->filename);
	if(ent) {
	    xptr = fopen(xfpath, "w");
	    
	    strcpy(save_title, xfile.title);
	    strcpy(xfpath, currboard);
	    strcpy(currboard, xboard);
	    write_header(xptr);
	    strcpy(currboard, xfpath);
	    
	    fprintf(xptr, "�� [��������� %s �H�c]\n\n", cuser.userid);
	    
	    b_suckinfile(xptr, fname);
	    addsignature(xptr,0);
	    fclose(xptr);
	} else {
	    unlink(xfpath);
	    Link(fname, xfpath);
	}
	
	setbdir(fname, xboard);
	append_record(fname, &xfile, sizeof(xfile));
	setbtotal(getbnum(xboard));
	if(!xfile.filemode)
	    outgo_post(&xfile, xboard);
	cuser.numposts++;
	passwd_update(usernum, &cuser);
	outs("�峹�������");
	pressanykey();
	currmode = currmode0;
    }
    return FULLUPDATE;
}

int mail_man() {
    char buf[64],buf1[64];
    if (HAS_PERM(PERM_MAILLIMIT)) {
	int mode0 = currutmp->mode;
	int stat0 = currstat;
	
	sethomeman(buf, cuser.userid);
	sprintf(buf1, "%s ���H��", cuser.userid);
	a_menu(buf1, buf, 1);
	currutmp->mode = mode0;
	currstat = stat0;
	return FULLUPDATE;
    }
    return DONOTHING;
}

static int mail_cite(int ent, fileheader_t *fhdr, char *direct) {
    char fpath[256];
    char title[TTLEN + 1];
    static char xboard[20];
    char buf[20];
    boardheader_t *bp;

    setuserfile(fpath, fhdr->filename);
    strcpy(title, "�� ");
    strncpy(title+3, fhdr->title, TTLEN-3);
    title[TTLEN] = '\0';
    a_copyitem(fpath, title, 0, 1);

    if(cuser.userlevel >= PERM_BM) {
	move(2, 0);
	clrtoeol();
	move(3, 0);
	clrtoeol();
	move(1, 0);
	make_blist();
	namecomplete("��J�ݪ��W�� (����Enter�i�J�p�H�H��)�G", buf);
	if(*buf)
	    strcpy(xboard, buf);
	if(*xboard && (bp = getbcache(getbnum(xboard)))) {
	    setapath(fpath, xboard);
	    setutmpmode(ANNOUNCE);
	    a_menu(xboard, fpath, HAS_PERM(PERM_ALLBOARD) ? 2 :
		   is_BM(bp->BM) ? 1 : 0);
	} else {
	    mail_man();
	}
	return FULLUPDATE;
    } else {
	mail_man();
        return FULLUPDATE;
    }
}

static int mail_save(int ent, fileheader_t *fhdr, char *direct) {
    char fpath[256];
    char title[TTLEN+1];

    if(HAS_PERM(PERM_MAILLIMIT)) {
	setuserfile(fpath, fhdr->filename);
	strcpy(title, "�� ");
	strncpy(title + 3, fhdr->title, TTLEN - 3);
	title[TTLEN] = '\0';
	a_copyitem(fpath, title, fhdr->owner, 1);
	sethomeman(fpath, cuser.userid);
	a_menu(cuser.userid, fpath, 1);
	return FULLUPDATE;
    }
    return DONOTHING;
}

#ifdef OUTJOBSPOOL
static int mail_waterball(int ent, fileheader_t *fhdr, char *direct)
{
    static  char address[60], cmode = 1;
    char    fname[500], genbuf[200];
    FILE    *fp;
    int     now;

    if(!address[0])
	strcpy(address, cuser.email);
    if(address[0]) {
	sprintf(genbuf, "�H�� [%s] ��(Y/N/Q)�H[Y] ", address);
	getdata(b_lines - 2, 0, genbuf, fname, 3, LCECHO);
	if(fname[0] == 'q') { outmsg("�����B�z"); return 1; }
	if(fname[0] == 'n')
	    address[0] = '\0';
    }
    
    if(!address[0]) {
	getdata(b_lines - 2, 0, "�п�J�l��a�}�G", fname, 60, DOECHO);
	if(fname[0] && strchr(fname, '.')) {
	    strcpy(address, fname);
	} else {
	    outmsg("�����B�z");
	    return 1;
	}
    }
    if(invalidaddr(address))
	return -2;
    
    //    sprintf(fname, "%d\n", cmode);
    getdata(b_lines - 1, 0, "�ϥμҦ�(0/1)? [1]", fname, 3, LCECHO);
    cmode = (fname[0] != '0' && fname[0] != '1') ? 1 : fname[0] - '0';
    
    now = time(NULL);
    sprintf(fname, BBSHOME "/jobspool/water.src.%s-%d",
	    cuser.userid, now);
    sprintf(genbuf, "cp " BBSHOME "/home/%c/%s/%s %s",
	    cuser.userid[0], cuser.userid, fhdr->filename, fname);
    system(genbuf);
    /* dirty code ;x */
    sprintf(fname, BBSHOME "/jobspool/water.des.%s-%d",
	    cuser.userid, now);
    fp = fopen(fname, "wt");
    fprintf(fp, "%s\n%s\n%d\n", cuser.userid, address, cmode);
    fclose(fp);
    return FULLUPDATE;
}
#endif
static struct onekey_t mail_comms[] = {
    {'z', mail_man},
    {'c', mail_cite},
    {'s', mail_save},
    {'d', mail_del},
    {'D', del_range},
    {'r', mail_read},
    {'R', mail_reply},
    {'E', mail_edit},
    {'m', mail_mark},
    {'O', mail_nooutmail},
    {'T', edit_title},
    {'x', m_forward},
    {'X', mail_cross_post},
    {Ctrl('G'), built_mail_index}, /* �׫H�c */
    {'y', multi_reply},
    {Ctrl('I'), m_idle},
    {'h', m_help},
#ifdef OUTJOBSPOOL
    {'u', mail_waterball},
#endif
    {'\0', NULL}
};

int m_read() {
    if(get_num_records(currmaildir, sizeof(fileheader_t))) {
	curredit = EDIT_MAIL;
	curredit &= ~EDIT_ITEM;
	i_read(RMAIL, currmaildir, mailtitle, maildoent, mail_comms,  -1);
	curredit = 0;
        currutmp->mailalert = load_mailalert(cuser.userid);
	return 0;
    } else {
	outs("�z�S���ӫH");
	return XEASY;
    }
}

/* �H�����H */
static int send_inner_mail(char *fpath, char *title, char *receiver) {
    char genbuf[256];
    fileheader_t mymail;
    
    if(!searchuser(receiver))
	return -2;
    sethomepath(genbuf, receiver);
    stampfile(genbuf, &mymail);
    if(!strcmp(receiver, cuser.userid)) {
	strcpy(mymail.owner, "[" BBSNAME "]");
	mymail.filemode = FILE_READ;
    } else
	strcpy(mymail.owner, cuser.userid);
    strncpy(mymail.title, title, TTLEN);
    unlink(genbuf);
    Link(fpath, genbuf);
    sethomedir(genbuf, receiver);
    return do_append(genbuf, &mymail, sizeof(mymail));    
}

#include <netdb.h>
#include <pwd.h>
#include <time.h>

#ifndef USE_BSMTP
static int bbs_sendmail(char *fpath, char *title, char *receiver) {
    static int configured = 0;
    static char myhostname[STRLEN];
    static char myusername[20];
    struct hostent *hbuf;
    struct passwd *pbuf;
    char *ptr;
    char genbuf[256];
    FILE *fin, *fout;

    /* ���~�d�I */
    if((ptr = strchr(receiver, ';'))) {
	struct tm *ptime;
	time_t now;
	
	*ptr = '\0';
    }
    
    if((ptr = strstr(receiver, str_mail_address)) || !strchr(receiver,'@')) {
	char hacker[20];
	int len;

	if(strchr(receiver,'@')) {
            len = ptr - receiver;
            memcpy(hacker, receiver, len);
            hacker[len] = '\0';
        } else
            strcpy(hacker,receiver);
	return send_inner_mail(fpath, title, hacker);
    }
    
    /* setup the hostname and username */
    if(!configured) {
	/* get host name */
	hbuf = gethostbyname("localhost");
	if(hbuf)
	    strncpy(myhostname, hbuf->h_name, STRLEN);

	/* get bbs uident */
	pbuf = getpwuid(getuid());
	if(pbuf)
	    strncpy(myusername, pbuf->pw_name, 20);
	if(hbuf && pbuf)
	    configured = 1;
	else
	    return -1;
    }
    
    /* Running the sendmail */
    if(fpath == NULL) {
	sprintf(genbuf, "/usr/sbin/sendmail %s > /dev/null", receiver);
	fin = fopen("etc/confirm", "r");
    } else {
	sprintf(genbuf, "/usr/sbin/sendmail -f %s%s %s > /dev/null",
		cuser.userid, str_mail_address, receiver);
	fin = fopen(fpath, "r");
    }
    fout = popen(genbuf, "w");
    if(fin == NULL || fout == NULL)
	return -1;
    
    if(fpath)
	fprintf(fout, "Reply-To: %s%s\nFrom: %s%s\n",
		cuser.userid, str_mail_address, cuser.userid,
		str_mail_address);
    fprintf(fout, "To: %s\nSubject: %s\n", receiver, title);
    fprintf(fout, "X-Disclaimer: " BBSNAME "�糧�H���e�����t�d�C\n\n");
    
    while(fgets(genbuf, 255, fin)) {
	if(genbuf[0] == '.' && genbuf[1] == '\n')
	    fputs(". \n", fout);
	else
	    fputs(genbuf, fout);
    }
    fclose(fin);
    fprintf(fout, ".\n");
    pclose(fout);
    return 0;
}
#else /* USE_BSMTP */

int bsmtp(char *fpath, char *title, char *rcpt, int method) {
    char buf[80], *ptr;
    time_t chrono;
    MailQueue mqueue;

    /* check if the mail is a inner mail */
    if((ptr = strstr(rcpt, str_mail_address)) || !strchr(rcpt, '@')) {
	char hacker[20];
	int len;

	if(strchr(rcpt,'@')) {
            len = ptr - rcpt;
            memcpy(hacker, rcpt, len);
            hacker[len] = '\0';
        } else
            strcpy(hacker, rcpt);
	return send_inner_mail(fpath, title, hacker);
    }
    
    chrono = time(NULL);
    if(method != MQ_JUSTIFY) { /* �{�ҫH */
	/* stamp the queue file */
	strcpy(buf, "out/");
	for(;;) {
	    sprintf(buf + 4,"M.%ld.A", ++chrono);
	    if(!dashf(buf)) {
		Link(fpath, buf);
		break;
	    }
	}
	
	fpath = buf;

	strcpy(mqueue.filepath, fpath);
	strcpy(mqueue.subject, title);
    }
    /* setup mail queue */    
    mqueue.mailtime = chrono;
    mqueue.method = method;
    strcpy(mqueue.sender, cuser.userid);
    strcpy(mqueue.username, cuser.username);
    strcpy(mqueue.rcpt, rcpt);
    if(do_append("out/.DIR", (fileheader_t *)&mqueue, sizeof(mqueue)) < 0)
	return 0;
    return chrono;
}
#endif /* USE_BSMTP */

int doforward(char *direct, fileheader_t *fh, int mode) {
    static char address[60];
    char fname[500];
    int return_no;
    char genbuf[200];
    
    if(!address[0])
	strcpy(address, cuser.email);

    if(address[0]) {
	sprintf(genbuf, "�T�w��H�� [%s] ��(Y/N/Q)�H[Y] ", address);
	getdata(b_lines - 1, 0, genbuf, fname, 3, LCECHO);
	
	if(fname[0] == 'q') {
	    outmsg("������H");
	    return 1;
	}
	if(fname[0] == 'n')
	    address[0] = '\0';
    }
    
    if(!address[0]) {
	do{
	    getdata(b_lines - 1, 0, "�п�J��H�a�}�G", fname, 60, DOECHO);
	    if(fname[0]) {
		if(strchr(fname, '.'))
		    strcpy(address, fname);
		else
		    sprintf(address, "%s.bbs@%s", fname, MYHOSTNAME);
	    } else {
		outmsg("������H");
		return 1;
	    }
	}while(mode=='Z' && strstr(address, MYHOSTNAME));
    }
    if(invalidaddr(address))
	return -2;
    
    sprintf(fname, "����H�� %s, �еy��...", address);
    outmsg(fname);
    move(b_lines - 1, 0);
    refresh();
    
    /* �l�ܨϥΪ� */
    if(HAS_PERM(PERM_LOGUSER)) {
	time_t now = time(NULL);
	char msg[200];
	
	sprintf(msg, "%s mailforward to %s at %s",
		cuser.userid, address, Cdate(&now));
	log_user(msg);
    }
    
    if(mode == 'Z') {
	sprintf(fname, TAR_PATH " cfz - home/%c/%s | "
		"/usr/bin/uuencode %s.tgz > %s",
		cuser.userid[0], cuser.userid, cuser.userid, direct);
	system(fname);
	strcpy(fname, direct);
    } else if(mode == 'U') {
	char tmp_buf[128];

	sprintf(fname, "/tmp/bbs.uu%05d", currpid);
	sprintf(tmp_buf, "/usr/bin/uuencode %s/%s uu.%05d > %s",
		direct, fh->filename, currpid, fname);
	system(tmp_buf);
    } else if (mode == 'F'){
	char tmp_buf[128];
	
	sprintf(fname, "/tmp/bbs.f%05d", currpid);
	sprintf(tmp_buf, "cp %s/%s %s",direct,fh->filename,fname);
	system(tmp_buf);
    } else
	return -1;
    
    return_no =
#ifndef USE_BSMTP
	bbs_sendmail(fname, fh->title, address);
#else
    bsmtp(fname, fh->title, address,mode);
#endif
    unlink(fname);
    return (return_no);
}

int load_mailalert(char *userid) {
    struct stat st;
    char maildir[256];
    int fd;
    register int numfiles;
    fileheader_t my_mail;

    sethomedir(maildir, userid); 
    if(!HAS_PERM(PERM_BASIC))
	return 0;
    if(stat(maildir, &st) < 0)
	return 0;
    numfiles = st.st_size / sizeof(fileheader_t);
    if(numfiles <= 0)
	return 0;
    
    /* �ݬݦ��S���H���٨SŪ�L�H�q�ɧ��^�Y�ˬd�A�IJv���� */    
    if((fd = open(maildir, O_RDONLY)) > 0) {
	lseek(fd, st.st_size - sizeof(fileheader_t), SEEK_SET);
	while(numfiles--) {
	    read(fd, &my_mail, sizeof(fileheader_t));
	    if(!(my_mail.filemode & FILE_READ)) {
		close(fd);
		return 1;
	    }
	    lseek(fd, -(off_t)2 * sizeof(fileheader_t), SEEK_CUR);
	}
	close(fd);
    }
    return 0;
}

#ifdef  EMAIL_JUSTIFY
static void mail_justify(userec_t muser) {
    fileheader_t mhdr;
    char title[128], buf1[80];
    FILE* fp;
    
    sethomepath(buf1, muser.userid);
    stampfile(buf1, &mhdr);
    unlink(buf1);
    strcpy(mhdr.owner, cuser.userid);
    strncpy(mhdr.title, "[�f�ֳq�L]", TTLEN);
    mhdr.savemode = 0;
    mhdr.filemode = 0;

    if(valid_ident(muser.email) && !invalidaddr(muser.email)) {
	char title[80], *ptr;
	unsigned short checksum;            /* 16-bit is enough */
	char ch;
	
	checksum = searchuser(muser.userid);
	ptr = muser.email;
	while((ch = *ptr++)) {
	    if(ch <= ' ')
		break;
	    if(ch >= 'A' && ch <= 'Z')
		ch |= 0x20;
	    checksum = (checksum << 1) ^ ch;
	}
	
	sprintf(title, "[PTT BBS]To %s(%d:%d) [User Justify]",
		muser.userid, getuser(muser.userid) + MAGIC_KEY, checksum);
	if(
#ifndef USE_BSMTP
	    bbs_sendmail(NULL, title, muser.email)
#else
	    bsmtp(NULL, title, muser.email, MQ_JUSTIFY);
#endif
	    < 0)
	    Link("etc/bademail", buf1);
	else
	    Link("etc/replyemail", buf1);
    } else
	Link("etc/bademail", buf1);
    sethomedir(title, muser.userid);
    append_record(title, &mhdr, sizeof(mhdr));
}
#endif /* EMAIL_JUSTIFY */