⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 smtpr.c

📁 A simple smtp relay server. Which follows smtp protocol correctly. It receive an email. and relay it
💻 C
📖 第 1 页 / 共 2 页
字号:
/****************************************************/ 
/* AUTHOR         :  LAW CHIU YUEN                    */
                   */
/* FILENAME     :  smtpr.c                         */
/****************************************************/ 

#ifdef WIN32
#include <windows.h>
#include <winsock.h>
#else
#define closesocket	close
#include <unistd.h>
#include <netdb.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <sys/socket.h>
#endif

#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <string.h>
#include <arpa/inet.h>
#include <ctype.h>


//#define MYPORT 40711    // the port users will be connecting to
#define PORT 25
#define MAXBUFLEN 1024      // max buffer size
#define RELAY_NAME 255 // max length of file name
#define BACKLOG 10     // how many pending connections queue will hold
#define MAXDATASIZE 512 // max number of bytes we can get at once 
#define SQMAXDATASIZE 1048576 //1024 * 1024
#define RECVTIME 100    // max number of time to wait for client's message
#define MAXEMAILADDRESS 320 // 64 + 1 + 255 
#define MAXRCPT 50     //max number of mail receipients
/* State1 */
#define ACCEPT 0
#define HELO 1
#define MAILFROM 2
#define RCPTTO 3
#define DATA 4
#define MESSAGE 5
#define QUIT 6
#define RELAY 7
/* State2 */
#define FIRSTHELO 0
#define SECONDHELO 1
#define MAXHELO 1024

/*  tokenize mailto string, each time return the first email address */
/* eg.  a@a.com,b@b.com,c@c.com -->  a@a.com  */
char* tokenize(char *mailto){
     const char delimiters[] = ",";
     char *token, *cp;
     printf("b4 strtok: mailto:%s\n",mailto);     
                /* Make writable copy.  */
     token = strtok (mailto, delimiters);      /* token => "words" */
     printf("tokenize() speaking : mailto: %s\n",mailto);
     printf("tokenize() speaking : token: %s\n",token);
     return token;

}

/*  tokenize mailto string, each time return the email address other then the first one*/
/* first call:  a@a.com,b@b.com,c@c.com -->  b@b.com  */
/* second call:  a@a.com,b@b.com,c@c.com -->  c@c.com  */
char* tokenize_null(){
     const char delimiters[] = ",";
     char *token, *cp;

     token = strtok (NULL, delimiters);      /* token => "words" */
     printf("tokenize_null() speaking : token: %s\n",token);
     return token;
}

/* take in an email_address, and header; */
/*  convert to :  header: email_address  */
char* compose_mailheader(char *header,char *mail){
		char *a = malloc(strlen(mail)+30);
		char *b = NULL;
		char *c = NULL;
		strcpy(a, header);
	
		b = strcat(a, mail);
		c = strcat(b, "\r\n");
		printf("compose_mailheader:   b=%s\n", b);
		return b;
}
	
/*  1. receive message from smtp server  */
void receive(int fd, char* command, char *buf){
	int numbytes;
	
	  if ((numbytes=recv(fd, buf, MAXDATASIZE, 0)) == -1) {
        fprintf(stderr,"error in receiving\n");
        exit(1);
    }
    buf[numbytes] = '\0';
    printf("    receive() Received buf : %s",buf);
    if ( strstr(buf, command) != NULL ){
    printf("    receive() Received command : %s\n",command);
    }else{
    }
}
/*  helo  */
/*  1. called by relaymail()  */
/*  2. interact with a smtp server */
void helo(int sockfd){
		int numbytes;
		char buf2[MAXDATASIZE];
		char buf[MAXDATASIZE];
		printf("\n");
		printf("helo is called\n");
		/*receive 220*/
		receive(sockfd, "220 ", buf);

		/* send helo */
		if (send(sockfd, "HELO server\r\n", 13, 0) == -1)
				perror("HELO SERVER");
//		printf("sent HELO SERVER\n");

/* receive 250*/
		receive(sockfd, "250 ", buf);

/*      testing    */		
//		if (send(sockfd, "HELO server\r\n", 13, 0) == -1)
//				perror("HELO SERVER");
 
//		receive(sockfd, "250 ", buf);
}
	
/*  mailfrom  */
/*  1. called by relaymail()  */
/*  2. interact with a smtp server */
void mailfrom(int sockfd,char *mail_from){
		char buf[MAXDATASIZE] = "MAIL FROM:";

		char *out;
		int numbytes;
		int i;
		printf("\n");
		printf("mailfrom is called\n");

		/*  compose the "MAIL FROM:email@address.com" message  */	
		strcat(buf, mail_from);
		strcat(buf, "\r\n");
		printf("mailfrom() speaking: buf=%s\n", buf);
		printf("mailfrom() speaking: strlen(buf)=%i\n", strlen(buf));

		/* send out */
		if( send(sockfd, buf, strlen(buf), 0) == -1 )
			  perror("mailfrom()");

		/* receive 250*/
		receive(sockfd, "250 ", buf);

}  //mailfrom

/*  1. called by rcptto()  */
/*  2. interact with a smtp server */
void rcptto2(int sockfd,char *mailtos){
		char buf[MAXDATASIZE]="";
		char *a;
		char *out;
		int numbytes;
		int i,len;
		printf("\n");
		printf("rcptto2 is called\n");
		/*  compose the "RCPT TO:email@address.com" message  */	
				strcat(buf, "RCPT TO:");
				strcat(buf, tokenize_null());
				strcat(buf, "\r\n");
				printf("rcptto2() speaking: buf=%s\n", buf);
				printf("rcptto2() speaking: strlen(buf)=%i\n", strlen(buf));

				/*  send out */
				if( send(sockfd, buf, strlen(buf), 0) == -1 )
					  perror("rcptto()");

				/*  receive 250*/
				receive(sockfd, "250 ", buf);
				/*  clear the buffer  */
				for(i=0; i<strlen(buf);i++){
					buf[i]='\0';
				}//for()
				
}

/*  rcptto  */
/*  1. called by relaymail()  */
/*  2. interact with a smtp server */
void rcptto(int sockfd,char *mailtos, int mailto_num){
		char buf[MAXDATASIZE] = "RCPT TO:";
		char *a;
		char *out;
		int numbytes;
		int i,len;
		printf("\n");
		printf("rcptto is called\n");

/* sending the first address... */
				/*  compose the "RCPT TO:email@address.com" message  */	
				strcat(buf, tokenize(mailtos));
				strcat(buf, "\r\n");
				printf("rcptto() speaking: buf=%s\n", buf);
				printf("rcptto() speaking: strlen(buf)=%i\n", strlen(buf));

				/*  send out */
				if( send(sockfd, buf, strlen(buf), 0) == -1 )
					  perror("rcptto()");

				/*  receive 250*/
				receive(sockfd, "250 ", buf);
				/*  clear the buffer  */
				
				/*  handle multiple recipients case*/
				for(i=0;i<mailto_num-1;i++)
						rcptto2(sockfd, mailtos);
							
							
/* sending remaining addresses... */
}  //rcptto

/*  1. called by relaymail()  */
/*  2. interact with a smtp server */
void data(int sockfd){
		char buf[MAXDATASIZE] = "";
		printf("\n");
		printf("data() is called\n");

		/*  send "DATA"  */
		if( send(sockfd, "DATA\r\n", 6, 0) == -1 )
			  perror("data()");

		/*  receive 354  */
		receive(sockfd, "354 ", buf);
}


/*  1. called by relaymail()  */
/*  2. interact with a smtp server */
void message(int sockfd, char *msg){
		int times,i,j;
		int remainder;
		printf("\n");
		char out[1025];
		printf("message() is called\n");
		
		times = strlen(msg) / MAXDATASIZE;
		remainder = strlen(msg) - (times * MAXDATASIZE);
		
		printf("remainder: %i\n", remainder);
		printf("times: %i\n", times);
			
		for (i=0;i< times;i++){
					for (j=0;j< 1024;j++)
								out[j]= msg[1024*i + j];
					out[1024 +1] = '\0';
			
					printf("sending msg: %i\n", i);
						if( send(sockfd, out, 1025, 0) == -1 );
		}
		printf("end while: %i\n", i);
		printf("out: %s\n", out);
					for (j=0;j< remainder;j++)
								out[j]= msg[1024*times + j];
								out[remainder +1] = '\0';
		if( send(sockfd, out, remainder+1, 0) == -1 )
							perror("message");
							printf("out: %s\n", out);
}

/*  1. called by relaymail()  */
/*  2. interact with a smtp server */
void quit(int sockfd){
		char buf[MAXDATASIZE] = "";
		printf("\n");
		printf("quit() is called\n");

		/*  send "QUIT"  */
		if( send(sockfd, "QUIT\r\n", 6, 0) == -1 )
			  perror("quit()");

		/*  receive 354  */
		receive(sockfd, "250 ", buf);
}


/*relay mail to a email server*/
void relaymail(char *relay,char *mail_from, char *mailto, int mailto_num, char *msg){

    int sockfd, numbytes;  
    char buf[MAXDATASIZE];
    struct hostent *he;
    struct sockaddr_in their_addr; // connector's address information 
    int state = 1;
    int logswitch = 0; 
		int logwhile = 0;
		
		
    if ((he=gethostbyname(relay)) == NULL) {  // get the host info 
        fprintf(stderr,"gethostbyname fail\n");
        exit(1);
    }

    if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) == -1) {
        fprintf(stderr,"fail to create socket\n");
        exit(1);
    }

    their_addr.sin_family = AF_INET;    // host byte order 
    their_addr.sin_port = htons(PORT);  // short, network byte order 
    their_addr.sin_addr = *((struct in_addr *)he->h_addr);
    memset(&(their_addr.sin_zero), '\0', 8);  // zero the rest of the struct 

    if (connect(sockfd, (struct sockaddr *)&their_addr, sizeof(struct sockaddr)) == -1) {
        fprintf(stderr,"connect fail\n");
        exit(1);
    }

 		while (state <7 && logwhile <10){  /*  make sure the program won't run indefinitely  */

			logwhile++;
			/*   log   */	
//      printf("\n");
//			printf("logwhile = %i\n", logwhile);
//			printf("state = %i\n", state);
//      printf("\n");
			
			switch (state){
				case HELO :
					helo(sockfd);
					state++;
					printf ("end of case HELO\n");
					break;
				case MAILFROM :
					mailfrom(sockfd, mail_from);
					state++;
					printf ("relaymail():  end of case MAILFROM\n");				
					break;
				case RCPTTO :
					rcptto(sockfd, mailto, mailto_num);
					state++;
					printf ("relaymail():  end of case RCPTTO\n");									
					break;				
				case DATA :
					data(sockfd);
					state++;
					printf ("relaymail():  end of case DATA\n");
					break;
				case MESSAGE :
					message(sockfd, msg);
					printf ("relaymail():  end of case MESSAGE\n");
					state++;
					printf ("relaymail():  end of case MESSAGE\n");
				case QUIT :
					quit(sockfd);
					state++;
					printf ("end of case QUIT\n");
					closesocket(sockfd);
					break;

				default :
					break;				
				}
		}  // while()
    closesocket(sockfd);
}


/*  remove  < >   */
char* remove_brackets(char* input)
{
  int length;
  int i, j;
  char* output;

  length = strlen(input);
  output = (char*) malloc(length + 1); 
  j = 0;

  /* copy character of input which in not equal to < or > to output */
  for (i=0; i<length; i++)
    if ((input[i]!='<') && (input[i]!='>'))
    {
      output[j] = input[i];
      j++; 
    }     
  output[j] = '\0';

  return output;
}


/* trim the space(s) before and after the string */
char* trim_space(char* input)
{
  int i, j, length, is_ch, is_end, end_pos;
  char *output;
   
  /* trim the space(s) before the string */
  length = strlen(input);
  output = (char*) malloc (length+1);
  is_ch = 0;
  is_end = 0;
  j = 0;

  for(i=0; i<length; i++)
  {
    /* copy input characters to output */
    if (is_ch==1 || !isspace(input[i]))
    {
      output[j] = input[i];
      j++;
      is_ch = 1;
    }
 }
  output[j] = '\0';

  /* trim the space(s) after the string */
  length = strlen(output);
  end_pos = length-1;
  is_end = 0;
  
  for (i=0; i<length; i++)
    if (is_end==0 && isspace(output[i]))
    {
      is_end = 1;
      end_pos = i;   
    }   
    else if (!isspace(output[i]))
      is_end = 0; 
   
  output[end_pos] = '\0';
 
  return output;
}


/* convert :    MAIL FROM: a@a.com  --->  a@a.com */
char *extractemail(const char *buf, const int i){
char * email = NULL;
char * tmp_email = NULL;
char * tmp_email2 = NULL;
char * tmp_email3 = NULL;

	/*           extract email address              */
/*  1. remove MAIL FROM:  */
				email = malloc(strlen(buf));
        strcpy(email,buf);
        email += i;
        printf("\n");
        printf("email =%s\n", email);
        printf("email length =%i\n", strlen(email));
        printf("\n");
/*  2. trim head and trailing whitespace  */
        tmp_email = trim_space(email);
        printf("trimmed email= %s\n", tmp_email);
/*  3. remove <>  */
				tmp_email2 = remove_brackets(tmp_email);
				printf("remove<> email= %s\n", tmp_email2);
/*  4. trim again */
//				tmp_email3 = trim_space("ellen@cs.com.hk");
//				printf("\n");
//				printf("extracted email= ~~~~~~%s~~~~~~\n", tmp_email3);
//				printf("\n");

//				printf("extracted email= ~~~~~~%s~~~~~~\n", tmp_email3);
				return tmp_email2;
}


/* check if email address is a valid one  */
int check_email_validity(const char *address) {
  // check if email address is valid
	// return 1 if valid
	// return 0 if invalid
	
  int number = 0;
  const char *a, *host;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -