SMTP Engine!?!?
-
Ich möchte gerne eine kleine SMTP Engine schreiben die reine text e-mails versenden kann. hab mir dazu auch schon die wichtigsten RFC's angeschaut, ich scheue mich auch nicht zurück dafür ein wenig länger zu brauchen. Ich bin kein C++ neuling, aber kann trotzdem noch nicht alles so richtig gut.
Da wollte ich mal Fragen, kennt jemand evtl. schon eine OpenSource SMTP-Engine, die OHNE Server auskommt, die ich dann nach meinen bedürfnissen umschreiben könnte.
Außerdem konnte in den RFC's nicht entlesen ob für den ganzen verkehr winsocks verwendet werden, habt ihr da bissle mehr ahnung?
also mir hilft eigentlich alles außer blöden kommentaren was ihr wisst. das ganze soll ein großprojekt werden in dem ich mein ganzen wissen mal so richtig auf die probe stellen will. wegen mir kann das projekt auch ein halbes jahr dauern, ich brauch nur hier und da eure kleine unterstützung. (kenne mich mit großen projekten recht gut aus. damals noch VB)
MfG Mailmaster
-
Hi,
im Grunde sind die RFC schon die Anlaufstelle Nr. 1. Es gibt natürlich einige SMTP Dämons für Postfix, Sendmail etc. die du dir angucken könntest, sind aber überwiegend für Linux.
Und ja, natürlich werden Sockets benötigt. Dass du nix über winsocks findest liegt einfach daran, dass die RFC plattformunabhängig geschrieben sind.
-
hab sowas schonmal geschrieben
du kannst es in zwei teile aufteilen
zum einen ein modul, das eine verbindung zu einem server aufbaut und datensenden und empfangen kannund zum andern ein modul das den ablauf handelt, also kommandos verschickt und eingehende antworten auswertet
is kein hexenwerk... die meiste arbeit besteht darin es exakt standardkonform zu halten, damit es mit allen mailservern kommunizieren kann
-
könntest du mir die codes dafür per e-mail zuschicken??
Wenn du das nicht tun möchtest, kann ichs auch verstehn, aber wäre mir mit vorhandenen codes um einiges einfacher. selbst google brachte die letze 1 1/2 stunden keine brauchbaren ergebnisse außer der quellcode eines virus in Assembleraber andere frage, könntest du mir trotzdem eine mail schicken, das ich dich vllt noch ein paar sachen dazu befragen könnte. immerhin weist du ja schon wie es geht.
meine addy (gegen Spam so komisch geschrieben)
ich kann aber erst heut abend darauf antworten, die firmenfirewall lässt keine webmailer zu
MfG Mailmaster
-
sry für den spam, aber als nicht registrierter benutzer gibt's kein edit.
Sovok, hab grad in deinem profil gesehn, das du dort deine icq angegeben hast, kann ich dich über das anlabern? dann brauchen wir nicht über mail gehn.
ich adde dich mal (mein nick: Radiation)MfG Mailmaster
-
na ja im Grunde ist es ein einfaches Frage und Antwortspiel. Ich habe da mal was einen RelayServer für ´ne Anwendung geschrieben...
(Über Klassenzugriffe kannst Du getrost hinweg sehen, ist im wesentlichen nur Auswertung , außer bei "case DATA", dort mußt du die Übertragungsschnipsel irgendwie zusammenbringen)#define HELO 90 #define QUIT 91 #define MAIL 101 #define RCPT 102 #define DATA 103 #define VRFY 104 #define EXPN 105 #define SEND 106 #define SOML 107 #define SAML 108 #define NOOP 109 #define RSET 110 #define NONE -1 DWORD WINAPI mainControl(void* data); // Hauptcontrollprogramm int GetCommand(char* iComm); char* ReplyInfo(char* destPoint,int type, int onPos = 0); DWORD WINAPI StartSMTP(void* data) { int sockfd, newsockfd, clilen; struct sockaddr_in cli_addr, serv_addr; int serv_tcp_port = 25; struct timeval timeout; fd_set readfds, writefds; int reqlen, totreqlen; char tbuf[TBUF_LEN], rbuf[TBUF_LEN]; char *cli_ip; int file_length = 0; char file_name[TBUF_LEN]; WORD wVersionRequested; WSADATA wsaData; int err; wVersionRequested = MAKEWORD( 2, 2 ); err = WSAStartup( wVersionRequested, &wsaData ); if ( err != 0 ) return 1; if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0) { fprintf(stderr, "SMTP: Base Socket kann nicht geöffnet werden\n"); return 1; } AUTOCONTR autoMail; STDMAILADR mailListe = autoMail.getMailList(); memset((char *) &serv_addr, 0, sizeof(serv_addr)); serv_addr.sin_family = AF_INET; serv_addr.sin_addr.s_addr = htonl(INADDR_ANY); serv_addr.sin_port = htons((u_short) serv_tcp_port); if (bind(sockfd, (struct sockaddr *) &serv_addr, sizeof(serv_addr)) < 0) { fprintf(stderr, "SMTP: kann locales Port nicht binden\n"); return 1; } listen(sockfd, 5); for ( ; ; ) { FAXSTATUS* cxTest = new FAXSTATUS; cxTest->test(); clilen = sizeof(cli_addr); memset(tbuf,0,sizeof(tbuf)); if ((newsockfd = accept(sockfd, (struct sockaddr *) &cli_addr, &clilen)) < 0) { fprintf(stderr, "SMTP: Accept Fehler\n"); return 1; } if ((cli_ip = inet_ntoa(cli_addr.sin_addr)) == NULL) cli_ip = "<unknown ip>"; cxTest->ipAddr(cli_ip); timeout.tv_sec = 10; timeout.tv_usec = 0; FD_ZERO(&readfds); FD_ZERO(&writefds); FD_SET(newsockfd, &readfds); FD_SET(newsockfd, &writefds); if( select(32, NULL, &writefds, NULL, &timeout) != 1 || ((reqlen = send(newsockfd,rbuf,strlen(ReplyInfo(rbuf,220)), 0)) < 0 )) { FD_ZERO(&readfds); FD_ZERO(&writefds); continue ; }; for( ; ; ) { bool exitBit = false; if (select(32, &readfds, NULL, NULL, &timeout) == 1 && ((reqlen = recv(newsockfd, tbuf, TBUF_LEN-1, 0)) > 0) ) { tbuf[reqlen] = 0; switch(GetCommand(tbuf)) { case NOOP : ReplyInfo(rbuf,250) ; break; case RSET : ReplyInfo(rbuf,250) ; break; case HELO : cxTest->ident(tbuf); ReplyInfo(rbuf,250) ; break; case MAIL : if(!cxTest->from(tbuf)) ReplyInfo(rbuf,221); else ReplyInfo(rbuf,250); break; case RCPT : if(!cxTest->to(tbuf)) ReplyInfo(rbuf,551) ; else ReplyInfo(rbuf,250) ; break; case DATA : if((select(32, NULL, &writefds, NULL, &timeout) == 1) && (send(newsockfd, rbuf, strlen(ReplyInfo(rbuf,354)), 0) > 0) ) { totreqlen = 0; while((reqlen = recv(newsockfd, tbuf, TBUF_LEN-1, 0)) > 0) { totreqlen += reqlen; if(cxTest->add(tbuf,reqlen) <= 0) { cxTest->set(); cxTest->writeList(); cxTest->updateSQL(2,&autoMail); memset(tbuf,0,sizeof(tbuf)); break; }; }; if(reqlen >= 0) ReplyInfo(rbuf,2501); break; }; case QUIT : exitBit = true; ReplyInfo(rbuf,221); break; default : ReplyInfo(rbuf,500); }; if( select(32, NULL, &writefds, NULL, &timeout) != 1 || ((reqlen = send(newsockfd,rbuf,strlen(rbuf), 0)) < 0 )) exitBit = true; } else break ; if(exitBit) break; }; if(!cxTest->isFax() && cxTest->canrelease()) cxTest->releasemsg(); delete cxTest; closesocket(newsockfd); }; WSACleanup(); return 0; }; char* ReplyInfo(char* destPoint,int type, int onPos) { char* tP; switch(type) { case 500 : tP = "500 Systax error, command unreconnized \r\n"; break; case 501 : tP = "501 Systax error, in parameters or arguments \r\n"; break; case 502 : tP = "502 Command not implemented \r\n"; break; case 503 : tP = "503 Bad sequence of commands \r\n"; break; case 504 : tP = "504 Command parameter not implemented \r\n"; break; case 211 : tP = "211 System status, or system help reply \r\n"; break; case 214 : tP = "214 Help message \r\n"; break; case 220 : tP = "220 Here is <guifax@rasi.net>. Service ready \r\n"; break; case 221 : tP = "221 <guifax@rasi.net>. Service closing transmission channel \r\n"; break; case 421 : tP = "421 <guifax@rasi.net>. Service not available, closing transmission channel \r\n"; break; case 250 : tP = "250 Requested mail action okay, completed \r\n"; break; case 2501: tP = "250 Message accepted for delivery\r\n"; break; case 251 : tP = "251 User not local; will forward to <unknow> \r\n"; break; case 450 : tP = "450 Requested mail action not taken: mailbox unavailble \r\n"; break; case 451 : tP = "451 Requested action aborted: error in processing \r\n"; break; case 452 : tP = "452 Requested action not taken: insufficient system storage \r\n"; break; case 550 : tP = "550 Requested action not taken: mailbox unavailable \r\n"; break; case 551 : tP = "551 User not local; please try <unknow> \r\n"; break; case 552 : tP = "552 Requested mail action aborted: exceeded storage allocation \r\n"; break; case 553 : tP = "553 Requested action not taken: mailbox name not allowed \r\n"; break; case 354 : tP = "354 Start mail input, end with <\r\n>.<\r\n> \r\n"; break; case 554 : tP = "554 Transaction failed \r\n"; break; default : tP = "500 Systax error, command unreconnized \r\n"; }; strcpy(destPoint+onPos,tP); return destPoint; }; int GetCommand(char* iComm) { if(memcmp(iComm,"HELO",4) == 0) return HELO; if(memcmp(iComm,"QUIT",4) == 0) return QUIT; if(memcmp(iComm,"MAIL",4) == 0) return MAIL; if(memcmp(iComm,"RCPT",4) == 0) return RCPT; if(memcmp(iComm,"RSET",4) == 0) return RSET; if(memcmp(iComm,"DATA",4) == 0) return DATA; if(memcmp(iComm,"VRFY",4) == 0) return VRFY; if(memcmp(iComm,"EXPN",4) == 0) return EXPN; if(memcmp(iComm,"SEND",4) == 0) return SEND; if(memcmp(iComm,"SOML",4) == 0) return SOML; if(memcmp(iComm,"SAML",4) == 0) return SAML; if(memcmp(iComm,"NOOP",4) == 0) return NOOP; return NONE; };
Ist natürlich nicht vollständig, aber wie gesagt, vielleicht hift´s
-
Coole Sache, werde ich auf jeden fall einmal ausprobieren und dran rumbasteln.
falls es von meiner seite noch probleme/fragen geben sollte häng ich es bei bedarf einfach an.Danke schonmal für eure Hilfe.
MfG Mailmaster
-
ähm...
ich hab mir den ganzen code mal ausgedruckt und während dem heimfahren angeschaut, da hab ich gesehn das bei dem oben gezeigten code das socket gebunden wird. das hat mich dann schon ein wenig verwundert, eigentlich muss man doch nur server sockets binden oder verstehe ich das falsch?Vllt gibt es ja auch ein vertändnisproblem eurer seite. ich wollte nicht einen mail server schreiben, sondern nur einen client der per winsock mails ohne SMTP server versenden kann. mein tool soll in zukunft auf wunsch des anwenders problemberichte oder ähnliches verschicken können, dabei ich möchte aber voll und ganz auf einen server verzichten, obwohl ich genug davon hätte
Vllt könnt ihr mir nun a bissle besser helfen
MfG Mailmaster
-
macht doch auch keinen großen unterschied.. dann machst du halt n connect statt listen und spielst das frage-antwort spiel von der anderen seite wies eben im rfc steht
-
Na schon, in deinem Fall muss wahrscheinlich der Client ein Server sein, wenn er sofort Nachrichten ausgeben soll (einer muss lauschen).
Wenn Du aber sowas wie ein EMail-Client schreiben willst, ist es das falsche Protokoll, dazu solltest Du dann POP3 oder Nachfolger verwenden. Nachteil der eines echten EMail-Clients ist bloss, das er sich regelmäßig zum Server verbindet und nach Nachrichten nachfragen muss.
-
.. im Übrigen wie groß ist das Gesamte geplant ? Wieviel User ?
Ich habe schon so ein Komplettsystem eintwickelt (ca. 5000 User).
Wenn Du willst kann ich dir ein bißchen mehr darüber erzählen. Dann hinterlasse mal deine EMail-Adresse ...
-
also ich möchte keine pop3 fächer abrufen und dadurch auch nichts versenden.
einfach nur durch das frage/antwortspiel eine mail versenden.so in etwa:
HELO
->OK
MAIL
->OK
RCPT
->OK
DATA
->OK
QUIT
->OKmehr aber auch nicht. trotzdem bin ich immer gerne für erweiterungen offen...vllt wird es ja mal ein kompletter server, der nicht nur versenden kann, sondern auch empfangen und mails speichern. ne gute idee wäre eigentlich auch noch das ganze mit nem webserver zu koppeln, über dann man das abrufen könnte, als art webmailer. pop3 wäre dann auch noch net schlecht *träum*
ne ich will mal net übertreiben, aber wie gesagt man kann das ja immmer und immer wieder erweitern.daher hier meine addy (die komische schreibweise gegen spam) radiation.uc[at]gmx[dot]net
PS: sorry hätte nich client sagen sollen, is im prinzip schon ein server, der kann eben nur senden, aber nichts empfagen.
hab die ganze RFC zu SMTP jetzt durch, jetzt is mir auch vieles klar geworden.
in den nächsten 10 minuten fang ich mal an ne Klasse dafür zu schreiben.
hab ja genügend mail server hier im geschäft um es zu testendanke schonmal für deine hilfe
MfG Mailmaster