#include "popeml.h"
void SetSocketConnect(char *server,int *sockfd)
{
int nREUSEADDR = 1; //socket可重用
char IPaddr[24];
struct hostent *hp = NULL;
struct sockaddr_in addr;
hp = gethostbyname(server);
if( hp != NULL )
{
sprintf(IPaddr,"%d.%d.%d.%d",
(hp->h_addr_list[0][0]&0x00ff),
(hp->h_addr_list[0][1]&0x00ff),
(hp->h_addr_list[0][2]&0x00ff),
(hp->h_addr_list[0][3]&0x00ff));
}
#ifdef DEBUG_LOG
printf("Get IP Addr: %s\n ", IPaddr );
#endif
memset(&addr, 0, sizeof(addr));
addr.sin_family = AF_INET;
addr.sin_port = htons(110);
addr.sin_addr.s_addr = inet_addr(IPaddr);
*sockfd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if (*sockfd < 0) {
printf("socket error!");
exit(1);
}
setsockopt(*sockfd,SOL_SOCKET,SO_REUSEADDR,(const char*)&nREUSEADDR,sizeof(int));
if(connect(*sockfd, (struct sockaddr *) &addr,sizeof(addr)) < 0 ){
printf("connect error!\n");
exit(1);
}
memset(recvbuf,0x0,BUFFLEN);
while ( read(*sockfd, recvbuf, BUFFLEN) == 0)
{
printf("reconnect...\n");
sleep(1);
close(*sockfd);
*sockfd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if (*sockfd < 0){
printf("resocket wrong!\n");
continue;
}
setsockopt(*sockfd,SOL_SOCKET,SO_REUSEADDR,(const char*)&nREUSEADDR,sizeof(int));
if(connect(*sockfd, (struct sockaddr *) &addr,sizeof(addr)) < 0 ){
printf("reconnect error!\n");
continue; ;
}
memset(recvbuf, 0, BUFFLEN);
}
#ifdef DEBUG_LOG
printf("recv :%s \n",recvbuf);
#endif
return ;
}
int send_recv_function(int sc,char *s,char *r)
{
if (send(sc, s, strlen(s), 0) < 0)
{
printf(" send %s error!\n",s);
return -1;
}
sleep(1);
memset(r, 0, BUFFLEN);
if (read(sc, r, BUFFLEN) < 0)
{
printf(" read [send]%s error!\n",s);
return -1;
}
else
{
#ifdef DEBUG_LOG
printf("send:%s recv :%s \n",s,r);
#endif
}
return 0;
}
int send_recv_function2(int sc,char *s,char *maxr)
{
if (send(sc, s, strlen(s), 0) < 0)
{
printf(" send %s error!\n",s);
return -1;
}
sleep(1);
memset(maxr, 0, MAXBUFF);
if (read(sc, maxr, MAXBUFF) < 0)
{
printf(" read [send]%s error!\n",s);
return -1;
}
else
{
#ifdef DEBUG_LOG
printf("send:%s recv :%s \n",s,maxr);
#endif
}
return 0;
}
void Dfree_mes_list(struct _message_list *msl)
{
struct _message_list *p ,*q;
p = msl;
while(p)
{
q = p->next;
free(p);
p = q;
}
return ;
}
void Show_mes_list(struct _message_list *msl)
{
int i = 0;
struct _message_list *p ;
p = msl;
while(p)
{
printf("[%d] mid :%d ,size:%d .\n",i,p->mid,p->msize);
p = p->next;
i++;
}
return ;
}
void get_message_num(char *s,int *num)
{
char buff[10];
char *p ,*q;
p = q = NULL;
memset(buff,0x0,10);
p = strstr(s,"has");
q = strstr(s,"messages");
if (q && p)
{
*q-- = '\0';
strcpy(buff,p+4);
*num = atoi(buff);
printf("List %d messages \n",*num);
}
else{
printf("List messages num error \n");
}
return;
}
int get_message_list(message_s *msl,char *buff,int emlsum)
{
char *p;
char id[10];
char msize[10];
int i;
int flag;
message_s *q;
i = flag = 0;
/*init message list*/
q = msl;
while(emlsum)
{
q->flag=0;
q->next = (message_s *)calloc(1,sizeof(message_s));
if (!q){
return -1;
}
q = q->next;
emlsum--;
}
/*get eml list*/
p = buff;
while((*p != '\0')&&(*p != 0x2e))
{
if ((*p == 0x20)&&(i != 0)){
id[i] = '\0';
msl->mid = atoi(id);
i = 0;
p++;
flag = 1;
continue;
}
if (*p == 0x0d){
msize[i] = '\0';
msl->msize = atoi(msize);
i =0;
p++;
flag = 0;
msl = msl->next ;
continue;
}
if ((*p >= 0x30) && (*p <= 0x39))
{
if (flag == 0)
id[i] = *p;
else
msize[i] = *p;
i++;
/*#ifdef DEBUG_LOG
printf("%02x",*p);
#endif*/
}
/*#ifdef DEBUG_LOG
if (*p == 0x0a) printf("\n\n");
#endif*/
p ++;
}
return 0;
}
static void error_write_eml(FILE *fp, char *fname)
{
fclose(fp);
fp = NULL;
remove(fname);
return;
}
int write_eml (int id,int size,int *flag,char *fname,int sockfd)
{
int rsize;
int tmpsize;
char *p = NULL;
char *q = NULL;
FILE *fp = NULL;
char tmpstr[48];
snprintf(tmpstr,48,"+OK %d octets\r\n",size);
tmpsize = strlen(tmpstr);
fp = fopen(fname,"w+");
if(!fp)
{
printf("fopen %s failed , because %s.\n",fname,strerror(errno));
return -1;
}
snprintf(sendbuf,BUFFLEN,"retr %d\r\n",id);
if (send(sockfd, sendbuf, strlen(sendbuf), 0) < 0)
{
printf(" send %s error!\n",sendbuf);
return -1;
}
while(1)
{
rsize = 0;
memset(recvbuf,0x0,BUFFLEN);
if ( (rsize = read(sockfd,recvbuf,BUFFLEN)) > 0)
{
#ifdef DEBUG_LOG
printf("%s",recvbuf);
#endif
if (rsize < 10)
break;
if(strstr(recvbuf,"error code")) {
error_write_eml(fp,fname);
break;
}
if ((q = strstr(recvbuf,tmpstr)) != NULL)
{
rsize = strlen(q);
fwrite(q+tmpsize+1,1,rsize,fp);
}
else if (( p = strstr(recvbuf,"\r\n.\r\n")) != NULL)
{
*(p+2) = '\0';
rsize = strlen(recvbuf);
fwrite(recvbuf,1,rsize,fp);
fclose(fp);
*flag = 1;
break;
}
else
fwrite(recvbuf,1,rsize,fp);
}
else if (rsize == 0)
{
error_write_eml(fp,fname);
close(sockfd);
exit(-1);
}
else //rsize < 0
{
if(errno != EINTR && errno != EWOULDBLOCK && errno != EAGAIN){
error_write_eml(fp,fname);
fprintf(stderr,"socket error errno=%d ,%s",errno,strerror(errno));
int j ;
for(j=1;j<=id;j++) {
snprintf(sendbuf,BUFFLEN,"dele %d\r\n",j);
send_recv_function(sockfd,sendbuf,recvbuf);
}
snprintf(sendbuf,BUFFLEN,"%s\r\n","QUIT");
send_recv_function(sockfd,sendbuf,recvbuf);
exit(1);
}
else if((errno == EINTR || errno == EWOULDBLOCK || errno == EAGAIN)) {
printf("errno %d error:%s\n",errno,strerror(errno));
continue;
sleep(1);
}
}
}
return 0;
}
int download_eml(message_s *msl,int sockfd,char *dir)
{
char fname[512];
struct _message_list *p,*q ;
time_t tNow;
struct tm tmNow;
char dirname[256];
time(&tNow);
localtime_r(&tNow, &tmNow);
snprintf(dirname,256,"%s/%04d%02d%02d/dyn_10/key_%02d%02d",dir,
(1900+tmNow.tm_year),(1+tmNow.tm_mon),tmNow.tm_mday,tmNow.tm_hour,tmNow.tm_min);
if(access(dirname,0 ) != 0)
{
umask(0);
mkdir(dirname,0777);
}
#ifdef DEBUG_LOG
printf("maildata path %s\n",dirname);
#endif
q = p = msl->next;//第一行为邮件列表总数
while(p)
{
memset(fname,0x0,512);
snprintf(fname,512,"%s/%ld.%d.eml",dirname,time(NULL),p->mid);
write_eml(p->mid,p->msize,&(p->flag),fname,sockfd);
p = p->next;
}
while(q)
{
if (q->flag)
{
snprintf(sendbuf,BUFFLEN,"dele %d\r\n",q->mid);
send_recv_function(sockfd,sendbuf,recvbuf);
}
q = q->next;
}
return 0;
}
int pop_eml_down(char *server,char *usr,char *pwd,char *path)
{
int messageNum = 0;
int sockfd = -1;
struct _message_list *msl ;
msl = NULL;
msl = (message_s*)calloc(1,sizeof(message_s));
//msl = (message_s *)malloc(sizeof(message_s));
if (!msl){
return -1;
}
/*create socket and connect*/
SetSocketConnect(server,&sockfd);
/*auth login */
memset(sendbuf,0,BUFFLEN);
memset(recvbuf,0x0,BUFFLEN);
snprintf(sendbuf,BUFFLEN,"%s\r\n",usr);
send_recv_function(sockfd,sendbuf,recvbuf);
snprintf(sendbuf,BUFFLEN,"%s\r\n",pwd);
send_recv_function(sockfd,sendbuf,recvbuf);
get_message_num(recvbuf,&messageNum);
if (messageNum == 0)
goto END_POP_EML_DOWN;
snprintf(sendbuf,BUFFLEN,"%s\r\n","list");
send_recv_function2(sockfd,sendbuf,maxrecvbuf);
/*eml list*/
get_message_list(msl,maxrecvbuf,messageNum);
//Show_mes_list(msl);
/*pop eml*/
download_eml(msl,sockfd,path);
snprintf(sendbuf,BUFFLEN,"%s\r\n","QUIT");
send_recv_function(sockfd,sendbuf,recvbuf);
END_POP_EML_DOWN:
if (sockfd > 0) close(sockfd);
Dfree_mes_list(msl) ;
return 0;
}
void SetSocketConnect(char *server,int *sockfd)
{
int nREUSEADDR = 1; //socket可重用
char IPaddr[24];
struct hostent *hp = NULL;
struct sockaddr_in addr;
hp = gethostbyname(server);
if( hp != NULL )
{
sprintf(IPaddr,"%d.%d.%d.%d",
(hp->h_addr_list[0][0]&0x00ff),
(hp->h_addr_list[0][1]&0x00ff),
(hp->h_addr_list[0][2]&0x00ff),
(hp->h_addr_list[0][3]&0x00ff));
}
#ifdef DEBUG_LOG
printf("Get IP Addr: %s\n ", IPaddr );
#endif
memset(&addr, 0, sizeof(addr));
addr.sin_family = AF_INET;
addr.sin_port = htons(110);
addr.sin_addr.s_addr = inet_addr(IPaddr);
*sockfd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if (*sockfd < 0) {
printf("socket error!");
exit(1);
}
setsockopt(*sockfd,SOL_SOCKET,SO_REUSEADDR,(const char*)&nREUSEADDR,sizeof(int));
if(connect(*sockfd, (struct sockaddr *) &addr,sizeof(addr)) < 0 ){
printf("connect error!\n");
exit(1);
}
memset(recvbuf,0x0,BUFFLEN);
while ( read(*sockfd, recvbuf, BUFFLEN) == 0)
{
printf("reconnect...\n");
sleep(1);
close(*sockfd);
*sockfd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if (*sockfd < 0){
printf("resocket wrong!\n");
continue;
}
setsockopt(*sockfd,SOL_SOCKET,SO_REUSEADDR,(const char*)&nREUSEADDR,sizeof(int));
if(connect(*sockfd, (struct sockaddr *) &addr,sizeof(addr)) < 0 ){
printf("reconnect error!\n");
continue; ;
}
memset(recvbuf, 0, BUFFLEN);
}
#ifdef DEBUG_LOG
printf("recv :%s \n",recvbuf);
#endif
return ;
}
int send_recv_function(int sc,char *s,char *r)
{
if (send(sc, s, strlen(s), 0) < 0)
{
printf(" send %s error!\n",s);
return -1;
}
sleep(1);
memset(r, 0, BUFFLEN);
if (read(sc, r, BUFFLEN) < 0)
{
printf(" read [send]%s error!\n",s);
return -1;
}
else
{
#ifdef DEBUG_LOG
printf("send:%s recv :%s \n",s,r);
#endif
}
return 0;
}
int send_recv_function2(int sc,char *s,char *maxr)
{
if (send(sc, s, strlen(s), 0) < 0)
{
printf(" send %s error!\n",s);
return -1;
}
sleep(1);
memset(maxr, 0, MAXBUFF);
if (read(sc, maxr, MAXBUFF) < 0)
{
printf(" read [send]%s error!\n",s);
return -1;
}
else
{
#ifdef DEBUG_LOG
printf("send:%s recv :%s \n",s,maxr);
#endif
}
return 0;
}
void Dfree_mes_list(struct _message_list *msl)
{
struct _message_list *p ,*q;
p = msl;
while(p)
{
q = p->next;
free(p);
p = q;
}
return ;
}
void Show_mes_list(struct _message_list *msl)
{
int i = 0;
struct _message_list *p ;
p = msl;
while(p)
{
printf("[%d] mid :%d ,size:%d .\n",i,p->mid,p->msize);
p = p->next;
i++;
}
return ;
}
void get_message_num(char *s,int *num)
{
char buff[10];
char *p ,*q;
p = q = NULL;
memset(buff,0x0,10);
p = strstr(s,"has");
q = strstr(s,"messages");
if (q && p)
{
*q-- = '\0';
strcpy(buff,p+4);
*num = atoi(buff);
printf("List %d messages \n",*num);
}
else{
printf("List messages num error \n");
}
return;
}
int get_message_list(message_s *msl,char *buff,int emlsum)
{
char *p;
char id[10];
char msize[10];
int i;
int flag;
message_s *q;
i = flag = 0;
/*init message list*/
q = msl;
while(emlsum)
{
q->flag=0;
q->next = (message_s *)calloc(1,sizeof(message_s));
if (!q){
return -1;
}
q = q->next;
emlsum--;
}
/*get eml list*/
p = buff;
while((*p != '\0')&&(*p != 0x2e))
{
if ((*p == 0x20)&&(i != 0)){
id[i] = '\0';
msl->mid = atoi(id);
i = 0;
p++;
flag = 1;
continue;
}
if (*p == 0x0d){
msize[i] = '\0';
msl->msize = atoi(msize);
i =0;
p++;
flag = 0;
msl = msl->next ;
continue;
}
if ((*p >= 0x30) && (*p <= 0x39))
{
if (flag == 0)
id[i] = *p;
else
msize[i] = *p;
i++;
/*#ifdef DEBUG_LOG
printf("%02x",*p);
#endif*/
}
/*#ifdef DEBUG_LOG
if (*p == 0x0a) printf("\n\n");
#endif*/
p ++;
}
return 0;
}
static void error_write_eml(FILE *fp, char *fname)
{
fclose(fp);
fp = NULL;
remove(fname);
return;
}
int write_eml (int id,int size,int *flag,char *fname,int sockfd)
{
int rsize;
int tmpsize;
char *p = NULL;
char *q = NULL;
FILE *fp = NULL;
char tmpstr[48];
snprintf(tmpstr,48,"+OK %d octets\r\n",size);
tmpsize = strlen(tmpstr);
fp = fopen(fname,"w+");
if(!fp)
{
printf("fopen %s failed , because %s.\n",fname,strerror(errno));
return -1;
}
snprintf(sendbuf,BUFFLEN,"retr %d\r\n",id);
if (send(sockfd, sendbuf, strlen(sendbuf), 0) < 0)
{
printf(" send %s error!\n",sendbuf);
return -1;
}
while(1)
{
rsize = 0;
memset(recvbuf,0x0,BUFFLEN);
if ( (rsize = read(sockfd,recvbuf,BUFFLEN)) > 0)
{
#ifdef DEBUG_LOG
printf("%s",recvbuf);
#endif
if (rsize < 10)
break;
if(strstr(recvbuf,"error code")) {
error_write_eml(fp,fname);
break;
}
if ((q = strstr(recvbuf,tmpstr)) != NULL)
{
rsize = strlen(q);
fwrite(q+tmpsize+1,1,rsize,fp);
}
else if (( p = strstr(recvbuf,"\r\n.\r\n")) != NULL)
{
*(p+2) = '\0';
rsize = strlen(recvbuf);
fwrite(recvbuf,1,rsize,fp);
fclose(fp);
*flag = 1;
break;
}
else
fwrite(recvbuf,1,rsize,fp);
}
else if (rsize == 0)
{
error_write_eml(fp,fname);
close(sockfd);
exit(-1);
}
else //rsize < 0
{
if(errno != EINTR && errno != EWOULDBLOCK && errno != EAGAIN){
error_write_eml(fp,fname);
fprintf(stderr,"socket error errno=%d ,%s",errno,strerror(errno));
int j ;
for(j=1;j<=id;j++) {
snprintf(sendbuf,BUFFLEN,"dele %d\r\n",j);
send_recv_function(sockfd,sendbuf,recvbuf);
}
snprintf(sendbuf,BUFFLEN,"%s\r\n","QUIT");
send_recv_function(sockfd,sendbuf,recvbuf);
exit(1);
}
else if((errno == EINTR || errno == EWOULDBLOCK || errno == EAGAIN)) {
printf("errno %d error:%s\n",errno,strerror(errno));
continue;
sleep(1);
}
}
}
return 0;
}
int download_eml(message_s *msl,int sockfd,char *dir)
{
char fname[512];
struct _message_list *p,*q ;
time_t tNow;
struct tm tmNow;
char dirname[256];
time(&tNow);
localtime_r(&tNow, &tmNow);
snprintf(dirname,256,"%s/%04d%02d%02d/dyn_10/key_%02d%02d",dir,
(1900+tmNow.tm_year),(1+tmNow.tm_mon),tmNow.tm_mday,tmNow.tm_hour,tmNow.tm_min);
if(access(dirname,0 ) != 0)
{
umask(0);
mkdir(dirname,0777);
}
#ifdef DEBUG_LOG
printf("maildata path %s\n",dirname);
#endif
q = p = msl->next;//第一行为邮件列表总数
while(p)
{
memset(fname,0x0,512);
snprintf(fname,512,"%s/%ld.%d.eml",dirname,time(NULL),p->mid);
write_eml(p->mid,p->msize,&(p->flag),fname,sockfd);
p = p->next;
}
while(q)
{
if (q->flag)
{
snprintf(sendbuf,BUFFLEN,"dele %d\r\n",q->mid);
send_recv_function(sockfd,sendbuf,recvbuf);
}
q = q->next;
}
return 0;
}
int pop_eml_down(char *server,char *usr,char *pwd,char *path)
{
int messageNum = 0;
int sockfd = -1;
struct _message_list *msl ;
msl = NULL;
msl = (message_s*)calloc(1,sizeof(message_s));
//msl = (message_s *)malloc(sizeof(message_s));
if (!msl){
return -1;
}
/*create socket and connect*/
SetSocketConnect(server,&sockfd);
/*auth login */
memset(sendbuf,0,BUFFLEN);
memset(recvbuf,0x0,BUFFLEN);
snprintf(sendbuf,BUFFLEN,"%s\r\n",usr);
send_recv_function(sockfd,sendbuf,recvbuf);
snprintf(sendbuf,BUFFLEN,"%s\r\n",pwd);
send_recv_function(sockfd,sendbuf,recvbuf);
get_message_num(recvbuf,&messageNum);
if (messageNum == 0)
goto END_POP_EML_DOWN;
snprintf(sendbuf,BUFFLEN,"%s\r\n","list");
send_recv_function2(sockfd,sendbuf,maxrecvbuf);
/*eml list*/
get_message_list(msl,maxrecvbuf,messageNum);
//Show_mes_list(msl);
/*pop eml*/
download_eml(msl,sockfd,path);
snprintf(sendbuf,BUFFLEN,"%s\r\n","QUIT");
send_recv_function(sockfd,sendbuf,recvbuf);
END_POP_EML_DOWN:
if (sockfd > 0) close(sockfd);
Dfree_mes_list(msl) ;
return 0;
}