Skip to content
Snippets Groups Projects
netmail.cpp 38.5 KiB
Newer Older
	if(remsg != NULL && resmb != NULL && !(mode&WM_QUOTE)) {
		if(quotemsg(resmb, remsg, /* include tails: */true))
			mode |= WM_QUOTE;
	}

	SAFEPRINTF(msgpath,"%snetmail.msg",cfg.node_dir);
	if(!writemsg(msgpath,nulstr,title,WM_NETMAIL|mode,INVALID_SUB, to_list, /* from: */your_addr, &editor, &charset)) {
		strListFree(&rcpt_list);
		bputs(text[Aborted]);
		return(false); 
	}
		SAFEPRINTF2(str2,"%sfile/%04u.out",cfg.data_dir,useron.number);
rswindell's avatar
rswindell committed
		MKDIR(str2);
		SAFEPRINTF3(str2,"%sfile/%04u.out/%s",cfg.data_dir,useron.number,title);
			strListFree(&rcpt_list);
			bputs(text[FileAlreadyThere]);
			remove(msgpath);
			return(false); 
		}
		{ /* Remote */
			mnemonics(text[ProtocolOrQuit]);
			SAFEPRINTF(str,"%c",text[YNQP][2]);
			for(x=0;x<cfg.total_prots;x++)
rswindell's avatar
rswindell committed
				if(cfg.prot[x]->ulcmd[0] && chk_ar(cfg.prot[x]->ar,&useron,&client)) {
					SAFEPRINTF(tmp,"%c",cfg.prot[x]->mnemonic);
					SAFECAT(str,tmp); 
			ch=(char)getkeys(str,0);
			if(ch==text[YNQP][2] || sys_status&SS_ABORT) {
				bputs(text[Aborted]);
				strListFree(&rcpt_list);
				remove(msgpath);
				return(false); 
			}
			for(x=0;x<cfg.total_prots;x++)
				if(cfg.prot[x]->ulcmd[0] && cfg.prot[x]->mnemonic==ch
rswindell's avatar
rswindell committed
					&& chk_ar(cfg.prot[x]->ar,&useron,&client))
					break;
			if(x<cfg.total_prots)	/* This should be always */
				protocol(cfg.prot[x],XFER_UPLOAD,str2,nulstr,true); 
		SAFEPRINTF2(tmp,"%s%s",cfg.temp_dir,title);
		if(!fexistcase(str2) && fexistcase(tmp))
			mv(tmp,str2,0);
		if(l>0)
			bprintf(text[FileNBytesReceived],title,ultoac(l,tmp));
		else {
			bprintf(text[FileNotReceived],title);
			strListFree(&rcpt_list);
			remove(msgpath);
			return(false); 
		} 
	}
	if((i=smb_open_sub(&cfg, &smb, INVALID_SUB))!=SMB_SUCCESS) {
		strListFree(&rcpt_list);
		errormsg(WHERE,ERR_OPEN,smb.file,i,smb.last_error);
		return(false); 
	}
	if((instream=fnopen(&file,msgpath,O_RDONLY|O_BINARY))==NULL) {
		strListFree(&rcpt_list);
		smb_close(&smb);
		errormsg(WHERE,ERR_OPEN,msgpath,O_RDONLY|O_BINARY);
		return(false); 
	}
	off_t length = filelength(file);
	if(length < 1) {
		strListFree(&rcpt_list);
		smb_close(&smb);
		errormsg(WHERE, ERR_LEN, msgpath, length);
		return(false); 
	}
	char* msgbuf;
	if((msgbuf = (char*)malloc(length + 1)) == NULL) {
		strListFree(&rcpt_list);
		smb_close(&smb);
		errormsg(WHERE, ERR_ALLOC, msgpath, length);
		return(false); 
	}
	if(fread(msgbuf, sizeof(char), length, instream) != (size_t)length) {
		strListFree(&rcpt_list);
		smb_close(&smb);
		errormsg(WHERE, ERR_READ, msgpath, length);
		return(false); 
	}
	fclose(instream);

	memset(&msg,0,sizeof(smbmsg_t));
	msg.hdr.version=smb_ver();
	if(mode&WM_FILE)
		msg.hdr.auxattr |= (MSG_FILEATTACH | MSG_KILLFILE);
	msg.hdr.when_written.time=msg.hdr.when_imported.time=time32(NULL);
	msg.hdr.when_written.zone=msg.hdr.when_imported.zone=sys_timezone(&cfg);
	msg.hdr.netattr |= MSG_LOCAL;
	if(cfg.inetmail_misc&NMAIL_KILL)
		msg.hdr.netattr |= MSG_KILLSENT;

	if(rcpt_count > 1)
		smb_hfield_str(&msg, RECIPIENTLIST, to_list);
	smb_hfield_str(&msg,SENDER,cfg.inetmail_misc&NMAIL_ALIAS ? useron.alias : useron.name);
	SAFEPRINTF(str,"%u",useron.number);
	smb_hfield_str(&msg,SENDEREXT,str);
	smb_hfield_str(&msg,SENDERSERVER,startup->host_name);
	smb_hfield_str(&msg,SUBJECT,title);
	editor_info_to_msg(&msg, editor, charset);
	i = savemsg(&cfg, &smb, &msg, &client, startup->host_name, msgbuf, remsg);
	free(msgbuf);
		smb_close(&smb);
		smb_freemsgmem(&msg);
		strListFree(&rcpt_list);
		errormsg(WHERE,ERR_WRITE,smb.file,i,smb.last_error);
	for(rcpt_count = 0; rcpt_list[rcpt_count] != NULL; rcpt_count++) {

		uint16_t net_type = smb_netaddr_type(rcpt_list[rcpt_count]);
		if(net_type != NET_INTERNET) {
			bprintf(text[InvalidNetMailAddr], rcpt_list[rcpt_count]);
			break;
		}

		/* Get destination user address */
		if((p = strrchr(rcpt_list[rcpt_count], '<')) != NULL) {
			p++;
			SKIP_WHITESPACE(p);
			SAFECOPY(addr, p);
			p = strrchr(addr, '>');
			if(p == NULL) {
				bprintf(text[InvalidNetMailAddr], rcpt_list[rcpt_count]);
				break;
			}
			*p = 0;
		} else {
			p = rcpt_list[rcpt_count];
			SKIP_WHITESPACE(p);
			SAFECOPY(addr, p);
		}
		truncsp(addr);

		/* Get destination user name */
		p = rcpt_list[rcpt_count];
		SKIP_WHITESPACE(p);
		SAFECOPY(name, p);
		p=strrchr(name,'<');
		if(!p)
			p=strrchr(name,'@');
		if(!p)
			p=strrchr(name,'!');
		if(p) {
			*p=0;
			if(name[0] == 0)
				SAFECOPY(name, addr);
		}
		truncsp(name);

		smbmsg_t newmsg;
		if((i = smb_copymsgmem(&smb, &newmsg, &msg)) != SMB_SUCCESS) {
			errormsg(WHERE, "copying", "message header", i, smb.last_error);
			break;
		}

		smb_hfield_str(&newmsg, RECIPIENT, name);
		smb_hfield(&newmsg, RECIPIENTNETTYPE, sizeof(net_type), &net_type);
		smb_hfield_str(&newmsg, RECIPIENTNETADDR, addr);
		i=smb_addmsghdr(&smb, &newmsg, smb_storage_mode(&cfg, &smb));
		smb_freemsgmem(&newmsg);
		if(i != SMB_SUCCESS) {
			errormsg(WHERE, "adding", "message header", i, smb.last_error);
			break;
		}
	}

	if(rcpt_count > 1)
		smb_incmsg_dfields(&smb, &msg, (uint16_t)(rcpt_count - 1));

	smb_close(&smb);

	smb_freemsgmem(&msg);
	strListFree(&rcpt_list);

	if(mode&WM_FILE && online==ON_REMOTE)
		autohangup();

	if(cfg.inetmail_sem[0]) 	 /* update semaphore file */
		ftouch(cmdstr(cfg.inetmail_sem,nulstr,nulstr,NULL));
	if(!(useron.exempt&FLAG('S')))
		subtract_cdt(&cfg,&useron,cfg.inetmail_cost * rcpt_count);
	useron.emails += (ushort)rcpt_count;
	logon_emails += rcpt_count;
	putuserrec(&cfg,useron.number,U_EMAILS,5,ultoa(useron.emails,tmp,10)); 
	useron.etoday += (ushort)rcpt_count;
	putuserrec(&cfg,useron.number,U_ETODAY,5,ultoa(useron.etoday,tmp,10));
	SAFEPRINTF(str, "sent Internet Mail to %s", to_list);
	logline("EN",str);
	return(true);
}

bool sbbs_t::qnetmail(const char *into, const char *subj, long mode, smb_t* resmb, smbmsg_t* remsg)
	char	str[256],msgpath[128],fulladdr[128]
			,buf[SDT_BLOCK_LEN],*addr;
	char	title[128] = "";
	char	to[128] = "";
	const char*	editor=NULL;
	const char*	charset=NULL;
	ushort	xlat=XLAT_NONE,net=NET_QWK,touser;
	int 	i,j,x,file;
	ulong	length,offset;
	FILE	*instream;
	smbmsg_t msg;

	if(useron.etoday>=cfg.level_emailperday[useron.level] && !SYSOP && !(useron.exempt&FLAG('M'))) {
		bputs(text[TooManyEmailsToday]);
		return(false); 
	}

	if(into != NULL)
		SAFECOPY(to,into);
	if(subj != NULL)
		SAFECOPY(title,subj);

	if(useron.rest&FLAG('M')) {
		bputs(text[NoNetMailAllowed]);
		return(false); 
	}

	addr=strrchr(to,'@');
	if(!addr) {
		bprintf(text[InvalidNetMailAddr], to);
	*addr=0;
	addr++;
	strupr(addr);
	truncsp(addr);
	touser=qwk_route(&cfg,addr,fulladdr,sizeof(fulladdr)-1);
	if(!fulladdr[0]) {
		bprintf(text[InvalidNetMailAddr], addr);

	truncsp(to);
	if(!stricmp(to,"SBBS") && !SYSOP) {
		bprintf(text[InvalidNetMailAddr], to);
	bprintf(text[NetMailing],to,fulladdr
		,useron.alias,cfg.sys_id);
	action=NODE_SMAL;
	nodesync();

	if(remsg != NULL && resmb != NULL && !(mode&WM_QUOTE)) {
		if(quotemsg(resmb, remsg, /* include tails: */true))
			mode |= WM_QUOTE;
	}

	SAFEPRINTF(msgpath,"%snetmail.msg",cfg.node_dir);
	if(!writemsg(msgpath,nulstr,title, (mode|WM_QWKNET|WM_NETMAIL) ,INVALID_SUB,to,/* from: */useron.alias, &editor, &charset)) {
		bputs(text[Aborted]);
		return(false); 
	}
	if((i=smb_stack(&smb,SMB_STACK_PUSH))!=SMB_SUCCESS) {
		errormsg(WHERE,ERR_OPEN,"MAIL",i);
		return(false); 
	}
	smb.retry_time=cfg.smb_retry_time;
	if((i=smb_open(&smb))!=SMB_SUCCESS) {
		smb_stack(&smb,SMB_STACK_POP);
		errormsg(WHERE,ERR_OPEN,smb.file,i,smb.last_error);
		return(false); 
	}

	if(filelength(fileno(smb.shd_fp))<1) {	 /* Create it if it doesn't exist */
		smb.status.max_crcs=cfg.mail_maxcrcs;
		smb.status.max_age=cfg.mail_maxage;
		smb.status.attr=SMB_EMAIL;
		if((i=smb_create(&smb))!=SMB_SUCCESS) {
			smb_close(&smb);
			smb_stack(&smb,SMB_STACK_POP);
			errormsg(WHERE,ERR_CREATE,smb.file,i,smb.last_error);
			return(false); 
		} 
	}
	if((i=smb_locksmbhdr(&smb))!=SMB_SUCCESS) {
		smb_close(&smb);
		smb_stack(&smb,SMB_STACK_POP);
		errormsg(WHERE,ERR_LOCK,smb.file,i,smb.last_error);
		return(false); 
	}
	length=(long)flength(msgpath)+2;	 /* +2 for translation string */

	if(length&0xfff00000UL) {
		smb_unlocksmbhdr(&smb);
		smb_close(&smb);
		smb_stack(&smb,SMB_STACK_POP);
		errormsg(WHERE,ERR_LEN,msgpath,length);
		return(false); 
	}
	if((i=smb_open_da(&smb))!=SMB_SUCCESS) {
		smb_unlocksmbhdr(&smb);
		smb_close(&smb);
		smb_stack(&smb,SMB_STACK_POP);
		errormsg(WHERE,ERR_OPEN,smb.file,i,smb.last_error);
		return(false); 
	}
	if(cfg.sys_misc&SM_FASTMAIL)
		offset=smb_fallocdat(&smb,length,1);
	else
		offset=smb_allocdat(&smb,length,1);
	smb_close_da(&smb);

	if((instream=fnopen(&file,msgpath,O_RDONLY|O_BINARY))==NULL) {
		smb_freemsgdat(&smb,offset,length,1);
		smb_unlocksmbhdr(&smb);
		smb_close(&smb);
		smb_stack(&smb,SMB_STACK_POP);
		errormsg(WHERE,ERR_OPEN,msgpath,O_RDONLY|O_BINARY);
		return(false); 
	}

	setvbuf(instream,NULL,_IOFBF,2*1024);
	fseek(smb.sdt_fp,offset,SEEK_SET);
	xlat=XLAT_NONE;
	fwrite(&xlat,2,1,smb.sdt_fp);
	x=SDT_BLOCK_LEN-2;				/* Don't read/write more than 255 */
	while(!feof(instream)) {
		memset(buf,0,x);
		j=fread(buf,1,x,instream);
		if(j<1)
			break;
		if(j>1 && (j!=x || feof(instream)) && buf[j-1]==LF && buf[j-2]==CR)
			buf[j-1]=buf[j-2]=0;
		fwrite(buf,j,1,smb.sdt_fp);
		x=SDT_BLOCK_LEN; 
	}
	fflush(smb.sdt_fp);
	fclose(instream);

	memset(&msg,0,sizeof(smbmsg_t));
	msg.hdr.version=smb_ver();
	if(mode&WM_FILE)
		msg.hdr.auxattr |= (MSG_FILEATTACH | MSG_KILLFILE);
	msg.hdr.when_written.time=msg.hdr.when_imported.time=time32(NULL);
	msg.hdr.when_written.zone=msg.hdr.when_imported.zone=sys_timezone(&cfg);

	msg.hdr.offset=offset;

	net=NET_QWK;
	smb_hfield_str(&msg,RECIPIENT,to);
	sprintf(str,"%u",touser);
	smb_hfield_str(&msg,RECIPIENTEXT,str);
	smb_hfield(&msg,RECIPIENTNETTYPE,sizeof(net),&net);
	smb_hfield_str(&msg,RECIPIENTNETADDR,fulladdr);
	smb_hfield_str(&msg,SENDER,useron.alias);

	sprintf(str,"%u",useron.number);
	smb_hfield_str(&msg,SENDEREXT,str);
	smb_hfield_str(&msg,SENDERSERVER,startup->host_name);
	smb_hfield_str(&msg,SUBJECT,title);
	add_msg_ids(&cfg, &smb, &msg, /* remsg: */NULL);
	editor_info_to_msg(&msg, editor, charset);
	smb_dfield(&msg,TEXT_BODY,length);

	i=smb_addmsghdr(&smb,&msg,smb_storage_mode(&cfg, &smb)); // calls smb_unlocksmbhdr() 
	smb_close(&smb);
	smb_stack(&smb,SMB_STACK_POP);

	smb_freemsgmem(&msg);
		errormsg(WHERE,ERR_WRITE,smb.file,i,smb.last_error);
		smb_freemsgdat(&smb,offset,length,1);
		return(false); 
	}

	useron.emails++;
	logon_emails++;
	putuserrec(&cfg,useron.number,U_EMAILS,5,ultoa(useron.emails,tmp,10)); 
	useron.etoday++;
	putuserrec(&cfg,useron.number,U_ETODAY,5,ultoa(useron.etoday,tmp,10));
	sprintf(str,"sent QWK NetMail to %s (%s)"
	logline("EN",str);
	return(true);
}