📄 mail.c
字号:
/*************************************************************************** filename : mail.c begin : Sun Nov 25 2001 copyright : (C) 2001 by Henrik Witt-Hansen email : bean@daisy.net ***************************************************************************//*************************************************************************** * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * ***************************************************************************//*base configuration*/#ifdef HAVE_CONFIG_H#include <config.h>#endif/*standard includes*/#include <stdio.h>#include <pthread.h>#include <stdlib.h>#include <unistd.h>#include <string.h>#include <sys/types.h>#include <sys/stat.h>#include <fcntl.h>#include <errno.h>/*local headers*/#include "sitback.h"/*special includes*/#include <sys/errno.h>#include <time.h>#include <sys/ioctl.h>#include <signal.h>#include <sys/wait.h>#include <sys/types.h>#include <sys/socket.h>#include <sys/ipc.h>#include <sys/sem.h>#include <sys/time.h>#include <netinet/in.h>#include <sys/wait.h>#include <netdb.h>#include <arpa/inet.h>/*local prototypes*/int __socket_command(int clientsocket,char *send,char *expect);/*local data*/extern int errno;/******************************************************************** int SendMail() Send a mail with the content of some file arguments: file; Name of file with message subject; The subject line return: 0 on success -1 on error********************************************************************/int SendMail(char *file,char *subject){ int clientsocket; struct sockaddr_in dest_addr; struct hostent *h; char hostname[1024]; char hosts_entry[1024]; char domainname[1024]; char msg[1024]; FILE *fd; char buffer[4096]; char *p; int state=0; int lookup_retry=0; struct hostent *myhost; time_t now; char date[256]; struct tm *now_tm; unsigned char CR = 0; if(conf__smtp_host[0]!='\0') { /* get our local hostname */ if(gethostname(hostname,1024)) { debug("Unable to get our local hostname\n"); log("Unable to get local hostname\n"); return -1; } debug("Hostname '%s'\n",hostname); /* Try to locate a line in '/etc/hosts' with this hostname */ do { myhost = gethostent(); if( snprintf(hosts_entry,1024,"%s",myhost->h_name)<=0 ) { debug("Unable to get full hostname with gethostent()\n"); log("Unable to get the full host- and domainname. Check '/etc/hosts'\n"); return -1; } debug("gethostent: '%s'\n",hosts_entry); } while( memcmp(hosts_entry,hostname,strlen(hostname)) ); debug("Got the right line from /etc/hosts\n"); strcpy(hostname,hosts_entry); /* Make sure we have a sane hostname */ if(strchr(hostname,'.')==NULL) { debug("Hostname not complete (missing domain).\n"); if(getdomainname(domainname,1024-strlen(hostname)-1)) { debug("Unable to get our local domainname\n"); log("Unable to get local domainname\n"); return -1; } /* Check that the domainname is ok */ if(!strcmp(domainname,"(none)")) { UI__Warning(" Invalid hostname and/or domainname.\n 'hostname' does not return a full host+domain name,\n and trying to obtain your domainname with\n 'domainname' failed\n"); log("Invalid host and/or domainname. Check network settings\n"); Report("Invalid host and/or domainname. Check network settings\n"); return -1; } /* Combine host and domainname */ strcat(hostname,"."); strcat(hostname,domainname); debug("Hostname seems to be '%s'\n",hostname); } debug("Full hostname is '%s'\n",hostname); /* Resolv smtp hostname */ RETRY_TRANSFER: if((h=gethostbyname(conf__smtp_host))==NULL) { debug("Host lookup failure for '%s'\n",conf__smtp_host); if(lookup_retry<3) { debug("Retrying host lookup in case we have a slow dialup connection\n"); lookup_retry++; goto RETRY_TRANSFER; } log("Host lookup failure for '%s'",conf__smtp_host); return -1; } debug("smtp host ip: %s\n",inet_ntoa(*((struct in_addr *)h->h_addr))); /* get a brand new socket */ if((clientsocket = socket(AF_INET, SOCK_STREAM, 0))==-1) { debug("Unable to create tcp/ip socket\n"); log("Unable to create tcp/ip socket\n"); return -1; } debug("Got tcp/ip socket\n"); /* Prepare to connect */ dest_addr.sin_family = AF_INET; dest_addr.sin_port = htons(25); dest_addr.sin_addr.s_addr = inet_addr(inet_ntoa(*((struct in_addr *)h->h_addr))); bzero(&(dest_addr.sin_zero), 8); /* connect */ if(connect(clientsocket, (struct sockaddr *)&dest_addr, sizeof(struct sockaddr))==-1) { debug("Unable to connect\n"); close(clientsocket); return -1; } debug("Connected\n"); /* First, the smtp server must send us a HELO with code 220 */ debug("Receiving initial HELO\n"); if(__socket_command(clientsocket,NULL,"220")) { debug("Unexpected answer from the server\n"); close(clientsocket); return -1; } /* now send a HELO with our hostname, expect 250 in return */ sprintf(msg,"HELO %s\r\n",hostname); debug("Sending HELO: %s",msg); if(__socket_command(clientsocket,msg,"250")) { debug("Unexpected answer from the server\n"); log("Unexpected answer from server (HELO %s)",msg); close(clientsocket); return -1; } /* username/password ?? */ if(conf__smtp_user[0]!='\0' && conf__smtp_pass[0]!='\0') { /* Request authentication */ sprintf(msg,"AUTH LOGIN\r\n"); debug("Request authentication: %s",msg); if(__socket_command(clientsocket,msg,"334")) { debug("Unexpected answer from the server\n"); log("Server can not do smtp authentication"); goto MAIL_TRANSFER; } /* Send username */ sprintf(msg,"%s\r\n",conf__smtp_user); debug("Sending username: %s",msg); if(__socket_command(clientsocket,msg,"334")) { debug("Unexpected answer from the server\n"); log("User unknown"); close(clientsocket); return -1; } /* Send password */ sprintf(msg,"%s\r\n",conf__smtp_pass); debug("Sending password: %s",msg); if(__socket_command(clientsocket,msg,"235")) { debug("Unexpected answer from the server\n"); log("Incorrect password"); close(clientsocket); return -1; } } /* Prepare mail transfer */ MAIL_TRANSFER: sprintf(msg,"MAIL FROM:<sitback@%s>\r\n",strchr(hostname,'.')+1); debug("Prepare mail transfer: %s",msg); if(__socket_command(clientsocket,msg,"250")) { debug("Unexpected answer from the server\n"); log("Sender address not accepted by mailserver"); close(clientsocket); return -1; } /* Recipient */ sprintf(msg,"RCPT TO:<%s>\r\n",conf__report_mail); debug("Recipient: %s",msg); if(__socket_command(clientsocket,msg,"250")) { debug("Unexpected answer from the server\n"); log("Recipient not accepted by mailserver (%s)",msg); close(clientsocket); return -1; } /* Ready to start */ sprintf(msg,"DATA\r\n"); debug("Starting mail transfer: %s",msg); if(__socket_command(clientsocket,msg,"354")) { debug("Unexpected answer from the server\n"); close(clientsocket); return -1; } /* From field in the mail */ sprintf(msg,"From: sitback@%s\r\n",strchr(hostname,'.')+1); debug("From field: %s",msg); if(__socket_command(clientsocket,msg,NULL)) { debug("Error while talking to the mailserver\n"); close(clientsocket); return -1; } /* To field in the mail */ sprintf(msg,"To: %s\r\n",conf__report_mail); debug("To field: %s",msg); if(__socket_command(clientsocket,msg,NULL)) { debug("Error while talking to the mailserver\n"); close(clientsocket); return -1; } /* Subject field in the mail */ sprintf(msg,"Subject: %s - %s\r\n",subject,hostname); debug("Subject field: %s",msg); if(__socket_command(clientsocket,msg,NULL)) { debug("Error while talking to the mailserver\n"); close(clientsocket); return -1; } /* Date field in the mail */ now = time(NULL); now_tm = localtime(&now); strftime(date,256,"%a, %d %b %Y %H:%M:%S %z",now_tm); sprintf(msg,"Date: %s\r\n",date); debug("Date field: %s",msg); if(__socket_command(clientsocket,msg,NULL)) { debug("Error while talking to the mailserver\n"); close(clientsocket); return -1; } /* Send the report */ if((fd=fopen(file,"r"))==NULL) { debug("Unable to open the specified file '%s'\n",file); if(__socket_command(clientsocket,"(Internal error: Unable to open the report)\r\n",NULL)) { debug("Error while talking to the mailserver\n"); close(clientsocket); return -1; } } else { debug("Transmitting report file '%s'\n",file); for(;;) { /* Get a chunk */ memset(buffer,'\0',1025); fread(buffer,1024,1,fd); /* Check for standalone linefeeds */ p=buffer; while( *p!='\0' ) { if( *p=='\r' ) { CR = 1; } else if( *p=='\n' && CR==0 ) { memmove(p+1,p,strlen(p)+1); *p = '\r'; p++; } else CR = 0; p++; } /* Send the buffer */ if(__socket_command(clientsocket,buffer,NULL)) { debug("Error while talking to the mailserver\n"); close(clientsocket); fclose(fd); return -1; } /* Anymore data ?? */ if(feof(fd)) break; } fclose(fd); } /* Ending mail transfer */ sprintf(msg,"\r\n.\r\n"); debug("Ending mail transfer\n"); if(__socket_command(clientsocket,msg,"250")) { debug("Unexpected answer from the server\n"); close(clientsocket); return -1; } /* Close connection */ sprintf(msg,"QUIT\r\n"); debug("Sending QUIT\n"); if(__socket_command(clientsocket,msg,"221")) { debug("Unexpected answer from the server\n"); close(clientsocket); return -1; } /* close the socket */ debug("Closing socket\n"); close(clientsocket); } /* done */ return 0;}/******************************************************************** int __socket_command() Send on a socket, thereafter receive an answer and compare agains an 'expected' string arguments: clientsocket: The socket to use send; String to send, NULL if nothing is to be send expect; Receive an answer and compare to this string returns: 0 on success 1 if compare fails -1 on error********************************************************************/int __socket_command(int clientsocket,char *send,char *expect){ int rc; unsigned len; char recv[1025]; int result=0; fd_set rfds; struct timeval tv; /* paranoid check */ if(expect!=NULL && strlen(expect)>1024) { debug("Internal error: Unable to compare more than 1024 characters\n"); return -1; } /* Anything to send ?? */ if(send!=NULL) { len=0; while(len<strlen(send)) { if((rc=write(clientsocket,send,strlen(send)))==-1) { debug("Error in write(), '%s'\n",strerror(errno)); return -1; } len+=rc; debug("rc=%d len=%u\n",rc,len); } } /* should we try to receive an answer ?? */ if(expect!=NULL) { /* wait until some data is available, or timeout */ debug("Waiting until there is data on the socket\n"); FD_ZERO(&rfds); FD_SET(clientsocket,&rfds); tv.tv_sec=30; tv.tv_usec=0; if(select(clientsocket+1,&rfds,NULL,NULL,&tv)<1) { debug("Timeout waiting for answer on socket\n"); return -1; } /* Read some data */ debug("Receiving answer\n"); if((rc=read(clientsocket,recv,1024))==-1) { debug("Error in read(), '%s'\n",strerror(errno)); return -1; } recv[rc]='\0'; /* compare */ debug("expect: %s\n",expect); debug("recv: %s",recv); if(rc<strlen(expect)) result=1; else if(memcmp(recv,expect,strlen(expect))) result=1; debug("result=%d\n",result); /* Keep receiving if there is more data on the socket */ if(rc==1024) { debug("Trying to clean the socket\n"); for(;;) { /* wait until some data is available, or timeout */ debug("Waiting until there is data on the socket\n"); FD_ZERO(&rfds); FD_SET(clientsocket,&rfds); tv.tv_sec=3; tv.tv_usec=0; if(select(clientsocket+1,&rfds,NULL,NULL,&tv)<1) { debug("No more data on the socket (timeout)\n"); break; } /* Read some data */ debug("Receiving answer\n"); if((rc=read(clientsocket,recv,1024))==-1) { debug("Error in read(), '%s'\n",strerror(errno)); return -1; } debug("rc=%d\n",rc); recv[rc]='\0'; debug("Received: '%s'\n",recv); if(rc!=1024) { debug("No more data\n"); break; } } } } /* done */ return result;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -