|
|
| version 1.13, 2002/08/01 11:41:14 | version 1.20.2.2, 2003/02/04 14:04:47 |
|---|---|
| Line 1 | Line 1 |
| /** @file | /** @file |
| Parser: SMTP sender. | Parser: SMTP sender. |
| Copyright (c) 2001, 2002 ArtLebedev Group (http://www.artlebedev.com) | Copyright (c) 2001-2003 ArtLebedev Group (http://www.artlebedev.com) |
| Author: Alexandr Petrosian <paf@design.ru> (http://paf.design.ru) | Author: Alexandr Petrosian <paf@design.ru> (http://paf.design.ru) |
| Parts of the code here is based upon an early gensock and blat | Parts of the code here is based upon an early gensock and blat |
| Line 12 static const char* IDENT_SMTP_C="$Date$" | Line 12 static const char* IDENT_SMTP_C="$Date$" |
| #include "pa_exception.h" | #include "pa_exception.h" |
| #include "smtp.h" | #include "smtp.h" |
| SMTP::SMTP(Pool& pool, const String& aorigin_string) : Pooled(pool), | //#define DEBUG_SHOW |
| origin_string(aorigin_string) { | |
| SMTP::SMTP(StringPtr aorigin_string): origin_string(aorigin_string) { | |
| the_socket = 0; | the_socket = 0; |
| in_index = 0; | in_index = 0; |
| out_index = 0; | out_index = 0; |
| Line 30 SMTP::SMTP(Pool& pool, const String& aor | Line 31 SMTP::SMTP(Pool& pool, const String& aor |
| // --------------------------------------------------------------------------- | // --------------------------------------------------------------------------- |
| void SMTP:: | void SMTP:: |
| ConnectToHost(const char *hostname, const char *service) | ConnectToHost(const char* hostname, const char* service) |
| { | { |
| struct sockaddr_in sa_in; | struct sockaddr_in sa_in; |
| int our_port; | int our_port; |
| Line 57 ConnectToHost(const char *hostname, cons | Line 58 ConnectToHost(const char *hostname, cons |
| CloseConnect(); | CloseConnect(); |
| throw Exception("smtp.connect", | throw Exception("smtp.connect", |
| &origin_string, | origin_string, |
| "connect to %s:%s failed", | "connect to %s:%s failed", |
| hostname, service); | hostname, service); |
| } | } |
| Line 210 get_line( void ) | Line 211 get_line( void ) |
| //--------------------------------------------------------------------------- | //--------------------------------------------------------------------------- |
| // returns 0 if all is OK | // returns 0 if all is OK |
| void SMTP:: | void SMTP:: |
| SendLine(const char *data, unsigned long length) | SendLine(const char* data, unsigned long length) |
| { | { |
| int num_sent; | int num_sent; |
| Line 223 SendLine(const char *data, unsigned long | Line 224 SendLine(const char *data, unsigned long |
| { | { |
| if( SOCKET_ERROR == select(0, NULL, &fds, NULL, &timeout) ) | if( SOCKET_ERROR == select(0, NULL, &fds, NULL, &timeout) ) |
| throw Exception("smtp.execute", | throw Exception("smtp.execute", |
| &origin_string, | origin_string, |
| "connection::put_data() unexpected error from select: %d", | "connection::put_data() unexpected error from select: %d", |
| WSAGetLastError()); | WSAGetLastError()); |
| Line 248 SendLine(const char *data, unsigned long | Line 249 SendLine(const char *data, unsigned long |
| default: | default: |
| throw Exception("smtp.execute", | throw Exception("smtp.execute", |
| &origin_string, | origin_string, |
| "connection::put_data() unexpected error from send(): %d", | "connection::put_data() unexpected error from send(): %d", |
| ws_error); | ws_error); |
| } | } |
| Line 264 SendLine(const char *data, unsigned long | Line 265 SendLine(const char *data, unsigned long |
| //--------------------------------------------------------------------------- | //--------------------------------------------------------------------------- |
| // returns 0 if all is OK | // returns 0 if all is OK |
| void SMTP:: | void SMTP:: |
| SendBuffer(const char *data, unsigned long length) | SendBuffer(const char* data, unsigned long length) |
| { | { |
| DWORD retval = 0; | DWORD retval = 0; |
| unsigned int sorta_sent = 0; | unsigned int sorta_sent = 0; |
| Line 316 CloseConnect() | Line 317 CloseConnect() |
| //---------------------------------------------------------------------- | //---------------------------------------------------------------------- |
| void SMTP:: | void SMTP:: |
| SendSmtpError(const char * message) | SendSmtpError(const char* message) |
| { | { |
| SendLine("QUIT\r\n", 6); | SendLine("QUIT\r\n", 6); |
| CloseConnect(); | CloseConnect(); |
| throw Exception("smtp.execute", | throw Exception("smtp.execute", |
| &origin_string, | origin_string, |
| "failed: %s", message); | "failed: %s", message); |
| } | } |
| Line 331 SendSmtpError(const char * message) | Line 332 SendSmtpError(const char * message) |
| // returns 20, 21, 22, 23, 24, 25 if SendBuffer() fails | // returns 20, 21, 22, 23, 24, 25 if SendBuffer() fails |
| // returns 26 if FlushBuffer() fails | // returns 26 if FlushBuffer() fails |
| void SMTP:: | void SMTP:: |
| transform_and_send_edit_data(const char * editptr ) | transform_and_send_edit_data(const char* editptr ) |
| { | { |
| const char *index; | const char *index; |
| const char *header_end; | |
| char previous_char = 'x'; | char previous_char = 'x'; |
| unsigned int send_len; | unsigned int send_len; |
| BOOL done = 0; | BOOL done = 0; |
| Line 342 transform_and_send_edit_data(const char | Line 342 transform_and_send_edit_data(const char |
| send_len = lstrlen(editptr); | send_len = lstrlen(editptr); |
| index = editptr; | index = editptr; |
| header_end = strstr(editptr, "\r\n\r\n"); | |
| while( !done ) | while( !done ) |
| { | { |
| // room for extra char for double dot on end case | // room for extra char for double dot on end case |
| Line 353 transform_and_send_edit_data(const char | Line 351 transform_and_send_edit_data(const char |
| { | { |
| case '.': | case '.': |
| if( previous_char == '\n' ) | if( previous_char == '\n' ) |
| { | SendBuffer(index, 1); // send _two_ dots... |
| /* send _two_ dots... */ | |
| SendBuffer(index, 1); | |
| } | |
| SendBuffer(index, 1); | SendBuffer(index, 1); |
| break; | break; |
| case '\r': | case '\n': // x\n -> \r\n |
| // watch for soft-breaks in the header, and ignore them | if( previous_char != '\r' ) { |
| if( index < header_end && (strncmp(index, "\r\r\n", 3) == 0) ) | SendBuffer("\r", 1); |
| index += 2; | SendBuffer(index, 1); |
| else | } |
| if( previous_char != '\r' ) | |
| SendBuffer(index, 1); | |
| // soft line-break (see EM_FMTLINES), skip extra CR */ | |
| break; | break; |
| default: | default: |
| SendBuffer(index, 1); | SendBuffer(index, 1); |
| break; | break; |
| Line 397 transform_and_send_edit_data(const char | Line 390 transform_and_send_edit_data(const char |
| // returns 16 if any get_line()'s fail | // returns 16 if any get_line()'s fail |
| // returns 20, 21, 22, 23, 24, 25, 26 if transform_and_send_edit_data() fails | // returns 20, 21, 22, 23, 24, 25, 26 if transform_and_send_edit_data() fails |
| void SMTP:: | void SMTP:: |
| send_data(const char * message) | send_data(const char* message) |
| { | { |
| transform_and_send_edit_data(message); | transform_and_send_edit_data(message); |
| if( 250 != get_line() ) | if( 250 != get_line() ) |
| Line 408 send_data(const char * message) | Line 401 send_data(const char * message) |
| // returns 0 if all is OK | // returns 0 if all is OK |
| // returns 50, 51, 52 if fails | // returns 50, 51, 52 if fails |
| void SMTP:: | void SMTP:: |
| open_socket( const char *server, const char *service ) | open_socket( const char* server, const char* service ) |
| { | { |
| ConnectToHost(server, service); | ConnectToHost(server, service); |
| if( gethostname(my_hostname, sizeof(my_hostname)) ) | if( gethostname(my_hostname, sizeof(my_hostname)) ) |
| throw Exception("smtp.connect", | throw Exception("smtp.connect", |
| &origin_string, | origin_string, |
| "lookup of '%s' failed", my_hostname); | "lookup of '%s' failed", my_hostname); |
| } | } |
| Line 423 open_socket( const char *server, const c | Line 416 open_socket( const char *server, const c |
| // returns 50, 51, 52 if open_socket() fails | // returns 50, 51, 52 if open_socket() fails |
| // returns 10, 11, 12, 13, 14, 15 if any get_line()'s fail | // returns 10, 11, 12, 13, 14, 15 if any get_line()'s fail |
| void SMTP:: | void SMTP:: |
| prepare_message(char *from, char *to, const char *server, const char *service) | prepare_message(char *from, char *to, const char* server, const char* service) |
| { | { |
| char out_data[MAXOUTLINE]; | char out_data[MAXOUTLINE]; |
| char *ptr; | char *ptr; |
| Line 465 prepare_message(char *from, char *to, co | Line 458 prepare_message(char *from, char *to, co |
| if( 250 != get_line() ) | if( 250 != get_line() ) |
| throw Exception("smtp.execute", | throw Exception("smtp.execute", |
| &origin_string, | origin_string, |
| "The mail server doesn't like the name %s. Have you set the 'To: ' field correctly?", | "The mail server doesn't like the name %s. Have you set the 'To: ' field correctly?", |
| ptr); | ptr); |
| Line 508 static char *rsplit(char *string, char d | Line 501 static char *rsplit(char *string, char d |
| // returns 1 if MakeSmtpHeader() fails | // returns 1 if MakeSmtpHeader() fails |
| // returns 10, 11, 12, 13, 14, 15, 50, 51, 52 if prepare_message() fails | // returns 10, 11, 12, 13, 14, 15, 50, 51, 52 if prepare_message() fails |
| void SMTP:: | void SMTP:: |
| Send(const char *server, const char *service, const char *msg, char *from, char *to) | Send(const char* server, const char* service, const char* msg, char *from, char *to) |
| { | { |
| #ifdef DEBUG_SHOW | |
| throw Exception("paf.debug",0,"from=%s|to=%s|msg=%s", from,to,msg); | |
| #endif | |
| prepare_message( from, to, server, service); | prepare_message( from, to, server, service); |
| send_data(msg); | send_data(msg); |