sendmail.c

来自「在linux系统下发送email 程序。」· C语言 代码 · 共 300 行

C
300
字号
/********************
一般来说就是socket通讯的问题:   
  要确认邮件服务器是否需要密码验证   
  1、首先连接邮件服务器的25端口   
  2、发送EHLO到该连接,并检查返回。   
  3、根据服务器类型选择是否发送AUTH   LOGIN。   
  4、发送MAIL   FROM   与发送方地址并检查返回。   
  5、发送RCPT   TO与接收方地址并检查返回。   
  6、发送DATA与正文。   
  具体命令及返回信息可看有关smtp协议的资料。   
  如果手头有smtp服务器可telnet   xxx.xxx.xx.xxx   25到该服务器上试验。   
************************/

#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <netdb.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <string.h>
#include <sys/ioctl.h>
#include <errno.h>
#include <ctype.h>
#include <time.h>


#include <string.h>



#define		MAIL_WELCOME		220		//连接服务器,响应成功
#define		MAIL_OK				250		//mail from: rcpt to : 等命令发送,响应成功。
#define 	MAIL_GO_AHEAD		354		//准备发送数据data命令,响应成功。
#define 	MAIL_GOODBYE		221		//关闭连接,响应成功。
#define SMTP_PORT 	25
#define BUFSIZE 	4096
#define ERROR -1
#define 	Debug
#define TRUE 	1
#define AUTH_LOGIN 8
#define E_NO_SOCKET_CONN -1
#define E_PROTOCOL_ERROR -2 
void to64frombits(unsigned char *out, const unsigned char *in,int inlen)
{
	const char base64digits[]=
		"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
		
	for(;inlen >=3;inlen -=3)
	{
		*out++ = base64digits[in[0]>>2];
		*out++ = base64digits[(( in[0]<<4) & 0x30 ) | ( in[1]>>4 )];
		*out++ = base64digits[(( in[1]<<2) & 0x3c) | ( in[2]>>6)];
		*out++ = base64digits[in[2]&0x3f];
		in+=3;
	}
	
	if( inlen > 0 )
	{
		unsigned char fragment;
		
		*out++ = base64digits[in[0]>>2];
		fragment=(in[0] <<4)&0x30;
		if(inlen > 1)
			fragment |=in[1]>>4;
		*out++ = base64digits[fragment];
		*out++ = (inlen<2) ? '=' : base64digits[(in[1]<<2)&0x3c];
		*out++ = '=';
	}
	*out = '\0';
}


int connect_to_server(const char *server)
{
	struct hostent *host;
	struct in_addr inp;
	struct protoent *proto;
	struct sockaddr_in sa;
	int n_sock;
	char s_buf[BUFSIZE]="";
	int n_ret;
	
#if 1	
	host=gethostbyname(server);
	if(host ==  NULL)
	{
		fprintf(stderr,"could not resolve hostname %s .aborting .... \n",server);
			return ERROR;
	}
#else
	int num=0;
	while ((host=gethostbyname(server)) == NULL)
	{
		usleep(100);
		if(num++>15)
			break;
	}
	printf("num = %d \n",num);
	if(num> 15)
	{
		fprintf(stderr,"could not resolve hostname %s .aborting .... \n",server);
		return ERROR;
	}
#endif
	#ifdef Debug
		printf("connect_to_server() fun: server host name : %s\n",host->h_name);
	#endif
	
	memcpy(&inp,host->h_addr_list[0],host->h_length);
	
	if((proto=getprotobyname("tcp")) == NULL)
	{
		fprintf(stderr,"Could not get the protocol for TCP. Aborting ... \n");
		return ERROR;
	}
	
	#ifdef Debug
		printf("connect_to_server(): proto name : %s \n",proto->p_name);
	#endif
	
	//if((n_sock = socket(PF_INET,SOCK_STREAM,proto->p_proto)) == -1)
	if((n_sock = socket(AF_INET,SOCK_STREAM,proto->p_proto)) == -1)
	{
		fprintf(stderr,"Could not create a TCP socket. Aborting... \n");
		return ERROR;
	}
	printf("	n_sock = %d \n",n_sock);
	memset(&sa,0,sizeof(sa));
	sa.sin_addr=inp;
	sa.sin_family=host->h_addrtype;
	sa.sin_port=htons(SMTP_PORT);
	if(connect(n_sock,(struct sockaddr *) &sa,sizeof(sa)) == -1)
	{
		fprintf(stderr,"Connect refused by host %s .\n",server);
		return ERROR;
	}
	n_ret=recv(n_sock,s_buf,BUFSIZE,0);
	#ifdef Debug
		printf("connect_to_server(): %s \n",s_buf);
		printf("connect_to_server() %s success !\n",server);
	#endif
	
	return n_sock;	
}
int send_command(int n_sock,const char *prefix,const char *cmd, const char *suffix,
					int ret_code)
{
	#define BUFSIZE 4096
	char s_buf[BUFSIZE]="";
	char s_buf2[50];
	
	strncpy(s_buf,prefix,BUFSIZE);
	strncat(s_buf,cmd,BUFSIZE);
	strncat(s_buf,suffix,BUFSIZE);
	
	#ifdef Debug
		printf("send_commadn(): command = %s \n",s_buf);
	#endif
	if(send(n_sock,s_buf,strlen(s_buf),0) == -1)
	{
		fprintf(stderr,"Could not send command string %s to server.",s_buf);
		return ERROR;
	}
	recv(n_sock,s_buf,BUFSIZE,0);
	#ifdef Debug
		printf("send command (): recv = %s \n\n",s_buf);
	#endif
	
	sprintf(s_buf2,"%d",ret_code);
	if(strstr(s_buf,s_buf2) !=NULL)
		return TRUE;
	else
		return ERROR;
		
}
#define BUFSIZE 	4096
#define BUFSIZE2 	100
#define MSG_TERM 	"\r\n.\r\n"
#define MAIL_AGENT 	" This is a test mail!"

int send_mail_message(int n_sock,const char *from,const char *to, const char *subject,
						const char *replyto,const char *msg)
{
	char s_buf[BUFSIZE];
	char s_buf2[BUFSIZE2];
	int n_ret;
	
	time_t t_now=time(NULL);
	// strftime( tmpbuf, 128, "Today is %A, day %d of %B in the year %Y.\n", newtime);
	strftime(s_buf2,BUFSIZE2,"%A,%d %B  %Y %H : %M: %S +0000",localtime(&t_now));
	snprintf(s_buf,BUFSIZE,"Date: %s\r\nFrom: %s\r\nTo: %s \r\nSubject: %s\r\nX-Mailer: %s\r\nReply_To : %s \r\n\r\n",s_buf2,from,to,subject,MAIL_AGENT,replyto);
			
	if(send(n_sock,s_buf,strlen(s_buf),0) ==  -1)
	{
		fprintf(stderr,"Could not send message header : %s",s_buf);
		return ERROR;
	}
	#ifdef Debug
		printf("send_mail_message s_buf = %s \n",s_buf);
	#endif
	
	if(send(n_sock,msg,strlen(msg),0) ==-1)
	{
		fprintf(stderr,"Could not send the message %s \n",msg);
		return ERROR;
	}
	
	#ifdef Debug
		printf("send_mail_message msg = %s \n",msg);
	#endif
	if(send(n_sock,MSG_TERM,strlen(MSG_TERM),0) == -1)
	{
		fprintf(stderr,"Could not send the message terminator %s. \n",msg);
		return ERROR;
	}
	#ifdef Debug
		printf("send_mail_message MSG_TERM = %s \n",MSG_TERM);
	#endif
	
	n_ret=recv(n_sock,s_buf,BUFSIZE,0);
	#ifdef Debug
		printf("recv s_buf = %s \n",s_buf);
	#endif
	
	printf("run ok. \n");
	return TRUE;
}

int send_mail(const char *smtpserver,const char *from,const char *to,const char *subject,
				const char *replyto, const char *msg, char *user,char *pass)
{
	int n_socket;
	int n_retval=0;
	char user_base64[50];
	char pass_base64[50];
	#ifdef WIN32
		startup_sockets_lib();
	#endif
	
	#ifdef Debug
		printf("user = %s \n",user);
		printf("pass =  %s \n",pass);
		printf("n= %d \n",strlen(user));
	#endif
	
	to64frombits(user_base64,user,strlen(user));
	to64frombits(pass_base64,pass,strlen(pass));
	
	if((n_socket = connect_to_server(smtpserver )) == ERROR)
		n_retval=E_NO_SOCKET_CONN;			//HELO
	if(n_retval == 0 && send_command(n_socket,"EHLO ",smtpserver,"\r\n",MAIL_OK) == ERROR)
		n_retval=E_PROTOCOL_ERROR;
/*
	if(n_retval == 0 && send_command(n_socket,"","AUTH_LOGIN","\r\n",334) == ERROR)
		n_retval=-1;

	if(n_retval == 0 && send_command(n_socket,"",user_base64,"\r\n",334) == ERROR)
		n_retval=-1;

	if(n_retval == 0 && send_command(n_socket,"",pass_base64,"\r\n",235) == ERROR)
		n_retval=-1;
*/
	if(n_retval == 0 && send_command(n_socket,"MAIL From:<",from,">\r\n",MAIL_OK) == ERROR)
		n_retval=E_PROTOCOL_ERROR;

	if(n_retval == 0 && send_command(n_socket,"RCPT to:<",to,">\r\n",MAIL_OK) == ERROR)
		n_retval=E_PROTOCOL_ERROR;

	if(n_retval == 0 && send_command(n_socket,"","DATA","\r\n",MAIL_GO_AHEAD) == ERROR)
		n_retval=E_PROTOCOL_ERROR;

	if(n_retval == 0 && send_mail_message(n_socket,from,to,subject,replyto,msg) == ERROR)
		n_retval=E_PROTOCOL_ERROR;

	if(n_retval == 0 && send_command(n_socket,"","QUIT","\r\n",MAIL_GOODBYE) == ERROR)
		n_retval=E_PROTOCOL_ERROR;

	if(close(n_socket) == ERROR)
	{
		fprintf(stderr,"could not close socket.\n");
		n_retval = ERROR;
	}
	
	#ifdef WIN32
		cleanup_sockets_lib();
	#endif
	
	return n_retval;
}
int 
main( void )
{
	send_mail("localhost","root@localhost.localdomain","root@localhost.localdomain","Test","","This is test mail .","","");
	//send_mail("stmp.163.com","bhw1996@163.com","bhw1996@126.com","Test","","This is test mail .","bhw1996","bhwbhd");
	exit(0);
}

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?