Annotation of sbbs/src/sbbs3/email.cpp, revision 1.1.1.2

1.1       root        1: /* email.cpp */
                      2: 
                      3: /* Synchronet email function - for sending private e-mail */
                      4: 
1.1.1.2 ! root        5: /* $Id: email.cpp,v 1.53 2011/08/30 22:51:21 rswindell Exp $ */
1.1       root        6: 
                      7: /****************************************************************************
                      8:  * @format.tab-size 4          (Plain Text/Source Code File Header)                    *
                      9:  * @format.use-tabs true       (see http://www.synchro.net/ptsc_hdr.html)              *
                     10:  *                                                                                                                                                     *
1.1.1.2 ! root       11:  * Copyright 2011 Rob Swindell - http://www.synchro.net/copyright.html         *
1.1       root       12:  *                                                                                                                                                     *
                     13:  * This program is free software; you can redistribute it and/or                       *
                     14:  * modify it under the terms of the GNU General Public License                         *
                     15:  * as published by the Free Software Foundation; either version 2                      *
                     16:  * of the License, or (at your option) any later version.                                      *
                     17:  * See the GNU General Public License for more details: gpl.txt or                     *
                     18:  * http://www.fsf.org/copyleft/gpl.html                                                                                *
                     19:  *                                                                                                                                                     *
                     20:  * Anonymous FTP access to the most recent released source is available at     *
                     21:  * ftp://vert.synchro.net, ftp://cvs.synchro.net and ftp://ftp.synchro.net     *
                     22:  *                                                                                                                                                     *
                     23:  * Anonymous CVS access to the development source and modification history     *
                     24:  * is available at cvs.synchro.net:/cvsroot/sbbs, example:                                     *
                     25:  * cvs -d :pserver:[email protected]:/cvsroot/sbbs login                       *
                     26:  *     (just hit return, no password is necessary)                                                     *
                     27:  * cvs -d :pserver:[email protected]:/cvsroot/sbbs checkout src                *
                     28:  *                                                                                                                                                     *
                     29:  * For Synchronet coding style and modification guidelines, see                                *
                     30:  * http://www.synchro.net/source.html                                                                          *
                     31:  *                                                                                                                                                     *
                     32:  * You are encouraged to submit any modifications (preferably in Unix diff     *
                     33:  * format) via e-mail to [email protected]                                                                      *
                     34:  *                                                                                                                                                     *
                     35:  * Note: If this box doesn't appear square, then you need to fix your tabs.    *
                     36:  ****************************************************************************/
                     37: 
                     38: #include "sbbs.h"
                     39: #include "cmdshell.h"
                     40: 
                     41: /****************************************************************************/
                     42: /* Mails a message to usernumber. 'top' is a buffer to place at beginning   */
                     43: /* of message.                                                              */
                     44: /* Called from functions main_sec, newuser, readmail and scanposts                     */
                     45: /****************************************************************************/
1.1.1.2 ! root       46: bool sbbs_t::email(int usernumber, const char *top, const char *subj, long mode)
1.1       root       47: {
1.1.1.2 ! root       48:        char            str[256],str2[256],msgpath[256],title[LEN_TITLE+1],ch
        !            49:                                ,buf[SDT_BLOCK_LEN];
        !            50:        char            tmp[512];
        !            51:        char            pid[128];
        !            52:        char*           editor=NULL;
        !            53:        ushort          msgattr=0;
        !            54:        uint16_t        xlat=XLAT_NONE;
        !            55:        ushort          nettype;
        !            56:        int             i,j,x,file;
        !            57:        long            l;
        !            58:        long            length;
        !            59:        ulong           offset;
        !            60:        uint32_t        crc=0xffffffffUL;
        !            61:        FILE*           instream;
        !            62:        node_t          node;
        !            63:        smbmsg_t        msg;
1.1       root       64: 
                     65:        SAFECOPY(title,subj);
                     66: 
1.1.1.2 ! root       67:        if(useron.etoday>=cfg.level_emailperday[useron.level] && !SYSOP && !(useron.exempt&FLAG('M'))) {
1.1       root       68:                bputs(text[TooManyEmailsToday]);
1.1.1.2 ! root       69:                return(false); 
        !            70:        }
1.1       root       71: 
                     72:        if(usernumber==1 && useron.rest&FLAG('S')
                     73:                && (cfg.node_valuser!=1 || useron.fbacks || useron.emails)) { /* ! val fback */
                     74:                bprintf(text[R_Feedback],cfg.sys_op);
1.1.1.2 ! root       75:                return(false); 
        !            76:        }
1.1       root       77:        if(usernumber!=1 && useron.rest&FLAG('E')
                     78:                && (cfg.node_valuser!=usernumber || useron.fbacks || useron.emails)) {
                     79:                bputs(text[R_Email]);
1.1.1.2 ! root       80:                return(false); 
        !            81:        }
1.1       root       82:        if(!usernumber) {
                     83:                bputs(text[UnknownUser]);
1.1.1.2 ! root       84:                return(false); 
        !            85:        }
1.1       root       86:        getuserrec(&cfg,usernumber,U_MISC,8,str);
                     87:        l=ahtoul(str);
                     88:        if(l&(DELETED|INACTIVE)) {              /* Deleted or Inactive User */
                     89:                bputs(text[UnknownUser]);
1.1.1.2 ! root       90:                return(false); 
        !            91:        }
1.1       root       92:        if(l&NETMAIL && cfg.sys_misc&SM_FWDTONET) {
                     93:                getuserrec(&cfg,usernumber,U_NETMAIL,LEN_NETMAIL,str);
                     94:                bprintf(text[UserNetMail],str);
1.1.1.2 ! root       95:                if(text[ForwardMailQ][0]==0 || yesno(text[ForwardMailQ])) /* Forward to netmail address */
1.1       root       96:                        return(netmail(str,subj,mode));
                     97:        }
                     98:        bprintf(text[Emailing],username(&cfg,usernumber,tmp),usernumber);
                     99:        action=NODE_SMAL;
                    100:        nodesync();
                    101: 
                    102:        sprintf(str,"%sfeedback.*", cfg.exec_dir);
                    103:        if(usernumber==1 && useron.fbacks && fexist(str)) {
                    104:                exec_bin("feedback",&main_csi);
                    105:                if(main_csi.logic!=LOGIC_TRUE)
1.1.1.2 ! root      106:                        return(false); 
        !           107:        }
1.1       root      108: 
                    109:        if(cfg.sys_misc&SM_ANON_EM && useron.exempt&FLAG('A')
                    110:                && !noyes(text[AnonymousQ]))
                    111:                msgattr|=MSG_ANONYMOUS;
                    112: 
                    113:        if(cfg.sys_misc&SM_DELREADM)
                    114:                msgattr|=MSG_KILLREAD;
                    115: 
                    116:        msg_tmp_fname(useron.xedit, msgpath, sizeof(msgpath));
                    117:        username(&cfg,usernumber,str2);
1.1.1.2 ! root      118:        if(!writemsg(msgpath,top,title,mode,INVALID_SUB,str2,&editor)) {
1.1       root      119:                bputs(text[Aborted]);
                    120:                return(false); 
                    121:        }
                    122: 
                    123:        if(mode&WM_FILE && !SYSOP && !(cfg.sys_misc&SM_FILE_EM))
                    124:                mode&=~WM_FILE;
                    125: 
                    126: 
                    127:        if(mode&WM_FILE) {
                    128:                sprintf(str2,"%sfile/%04u.in", cfg.data_dir,usernumber);
                    129:                MKDIR(str2);
                    130:                sprintf(str2,"%sfile/%04u.in/%s", cfg.data_dir,usernumber,title);
                    131:                if(fexistcase(str2)) {
                    132:                        bputs(text[FileAlreadyThere]);
                    133:                        remove(msgpath);
1.1.1.2 ! root      134:                        return(false); 
        !           135:                }
1.1       root      136:                { /* Remote */
                    137:                        xfer_prot_menu(XFER_UPLOAD);
                    138:                        mnemonics(text[ProtocolOrQuit]);
                    139:                        strcpy(str,"Q");
                    140:                        for(x=0;x<cfg.total_prots;x++)
1.1.1.2 ! root      141:                                if(cfg.prot[x]->ulcmd[0] && chk_ar(cfg.prot[x]->ar,&useron,&client)) {
1.1       root      142:                                        sprintf(tmp,"%c",cfg.prot[x]->mnemonic);
1.1.1.2 ! root      143:                                        strcat(str,tmp); 
        !           144:                                }
1.1       root      145:                        ch=(char)getkeys(str,0);
                    146:                        if(ch=='Q' || sys_status&SS_ABORT) {
                    147:                                bputs(text[Aborted]);
                    148:                                remove(msgpath);
1.1.1.2 ! root      149:                                return(false); 
        !           150:                        }
1.1       root      151:                        for(x=0;x<cfg.total_prots;x++)
                    152:                                if(cfg.prot[x]->ulcmd[0] && cfg.prot[x]->mnemonic==ch
1.1.1.2 ! root      153:                                        && chk_ar(cfg.prot[x]->ar,&useron,&client))
1.1       root      154:                                        break;
                    155:                        if(x<cfg.total_prots)   /* This should be always */
                    156:                                protocol(cfg.prot[x],XFER_UPLOAD,str2,nulstr,true); 
                    157:                }
                    158:                sprintf(tmp,"%s%s",cfg.temp_dir,title);
                    159:                if(!fexistcase(str2) && fexistcase(tmp))
                    160:                        mv(tmp,str2,0);
1.1.1.2 ! root      161:                l=(long)flength(str2);
1.1       root      162:                if(l>0)
                    163:                        bprintf(text[FileNBytesReceived],title,ultoac(l,tmp));
                    164:                else {
                    165:                        bprintf(text[FileNotReceived],title);
                    166:                        remove(msgpath);
1.1.1.2 ! root      167:                        return(false); 
        !           168:                } 
        !           169:        }
1.1       root      170: 
                    171:        bputs(text[WritingIndx]);
                    172: 
                    173:        if((i=smb_stack(&smb,SMB_STACK_PUSH))!=0) {
                    174:                errormsg(WHERE,ERR_OPEN,"MAIL",i);
1.1.1.2 ! root      175:                return(false); 
        !           176:        }
1.1       root      177:        sprintf(smb.file,"%smail", cfg.data_dir);
                    178:        smb.retry_time=cfg.smb_retry_time;
                    179:        smb.subnum=INVALID_SUB;
                    180:        if((i=smb_open(&smb))!=0) {
                    181:                smb_stack(&smb,SMB_STACK_POP);
                    182:                errormsg(WHERE,ERR_OPEN,smb.file,i,smb.last_error);
1.1.1.2 ! root      183:                return(false); 
        !           184:        }
1.1       root      185: 
                    186:        if(smb_fgetlength(smb.shd_fp)<1) {       /* Create it if it doesn't exist */
                    187:                smb.status.max_crcs=cfg.mail_maxcrcs;
                    188:                smb.status.max_age=cfg.mail_maxage;
                    189:                smb.status.max_msgs=0;
                    190:                smb.status.attr=SMB_EMAIL;
                    191:                if((i=smb_create(&smb))!=0) {
                    192:                        smb_close(&smb);
                    193:                        smb_stack(&smb,SMB_STACK_POP);
                    194:                        errormsg(WHERE,ERR_CREATE,smb.file,i,smb.last_error);
1.1.1.2 ! root      195:                        return(false); 
        !           196:                } 
        !           197:        }
1.1       root      198: 
                    199:        if((i=smb_locksmbhdr(&smb))!=0) {
                    200:                smb_close(&smb);
                    201:                smb_stack(&smb,SMB_STACK_POP);
                    202:                errormsg(WHERE,ERR_LOCK,smb.file,i,smb.last_error);
1.1.1.2 ! root      203:                return(false); 
        !           204:        }
1.1       root      205: 
1.1.1.2 ! root      206:        length=(long)flength(msgpath)+2;         /* +2 for translation string */
1.1       root      207: 
                    208:        if(length&0xfff00000UL) {
                    209:                smb_unlocksmbhdr(&smb);
                    210:                smb_close(&smb);
                    211:                smb_stack(&smb,SMB_STACK_POP);
                    212:                errormsg(WHERE,ERR_LEN,msgpath,length);
1.1.1.2 ! root      213:                return(false); 
        !           214:        }
1.1       root      215: 
                    216:        if((i=smb_open_da(&smb))!=0) {
                    217:                smb_unlocksmbhdr(&smb);
                    218:                smb_close(&smb);
                    219:                smb_stack(&smb,SMB_STACK_POP);
                    220:                errormsg(WHERE,ERR_OPEN,smb.file,i,smb.last_error);
1.1.1.2 ! root      221:                return(false); 
        !           222:        }
1.1       root      223:        if(cfg.sys_misc&SM_FASTMAIL)
                    224:                offset=smb_fallocdat(&smb,length,1);
                    225:        else
                    226:                offset=smb_allocdat(&smb,length,1);
                    227:        smb_close_da(&smb);
                    228: 
                    229:        if((file=open(msgpath,O_RDONLY|O_BINARY))==-1
                    230:                || (instream=fdopen(file,"rb"))==NULL) {
                    231:                smb_freemsgdat(&smb,offset,length,1);
                    232:                smb_unlocksmbhdr(&smb);
                    233:                smb_close(&smb);
                    234:                smb_stack(&smb,SMB_STACK_POP);
                    235:                errormsg(WHERE,ERR_OPEN,msgpath,O_RDONLY|O_BINARY);
1.1.1.2 ! root      236:                return(false); 
        !           237:        }
1.1       root      238: 
                    239:        setvbuf(instream,NULL,_IOFBF,2*1024);
                    240:        smb_fseek(smb.sdt_fp,offset,SEEK_SET);
                    241:        xlat=XLAT_NONE;
                    242:        smb_fwrite(&smb,&xlat,2,smb.sdt_fp);
                    243:        x=SDT_BLOCK_LEN-2;                              /* Don't read/write more than 255 */
                    244:        while(!feof(instream)) {
                    245:                memset(buf,0,x);
                    246:                j=fread(buf,1,x,instream);
                    247:                if(j<1)
                    248:                        break;
                    249:                if(j>1 && (j!=x || feof(instream)) && buf[j-1]==LF && buf[j-2]==CR)
                    250:                        buf[j-1]=buf[j-2]=0;
                    251:                if(cfg.mail_maxcrcs) {
                    252:                        for(i=0;i<j;i++)
1.1.1.2 ! root      253:                                crc=ucrc32(buf[i],crc); 
        !           254:                }
1.1       root      255:                smb_fwrite(&smb,buf,j,smb.sdt_fp);
1.1.1.2 ! root      256:                x=SDT_BLOCK_LEN; 
        !           257:        }
1.1       root      258:        smb_fflush(smb.sdt_fp);
                    259:        fclose(instream);
                    260:        crc=~crc;
                    261: 
                    262:        memset(&msg,0,sizeof(smbmsg_t));
                    263:        msg.hdr.version=smb_ver();
                    264:        msg.hdr.attr=msgattr;
                    265:        if(mode&WM_FILE)
                    266:                msg.hdr.auxattr|=MSG_FILEATTACH;
                    267:        msg.hdr.when_written.time=msg.hdr.when_imported.time=time(NULL);
                    268:        msg.hdr.when_written.zone=msg.hdr.when_imported.zone=sys_timezone(&cfg);
                    269: 
                    270:        if(cfg.mail_maxcrcs) {
                    271:                i=smb_addcrc(&smb,crc);
                    272:                if(i) {
                    273:                        smb_freemsgdat(&smb,offset,length,1);
                    274:                        smb_unlocksmbhdr(&smb);
                    275:                        smb_close(&smb);
                    276:                        smb_stack(&smb,SMB_STACK_POP);
                    277:                        attr(cfg.color[clr_err]);
1.1.1.2 ! root      278:                        bputs(text[CantPostMsg]);
1.1       root      279:                        return(false); 
                    280:                } 
                    281:        }
                    282: 
                    283:        msg.hdr.offset=offset;
                    284: 
                    285:        username(&cfg,usernumber,str);
                    286:        smb_hfield_str(&msg,RECIPIENT,str);
                    287: 
                    288:        sprintf(str,"%u",usernumber);
                    289:        smb_hfield_str(&msg,RECIPIENTEXT,str);
                    290: 
                    291:        strcpy(str,useron.alias);
                    292:        smb_hfield_str(&msg,SENDER,str);
                    293: 
                    294:        sprintf(str,"%u",useron.number);
                    295:        smb_hfield_str(&msg,SENDEREXT,str);
                    296: 
                    297:        if(useron.misc&NETMAIL) {
1.1.1.2 ! root      298:                if(useron.rest&FLAG('G'))
        !           299:                        smb_hfield_str(&msg,REPLYTO,useron.name);
1.1       root      300:                nettype=smb_netaddr_type(useron.netmail);
                    301:                if(nettype!=NET_NONE && nettype!=NET_UNKNOWN) {
                    302:                        smb_hfield(&msg,REPLYTONETTYPE,sizeof(nettype),&nettype);
                    303:                        smb_hfield_str(&msg,REPLYTONETADDR,useron.netmail);
                    304:                }
                    305:        }
                    306: 
                    307:        /* Security logging */
                    308:        msg_client_hfields(&msg,&client);
1.1.1.2 ! root      309:        smb_hfield_str(&msg,SENDERSERVER,startup->host_name);
1.1       root      310: 
                    311:        smb_hfield_str(&msg,SUBJECT,title);
                    312: 
1.1.1.2 ! root      313:        /* Generate FidoNet Program Identifier */
        !           314:        smb_hfield_str(&msg,FIDOPID,msg_program_id(pid));
        !           315: 
        !           316:        if(editor!=NULL)
        !           317:                smb_hfield_str(&msg,SMB_EDITOR,editor);
        !           318: 
1.1       root      319:        smb_dfield(&msg,TEXT_BODY,length);
                    320: 
                    321:        i=smb_addmsghdr(&smb,&msg,SMB_SELFPACK); // calls smb_unlocksmbhdr() 
                    322:        smb_close(&smb);
                    323:        smb_stack(&smb,SMB_STACK_POP);
                    324: 
                    325:        smb_freemsgmem(&msg);
                    326:        if(i!=SMB_SUCCESS) {
                    327:                smb_freemsgdat(&smb,offset,length,1);
                    328:                errormsg(WHERE,ERR_WRITE,smb.file,i,smb.last_error);
                    329:                return(false); 
                    330:        }
                    331: 
                    332:        if(usernumber==1)
                    333:                logon_fbacks++;
                    334:        else
                    335:                logon_emails++;
                    336:        user_sent_email(&cfg, &useron, 1, usernumber==1);
                    337:        bprintf(text[Emailed],username(&cfg,usernumber,tmp),usernumber);
                    338:        sprintf(str,"%s sent e-mail to %s #%d"
                    339:                ,useron.alias,username(&cfg,usernumber,tmp),usernumber);
                    340:        logline("E+",str);
                    341:        if(mode&WM_FILE && online==ON_REMOTE)
                    342:                autohangup();
                    343:        if(msgattr&MSG_ANONYMOUS)                               /* Don't tell user if anonymous */
                    344:                return(true);
                    345:        for(i=1;i<=cfg.sys_nodes;i++) { /* Tell user, if online */
                    346:                getnodedat(i,&node,0);
                    347:                if(node.useron==usernumber && !(node.misc&NODE_POFF)
                    348:                        && (node.status==NODE_INUSE || node.status==NODE_QUIET)) {
                    349:                        sprintf(str,text[EmailNodeMsg],cfg.node_num,useron.alias);
                    350:                        putnmsg(&cfg,i,str);
1.1.1.2 ! root      351:                        break; 
        !           352:                } 
        !           353:        }
1.1       root      354:        if(i>cfg.sys_nodes) {   /* User wasn't online, so leave short msg */
                    355:                sprintf(str,text[UserSentYouMail],useron.alias);
1.1.1.2 ! root      356:                putsmsg(&cfg,usernumber,str); 
        !           357:        }
1.1       root      358:        return(true);
                    359: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.