📄 vdelivermail.c
字号:
}#ifdef MAKE_SEEKABLE if (!Seekable(0)) MakeSeekable(stdin);#endif lseek(0,0L,SEEK_SET); while(fgets(loop_buf,sizeof(loop_buf),stdin)!=NULL){ /* if we find the line, return error (looping) */ if (strncmp(loop_buf, "Delivered-To: ", 14) == 0 && is_loop_match(loop_buf, address)==1 ) { /* return the loop found */ return(1); /* check for the start of the body, we only need * to check the headers. */ } else { /* walk through the charaters in the body */ for(i=0,found=0;loop_buf[i]!=0&&found==0;++i){ switch(loop_buf[i]){ /* skip blank spaces and new lines */ case ' ': case '\n': case '\t': case '\r': break; /* found a non blank, so we are still * in the headers */ default: /* set the found non blank char flag */ found = 1; break; } } /* if the line only had blanks, then it is the * delimiting line between the headers and the * body. We don't need to check the body for * the duplicate Delivered-To: line. Hence, we * are done with our search and can return the * looping not found value */ if ( found == 0 ) { /* return not found looping message value */ return(0); } } } /* if we get here then the there is either no body * or the logic above failed and we scanned * the whole email, headers and body. */ return(0);}/* * Get the size of the email message * return the size */off_t get_message_size(){ ssize_t message_size; ssize_t bytes;#ifdef MAKE_SEEKABLE if (!Seekable(0)) MakeSeekable(stdin);#endif if ( lseek(0, 0L,SEEK_SET) < 0 ) { printf("lseek error %d\n", errno); return(-1); } message_size = 0; while((bytes=read(0,msgbuf,MSG_BUF_SIZE))>0) { message_size += bytes; } return(message_size);}/* * check for locked account * deliver to .qmail file if any * deliver to user if no .qmail file */void checkuser() { struct stat mystatbuf; if (vpw->pw_gid & BOUNCE_MAIL ) { printf("vdelivermail: account is locked email bounced %s@%s\n", TheUser, TheDomain); vexit(100); } /* If thier directory path is empty make them a new one */ if ( vpw->pw_dir == NULL || vpw->pw_dir[0]==0 ) { if ( make_user_dir(vpw->pw_name, TheDomain, TheDomainUid, TheDomainGid)==NULL){ printf("Auto creation of maildir failed. vpopmail (#5.9.8)\n"); vexit(100); } /* Re-read the vpw entry, because we need to lookup the newly created * pw_dir entry */ if ((vpw=vauth_getpw(TheUser, TheDomain)) == NULL ) { printf("Failed to vauth_getpw(). vpopmail (#5.9.8.1)\n"); vexit(100); } } /* check if the directory exists and create if needed */ if ( stat(vpw->pw_dir, &mystatbuf ) == -1 ) { if ( vmake_maildir(TheDomain, vpw->pw_dir )!= VA_SUCCESS ) { printf("Auto re-creation of maildir failed. vpopmail (#5.9.9)\n"); vexit(100); } } /* check for a .qmail file in thier Maildir * If it exists, then deliver to the contents and exit */ if ( check_forward_deliver(vpw->pw_dir) == 1 ) { vexit(0); } snprintf(TheDir, AUTH_SIZE, "%s/Maildir/", vpw->pw_dir); if ( deliver_mail(TheDir, vpw->pw_shell) != 0 ) { vexit(100); }}/* * the vpopmail user does not exist. Follow the rest of * the directions in the .qmail-default file */void usernotfound() { int ret; /* If they want to delete email for non existant users * then just exit 0. Qmail will delete the email for us */ if ( strcmp(bounce, DELETE_ALL) == 0 ) { /* just exit 0 and qmail will delete the email from the system */ vexit(0); /* If they want to bounce the email back then * print a message and exit 100 */ } else if ( strcmp(bounce, BOUNCE_ALL) == 0 ) { FILE *fs; char *tmp_file; tmp_file = malloc(256); sprintf(tmp_file, "%s/.no-user.msg",TheDomainDir); if ( (fs=fopen(tmp_file, "r")) == NULL ) { /* if no domain no user then check in vpopmail dir */ sprintf(tmp_file, "%s/domains/.no-user.msg",VPOPMAILDIR); fs=fopen(tmp_file, "r"); } if ( fs == NULL ) { printf("Sorry, no mailbox here by that name. vpopmail (#5.1.1)\n"); } else { while( fgets( tmp_file, 256, fs ) != NULL ) { fputs(tmp_file, stdout); } fclose(fs); } free(tmp_file); /* exit 100 causes the email to be bounced back */ vexit(100); } /* check if it is a path add the /Maildir/ for delivery */ if ( bounce[0] == '/' ) { if (bounce[strlen(bounce)-1] != '/') strcat( bounce, "/"); printf ("user does not exist, but will deliver to %s\n", bounce); if( check_forward_deliver(bounce) == 1 ) vexit(0); else strcat( bounce, "Maildir/"); } ret = deliver_mail(bounce, "NOQUOTA" ); /* Send the email out, if we get a -1 then the user is over quota */ if ( ret == -1 ) { printf("user is over quota, mail bounced\n"); vexit(100); } else if ( ret == -2 ) { printf("system error\n"); vexit(100); } else if ( ret != 0 ) { printf("mail is looping\n"); vexit(100); }}/* * Deliver an quota warning message * Return 0 on success * Return less than zero on failure * * -1 = user is over quota * -2 and below are system failures * -3 mail is looping */int deliver_quota_warning(const char *dir, const char *q){ time_t tm; long unsigned pid; long unsigned wrn_msg_sz; int write_fd, fdin, fd; size_t l; char newdir[400]; char *qname = 0; struct stat sb; char buf[4096]; FILE *fs; char quotawarnmsg[BUFF_SIZE]; /* Look in the domain for a .quotawarn.msg */ sprintf(quotawarnmsg, "%s/.quotawarn.msg", TheDomainDir); if ( ((fdin=open(quotawarnmsg, O_RDONLY)) < 0) || (stat(quotawarnmsg, &sb)<0)) { /* if that fails look in vpopmail dir */ sprintf(quotawarnmsg, "%s/domains/.quotawarn.msg", VPOPMAILDIR); if ( ((fdin=open(quotawarnmsg, O_RDONLY)) < 0) || (stat(quotawarnmsg, &sb)<0)) { return(0); } } wrn_msg_sz = sb.st_size; l = strlen(dir)+sizeof("/quotawarn"); if ((qname = malloc(l)) == 0) { close(fdin); perror("malloc"); return(-1); } strcat(strcpy(qname, dir), "/quotawarn"); time(&tm); /* Send only one warning every 24 hours */ if (stat(qname, &sb) == 0 && ((sb.st_mtime + 86400) > tm)) { free(qname); close(fdin); return(0); } fd = open(qname, O_WRONLY|O_CREAT|O_TRUNC, 0644); if (!fd) { free(qname); close(fdin); perror("open"); exit(111); } write(fd, buf, 0); close(fd); /* Format the email file name */ gethostname(hostname,sizeof(hostname)); pid=getpid(); time (&tm); snprintf(local_file, 156, "%stmp/%lu.%lu.%s,S=%lu", dir,(long unsigned)tm,pid,hostname, wrn_msg_sz); snprintf(local_file_new, 156, "%snew/%lu.%lu.%s,S=%lu", dir,(long unsigned)tm,pid,hostname,wrn_msg_sz); /* open the new email file */ if ((write_fd=open(local_file,O_CREAT|O_RDWR,S_IRUSR|S_IWUSR))== -1) { printf("can not open new email file errno=%d file=%s\n", errno, local_file); return(-2); } if ( strcmp( dir, bounce) == 0 ) { snprintf(DeliveredTo, sizeof(DeliveredTo), "%s%s%s", getenv("RPLINE"), getenv("DTLINE"), date_header()); } else { strcpy(newdir, dir); snprintf(DeliveredTo, sizeof(DeliveredTo), "%sDelivered-To: %s\n%s", getenv("RPLINE"), maildir_to_email(newdir), date_header()); } /* write the Return-Path: and Delivered-To: headers */ if (write(write_fd,DeliveredTo,strlen(DeliveredTo)) != strlen(DeliveredTo)) { close(write_fd); /* Check if the user is over quota */ if ( errno == EDQUOT ) { return(-1); } else { printf("failed to write delivered to line errno=%d\n",errno); return(errno); } } /* read the quota message in chunks and write it to the new file */ if((fs=fopen(quotawarnmsg, "ro")) != NULL) { while(fgets(buf, MSG_BUF_SIZE, fs)) { if ( write(write_fd,buf,strlen(buf)) == -1 ) { close(write_fd); /* if the write fails and we are writing to a Maildir * then unlink the file */ if ( unlink(local_file) != 0 ) { printf("unlink failed %s errno = %d\n", local_file, errno); return(errno); } /* Check if the user is over quota */ if ( errno == EDQUOT ) { return(-1); } else { printf("write failed errno = %d\n", errno); return(errno); } } } } /* since we are writing to a Maildir, move it * into the new directory */ /* sync the data to disk and close the file */ errno = 0; if ( #ifdef FILE_SYNC#ifdef HAVE_FDATASYNC fdatasync(write_fd) == 0 &&#else fsync(write_fd) == 0 &&#endif#endif close(write_fd) == 0 ) { /* if this succeeds link the file to the new directory */ if ( link( local_file, local_file_new ) == 0 ) { if ( unlink(local_file) != 0 ) { printf("unlink failed %s errno = %d\n", local_file, errno); } } else { /* coda fs has problems with link, check for that error */ if ( errno==EXDEV ) { /* try to rename the file instead */ if (rename(local_file, local_file_new)!=0) { /* even rename failed, time to give up */ printf("rename failed %s %s errno = %d\n", local_file, local_file_new, errno); return(errno); /* rename worked, so we are okay now */ } else { errno = 0; } /* link failed and we are not on coda */ } else { printf("link fucking failed %s %s errno = %d\n", local_file, local_file_new, errno); } } } /* return success */ add_warningsize_to_quota(dir,q); return(0);}int is_loop_match( char *dt, char *address){ char *startdt; startdt = dt; /* walk forward in dt line for @ character */ while ( *dt != '@' && *dt != 0 ) ++dt; if (*dt == 0) return 0; /* no @ character found */ /* now walk back to first space */ while ( *dt != ' ' && dt != startdt) --dt; /* step forward one character */ ++dt; /* strcmp up to end of line or newline */ while ( *dt != 0 && *dt != '\n' && *dt != '\r' ) { /* if it does not match, then no loop */ if ( *dt != *address ) return(0); ++dt; ++address; } /* we have a match */ return(1);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -