?? smtpr.c
字號:
static char *special_characters = "()<>@,;:\\\"[]";
/* validate name */
for (a = address; *a; a++) {
if (*a == '\"' && (a == address || *(a - 1) == '.' || *(a - 1) ==
'\"')) {
while (*++a) {
if (*a == '\"') break;
if (*a == '\\' && (*++a == ' ')) continue;
if (*a <= ' ' || *a >= 127) return 0;
}
if (!*a++) return 0;
if (*a == '@') break;
if (*a != '.') return 0;
continue;
}
if (*a == '@') break;
if (*a <= ' ' || *a >= 127) return 0;
if (strchr(special_characters, *a)) return 0;
}
if (a == address || *(a - 1) == '.') return 0;
/* next we validate the host portion (name@host) */
if (!*(host = ++a)) return 0;
do {
if (*a == '.') {
if (a == host || *(a - 1) == '.') return 0;
number++;
}
if (*a <= ' ' || *a >= 127) return 0;
if (strchr(special_characters, *a)) return 0;
} while (*++a);
return (number >= 1);
}
int main(int argc, char *argv[])
{
int sockfd, new_fd; // listen on sock_fd, new connection on new_fd
struct sockaddr_in my_addr; // my address information
struct sockaddr_in their_addr; // connector's address information
int sin_size;
int yes=1;
socklen_t addr_len;
int numbytes=0;
char buf[MAXBUFLEN] = "";
char tmp_msg[MAXBUFLEN] ="";
char message[SQMAXDATASIZE];
char message_buf[10000];
char *msg = message;
char quit[MAXBUFLEN];
int MYPORT;
char relay[RELAY_NAME];
int i,j;
char *email = NULL;
char *email2 = NULL;
char *mail_from = NULL;
char *mail_to = NULL;
char *tmp_mail = NULL;
char mailtos[2000];
int mailto_num =0;
char *data = NULL;
char *data2 = NULL;
char *quit1 = NULL;
char *quit2 = NULL;
int state1 = 0; //
int state2 = 0; // keep track of number of 'helo's
int logwhile = 0;
char hardcode_email[15] = "cylaw@cs.hku.hk";
#ifdef WIN32
WSADATA wsaData;
WSAStartup(0x0101, &wsaData);
#endif
/* check number of parameters */
if ( argc != 3 && argc !=2 ) {
fprintf(stderr,"usage: smtpr <port number> (<relay server>)\n");
exit(1);
}
/* fill in port number */
MYPORT = atoi(argv[1]);
if ( MYPORT <= 0){
fprintf(stderr, "Invalid port number.\nusage: smtpr <port number> (<relay server>)\n");
exit(1);
}
/* fill in the server relay to */
if (argc == 2) strcpy(relay, "some.mail.server");
else if (argc == 3) strcpy(relay, argv[2]);
printf("relay to %s\n", relay);
/*create a TCP socket */
if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) == -1) {
perror("socket");
exit(1);
}
printf("port number : %i\n", MYPORT);
my_addr.sin_family = AF_INET; // host byte order
my_addr.sin_port = htons(MYPORT); // short, network byte order
my_addr.sin_addr.s_addr = htonl(INADDR_ANY); // automatically fill with my IP
memset(&(my_addr.sin_zero), '\0', 8); // zero the rest of the struct
/* bind to the port number*/
if (bind(sockfd, (struct sockaddr *)&my_addr, sizeof(struct sockaddr)) == -1) {
perror("bind");
exit(1);
}
/* listen*/
if (listen(sockfd, BACKLOG) == -1) {
perror("listen");
exit(1);
}
/* slow the receiving speed */
// sleep(1);
while(1){
logwhile++;
switch ( state1 ){
case ACCEPT:
/* accept */
sin_size = sizeof(struct sockaddr_in);
if ((new_fd = accept(sockfd, (struct sockaddr *)&their_addr, &sin_size)) == -1) {
perror("accept");
}
printf("server: got connection from %s\n",inet_ntoa(their_addr.sin_addr));
/* send msg : 220 */
if (send(new_fd, "220 cylaw's smtpr ready\r\n", 25, 0) == -1)
perror("send");
/*proceed to next state*/
printf("state1 = %i\n", state1);
state1++;
break;
case HELO:
if(state2 == 0){ //state2 keep track of if this is the first HELO
if ((numbytes=recv(new_fd, buf, MAXDATASIZE, 0)) == -1) {
perror("recv");
exit(1);
}
}
buf[numbytes] = '\0';
/* log */
printf("case HELO\n");
printf("============\n");
printf("buf :%s\n", buf);
/* check on length */
if ( strlen(buf) < 6 || strlen(buf) > MAXDATASIZE ){
printf("550 Syntax: <HELO>\n");
if (send(new_fd, "550 Syntax: <HELO|EHLO> <hostname>\r\n", 36, 0) == -1)
perror("HELO send");
}
/* compare (case-insensitively) the first 4 bytes of buf with "HELO" and "EHLO" */
if ( (strncasecmp(buf, "HELO ", 5) != 0) && (strncasecmp(buf, "EHLO ", 5) != 0 ) ){
printf("550 Syntax: <HELO>\n");
if (send(new_fd, "550 Syntax: <HELO|EHLO> <hostname>\r\n", 36, 0) == -1)
perror("HELO-1 send");
}
/* not implement case : helo<space>aaaaa<space> */
if ( buf[5] == '\0' && buf[5] == ' ' ){
printf("550 Syntax: <HELO|EHLO> <hostname>\n");
if (send(new_fd, "550 Syntax: <HELO|EHLO> <hostname>\r\n", 36, 0) == -1)
perror("HELO-2 send");
}
/* send 250 OK */
printf("250 HELO OK\n");
if ( send( new_fd, "250 HELO OK\r\n", 13, 0 ) == -1 )
perror("HELO-250-OK send");
printf("\n");
/*proceed to next state*/
state1++;
state2++;
break; //case HELO
case MAILFROM :
if ((numbytes=recv(new_fd, buf, MAXDATASIZE, 0)) == -1) {
perror("recv");
exit(1);
}
buf[numbytes] = '\0';
/* log */
printf("\n");
printf("case MAILFROM\n");
printf("=============\n");
printf("buf :%s\n", buf);
/* HELO */
if ( (strncasecmp(buf, "HELO ", 5) == 0) || (strncasecmp(buf, "EHLO ", 5) == 0 ) ){
printf("HELO received at case MAILFROM, go back to case HELO\n");
state1--;
break;
}
/* check "MAIL FROM:" */
if ( strncasecmp(buf, "MAIL FROM:", 10) != 0 ){
printf("550 Syntax: MAIL FROM: <email-address>\n");
if (send(new_fd, "550 Syntax: MAIL FROM: <email-address>\r\n", 40, 0) == -1)
perror("MAIL FROM: send()");
exit(1);
}
/* extract email address */
mail_from = extractemail(buf, 10);
/* check email validity */
if ( check_email_validity(mail_from) == 0 ){ //0 - invalid 1 - valid
printf("550 Invalid email address\r\n");
if (send(new_fd, "550 Invalid email address\r\n", 27, 0) == -1)
perror("Email address send()");
break; //case MAILFROM
}
/* send 250 OK */
printf("250 MAIL FROM OK\n");
if ( send( new_fd, "250 MAIL FROM OK\r\n", 18, 0 ) == -1 )
perror("MAILFROM-250-OK send()");
printf("\n");
state1++;
break; //case MAILFROM
case RCPTTO :
/* check if this is the first MAIL FROM: <> line */
if ( mailto_num == 0){
if ((numbytes=recv(new_fd, buf, MAXDATASIZE, 0)) == -1) {
perror("recv");
exit(1);
}
buf[numbytes] = '\0';
}
/* log */
printf("\n");
printf("case RCPTTO\n");
printf("=============\n");
printf("state1 = %i\n", state1);
printf("buf :%s\n", buf);
/* check RCPT TO: <...> */
if ( strncasecmp(buf, "RCPT TO:", 8) != 0 ){
printf("550 Syntax: RCPT TO: <email-address>\n");
if (send(new_fd, "550 Syntax: RCPT TO: <email-address>\r\n", 38, 0) == -1)
perror("MAIL FROM: send()");
}
/* extract email address */
mail_to = extractemail(buf, 8); // 8 = strlen("RPCT TO:")
/* recipients address on to mailtos []*/
strcat(mailtos, mail_to);
strcat(mailtos, ",");
mailto_num++;
printf("mailtos %s\n", mailtos);
printf("mailto_num %i\n", mailto_num);
/* check email validity */
if ( check_email_validity(mail_to) == 0 ){
printf("550 Invalid email address\n");
if (send(new_fd, "550 Invalid email address\r\n", 27, 0) == -1)
perror("RCPTTO address send()");
break; //case MAILFROM
}
/* send 250 OK */
printf("250 RCPT TO OK\n");
if ( send( new_fd, "250 RCPT TO OK\r\n", 16, 0 ) == -1 )
perror("MAILFROM-250-OK send()");
state1++;
break; // case RCPTTO
case DATA :
if ((numbytes=recv(new_fd, buf, MAXDATASIZE, 0)) == -1) {
perror("recv");
exit(1);
}
buf[numbytes] = '\0';
/* log */
printf("\n");
printf("case DATA\n");
printf("=============\n");
printf("state1 = %i\n", state1);
printf("buf :%s\n", buf);
/* multiple recipients */
if ( strncasecmp(buf, "RCPT TO:", 8 ) == 0){
printf("Multiple recipients -- Go back to state RCPT TO\n");
printf("\n");
state1--;
break;
}
if ( strncasecmp(buf,"DATA", 4) != 0 ){
printf("451 Syntax: DATA\n");
if (send(new_fd, "451 Syntax: DATA\r\n", 18, 0) == -1)
perror("DATA send");
} else{
/* send 354 OK */
// send( new_fd, "354 End\r\n", 10, 0 );
printf("354 End data with <CR><LF>.<CR><LF>\n");
if ( send( new_fd, "354 End data with <CR><LF>.<CR><LF>\r\n", 37, 0 ) == -1 ){
perror("MAILFROM-354-OK send()");
printf("354 error\n");
exit(1);
}
printf("\n");
}
state1++;
break; // case DATA
case MESSAGE :
printf("\n");
printf("case MESSAGE\n");
printf("============\n");
i=0;
while(i<10000){
i++;
if ((numbytes=recv(new_fd, message_buf, 9999, 0)) == -1) {
perror("recv");
exit(1);
}
message_buf[numbytes] = '\0';
/* log */
// printf("message_buf:\n\n%s", message_buf);
/* append message_buf to message */
strcat(message, message_buf);
if (strstr (message_buf, "\r\n.\r\n") != NULL ){
/* send 250 OK */
printf(". found\n");
if ( send( new_fd, "250 message received\r\n", 22, 0 ) == -1 )
perror("MESSAGE");
printf("message:\n\n %s\n", message);
state1++;
break;
}//if()
}//while()
state1++;
break;
case QUIT :
if ((numbytes=recv(new_fd, quit, MAXDATASIZE, 0)) == -1) {
perror("recv");
exit(1);
}
quit[numbytes] = '\0';
/* log */
printf("\n");
printf("case QUIT\n");
printf("=============\n");
printf("buf :%s\n", quit);
printf("\n");
/* trim space " QUIT " */
// quit1 = malloc(strlen(quit));
// strcpy(quit1, quit);
// printf("quit :%s\n", quit1);
// quit2 = trim_space(quit1);
// printf("quit :%s\n", quit1);
/* check QUIT */
if ( strncasecmp(quit, "QUIT", 4) != 0 ){
state1 = QUIT;
if (send(new_fd, "550 Syntax: QUIT\r\n", 18, 0) == -1)
perror("QUIT");
}else{
/* send 221 OK */
if ( send( new_fd, "221 QUIT.\r\n", 11, 0 ) == -1 )
perror("QUIT");
printf("QUIT!\n");
closesocket(new_fd);
state1++;
break;
}
break; // case QUIT
case RELAY :
relaymail(relay,mail_from,mailtos,mailto_num, msg);
/* go back to ACCEPT states */
state1 = ACCEPT;
/* reset variables */
strcpy(buf, "");
strcpy(tmp_msg, "");
strcpy(message, "");
strcpy(message_buf, "");
strcpy(quit,"");
i=0;j=0;
email = NULL;
email2 = NULL;
mail_from = NULL;
mail_to = NULL;
tmp_mail = NULL;
strcpy(mailtos, "");
mailto_num =0;
data = NULL;
data2 = NULL;
quit1 = NULL;
quit2 = NULL;
state2 = 0;
break;
default : break;
}//switch
} // while(1)
close(new_fd);
#ifdef WIN32
WSACleanup();
#endif
return 0;
}
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -