📄 server.c
字号:
/*
* Embedded SMTP Server
*
* ./software/ch5/emsmtpd/server.c
*
* mtj@cogitollc.com
*
* Copyright 2001,2002 M. Tim Jones <mtj@cogitollc.com>
*
* 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, or (at your option) any
* later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
*/
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <signal.h>
#include <stdio.h>
#include <sys/un.h>
#include <unistd.h>
#include "server.h"
const char *salutation={"220 Embedded Mail Transport (mtj@mtjones.com)\n"};
const char *conclose={"221 EMT closing connection.\n"};
const char *goahead={"250 OK\n"};
const char *gimmesome={"354 Gimme!\n"};
const char *closeit={"221 Service closing transmission channel.\n"};
parseMailType mail;
/*
* closeConnection()
*
* This function performs an SMTP close on the named socket.
*
*/
void closeConnection(int fd)
{
write(fd, conclose, strlen(conclose));
printf("Aborted the connection...\n");
}
/*
* grabAddress()
*
* Grab an address from the line as delimited by '<' and '>'.
* Argument 'src' is the input text line of max length 'len',
* and 'dest' is where the email address is copied.
*
*/
void grabAddress(char *src, char *dest, int len)
{
int i;
int j=0;
for (i = 1 ; i < len ; i++) if (src[i-1] == '<') break;
if (i == len) { dest[0] = 0; return; }
for ( ; i < len ; i++) {
if (src[i] == '>') break;
dest[j++] = src[i];
}
if (i == len) { dest[0] = 0; return; }
dest[j] = 0;
return;
}
/*
* handleConnection()
*
* This function handles a single SMTP dialog. The SMTP server protocol
* is implemented here as well as buffering of the email header and
* body. This function calls 'parseMail' when an email has been
* received to further parse and process the incoming email.
*
*/
void handleConnection(int fd)
{
int bufIdx = 0;
int state = 0, len, i, stop=0;
char buffer[81];
memset((void *)&mail, 0, sizeof(mail));
/* Indicate ready to go... */
len = write(fd, salutation, strlen(salutation));
/* Fix the nmap problem. */
if (len <= 0) {
return;
}
/* Wait for salutation response... */
len = read(fd, buffer, 255); buffer[len] = 0;
if ((strncmp(buffer, "HELO", 4)) && (strncmp(buffer, "EHLO", 4))) {
closeConnection(fd);
return;
}
write(fd, goahead, strlen(goahead));
/* Wait for Mail From: */
len = read(fd, buffer, 255); buffer[len] = 0;
if (strncmp(buffer, "MAIL FROM", 9)) { closeConnection(fd); return; }
grabAddress(buffer, mail.sender, 256);
if (mail.sender[0] == 0) { closeConnection(fd); return; }
write(fd, goahead, strlen(goahead));
/* Wait for Rcpt To: */
len = read(fd, buffer, 255); buffer[len] = 0;
if (strncmp(buffer, "RCPT TO", 7)) { closeConnection(fd); return; }
grabAddress(buffer, mail.recipient, 256);
if (mail.recipient[0] == 0) { closeConnection(fd); return; }
write(fd, goahead, strlen(goahead));
/* Wait for DATA */
len = read(fd, buffer, 255); buffer[len] = 0;
if (strncmp(buffer, "DATA", 4)) { closeConnection(fd); return; }
write(fd, gimmesome, strlen(gimmesome));
/* Loop to collect all of the email body */
bufIdx = state = stop = 0;
while (!stop) {
if (bufIdx > MAX_MAIL - 80) { closeConnection(fd); return; }
len = read(fd, &mail.rawMail[bufIdx], (MAX_MAIL-bufIdx));
if ((len <= 0) || (bufIdx+len > MAX_MAIL)) {
closeConnection(fd); return;
}
/* Search for the end in the current buffer */
for (i = bufIdx ; i < bufIdx+len ; i++) {
if ((state == 0) && (mail.rawMail[i] == 0x0d)) state = 1;
else if ((state == 1) && (mail.rawMail[i] == 0x0a)) state = 2;
else if ((state == 2) && (mail.rawMail[i] == 0x0d)) state = 1;
else if ((state == 2) && (mail.rawMail[i] == '.')) state = 3;
else if ((state == 3) && (mail.rawMail[i] == 0x0d)) state = 4;
else if ((state == 4) && (mail.rawMail[i] == 0x0a)) { stop = 1; break; }
else state = 0;
}
bufIdx += len;
}
write(fd, goahead, strlen(goahead));
state = 0;
while (state++ < 10) {
// Wait for QUIT
len = read(fd, buffer, 80); buffer[len] = 0;
if (strncmp(buffer, "QUIT", 4)) {
closeConnection(fd); return;
} else break;
}
/* We now have an email in the mail structure, try now to parse it */
parseMail(&mail, bufIdx);
write(fd, closeit, strlen(closeit));
return;
}
/*
* main()
*
* This main function performs SMTP socket setup and connection
* handling. Calls handleConnection when a peer connects.
*
*/
int main(int argc, char **argv)
{
int listenfd, connfd;
socklen_t clilen;
struct sockaddr_in cliaddr, servaddr;
listenfd = socket(AF_INET, SOCK_STREAM, 0);
bzero(&servaddr, sizeof(servaddr));
servaddr.sin_family = AF_INET;
servaddr.sin_addr.s_addr = htonl(INADDR_ANY);
servaddr.sin_port = htons(25);
bind(listenfd, (struct sockaddr *)&servaddr, sizeof(servaddr));
listen(listenfd, 5);
for ( ; ; ) {
clilen = sizeof(cliaddr);
connfd = accept(listenfd, (struct sockaddr *)&cliaddr, &clilen);
if (connfd <= 0) {
break;
}
handleConnection(connfd);
close(connfd);
}
close(listenfd);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -