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 + -
显示快捷键?