Back to index

nordugrid-arc-nox  1.1.0~rc6
smtp-send.c
Go to the documentation of this file.
00001 /*
00002    Simple program to mail information piped to stdin to address 'to' 
00003   from address 'from'. It tries to connect directly to SMTP server 
00004   responsible for destination address.
00005 */
00006 #ifdef HAVE_CONFIG_H
00007 #include <config.h>
00008 #endif
00009 
00010 #include <stdlib.h>
00011 #include <stdio.h>
00012 #include <unistd.h>
00013 #include <netinet/in.h>
00014 #include <arpa/nameser.h>
00015 #include <arpa/nameser_compat.h>
00016 #include <resolv.h>
00017 #include <sys/socket.h>
00018 #include <netdb.h>
00019 #include <string.h>
00020 #define SMTP_PORT 25
00021 
00022 typedef union {
00023   HEADER hdr;
00024   unsigned char buf[8192];
00025 } answer_t;
00026 
00027 void usage(void) {
00028   fprintf(stdout,"smtp-send from to\n");
00029   exit(1);
00030 }
00031 
00032 int send_mail(char* mail_server,char* mail_from,char* mail_to) {
00033   char buf[256];
00034   int s,i;
00035   FILE* S;
00036   int err_code;
00037   char my_hostname[256];
00038   struct addrinfo *res = NULL;
00039   struct addrinfo *r = NULL;
00040 
00041   memset(my_hostname,0,256);  
00042   gethostname(my_hostname,255);
00043   if(getaddrinfo(my_hostname,NULL,NULL,&res) != 0) return 2;
00044   if(res == NULL) return 2;
00045   for(r=res;r;r=r->ai_next) {
00046     if(r->ai_addr == NULL) continue;
00047     if(r->ai_socktype != SOCK_STREAM) continue;
00048     if(r->ai_protocol != IPPROTO_TCP) continue;
00049     if(r->ai_family == AF_INET) {
00050       ((struct sockaddr_in*)(r->ai_addr))->sin_port=htons(SMTP_PORT);
00051       break;
00052     };
00053     if(r->ai_family == AF_INET6) {
00054       ((struct sockaddr_in6*)(r->ai_addr))->sin6_port=htons(SMTP_PORT);
00055       break;
00056     };
00057   };
00058   if(!r) {
00059     freeaddrinfo(res);
00060     return 2;
00061   };
00062   s=socket(r->ai_family,r->ai_socktype,r->ai_protocol);
00063   if(s==-1) {
00064     freeaddrinfo(res);
00065     return 2;
00066   };
00067   if(connect(s,r->ai_addr,r->ai_addrlen)==-1) {
00068     freeaddrinfo(res);
00069     close(s);
00070     return 2;
00071   };
00072   freeaddrinfo(res);
00073   if((S=fdopen(s,"r+")) == NULL) {
00074     close(s);
00075     return 2;
00076   };
00077   if(fscanf(S,"%i%*[^\n]",&err_code) != 1) { fclose(S); return 2; }; fgetc(S);
00078   if( err_code != 220 ) { fclose(S); return 2; };
00079   fprintf(S,"HELO %s\r\n",my_hostname); fflush(S);
00080   if(fscanf(S,"%i%*[^\n]",&err_code) != 1) { fclose(S); return 2; }; fgetc(S);
00081   if( err_code != 250 ) { fclose(S); return 2; };
00082   fprintf(S,"MAIL FROM: <%s>\r\n",mail_from); fflush(S);
00083   if(fscanf(S,"%i%*[^\n]",&err_code) != 1) { fclose(S); return 2; }; fgetc(S);
00084   if( err_code != 250 ) { fclose(S); return 2; };
00085   fprintf(S,"RCPT TO: <%s>\r\n",mail_to); fflush(S);
00086   if(fscanf(S,"%i%*[^\n]",&err_code) != 1) { fclose(S); return 2; }; fgetc(S);
00087   if( err_code != 250 ) { fclose(S); return 2; };
00088   fprintf(S,"DATA\r\n"); fflush(S);
00089   if(fscanf(S,"%i%*[^\n]",&err_code) != 1) { fclose(S); return 2; }; fgetc(S);
00090   if( err_code != 354 ) { fclose(S); return 2; };
00091   /* read from stdin and send to socket */
00092   for(;;) {
00093     buf[0]=0;
00094     if((i=fscanf(stdin,"%255[^\n]",buf)) == EOF) break; 
00095     (fscanf(stdin,"%*[^\n]") != EOF); fgetc(stdin);
00096     if(!strcmp(".",buf)) { fputc(' ',S); };
00097     fprintf(S,"%s\r\n",buf); fflush(S);
00098   };
00099   fprintf(S,".\r\n"); fflush(S);
00100   if(fscanf(S,"%i%*[^\n]",&err_code) != 1) { fclose(S); return 1; }; fgetc(S);
00101   if( err_code != 250 ) { fclose(S); return 1; };
00102   fprintf(S,"QUIT\r\n"); fflush(S);
00103   fclose(S);
00104   return 0;
00105 }
00106 
00107 int connect_mail(char* domain,char* mail_from,char* mail_to) { 
00108   char mxbuf[1024];
00109   unsigned short mxtype;
00110   unsigned short mxpref;
00111   answer_t answer;
00112   int l,na,nq;
00113   unsigned char *sp;
00114   unsigned char *cp;
00115   unsigned char *ep;
00116   HEADER *hp;
00117   int err_code = 2;
00118 
00119   fprintf(stdout,"Searching for domain %s\n",domain);
00120   if((l=res_search(domain,C_IN,T_MX,answer.buf,sizeof(answer))) == -1) {
00121     fprintf(stderr,"Query failed\n");
00122     return 2;
00123   };
00124   hp = &(answer.hdr);
00125   sp = answer.buf;
00126   cp = answer.buf + HFIXEDSZ;
00127   ep = answer.buf + l;
00128   nq=ntohs(hp->qdcount);
00129   for(;nq>0;nq--) {
00130     if((l=dn_skipname(cp,ep)) == -1) {
00131       fprintf(stderr,"skipname failed\n");
00132       return 2;
00133     };
00134     cp+=l+QFIXEDSZ;
00135   };
00136   na=ntohs(hp->ancount);
00137   for(;(na>0) && (cp<ep);na++) {
00138     if((l=dn_expand(sp,ep,cp,mxbuf,sizeof(mxbuf))) == -1) {
00139       fprintf(stderr,"expand failed\n");
00140       return 2;
00141     };
00142     cp+=l;
00143     GETSHORT(mxtype,cp);
00144     cp+=INT16SZ+INT32SZ;
00145     GETSHORT(l,cp);
00146     if(mxtype != T_MX) {
00147       cp+=l; continue;
00148     };
00149     GETSHORT(mxpref,cp);
00150     if((l=dn_expand(sp,ep,cp,mxbuf,sizeof(mxbuf))) == -1) {
00151       fprintf(stderr,"expand failed\n");
00152       return 2;
00153     };
00154     fprintf(stdout,"Trying to send through %s\n",mxbuf);
00155     if((err_code=send_mail(mxbuf,mail_from,mail_to)) == 0) {
00156       fprintf(stdout,"Sending finished\n");
00157       break;
00158     }; 
00159     fprintf(stdout,"Sending failed\n");
00160     cp+=l;
00161     if(err_code == 1) break;
00162   };
00163   if(err_code == 2) {
00164     fprintf(stdout,"Trying to send through %s\n",mxbuf);
00165     if((err_code=send_mail(domain,mail_from,mail_to)) == 0) {
00166       fprintf(stdout,"Sending finished\n");
00167     } else {
00168       fprintf(stdout,"Sending failed\n");
00169     };
00170   };
00171   return err_code;
00172 }
00173 
00174 int main(int argc,char** argv) {
00175   char* mail_from;
00176   char* mail_to;
00177   char* domain_rcpt;
00178   char* domain_snd;
00179   int err_code;
00180   
00181   if(argc != 3) { usage(); };
00182   mail_from=argv[1];  
00183   mail_to=argv[2];  
00184 
00185   domain_rcpt=strchr(mail_to,'@');
00186   if(domain_rcpt == NULL) {
00187     fprintf(stderr,"Bad recepient address\n");
00188     exit(1);
00189   };
00190   domain_rcpt++;
00191   if(strlen(domain_rcpt) == 0) {
00192     fprintf(stderr,"Recepient address does not contain domain\n");
00193     exit(1);
00194   };
00195 
00196   domain_snd=strchr(mail_from,'@');
00197   if(domain_snd != NULL) {
00198     domain_snd++;
00199     if(strlen(domain_snd) == 0) domain_snd=NULL;
00200   };
00201 
00202   if(res_init() == -1) {
00203     fprintf(stderr,"Failed to init resolver\n");
00204     exit(1);
00205   };
00206 
00207   err_code = connect_mail(domain_rcpt,mail_from,mail_to);
00208   if((err_code == 2) && (domain_snd != NULL)) {
00209     err_code = connect_mail(domain_snd,mail_from,mail_to);
00210   };
00211   if(err_code != 0) {
00212     fprintf(stderr,"Sending mail failed\n");
00213   };
00214   exit(err_code);
00215 }
00216 
00217