?? smtpserv.c
字號:
fprintf(fp,"%s%s\n",
Hdrs[APPARTO],
ap->val);
fputc('\n',fp);
break;
}
fputs(buf,fp);
rip(buf);
switch(htype(buf)){
case TO:
case CC:
++tocnt;
break;
case RRECEIPT:
if((cp = getaddress(buf,0))
!= NULL){
free(host);
host = strdup(cp);
}
break;
}
}
while((c = fread(buf,1,sizeof(buf),data)) > 0)
if(fwrite(buf,1,c,fp) != c)
break;
if(ferror(fp))
fail = 1;
else
fprintf(fp,"\n");
/* Leave a blank line between msgs */
fclose(fp);
printf("New mail arrived for %s\n",ap->val);
if(host != NULL){
rewind(data); /* Send return receipt */
mdaemon(data,host,NULL,0);
free(host);
}
} else
fail = 1;
(void) rmlock(Mailspool,ap->val);
if (fail)
break;
smtplog("deliver: To: %s From: %s",ap->val,from);
}
}
return fail;
}
/* Return Date/Time in Arpanet format in passed string */
char *
ptime(t)
long *t;
{
/* Print out the time and date field as
* "DAY day MONTH year hh:mm:ss ZONE"
*/
register struct tm *ltm;
static char tz[4];
static char str[40];
char *p, *getenv();
/* Read the system time */
ltm = localtime(t);
if (*tz == '\0')
if ((p = getenv("TZ")) == NULL)
strcpy(tz,"UTC");
else
strncpy(tz,p,3);
/* rfc 822 format */
sprintf(str,"%s, %.2d %s %02d %02d:%02d:%02d %.3s\n",
Days[ltm->tm_wday],
ltm->tm_mday,
Months[ltm->tm_mon],
ltm->tm_year,
ltm->tm_hour,
ltm->tm_min,
ltm->tm_sec,
tz);
return(str);
}
long
get_msgid()
{
char sfilename[LINELEN];
char s[20];
register long sequence = 0;
FILE *sfile;
sprintf(sfilename,"%s/sequence.seq",Mailqdir);
sfile = fopen(sfilename,READ_TEXT);
/* if sequence file exists, get the value, otherwise set it */
if (sfile != NULL) {
(void) fgets(s,sizeof(s),sfile);
sequence = atol(s);
/* Keep it in range of and 8 digit number to use for dos name prefix. */
if (sequence < 0L || sequence > 99999999L )
sequence = 0;
fclose(sfile);
}
/* increment sequence number, and write to sequence file */
sfile = fopen(sfilename,WRITE_TEXT);
fprintf(sfile,"%ld",++sequence);
fclose(sfile);
return sequence;
}
#ifdef MSDOS
/* Illegal characters in a DOS filename */
static char baddoschars[] = "\"[]:|<>+=;,";
#endif
/* test if mail address is valid */
int
validate_address(s)
char *s;
{
char *cp;
int32 addr;
/* if address has @ in it the check dest address */
if ((cp = strrchr(s,'@')) != NULL) {
cp++;
/* 1st check if its our hostname
* if not then check the hosts file and see
* if we can resolve ther address to a know site
* or one of our aliases
*/
if (strcmp(cp,Hostname) != 0) {
if ((addr = mailroute(cp)) == 0
&& (Smtpmode & QUEUE) == 0)
return BADADDR;
if (ismyaddr(addr) == NULL)
return DOMAIN;
}
/* on a local address remove the host name part */
*--cp = '\0';
}
/* if using an external router leave address alone */
if ((Smtpmode & QUEUE) != 0)
return LOCAL;
/* check for the user%host hack */
if ((cp = strrchr(s,'%')) != NULL) {
*cp = '@';
cp++;
/* reroute based on host name following the % seperator */
if (mailroute(cp) == 0)
return BADADDR;
else
return DOMAIN;
}
#ifdef MSDOS /* dos file name checks */
/* Check for characters illegal in MS-DOS file names */
for(cp = baddoschars;*cp != '\0';cp++){
if(strchr(s,*cp) != NULL)
return BADADDR;
}
#endif
return LOCAL;
}
/* place a mail job in the outbound queue */
int
queuejob(dfile,host,to,from)
FILE *dfile;
char *host;
struct list *to;
char *from;
{
FILE *fp;
struct list *ap;
char tmpstring[50], prefix[9], buf[LINELEN];
register int cnt;
sprintf(prefix,"%ld",get_msgid());
mlock(Mailqdir,prefix);
sprintf(tmpstring,"%s/%s.txt",Mailqdir,prefix);
if((fp = fopen(tmpstring,WRITE_TEXT)) == NULL) {
(void) rmlock(Mailqdir,prefix);
return 1;
}
while((cnt = fread(buf, 1, LINELEN, dfile)) > 0)
if(fwrite(buf, 1, cnt, fp) != cnt)
break;
if(ferror(fp)){
fclose(fp);
(void) rmlock(Mailqdir,prefix);
return 1;
}
fclose(fp);
sprintf(tmpstring,"%s/%s.wrk",Mailqdir,prefix);
if((fp = fopen(tmpstring,WRITE_TEXT)) == NULL) {
(void) rmlock(Mailqdir,prefix);
return 1;
}
fprintf(fp,"%s\n%s\n",host,from);
for(ap = to; ap != NULL; ap = ap->next) {
fprintf(fp,"%s\n",ap->val);
smtplog("queue job %s To: %s From: %s",prefix,ap->val,from);
}
fclose(fp);
(void) rmlock(Mailqdir,prefix);
return 0;
}
/* Deliver mail to the appropriate mail boxes */
static int
router_queue(data,from,to)
FILE *data;
char *from;
struct list *to;
{
int c;
register struct list *ap;
FILE *fp;
char tmpstring[50];
char prefix[9];
sprintf(prefix,"%ld",get_msgid());
mlock(Routeqdir,prefix);
sprintf(tmpstring,"%s/%s.txt",Routeqdir,prefix);
if((fp = fopen(tmpstring,WRITE_TEXT)) == NULL) {
(void) rmlock(Routeqdir,prefix);
return 1;
}
rewind(data);
while((c = getc(data)) != EOF)
if(putc(c,fp) == EOF)
break;
if(ferror(fp)){
fclose(fp);
(void) rmlock(Routeqdir,prefix);
return 1;
}
fclose(fp);
sprintf(tmpstring,"%s/%s.wrk",Routeqdir,prefix);
if((fp = fopen(tmpstring,WRITE_TEXT)) == NULL) {
(void) rmlock(Routeqdir,prefix);
return 1;
}
fprintf(fp,"From: %s\n",from);
for(ap = to;ap != NULL;ap = ap->next) {
fprintf(fp,"To: %s\n",ap->val);
}
fclose(fp);
(void) rmlock(Routeqdir,prefix);
smtplog("rqueue job %s From: %s",prefix,from);
return 0;
}
/* add an element to the front of the list pointed to by head
** return NULL if out of memory.
*/
struct list *
addlist(head,val,type)
struct list **head;
char *val;
int type;
{
register struct list *tp;
tp = (struct list *)callocw(1,sizeof(struct list));
tp->next = NULL;
/* allocate storage for the char string */
tp->val = strdup(val);
tp->type = type;
/* add entry to front of existing list */
if (*head == NULL)
*head = tp;
else {
tp->next = *head;
*head = tp;
}
return tp;
}
#define SKIPWORD(X) while(*X && *X!=' ' && *X!='\t' && *X!='\n' && *X!= ',') X++;
#define SKIPSPACE(X) while(*X ==' ' || *X =='\t' || *X =='\n' || *X == ',') X++;
/* check for and alias and expand alias into a address list */
static struct list *
expandalias(head, user)
struct list **head;
char *user;
{
FILE *fp;
register char *s,*p;
struct rr *rrp, *rrlp;
int inalias = 0;
struct list *tp;
char buf[LINELEN];
/* no alias file found */
if ((fp = fopen(Alias, READ_TEXT)) == NULL) {
/* Try MB, MG or MR domain name records */
rrlp = rrp = resolve_mailb(user);
while(rrp != NULL){
if(rrp->rdlength > 0){
/* remove the trailing dot */
rrp->rdata.name[rrp->rdlength-1] = '\0';
/* replace first dot with @ if there is no @ */
if(strchr(rrp->rdata.name,'@') == NULL
&& (p = strchr(rrp->rdata.name,'.')) !=
NULL)
*p = '@';
if(strchr(rrp->rdata.name,'@') != NULL)
tp = addlist(head,rrp->rdata.name,
DOMAIN);
else
tp = addlist(head,rrp->rdata.name,
LOCAL);
++inalias;
}
rrp = rrp->next;
}
free_rr(rrlp);
if(inalias)
return tp;
else
return addlist(head, user, LOCAL);
}
while (fgets(buf,LINELEN,fp) != NULL) {
p = buf;
if ( *p == '#' || *p == '\0')
continue;
rip(p);
/* if not in an matching entry skip continuation lines */
if (!inalias && isspace(*p))
continue;
/* when processing an active alias check for a continuation */
if (inalias) {
if (!isspace(*p))
break; /* done */
} else {
s = p;
SKIPWORD(p);
*p++ = '\0'; /* end the alias name */
if (strcmp(s,user) != 0)
continue; /* no match go on */
inalias = 1;
}
/* process the recipients on the alias line */
SKIPSPACE(p);
while(*p != '\0' && *p != '#') {
s = p;
SKIPWORD(p);
if (*p != '\0')
*p++ = '\0';
/* find hostname */
if (strchr(s,'@') != NULL)
tp = addlist(head,s,DOMAIN);
else
tp = addlist(head,s,LOCAL);
SKIPSPACE(p);
}
}
(void) fclose(fp);
if (inalias) /* found and processed and alias. */
return tp;
/* no alias found treat as a local address */
return addlist(head, user, LOCAL);
}
static void
smtplog(char *fmt, ...)
{
va_list ap;
char *cp;
long t;
FILE *fp;
if ((fp = fopen(Maillog,APPEND_TEXT)) == NULL)
return;
time(&t);
cp = ctime(&t);
rip(cp);
fprintf(fp,"%s ",cp);
va_start(ap,fmt);
vfprintf(fp,fmt,ap);
va_end(ap);
fprintf(fp,"\n");
fclose(fp);
}
/* send mail to a single user. Can be called from the ax24 mailbox or
** from the return mail function in the smtp client
*/
static int
mailuser(data,from,to)
FILE *data;
char *from;
char *to;
{
int address_type, ret;
struct list *tolist = NULL;
/* check if address is ok */
if ((address_type = validate_address(to)) == BADADDR) {
return 1;
}
/* if a local address check for an alias */
if (address_type == LOCAL)
expandalias(&tolist, to);
else
/* a remote address is added to the list */
addlist(&tolist, to, address_type);
ret = mailit(data,from,tolist);
del_list(tolist);
return ret;
}
/* Mailer daemon return mail mechanism */
int
mdaemon(data,to,lp,bounce)
FILE *data; /* pointer to rewound data file */
char *to; /* Overridden by Errors-To: line if bounce is true */
struct list *lp; /* error log for failed mail */
int bounce; /* True for failed mail, otherwise return receipt */
{
time_t t;
FILE *tfile;
char buf[LINELEN], *cp, *newto = NULL;
int cnt;
if(to == NULL || (to != NULL && *to == '\0') || bounce){
while(fgets(buf,sizeof(buf),data) != NULL) {
if(buf[0] == '\n')
break;
/* Look for Errors-To: */
if(htype(buf) == ERRORSTO &&
(cp = getaddress(buf,0)) != NULL){
free(newto);
newto = strdup(cp);
break;
}
}
if(newto == NULL && ((to != NULL && *to == '\0') ||
to == NULL))
return -1;
rewind(data);
}
if((tfile = tmpfile()) == NULL)
return -1;
time(&t);
fprintf(tfile,"%s%s",Hdrs[DATE],ptime(&t));
fprintf(tfile,"%s<%ld@%s>\n",Hdrs[MSGID],get_msgid(),Hostname);
fprintf(tfile,"%sMAILER-DAEMON@%s (Mail Delivery Subsystem)\n",
Hdrs[FROM],Hostname);
fprintf(tfile,"%s%s\n",Hdrs[TO],newto != NULL ? newto : to);
fprintf(tfile,"%s%s\n\n",Hdrs[SUBJECT],
bounce ? "Failed mail" : "Return receipt");
if(bounce) {
fprintf(tfile," ===== transcript follows =====\n\n");
for (; lp != NULL; lp = lp->next)
fprintf(tfile,"%s\n",lp->val);
fprintf(tfile,"\n");
}
fprintf(tfile," ===== %s follows ====\n",
bounce ? "Unsent message" : "Message header");
while(fgets(buf,sizeof(buf),data) != NULL){
if(buf[0] == '\n')
break;
fputs(buf,tfile);
}
if(bounce){
fputc('\n',tfile);
while((cnt = fread(buf,1,sizeof(buf),data)) > 0)
fwrite(buf,1,cnt,tfile);
}
fseek(tfile,0L,0);
/* A null From<> so no looping replys to MAIL-DAEMONS */
(void) mailuser(tfile,"",newto != NULL ? newto : to);
fclose(tfile);
free(newto);
return 0;
}
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -