version 1.1.1.1.2.1, 2013/07/22 00:39:41
|
version 1.1.1.1.2.2, 2016/10/18 13:48:41
|
Line 1
|
Line 1
|
/* mini_sendmail - accept email on behalf of real sendmail |
/* mini_sendmail - accept email on behalf of real sendmail |
** |
** |
** Copyright © 1999 by Jef Poskanzer <jef@mail.acme.com>. | ** Copyright © 1999,2015 by Jef Poskanzer <jef@mail.acme.com>. |
** All rights reserved. |
** All rights reserved. |
** |
** |
** Redistribution and use in source and binary forms, with or without |
** Redistribution and use in source and binary forms, with or without |
Line 44
|
Line 44
|
#include <sys/types.h> |
#include <sys/types.h> |
#include <sys/socket.h> |
#include <sys/socket.h> |
#include <netinet/in.h> |
#include <netinet/in.h> |
|
#include <arpa/inet.h> |
#include <netdb.h> |
#include <netdb.h> |
|
|
#ifdef DO_RECEIVED |
#ifdef DO_RECEIVED |
Line 93 static void sigcatch( int sig );
|
Line 94 static void sigcatch( int sig );
|
static void show_error( char* cause ); |
static void show_error( char* cause ); |
|
|
|
|
|
/* Do overlapping strcpy safely, by using memmove. */ |
|
#define ol_strcpy(dst,src) memmove(dst,src,strlen(src)+1) |
|
|
|
|
int |
int |
main( int argc, char** argv ) |
main( int argc, char** argv ) |
{ |
{ |
Line 175 main( int argc, char** argv )
|
Line 180 main( int argc, char** argv )
|
|
|
/* Strip off any angle brackets in the from address. */ |
/* Strip off any angle brackets in the from address. */ |
while ( from[0] == '<' ) |
while ( from[0] == '<' ) |
(void) strcpy( from, &from[1] ); | (void) ol_strcpy( from, &from[1] ); |
while ( from[strlen(from)-1] == '>' ) |
while ( from[strlen(from)-1] == '>' ) |
from[strlen(from)-1] = '\0'; |
from[strlen(from)-1] = '\0'; |
|
|
Line 349 make_received( char* from, char* username, char* hostn
|
Line 354 make_received( char* from, char* username, char* hostn
|
tmP = localtime( &t ); |
tmP = localtime( &t ); |
(void) strftime( timestamp, sizeof(timestamp), "%a, %d %b %Y %T %Z", tmP ); |
(void) strftime( timestamp, sizeof(timestamp), "%a, %d %b %Y %T %Z", tmP ); |
received_size = |
received_size = |
500 + strlen( from ) + strlen( hostname ) * 2 + strlen( VERSION ) + | 500 + strlen( from ) + strlen( hostname ) * 2 + strlen( MINI_SENDMAIL_VERSION ) + |
strlen( timestamp ) + strlen( username ); |
strlen( timestamp ) + strlen( username ); |
received = (char*) malloc( received_size ); |
received = (char*) malloc( received_size ); |
if ( received == (char*) 0 ) |
if ( received == (char*) 0 ) |
Line 360 make_received( char* from, char* username, char* hostn
|
Line 365 make_received( char* from, char* username, char* hostn
|
(void) snprintf( |
(void) snprintf( |
received, received_size, |
received, received_size, |
"Received: (from %s)\n\tby %s (%s);\n\t%s\n\t(sender %s@%s)\n", |
"Received: (from %s)\n\tby %s (%s);\n\t%s\n\t(sender %s@%s)\n", |
from, hostname, VERSION, timestamp, username, hostname ); | from, hostname, MINI_SENDMAIL_VERSION, timestamp, username, hostname ); |
return received; |
return received; |
} |
} |
#endif /* DO_RECEIVED */ |
#endif /* DO_RECEIVED */ |
Line 383 parse_for_recipients( char* message )
|
Line 388 parse_for_recipients( char* message )
|
#define ST_RECIPS 7 |
#define ST_RECIPS 7 |
char* cp; |
char* cp; |
char* bcc; |
char* bcc; |
char* recip; | char* recip = (char*) 0; |
|
|
state = ST_BOL; |
state = ST_BOL; |
bcc = (char*) 0; |
bcc = (char*) 0; |
Line 512 parse_for_recipients( char* message )
|
Line 517 parse_for_recipients( char* message )
|
if ( bcc != (char*) 0 ) |
if ( bcc != (char*) 0 ) |
{ |
{ |
/* Elide the Bcc: line, and reset cp. */ |
/* Elide the Bcc: line, and reset cp. */ |
(void) strcpy( bcc, cp + 1 ); | (void) ol_strcpy( bcc, cp + 1 ); |
cp = bcc - 1; |
cp = bcc - 1; |
bcc = (char*) 0; |
bcc = (char*) 0; |
} |
} |
Line 542 add_recipient( char* recipient, int len )
|
Line 547 add_recipient( char* recipient, int len )
|
} |
} |
|
|
/* Strip off any angle brackets. */ |
/* Strip off any angle brackets. */ |
|
/* |
while ( len > 0 && *recipient == '<' ) |
while ( len > 0 && *recipient == '<' ) |
{ |
{ |
++recipient; |
++recipient; |
Line 551 add_recipient( char* recipient, int len )
|
Line 557 add_recipient( char* recipient, int len )
|
--len; |
--len; |
|
|
(void) snprintf( buf, sizeof(buf), "RCPT TO:<%.*s>", len, recipient ); |
(void) snprintf( buf, sizeof(buf), "RCPT TO:<%.*s>", len, recipient ); |
|
*/ |
|
if (len > 0 && recipient[len-1] == '>' ) |
|
{ |
|
/* "<name@domain>" or: "Full Name <name@domain>" */ |
|
while (len > 0 && *recipient != '<' ) |
|
{ |
|
++recipient; |
|
--len; |
|
} |
|
(void) snprintf( buf, sizeof(buf), "RCPT TO:%.*s", len, recipient ); |
|
} |
|
else |
|
{ |
|
/* name@domain */ |
|
(void) snprintf( buf, sizeof(buf), "RCPT TO:<%.*s>", len, recipient ); |
|
} |
|
|
send_command( buf ); |
send_command( buf ); |
status = read_response(); |
status = read_response(); |
if ( status != 250 && status != 251 ) |
if ( status != 250 && status != 251 ) |
Line 572 static int
|
Line 595 static int
|
open_client_socket( void ) |
open_client_socket( void ) |
{ |
{ |
#ifdef USE_IPV6 |
#ifdef USE_IPV6 |
struct sockaddr_in6 sa; | struct sockaddr_in6 sa_in; |
#else /* USE_IPV6 */ |
#else /* USE_IPV6 */ |
struct sockaddr_in sa; | struct sockaddr_in sa_in; |
#endif /* USE_IPV6 */ |
#endif /* USE_IPV6 */ |
int sa_len, sock_family, sock_type, sock_protocol; |
int sa_len, sock_family, sock_type, sock_protocol; |
int sockfd; |
int sockfd; |
|
|
sock_type = SOCK_STREAM; |
sock_type = SOCK_STREAM; |
sock_protocol = 0; |
sock_protocol = 0; |
sa_len = sizeof(sa); | sa_len = sizeof(sa_in); |
(void) memset( (void*) &sa, 0, sa_len ); | (void) memset( (void*) &sa_in, 0, sa_len ); |
|
|
#ifdef USE_IPV6 |
#ifdef USE_IPV6 |
|
|
{ |
{ |
#ifdef DO_MINUS_SP |
#ifdef DO_MINUS_SP |
struct sockaddr_in sa4; | struct sockaddr_in sa_in4; |
struct addrinfo hints; |
struct addrinfo hints; |
char portstr[10]; |
char portstr[10]; |
int gaierr; |
int gaierr; |
Line 601 open_client_socket( void )
|
Line 624 open_client_socket( void )
|
sock_family = PF_INET6; |
sock_family = PF_INET6; |
|
|
#ifdef DO_MINUS_SP |
#ifdef DO_MINUS_SP |
(void) memset( (void*) &sa4, 0, sizeof(sa4) ); | (void) memset( (void*) &sa_in4, 0, sizeof(sa_in4) ); |
if ( inet_pton( AF_INET, server, (void*) &sa4.sin_addr ) == 1 ) | if ( inet_pton( AF_INET, server, (void*) &sa_in4.sin_addr ) == 1 ) |
{ |
{ |
sock_family = PF_INET; |
sock_family = PF_INET; |
sa4.sin_port = htons( port ); | sa_in4.sin_port = htons( port ); |
sa_len = sizeof(sa4); | sa_len = sizeof(sa_in4); |
(void) memmove( &sa, &sa4, sa_len ); | (void) memmove( &sa_in, &sa_in4, sa_len ); |
} |
} |
else if ( inet_pton( AF_INET6, server, (void*) &sa.sin6_addr ) != 1 ) | else if ( inet_pton( AF_INET6, server, (void*) &sa_in.sin6_addr ) != 1 ) |
{ |
{ |
#ifdef DO_DNS |
#ifdef DO_DNS |
(void) memset( &hints, 0, sizeof(hints) ); |
(void) memset( &hints, 0, sizeof(hints) ); |
Line 645 open_client_socket( void )
|
Line 668 open_client_socket( void )
|
/* If there's an IPv4 address, use that, otherwise try IPv6. */ |
/* If there's an IPv4 address, use that, otherwise try IPv6. */ |
if ( aiv4 != (struct addrinfo*) 0 ) |
if ( aiv4 != (struct addrinfo*) 0 ) |
{ |
{ |
if ( sizeof(sa) < aiv4->ai_addrlen ) | if ( sizeof(sa_in) < aiv4->ai_addrlen ) |
{ |
{ |
(void) fprintf( |
(void) fprintf( |
stderr, "%s - sockaddr too small (%lu < %lu)\n", |
stderr, "%s - sockaddr too small (%lu < %lu)\n", |
server, (unsigned long) sizeof(sa), | server, (unsigned long) sizeof(sa_in), |
(unsigned long) aiv4->ai_addrlen ); |
(unsigned long) aiv4->ai_addrlen ); |
exit( 1 ); |
exit( 1 ); |
} |
} |
Line 657 open_client_socket( void )
|
Line 680 open_client_socket( void )
|
sock_type = aiv4->ai_socktype; |
sock_type = aiv4->ai_socktype; |
sock_protocol = aiv4->ai_protocol; |
sock_protocol = aiv4->ai_protocol; |
sa_len = aiv4->ai_addrlen; |
sa_len = aiv4->ai_addrlen; |
(void) memmove( &sa, aiv4->ai_addr, sa_len ); | (void) memmove( &sa_in, aiv4->ai_addr, sa_len ); |
goto ok; |
goto ok; |
} |
} |
if ( aiv6 != (struct addrinfo*) 0 ) |
if ( aiv6 != (struct addrinfo*) 0 ) |
{ |
{ |
if ( sizeof(sa) < aiv6->ai_addrlen ) | if ( sizeof(sa_in) < aiv6->ai_addrlen ) |
{ |
{ |
(void) fprintf( |
(void) fprintf( |
stderr, "%s - sockaddr too small (%lu < %lu)\n", |
stderr, "%s - sockaddr too small (%lu < %lu)\n", |
server, (unsigned long) sizeof(sa), | server, (unsigned long) sizeof(sa_in), |
(unsigned long) aiv6->ai_addrlen ); |
(unsigned long) aiv6->ai_addrlen ); |
exit( 1 ); |
exit( 1 ); |
} |
} |
Line 674 open_client_socket( void )
|
Line 697 open_client_socket( void )
|
sock_type = aiv6->ai_socktype; |
sock_type = aiv6->ai_socktype; |
sock_protocol = aiv6->ai_protocol; |
sock_protocol = aiv6->ai_protocol; |
sa_len = aiv6->ai_addrlen; |
sa_len = aiv6->ai_addrlen; |
(void) memmove( &sa, aiv6->ai_addr, sa_len ); | (void) memmove( &sa_in, aiv6->ai_addr, sa_len ); |
goto ok; |
goto ok; |
} |
} |
|
|
Line 691 open_client_socket( void )
|
Line 714 open_client_socket( void )
|
#endif /* DO_DNS */ |
#endif /* DO_DNS */ |
} |
} |
#else /* DO_MINUS_SP */ |
#else /* DO_MINUS_SP */ |
sa.sin6_addr = in6addr_any; | sa_in.sin6_addr = in6addr_any; |
sa.sin6_port = htons( SMTP_PORT ); | sa_in.sin6_port = htons( SMTP_PORT ); |
#endif /* DO_MINUS_SP */ |
#endif /* DO_MINUS_SP */ |
|
|
sa.sin6_family = sock_family; | sa_in.sin6_family = sock_family; |
|
|
} |
} |
|
|
Line 711 open_client_socket( void )
|
Line 734 open_client_socket( void )
|
sock_family = PF_INET; |
sock_family = PF_INET; |
|
|
#ifdef DO_MINUS_SP |
#ifdef DO_MINUS_SP |
sa.sin_addr.s_addr = inet_addr( server ); | sa_in.sin_addr.s_addr = inet_addr( server ); |
sa.sin_port = htons( port ); | sa_in.sin_port = htons( port ); |
if ( (int32_t) sa.sin_addr.s_addr == -1 ) | if ( (int32_t) sa_in.sin_addr.s_addr == -1 ) |
{ |
{ |
#ifdef DO_DNS |
#ifdef DO_DNS |
he = gethostbyname( server ); |
he = gethostbyname( server ); |
Line 725 open_client_socket( void )
|
Line 748 open_client_socket( void )
|
exit( 1 ); |
exit( 1 ); |
} |
} |
sock_family = he->h_addrtype; |
sock_family = he->h_addrtype; |
(void) memmove( &sa.sin_addr, he->h_addr, he->h_length ); | (void) memmove( &sa_in.sin_addr, he->h_addr, he->h_length ); |
#else /* DO_DNS */ |
#else /* DO_DNS */ |
(void) fprintf( |
(void) fprintf( |
stderr, "%s: bad server IP address %s\n", argv0, server ); |
stderr, "%s: bad server IP address %s\n", argv0, server ); |
Line 733 open_client_socket( void )
|
Line 756 open_client_socket( void )
|
#endif /* DO_DNS */ |
#endif /* DO_DNS */ |
} |
} |
#else /* DO_MINUS_SP */ |
#else /* DO_MINUS_SP */ |
(void) memmove( &sa.sin_addr, local_addr, sizeof(local_addr) ); | (void) memmove( &sa_in.sin_addr, local_addr, sizeof(local_addr) ); |
sa.sin_port = htons( SMTP_PORT ); | sa_in.sin_port = htons( SMTP_PORT ); |
#endif /* DO_MINUS_SP */ |
#endif /* DO_MINUS_SP */ |
|
|
sa.sin_family = sock_family; | sa_in.sin_family = sock_family; |
} |
} |
|
|
#endif /* USE_IPV6 */ |
#endif /* USE_IPV6 */ |
Line 746 open_client_socket( void )
|
Line 769 open_client_socket( void )
|
if ( sockfd < 0 ) |
if ( sockfd < 0 ) |
show_error( "socket" ); |
show_error( "socket" ); |
|
|
if ( connect( sockfd, (struct sockaddr*) &sa, sa_len ) < 0 ) | if ( connect( sockfd, (struct sockaddr*) &sa_in, sa_len ) < 0 ) |
show_error( "connect" ); |
show_error( "connect" ); |
|
|
return sockfd; |
return sockfd; |