linux 下给多人发送邮件源码(SMTP协议)

265 篇文章 0 订阅

http://blog.csdn.net/daydring/article/details/16966875

1. mail.c

  1. ///   
  2. //mail.c:   
  3. #include "mail.h"   
  4. #include "base64.h"   
  5. #include <string.h>   
  6. #include <stdlib.h>   
  7. #include <stdio.h>   
  8. #include <arpa/inet.h>   
  9. #include <netinet/in.h>   
  10. #include <netdb.h>   
  11. #include <unistd.h>   
  12. #include <ctype.h>   
  13. #include <time.h>   
  14.   
  15. static char  
  16.     *months [] = {  
  17.         "Jan""Feb""Mar""Apr""May""Jun",  
  18.         "Jul""Aug""Sep""Oct""Nov""Dec"  
  19.         };  
  20. static char  
  21.     *days [] = {"Sun""Mon""Tue""Wed""Thu""Fri""Sat"};  
  22.   
  23. char * encode_mime_time (long date, long time);  
  24. void local_to_gmt (long date, long time, long *gmt_date, long *gmt_time);  
  25. time_t date_to_timer (long date, long time);  
  26. long timer_to_gmdate (time_t time_secs);  
  27. long timer_to_gmtime (time_t time_secs);  
  28. int day_of_week (long date);  
  29. long time_now (void);  
  30. long date_now (void);  
  31.   
  32.   
  33.   
  34. #define GET_MONTH(d)        (int) (((d) % 10000L) / 100)   
  35. #define GET_DAY(d)          (int) ( (d) % 100)   
  36. #define GET_CCYEAR(d)       (int) ( (d) / 10000L)   
  37. #define GET_YEAR(d)         (int) (((d) % 1000000L) / 10000L)   
  38. #define GET_HOUR(t)         (int) ( (t) / 1000000L)   
  39. #define GET_MINUTE(t)       (int) (((t) % 1000000L) / 10000L)   
  40. #define GET_SECOND(t)       (int) (((t) % 10000L) / 100)   
  41. #define MAKE_DATE(c,y,m,d)  (long) (c) * 1000000L +                          \   
  42.                             (long) (y) * 10000L +                            \  
  43.                             (long) (m) * 100 + (d)  
  44. #define MAKE_TIME(h,m,s,c)  (long) (h) * 1000000L +                          \   
  45.                             (long) (m) * 10000L +                            \  
  46.                             (long) (s) * 100 + (c)  
  47.   
  48.   
  49. /*  ---------------------------------------------------------------------[<]- 
  50.     Function: encode_mime_time 
  51.  
  52.     Synopsis: Encode date and time (in long format) in Mime RFC1123 date 
  53.     format, e.g. Mon, 12 Jan 1995 12:05:01 GMT.  The supplied date and time 
  54.     are in local time.  Returns the date/time string if the date was legal, 
  55.     else returns "?".  Returned string is in a static buffer. 
  56.     ---------------------------------------------------------------------[>]-*/  
  57.   
  58. char * encode_mime_time (long date, long time)  
  59. {  
  60.     int day_week,                       /*  Day of week number (0 is sunday) */  
  61.         month;                          /*  Month number                     */  
  62.     static char buffer [50];  
  63.   
  64.     local_to_gmt (date, time, &date, &time);  
  65.     day_week = day_of_week (date);  
  66.     month    = GET_MONTH   (date);  
  67.     if (day_week >= 0 && day_week < 7 && month > 0 && month < 13)  
  68.       {  
  69.         sprintf (buffer, "%s, %02d %s %04d %02d:%02d:%02d GMT",  
  70.                          days       [day_week],  
  71.                          GET_DAY    (date),  
  72.                          months     [month - 1],  
  73.                          GET_CCYEAR (date),  
  74.                          GET_HOUR   (time),  
  75.                          GET_MINUTE (time),  
  76.                          GET_SECOND (time)  
  77.                  );  
  78.         return (buffer);  
  79.       }  
  80.     else  
  81.         return ("?");  
  82. //end proc encode_mime_time()   
  83.   
  84.   
  85.   
  86. /*  ---------------------------------------------------------------------[<]- 
  87.     Function: local_to_gmt 
  88.  
  89.     Synopsis: Converts the specified date and time to GMT.  Returns the GMT 
  90.     date and time in two arguments. 
  91.     ---------------------------------------------------------------------[>]-*/  
  92.   
  93. void local_to_gmt (long date, long time, long *gmt_date, long *gmt_time)  
  94. {  
  95.     time_t time_value;  
  96.   
  97.     time_value = date_to_timer   (date, time);  
  98.     *gmt_date  = timer_to_gmdate (time_value);  
  99.     *gmt_time  = timer_to_gmtime (time_value);  
  100. //end proc local_to_gmt()   
  101.   
  102.   
  103. /*  ---------------------------------------------------------------------[<]- 
  104.     Function: date_to_timer 
  105.  
  106.     Synopsis: Converts the supplied date and time into a time_t timer value. 
  107.     This is the number of non-leap seconds since 00:00:00 GMT Jan 1, 1970. 
  108.     Function was rewritten by Bruce Walter <walter@fortean.com>.  If the 
  109.     input date and time are invalid, returns 0. 
  110.     ---------------------------------------------------------------------[>]-*/  
  111.   
  112. time_t date_to_timer (long date, long time)  
  113. {  
  114.     struct tm time_struct;  
  115.     time_t timer;  
  116.   
  117.     time_struct.tm_sec   = GET_SECOND (time);  
  118.     time_struct.tm_min   = GET_MINUTE (time);  
  119.     time_struct.tm_hour  = GET_HOUR   (time);  
  120.     time_struct.tm_mday  = GET_DAY    (date);  
  121.     time_struct.tm_mon   = GET_MONTH  (date) - 1;  
  122.     time_struct.tm_year  = GET_CCYEAR (date) - 1900;  
  123.     time_struct.tm_isdst = -1;  
  124.     timer = mktime (&time_struct);  
  125.     if (timer == -1)  
  126.         return (0);  
  127.     else  
  128.         return (timer);  
  129. //end proc date_to_timer()   
  130.   
  131. /*  ---------------------------------------------------------------------[<]- 
  132.    Function: timer_to_date 
  133.  
  134.     Synopsis: Converts the supplied timer value into a long date value. 
  135.     Dates are stored as long values: CCYYMMDD.  If the supplied value is 
  136.     zero, returns zero.  If the supplied value is out of range, returns 
  137.     1 January, 1970 (19700101). The timer value is assumed to be UTC (GMT). 
  138.     ---------------------------------------------------------------------[>]-*/  
  139.   
  140. long timer_to_date (time_t time_secs)  
  141. {  
  142.     struct tm *time_struct;  
  143.   
  144.    if (time_secs == 0)  
  145.         return (0);  
  146.     else  
  147.       {  
  148.         /*  Convert into a long value CCYYMMDD                               */  
  149.         time_struct = localtime (&time_secs);  
  150.         if (time_struct)  
  151.           {  
  152.             time_struct-> tm_year += 1900;  
  153.             return (MAKE_DATE (time_struct-> tm_year / 100,  
  154.                                time_struct-> tm_year % 100,  
  155.                                time_struct-> tm_mon + 1,  
  156.                                time_struct-> tm_mday));  
  157.           }  
  158.         else  
  159.             return (19700101);  
  160.       }  
  161. //end proc timer_to_date()   
  162.   
  163. /*  ---------------------------------------------------------------------[<]- 
  164.     Function: timer_to_time 
  165.  
  166.     Synopsis: Converts the supplied timer value into a long time value. 
  167.     Times are stored as long values: HHMMSS00.  Since the timer value does 
  168.     not hold centiseconds, these are set to zero.  If the supplied value 
  169.     was zero or invalid, returns zero.  The timer value is assumed to be UTC 
  170.     (GMT). 
  171.     ---------------------------------------------------------------------[>]-*/  
  172.   
  173. long timer_to_time (time_t time_secs)  
  174. {  
  175.     struct tm *time_struct;  
  176.   
  177.     if (time_secs == 0)  
  178.         return (0);  
  179.     else  
  180.       {  
  181.         /*  Convert into a long value HHMMSS00                               */  
  182.         time_struct = localtime (&time_secs);  
  183.         if (time_struct)  
  184.             return (MAKE_TIME (time_struct-> tm_hour,  
  185.                                time_struct-> tm_min,  
  186.                                time_struct-> tm_sec,  
  187.                                0));  
  188.         else  
  189.             return (0);  
  190.       }  
  191. //end proc timer_to_time()   
  192.   
  193.   
  194. /*  ---------------------------------------------------------------------[<]- 
  195.     Function: timer_to_gmdate 
  196.  
  197.     Synopsis: Converts the supplied timer value into a long date value in 
  198.     Greenwich Mean Time (GMT).  Dates are stored as long values: CCYYMMDD. 
  199.     If the supplied value is zero, returns zero.  If the supplied value is 
  200.     out of range, returns 1 January, 1970 (19700101). 
  201.     ---------------------------------------------------------------------[>]-*/  
  202.   
  203. long timer_to_gmdate (time_t time_secs)  
  204. {  
  205.     struct tm *time_struct;  
  206.   
  207.     if (time_secs == 0)  
  208.         return (0);  
  209.     else  
  210.       {  
  211.         /*  Convert into a long value CCYYMMDD                               */  
  212.         time_struct = gmtime (&time_secs);  
  213.         if (time_struct == NULL)        /*  If gmtime is not implemented     */  
  214.             time_struct = localtime (&time_secs);  
  215.   
  216.         if (time_struct)  
  217.           {  
  218.             time_struct-> tm_year += 1900;  
  219.             return (MAKE_DATE (time_struct-> tm_year / 100,  
  220.                                time_struct-> tm_year % 100,  
  221.                                time_struct-> tm_mon + 1,  
  222.                                time_struct-> tm_mday));  
  223.           }  
  224.         else  
  225.             return (19700101);          /*  We had an invalid date           */  
  226.       }  
  227. //end proc timer_to_gmdate()   
  228.   
  229.   
  230. /*  ---------------------------------------------------------------------[<]- 
  231.     Function: timer_to_gmtime 
  232.  
  233.     Synopsis: Converts the supplied timer value into a long time value in 
  234.     Greenwich Mean Time (GMT).  Times are stored as long values: HHMMSS00. 
  235.     On most systems the clock does not return centiseconds, so these are 
  236.     set to zero.  If the supplied value is zero or invalid, returns zero. 
  237.     ---------------------------------------------------------------------[>]-*/  
  238.   
  239. long timer_to_gmtime (time_t time_secs)  
  240. {  
  241.     struct tm *time_struct;  
  242.   
  243.     if (time_secs == 0)  
  244.         return (0);  
  245.     else  
  246.       {  
  247.         /*  Convert into a long value HHMMSS00                               */  
  248.         time_struct = gmtime (&time_secs);  
  249.         if (time_struct == NULL)        /*  If gmtime is not implemented     */  
  250.             time_struct = localtime (&time_secs);  
  251.   
  252.         if (time_struct)  
  253.             return (MAKE_TIME (time_struct-> tm_hour,  
  254.                                time_struct-> tm_min,  
  255.                                time_struct-> tm_sec,  
  256.                                0));  
  257.         else  
  258.             return (0);  
  259.       }  
  260. //end proc timer_to_gmtime()   
  261.   
  262. /*  ---------------------------------------------------------------------[<]- 
  263.     Function: day_of_week 
  264.  
  265.     Synopsis: Returns the day of the week where 0 is Sunday, 1 is Monday, 
  266.     ... 6 is Saturday.  Uses Zeller's Congurence algorithm. 
  267.     ---------------------------------------------------------------------[>]-*/  
  268.   
  269. int day_of_week (long date)  
  270. {  
  271.     int year  = GET_CCYEAR (date),  
  272.         month = GET_MONTH  (date),  
  273.         day   = GET_DAY    (date);  
  274.   
  275.     if (month > 2)  
  276.         month -= 2;  
  277.     else  
  278.     {  
  279.         month += 10;  
  280.         year--;  
  281.     }  
  282.     day = ((13 * month - 1) / 5) + day + (year % 100) +  
  283.           ((year % 100) / 4) + ((year / 100) / 4) - 2 *  
  284.            (year / 100) + 77;  
  285.   
  286.     return (day - 7 * (day / 7));  
  287. //end proc day_of_week()   
  288.   
  289. /*  ---------------------------------------------------------------------[<]- 
  290.     Function: time_now 
  291.  
  292.     Synopsis: Returns the current time as a long value (HHMMSSCC).  If the 
  293.     system clock does not return centiseconds, these are set to zero. 
  294.     ---------------------------------------------------------------------[>]-*/  
  295.   
  296. long time_now (void)  
  297. {  
  298.     /*  The BSD gettimeofday function returns seconds and microseconds       */  
  299.     struct timeval  
  300.         time_struct;  
  301.   
  302.     gettimeofday (&time_struct, 0);  
  303.     return (timer_to_time (time_struct.tv_sec)  
  304.                          + time_struct.tv_usec / 10000);  
  305. //end proc time_now()   
  306.   
  307. /*  ---------------------------------------------------------------------[<]- 
  308.     Function: date_now 
  309.  
  310.     Synopsis: Returns the current date as a long value (CCYYMMDD).  Since 
  311.     most system clocks do not return a century, this function assumes that 
  312.     all years 80 and above are in the 20th century, and all years 00 to 79 
  313.     are in the 21st century.  For best results, consume before 1 Jan 2080. 
  314.     ---------------------------------------------------------------------[>]-*/  
  315.   
  316. long date_now (void)  
  317. {  
  318.     return (timer_to_date (time (NULL)));  
  319. //end proc date_now()   
  320.   
  321.   
  322.   
  323.   
  324.   
  325. /* 判断str开始的字符串是不是start*/  
  326. static int start_str(char *str,const char *start)  
  327. {  
  328.     if(strstr(str,start)==str)  
  329.         return 1;  
  330.     else  
  331.         return 0;  
  332. }  
  333.   
  334. /*将命令command发送到SMTP服务器,如果收到响应号为code,则返回true */  
  335. static int do_act(const char *code, mail_data_s *mail)  
  336. {  
  337.     if(write(mail->sock,mail->lastact,strlen(mail->lastact))<0)  
  338.     {  
  339.         perror("write");  
  340.         return 0;  
  341.     }  
  342.     //printf("send : %s\n", mail->lastact);   
  343.     memset(mail->lastmessage, 0, sizeof(mail->lastmessage));  
  344.     if(read(mail->sock,mail->lastmessage ,255)<0)  
  345.     {  
  346.         perror("read");  
  347.         return 0;  
  348.     }  
  349.     //printf("recv : %s\n", mail->lastmessage);   
  350.     if(start_str(mail->lastmessage,code))  
  351.         return 1;  
  352.     else  
  353.         return 0;  
  354. }  
  355. /* 发送email */  
  356. static int send_mail(mail_data_s *mail, account_s *user)  
  357.  {  
  358.     int tocnt = 0;  
  359.     char head[255];  
  360.     char to[255];  
  361.     char *tolist[32];  
  362.     char *ptr = NULL;  
  363.     struct sockaddr_in sa;  
  364.     struct hostent *he;  
  365.   
  366.     sa.sin_family = AF_INET;  
  367.     sa.sin_port = htons(user->port);  
  368.     
  369.     if((he=gethostbyname(user->smtp_server))!=NULL)  
  370.         bcopy(he->h_addr,&sa.sin_addr,he->h_length);   
  371.     else  
  372.     {  
  373.         perror("gethostbyname");  
  374.         return -1;  
  375.     }       
  376.      
  377.     //strcpy(mail->lastact,"connect");   
  378.     mail->sock=socket(AF_INET,SOCK_STREAM,0);  
  379.    
  380.     if ( mail->sock )  
  381.     {  
  382.         if(connect(mail->sock,(struct sockaddr*)&sa,sizeof(struct sockaddr))<0)  
  383.         {  
  384.             perror("conncect");  
  385.             return -1;  
  386.         }  
  387.   
  388.         read(mail->sock,mail->lastmessage,512);  
  389.         if ( !start_str(mail->lastmessage,"220"))  
  390.         {  
  391.             return -1;  
  392.         }  
  393.         else  
  394.         {  
  395.             /* Now, we must send chat command to smtp server. */  
  396.             strcpy(mail->lastact,"HELO ");  
  397.             strcat(mail->lastact,mail->welcome);  
  398.             strcat(mail->lastact,"\r\n");  
  399.             fflush(stdout);  
  400.             if(!do_act("250", mail))  
  401.             {  
  402.                 printf("HELO\n");  
  403.                 close(mail->sock);  
  404.                 return -1;  
  405.             }   
  406.   
  407.             strcpy(mail->lastact,"AUTH LOGIN\r\n");  
  408.             if(!do_act("334", mail))  
  409.             {  
  410.                 printf("AUTH LOGIN\n");  
  411.                 close(mail->sock);  
  412.                 return -1;  
  413.             }   
  414.   
  415.             char *code64=NULL;  
  416.             code64=base64_encode(user->username,strlen(user->username));  
  417.             strcpy(mail->lastact,code64);  
  418.             strcat(mail->lastact,"\r\n");  
  419.             if(!do_act("334", mail))  
  420.             {  
  421.                 printf("user name\n");  
  422.                 close(mail->sock);  
  423.                 return -1;  
  424.             }   
  425.               
  426.             //code64=NULL;   
  427.             //code64=base64_encode(user->passwd,strlen(user->passwd));   
  428.            // strcpy(mail->lastact,code64);   
  429.             strcpy(mail->lastact, user->passwd);  
  430.             strcat(mail->lastact,"\r\n");  
  431.             if(!do_act("235", mail))  
  432.             {  
  433.                 printf("passwd\n");  
  434.                 close(mail->sock);  
  435.                 return -1;  
  436.             }   
  437.                           
  438.             strcpy(mail->lastact,"MAIL FROM: ");  
  439.             strcat(mail->lastact,mail->from);  
  440.             strcat(mail->lastact,"\r\n");  
  441.               
  442.             if(!do_act("250", mail))  
  443.             {  
  444.                 printf("MAIL FROM");  
  445.                 close(mail->sock);  
  446.                 return -1;  
  447.             }  
  448. /* 
  449.             strcpy(mail->lastact,"RCPT TO: "); 
  450.             strcat(mail->lastact,mail->to); 
  451.             strcat(mail->lastact,"\r\n"); 
  452.             if(!do_act("250", mail)) 
  453.             { 
  454.                 close(mail->sock); 
  455.                 return -1; 
  456.             } 
  457.  */  
  458.             /* split mail to address */  
  459.             strcpy(to, mail->to);  
  460.             ptr = strtok(to, " ");  
  461.             tolist[tocnt++] = ptr;  
  462.             while((ptr = strtok(NULL, " ")))  
  463.             {  
  464.                 tolist[tocnt++] = ptr;  
  465.             }  
  466.             tolist[tocnt] = NULL;  
  467.             tocnt = 0;  
  468.   
  469.             /* Send peer mail address to smtp server */  
  470.             while(tolist[tocnt])  
  471.             {  
  472.                 strcpy(mail->lastact,"RCPT TO: ");  
  473.                 strcat(mail->lastact, tolist[tocnt++]);  
  474.                 strcat(mail->lastact,"\r\n");  
  475.                 printf("%s \n", mail->lastact);  
  476.                 if(!do_act("250", mail))  
  477.                 {  
  478.                     close(mail->sock);  
  479.                     return -1;  
  480.                 }  
  481.             }  
  482.   
  483.             /* Send mail data to smtp server */  
  484.             strcpy(mail->lastact,"DATA\r\n");  
  485.             if(!do_act("354", mail))  
  486.             {  
  487.                 close(mail->sock);  
  488.                 return -1;  
  489.             }  
  490.   
  491.             /* Send mail subject to smtp server */  
  492.             strcpy(head,"Subject: ");  
  493.             strcat(head,mail->subject);  
  494.             strcat(head,"\r\n");  
  495.             if(strlen(mail->subject)>0)  
  496.             {  
  497.                 write(mail->sock,head,strlen(head));  
  498.             }  
  499.   
  500.             /* Send mail sender address to smtp server */  
  501.             strcpy(head,"From: ");  
  502.             strcat(head,mail->from);  
  503.             strcat(head,"\r\n");              
  504.             if(strlen(mail->from)>0)  
  505.             {  
  506.                 write(mail->sock,head,strlen(head));  
  507.             }  
  508.   
  509.             /* 
  510.             strcpy(head,"To: "); 
  511.             //strncat(head,mail->to+1, strlen(mail->to)-2); 
  512.             strcat(head,mail->to); 
  513.             strcat(head,"\r\n"); 
  514.             if(strlen(head)>0) 
  515.             { 
  516.                 write(mail->sock,head,strlen(head)); 
  517.             }  
  518.             */  
  519.   
  520.             /* Send mail peer address infomation to smtp server */  
  521.             tocnt = 0;  
  522.             while(tolist[tocnt])  
  523.             {  
  524.                 strcpy(head,"To: ");  
  525.                 strncat(head, tolist[tocnt] + 1, strlen(tolist[tocnt]) - 2);  
  526.                 strcat(head, " ");  
  527.                 strcat(head, tolist[tocnt++]);  
  528.                 strcat(head,"\r\n");  
  529.                 printf("%s \n", head);  
  530.                 if(strlen(head)>0)  
  531.                 {  
  532.                     write(mail->sock,head,strlen(head));  
  533.                 }  
  534.             }  
  535.   
  536.             strcpy (head, "\r\n\r\n");  
  537.             if(strlen(head)>0)  
  538.             {  
  539.                 write(mail->sock, head, strlen(head));  
  540.             }  
  541.   
  542.             //code64 = NULL;   
  543.             //strcpy(head,message);   
  544.             //strcat(head,"\r\n");   
  545.             //code64=base64_encode(head,strlen(head));   
  546.             //strcpy(message,code64);   
  547.             /* Send mail message to smtp server */  
  548.             strcpy(head, mail->message);  
  549.             strcat(head, "\r\n");  
  550.             write(mail->sock, head, strlen(head));  
  551.   
  552.             strcpy(head, "Date: ");  
  553.             strcat(head, encode_mime_time (date_now (), time_now ()));  
  554.             strcat(head, "\r\n");  
  555.             write(mail->sock, head, strlen(head));  
  556.   
  557.             strcpy(head, "\r\n.\r\n");  
  558.             write(mail->sock, head, strlen(head));  
  559.   
  560.             /* Send quit command to smtp server, then chatting end. */  
  561.             strcpy(mail->lastact,"QUIT\r\n");  
  562.             if(!do_act("250", mail))  
  563.             {  
  564.                 close(mail->sock);  
  565.                 return -1;  
  566.             }  
  567.         }  
  568.         return 0;  
  569.     }  
  570.     else  
  571.     {  
  572.         printf("Connect failed!");  
  573.         return -1;  
  574.     }  
  575. }  
  576.   
  577. /* Create a mail struct */  
  578. mail_s *new_mail( char *to, char *from, char *welcome, char *subject, char *message)  
  579. {  
  580.     mail_s *mail = NULL;  
  581.     if((mail = (mail_s *)calloc(1, sizeof(mail_s))) == NULL)  
  582.         return NULL;  
  583.     if(strlen(to)<=0)  
  584.     {  
  585.         printf("Mail to cannt be NULL");  
  586.         goto NEW_FAIL;  
  587.     }  
  588.     else  
  589.     {  
  590.         if((mail->data.to = (char *)calloc(1, sizeof(char)*(strlen(to) + 1))))  
  591.             strcpy(mail->data.to, to);  
  592.         else  
  593.             goto NEW_FAIL;  
  594.     }  
  595.   
  596.     if(strlen(from)<=0)  
  597.     {  
  598.         printf("Mail from cannt be NULL");  
  599.         goto PARAM_FAIL;  
  600.     }  
  601.     else  
  602.         strcpy(mail->data.from,from);  
  603.   
  604.     if(strlen(subject)<=0)  
  605.     {  
  606.         strcpy(mail->data.subject,"Test");  
  607.     }  
  608.     else  
  609.         strcpy(mail->data.subject,subject);  
  610.   
  611.     if(strlen(welcome)<=0)  
  612.     {  
  613.         strcpy(mail->data.welcome,"localhost");  
  614.     }  
  615.     else  
  616.         strcpy(mail->data.welcome,welcome);  
  617.   
  618.     strcpy(mail->data.lastmessage,"");  
  619.     strcpy(mail->data.lastact,"");  
  620.   
  621.     mail->data.messagelen = strlen(message);  
  622.     if((mail->data.message =  (char *)calloc(1, sizeof(char)*mail->data.messagelen)) == NULL)  
  623.         goto PARAM_FAIL;  
  624.     strcpy(mail->data.message, message);  
  625.   
  626.     mail->send = &send_mail;  
  627.     return mail;  
  628. PARAM_FAIL:  
  629.     free(mail->data.to);  
  630. NEW_FAIL:  
  631.     free(mail);  
  632.     return NULL;  
  633. }  
  634.   
  635. /* Free mail struct */  
  636. void delete_mail( mail_s *mail )  
  637. {  
  638.     free(mail->data.message);  
  639.     free(mail->data.to);  
  640.     free(mail);  
  641.     mail = NULL;  
  642. }  
  643.   
  644. /* Create sender user account struct */  
  645. account_s *new_account(char *username, char *passwd, char *smtp_server, int port)  
  646. {  
  647.     char *code64 = NULL;  
  648.     account_s *user = NULL;  
  649.     if((user = (account_s *)calloc(1, sizeof(account_s))) == NULL)  
  650.         return NULL;  
  651.     memcpy(user->username, username, strlen(username));  
  652.     code64 = base64_encode(passwd, strlen(passwd));  
  653.     strcpy(user->passwd, code64);  
  654.     //memcpy(user->passwd, passwd, strlen(passwd));   
  655.     memcpy(user->smtp_server, smtp_server, strlen(smtp_server));  
  656.     user->port = port;  
  657.     return user;  
  658. }  
  659.   
  660. /* Free account struct */  
  661. void delete_account( account_s *user )  
  662. {  
  663.     free(user);  
  664.     user = NULL;  
  665. }  
  666.   
  667.   
  668. /* Test main */  
  669. int main()  
  670. {  
  671.     mail_s *mail = NULL;  
  672.     account_s *user = NULL;  
  673.     user = new_account("xxx@163.com""passwd""smtp.163.com", 25);  
  674.     if(!user)  
  675.     {  
  676.         printf("Alloc space for account fail.\n");  
///
//mail.c:
#include "mail.h"
#include "base64.h"
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <netdb.h>
#include <unistd.h>
#include <ctype.h>
#include <time.h>

static char
    *months [] = {
        "Jan", "Feb", "Mar", "Apr", "May", "Jun",
        "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
        };
static char
    *days [] = {"Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"};

char * encode_mime_time (long date, long time);
void local_to_gmt (long date, long time, long *gmt_date, long *gmt_time);
time_t date_to_timer (long date, long time);
long timer_to_gmdate (time_t time_secs);
long timer_to_gmtime (time_t time_secs);
int day_of_week (long date);
long time_now (void);
long date_now (void);



#define GET_MONTH(d)        (int) (((d) % 10000L) / 100)
#define GET_DAY(d)          (int) ( (d) % 100)
#define GET_CCYEAR(d)       (int) ( (d) / 10000L)
#define GET_YEAR(d)         (int) (((d) % 1000000L) / 10000L)
#define GET_HOUR(t)         (int) ( (t) / 1000000L)
#define GET_MINUTE(t)       (int) (((t) % 1000000L) / 10000L)
#define GET_SECOND(t)       (int) (((t) % 10000L) / 100)
#define MAKE_DATE(c,y,m,d)  (long) (c) * 1000000L +                          \
                            (long) (y) * 10000L +                            \
                            (long) (m) * 100 + (d)
#define MAKE_TIME(h,m,s,c)  (long) (h) * 1000000L +                          \
                            (long) (m) * 10000L +                            \
                            (long) (s) * 100 + (c)


/*  ---------------------------------------------------------------------[<]-
    Function: encode_mime_time

    Synopsis: Encode date and time (in long format) in Mime RFC1123 date
    format, e.g. Mon, 12 Jan 1995 12:05:01 GMT.  The supplied date and time
    are in local time.  Returns the date/time string if the date was legal,
    else returns "?".  Returned string is in a static buffer.
    ---------------------------------------------------------------------[>]-*/

char * encode_mime_time (long date, long time)
{
    int day_week,                       /*  Day of week number (0 is sunday) */
    	month;                          /*  Month number                     */
    static char buffer [50];

    local_to_gmt (date, time, &date, &time);
    day_week = day_of_week (date);
    month    = GET_MONTH   (date);
    if (day_week >= 0 && day_week < 7 && month > 0 && month < 13)
      {
        sprintf (buffer, "%s, %02d %s %04d %02d:%02d:%02d GMT",
                         days       [day_week],
                         GET_DAY    (date),
                         months     [month - 1],
                         GET_CCYEAR (date),
                         GET_HOUR   (time),
                         GET_MINUTE (time),
                         GET_SECOND (time)
                 );
        return (buffer);
      }
    else
        return ("?");
} //end proc encode_mime_time()



/*  ---------------------------------------------------------------------[<]-
    Function: local_to_gmt

    Synopsis: Converts the specified date and time to GMT.  Returns the GMT
    date and time in two arguments.
    ---------------------------------------------------------------------[>]-*/

void local_to_gmt (long date, long time, long *gmt_date, long *gmt_time)
{
    time_t time_value;

    time_value = date_to_timer   (date, time);
    *gmt_date  = timer_to_gmdate (time_value);
    *gmt_time  = timer_to_gmtime (time_value);
} //end proc local_to_gmt()


/*  ---------------------------------------------------------------------[<]-
    Function: date_to_timer

    Synopsis: Converts the supplied date and time into a time_t timer value.
    This is the number of non-leap seconds since 00:00:00 GMT Jan 1, 1970.
    Function was rewritten by Bruce Walter <walter@fortean.com>.  If the
    input date and time are invalid, returns 0.
    ---------------------------------------------------------------------[>]-*/

time_t date_to_timer (long date, long time)
{
    struct tm time_struct;
    time_t timer;

    time_struct.tm_sec   = GET_SECOND (time);
    time_struct.tm_min   = GET_MINUTE (time);
    time_struct.tm_hour  = GET_HOUR   (time);
    time_struct.tm_mday  = GET_DAY    (date);
    time_struct.tm_mon   = GET_MONTH  (date) - 1;
    time_struct.tm_year  = GET_CCYEAR (date) - 1900;
    time_struct.tm_isdst = -1;
    timer = mktime (&time_struct);
    if (timer == -1)
        return (0);
    else
        return (timer);
} //end proc date_to_timer()

/*  ---------------------------------------------------------------------[<]-
   Function: timer_to_date

    Synopsis: Converts the supplied timer value into a long date value.
    Dates are stored as long values: CCYYMMDD.  If the supplied value is
    zero, returns zero.  If the supplied value is out of range, returns
    1 January, 1970 (19700101). The timer value is assumed to be UTC (GMT).
    ---------------------------------------------------------------------[>]-*/

long timer_to_date (time_t time_secs)
{
    struct tm *time_struct;

   if (time_secs == 0)
        return (0);
    else
      {
        /*  Convert into a long value CCYYMMDD                               */
        time_struct = localtime (&time_secs);
        if (time_struct)
          {
            time_struct-> tm_year += 1900;
            return (MAKE_DATE (time_struct-> tm_year / 100,
                               time_struct-> tm_year % 100,
                               time_struct-> tm_mon + 1,
                               time_struct-> tm_mday));
          }
        else
            return (19700101);
      }
} //end proc timer_to_date()

/*  ---------------------------------------------------------------------[<]-
    Function: timer_to_time

    Synopsis: Converts the supplied timer value into a long time value.
    Times are stored as long values: HHMMSS00.  Since the timer value does
    not hold centiseconds, these are set to zero.  If the supplied value
    was zero or invalid, returns zero.  The timer value is assumed to be UTC
    (GMT).
    ---------------------------------------------------------------------[>]-*/

long timer_to_time (time_t time_secs)
{
    struct tm *time_struct;

    if (time_secs == 0)
        return (0);
    else
      {
        /*  Convert into a long value HHMMSS00                               */
        time_struct = localtime (&time_secs);
        if (time_struct)
            return (MAKE_TIME (time_struct-> tm_hour,
                               time_struct-> tm_min,
                               time_struct-> tm_sec,
                               0));
        else
            return (0);
      }
} //end proc timer_to_time()


/*  ---------------------------------------------------------------------[<]-
    Function: timer_to_gmdate

    Synopsis: Converts the supplied timer value into a long date value in
    Greenwich Mean Time (GMT).  Dates are stored as long values: CCYYMMDD.
    If the supplied value is zero, returns zero.  If the supplied value is
    out of range, returns 1 January, 1970 (19700101).
    ---------------------------------------------------------------------[>]-*/

long timer_to_gmdate (time_t time_secs)
{
    struct tm *time_struct;

    if (time_secs == 0)
        return (0);
    else
      {
        /*  Convert into a long value CCYYMMDD                               */
        time_struct = gmtime (&time_secs);
        if (time_struct == NULL)        /*  If gmtime is not implemented     */
            time_struct = localtime (&time_secs);

        if (time_struct)
          {
            time_struct-> tm_year += 1900;
            return (MAKE_DATE (time_struct-> tm_year / 100,
                               time_struct-> tm_year % 100,
                               time_struct-> tm_mon + 1,
                               time_struct-> tm_mday));
          }
        else
            return (19700101);          /*  We had an invalid date           */
      }
} //end proc timer_to_gmdate()


/*  ---------------------------------------------------------------------[<]-
    Function: timer_to_gmtime

    Synopsis: Converts the supplied timer value into a long time value in
    Greenwich Mean Time (GMT).  Times are stored as long values: HHMMSS00.
    On most systems the clock does not return centiseconds, so these are
    set to zero.  If the supplied value is zero or invalid, returns zero.
    ---------------------------------------------------------------------[>]-*/

long timer_to_gmtime (time_t time_secs)
{
    struct tm *time_struct;

    if (time_secs == 0)
        return (0);
    else
      {
        /*  Convert into a long value HHMMSS00                               */
        time_struct = gmtime (&time_secs);
        if (time_struct == NULL)        /*  If gmtime is not implemented     */
            time_struct = localtime (&time_secs);

        if (time_struct)
            return (MAKE_TIME (time_struct-> tm_hour,
                               time_struct-> tm_min,
                               time_struct-> tm_sec,
                               0));
        else
            return (0);
      }
} //end proc timer_to_gmtime()

/*  ---------------------------------------------------------------------[<]-
    Function: day_of_week

    Synopsis: Returns the day of the week where 0 is Sunday, 1 is Monday,
    ... 6 is Saturday.  Uses Zeller's Congurence algorithm.
    ---------------------------------------------------------------------[>]-*/

int day_of_week (long date)
{
    int year  = GET_CCYEAR (date),
        month = GET_MONTH  (date),
        day   = GET_DAY    (date);

    if (month > 2)
        month -= 2;
    else
    {
        month += 10;
        year--;
    }
    day = ((13 * month - 1) / 5) + day + (year % 100) +
          ((year % 100) / 4) + ((year / 100) / 4) - 2 *
           (year / 100) + 77;

    return (day - 7 * (day / 7));
} //end proc day_of_week()

/*  ---------------------------------------------------------------------[<]-
    Function: time_now

    Synopsis: Returns the current time as a long value (HHMMSSCC).  If the
    system clock does not return centiseconds, these are set to zero.
    ---------------------------------------------------------------------[>]-*/

long time_now (void)
{
    /*  The BSD gettimeofday function returns seconds and microseconds       */
    struct timeval
        time_struct;

    gettimeofday (&time_struct, 0);
    return (timer_to_time (time_struct.tv_sec)
                         + time_struct.tv_usec / 10000);
} //end proc time_now()

/*  ---------------------------------------------------------------------[<]-
    Function: date_now

    Synopsis: Returns the current date as a long value (CCYYMMDD).  Since
    most system clocks do not return a century, this function assumes that
    all years 80 and above are in the 20th century, and all years 00 to 79
    are in the 21st century.  For best results, consume before 1 Jan 2080.
    ---------------------------------------------------------------------[>]-*/

long date_now (void)
{
    return (timer_to_date (time (NULL)));
} //end proc date_now()





/* 判断str开始的字符串是不是start*/
static int start_str(char *str,const char *start)
{
    if(strstr(str,start)==str)
        return 1;
    else
        return 0;
}

/*将命令command发送到SMTP服务器,如果收到响应号为code,则返回true */
static int do_act(const char *code, mail_data_s *mail)
{
    if(write(mail->sock,mail->lastact,strlen(mail->lastact))<0)
    {
        perror("write");
        return 0;
    }
    //printf("send : %s\n", mail->lastact);
    memset(mail->lastmessage, 0, sizeof(mail->lastmessage));
    if(read(mail->sock,mail->lastmessage ,255)<0)
    {
        perror("read");
        return 0;
    }
    //printf("recv : %s\n", mail->lastmessage);
    if(start_str(mail->lastmessage,code))
        return 1;
    else
        return 0;
}
/* 发送email */
static int send_mail(mail_data_s *mail, account_s *user)
 {
	int tocnt = 0;
    char head[255];
    char to[255];
    char *tolist[32];
    char *ptr = NULL;
    struct sockaddr_in sa;
    struct hostent *he;

    sa.sin_family = AF_INET;
    sa.sin_port = htons(user->port);
  
    if((he=gethostbyname(user->smtp_server))!=NULL)
        bcopy(he->h_addr,&sa.sin_addr,he->h_length); 
    else
    {
        perror("gethostbyname");
        return -1;
    }     
   
    //strcpy(mail->lastact,"connect");
    mail->sock=socket(AF_INET,SOCK_STREAM,0);
 
    if ( mail->sock )
    {
        if(connect(mail->sock,(struct sockaddr*)&sa,sizeof(struct sockaddr))<0)
        {
            perror("conncect");
            return -1;
        }

        read(mail->sock,mail->lastmessage,512);
        if ( !start_str(mail->lastmessage,"220"))
        {
            return -1;
        }
        else
        {
        	/* Now, we must send chat command to smtp server. */
            strcpy(mail->lastact,"HELO ");
            strcat(mail->lastact,mail->welcome);
            strcat(mail->lastact,"\r\n");
            fflush(stdout);
            if(!do_act("250", mail))
            {
                printf("HELO\n");
                close(mail->sock);
                return -1;
            } 

            strcpy(mail->lastact,"AUTH LOGIN\r\n");
            if(!do_act("334", mail))
            {
                printf("AUTH LOGIN\n");
                close(mail->sock);
                return -1;
            } 

            char *code64=NULL;
            code64=base64_encode(user->username,strlen(user->username));
            strcpy(mail->lastact,code64);
            strcat(mail->lastact,"\r\n");
            if(!do_act("334", mail))
            {
                printf("user name\n");
                close(mail->sock);
                return -1;
            } 
            
            //code64=NULL;
            //code64=base64_encode(user->passwd,strlen(user->passwd));
           // strcpy(mail->lastact,code64);
            strcpy(mail->lastact, user->passwd);
            strcat(mail->lastact,"\r\n");
            if(!do_act("235", mail))
            {
                printf("passwd\n");
                close(mail->sock);
                return -1;
            } 
                        
            strcpy(mail->lastact,"MAIL FROM: ");
            strcat(mail->lastact,mail->from);
            strcat(mail->lastact,"\r\n");
            
            if(!do_act("250", mail))
            {
                printf("MAIL FROM");
                close(mail->sock);
                return -1;
            }
/*
            strcpy(mail->lastact,"RCPT TO: ");
            strcat(mail->lastact,mail->to);
            strcat(mail->lastact,"\r\n");
            if(!do_act("250", mail))
            {
                close(mail->sock);
                return -1;
            }
 */
            /* split mail to address */
            strcpy(to, mail->to);
            ptr = strtok(to, " ");
            tolist[tocnt++] = ptr;
            while((ptr = strtok(NULL, " ")))
            {
            	tolist[tocnt++] = ptr;
            }
            tolist[tocnt] = NULL;
            tocnt = 0;

            /* Send peer mail address to smtp server */
            while(tolist[tocnt])
            {
                strcpy(mail->lastact,"RCPT TO: ");
                strcat(mail->lastact, tolist[tocnt++]);
                strcat(mail->lastact,"\r\n");
                printf("%s \n", mail->lastact);
                if(!do_act("250", mail))
                {
                    close(mail->sock);
                    return -1;
                }
            }

            /* Send mail data to smtp server */
            strcpy(mail->lastact,"DATA\r\n");
            if(!do_act("354", mail))
            {
                close(mail->sock);
                return -1;
            }

            /* Send mail subject to smtp server */
            strcpy(head,"Subject: ");
            strcat(head,mail->subject);
            strcat(head,"\r\n");
            if(strlen(mail->subject)>0)
            {
                write(mail->sock,head,strlen(head));
            }

            /* Send mail sender address to smtp server */
            strcpy(head,"From: ");
            strcat(head,mail->from);
            strcat(head,"\r\n");            
            if(strlen(mail->from)>0)
            {
                write(mail->sock,head,strlen(head));
            }

            /*
            strcpy(head,"To: ");
            //strncat(head,mail->to+1, strlen(mail->to)-2);
            strcat(head,mail->to);
            strcat(head,"\r\n");
            if(strlen(head)>0)
            {
                write(mail->sock,head,strlen(head));
            } 
			*/

            /* Send mail peer address infomation to smtp server */
            tocnt = 0;
            while(tolist[tocnt])
            {
                strcpy(head,"To: ");
                strncat(head, tolist[tocnt] + 1, strlen(tolist[tocnt]) - 2);
                strcat(head, " ");
                strcat(head, tolist[tocnt++]);
                strcat(head,"\r\n");
                printf("%s \n", head);
                if(strlen(head)>0)
                {
                    write(mail->sock,head,strlen(head));
                }
            }

            strcpy (head, "\r\n\r\n");
            if(strlen(head)>0)
            {
            	write(mail->sock, head, strlen(head));
            }

            //code64 = NULL;
            //strcpy(head,message);
            //strcat(head,"\r\n");
            //code64=base64_encode(head,strlen(head));
            //strcpy(message,code64);
            /* Send mail message to smtp server */
            strcpy(head, mail->message);
            strcat(head, "\r\n");
            write(mail->sock, head, strlen(head));

            strcpy(head, "Date: ");
            strcat(head, encode_mime_time (date_now (), time_now ()));
            strcat(head, "\r\n");
            write(mail->sock, head, strlen(head));

            strcpy(head, "\r\n.\r\n");
            write(mail->sock, head, strlen(head));

            /* Send quit command to smtp server, then chatting end. */
            strcpy(mail->lastact,"QUIT\r\n");
            if(!do_act("250", mail))
            {
                close(mail->sock);
                return -1;
            }
        }
        return 0;
    }
    else
    {
        printf("Connect failed!");
        return -1;
    }
}

/* Create a mail struct */
mail_s *new_mail( char *to, char *from, char *welcome, char *subject, char *message)
{
	mail_s *mail = NULL;
    if((mail = (mail_s *)calloc(1, sizeof(mail_s))) == NULL)
    	return NULL;
    if(strlen(to)<=0)
    {
    	printf("Mail to cannt be NULL");
    	goto NEW_FAIL;
    }
    else
    {
    	if((mail->data.to = (char *)calloc(1, sizeof(char)*(strlen(to) + 1))))
    		strcpy(mail->data.to, to);
    	else
    		goto NEW_FAIL;
    }

    if(strlen(from)<=0)
    {
    	printf("Mail from cannt be NULL");
    	goto PARAM_FAIL;
    }
    else
        strcpy(mail->data.from,from);

    if(strlen(subject)<=0)
    {
        strcpy(mail->data.subject,"Test");
    }
    else
        strcpy(mail->data.subject,subject);

    if(strlen(welcome)<=0)
    {
        strcpy(mail->data.welcome,"localhost");
    }
    else
        strcpy(mail->data.welcome,welcome);

    strcpy(mail->data.lastmessage,"");
    strcpy(mail->data.lastact,"");

    mail->data.messagelen = strlen(message);
    if((mail->data.message =  (char *)calloc(1, sizeof(char)*mail->data.messagelen)) == NULL)
    	goto PARAM_FAIL;
    strcpy(mail->data.message, message);

    mail->send = &send_mail;
    return mail;
PARAM_FAIL:
	free(mail->data.to);
NEW_FAIL:
	free(mail);
	return NULL;
}

/* Free mail struct */
void delete_mail( mail_s *mail )
{
	free(mail->data.message);
	free(mail->data.to);
	free(mail);
	mail = NULL;
}

/* Create sender user account struct */
account_s *new_account(char *username, char *passwd, char *smtp_server, int port)
{
	char *code64 = NULL;
	account_s *user = NULL;
	if((user = (account_s *)calloc(1, sizeof(account_s))) == NULL)
		return NULL;
	memcpy(user->username, username, strlen(username));
	code64 = base64_encode(passwd, strlen(passwd));
	strcpy(user->passwd, code64);
	//memcpy(user->passwd, passwd, strlen(passwd));
	memcpy(user->smtp_server, smtp_server, strlen(smtp_server));
	user->port = port;
	return user;
}

/* Free account struct */
void delete_account( account_s *user )
{
	free(user);
	user = NULL;
}


/* Test main */
int main()
{
    mail_s *mail = NULL;
    account_s *user = NULL;
    user = new_account("xxx@163.com", "passwd", "smtp.163.com", 25);
    if(!user)
    {
    	printf("Alloc space for account fail.\n");
  1. <SPAN style="WHITE-SPACE: pre"> </SPAN>return 0;  
	return 0;
  1. }  
  2. mail = new_mail("<xxx@qq.com> <xxx@163.com>",  
  3.         "<xxx@163.com>""xxx",  "test""Hello, this is a test letter!");  
  4. if(!mail)  
  5. {  
  6.     printf("Alloc space for mail fail.\n");  
    }
    mail = new_mail("<xxx@qq.com> <xxx@163.com>",
    		"<xxx@163.com>", "xxx",  "test", "Hello, this is a test letter!");
    if(!mail)
    {
    	printf("Alloc space for mail fail.\n");
  1. <SPAN style="WHITE-SPACE: pre"> </SPAN>goto FREE_USER;  
  2.     }  
  3.     if(mail->send(&mail->data, user) == 0)  
  4.     {  
  5.         printf("发送成功!\n");  
  6.     }  
  7.     else  
  8.     {  
  9.         printf("发送失败!\n");  
  10.     }  
	goto FREE_USER;
    }
    if(mail->send(&mail->data, user) == 0)
    {
        printf("发送成功!\n");
    }
    else
    {
        printf("发送失败!\n");
    }
  1. delete_mail(mail);  
    delete_mail(mail);
  1. FREE_USER:  
  2.     delete_account(user);  
  3.     return 0;  
  4. }  
FREE_USER:
    delete_account(user);
    return 0;
}


2. mail.h

  1. ///   
  2. //mail.h:   
  3.   
  4. typedef struct {  
  5.     char username[32]; //username   
  6.     char passwd[32]; // password   
  7.     char smtp_server[64]; //smtp服务器地址   
  8.     int  port; //smtp端口号,25   
  9. }account_s;  
  10.   
  11. typedef struct user_list{  
  12.     account_s user;  
  13.     struct user_list *next;  
  14. }user_list;  
  15.   
  16. typedef struct {  
  17.     char lastmessage[255]; //记录最后返回的响应信息   
  18.     char lastact[255]; //最后的动作,字符串形式   
  19.     char welcome[255]; //用在HELO后面,欢迎用户   
  20.     char from[64]; //the mail from where   
  21.     char *to; //mail send to where   
  22.     char subject[64]; // mail subject   
  23.     char *message; // send message   
  24.     int  messagelen; //message length   
  25.     int  sock; //socket句柄   
  26. }mail_data_s;  
  27.   
  28. typedef struct {  
  29.     mail_data_s data;  
  30.     int  (*send)(mail_data_s *, account_s *);  
  31. } mail_s;  
  32.   
  33. mail_s *new_mail(char *, char *, char *, char *, char *);  
  34. void delete_mail( mail_s *mail );  
  35. account_s *new_account(char *, char *, char *, int);  
  36. void delete_account( account_s *user );  
///
//mail.h:

typedef struct {
	char username[32]; //username
	char passwd[32]; // password
	char smtp_server[64]; //smtp服务器地址
	int  port; //smtp端口号,25
}account_s;

typedef struct user_list{
	account_s user;
	struct user_list *next;
}user_list;

typedef struct {
	char lastmessage[255]; //记录最后返回的响应信息
	char lastact[255]; //最后的动作,字符串形式
	char welcome[255]; //用在HELO后面,欢迎用户
	char from[64]; //the mail from where
	char *to; //mail send to where
	char subject[64]; // mail subject
	char *message; // send message
	int  messagelen; //message length
	int  sock; //socket句柄
}mail_data_s;

typedef struct {
	mail_data_s data;
	int  (*send)(mail_data_s *, account_s *);
} mail_s;

mail_s *new_mail(char *, char *, char *, char *, char *);
void delete_mail( mail_s *mail );
account_s *new_account(char *, char *, char *, int);
void delete_account( account_s *user );

3. base64.h

  1. ///   
  2. //base64.h   
  3. //base64编码与解码   
  4.   
  5. #include <stdlib.h>   
  6. #include <string.h>   
  7.   
  8. static char basis_64[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";   
  9.    
  10. #define CHAR64(c)  (((c) < 0 || (c) > 127) ? -1 : index_64[(c)])    
  11.        
  12. static signed char index_64[128] = {       
  13.         -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1,       
  14.         -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1,       
  15.         -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,62, -1,-1,-1,63,       
  16.         52,53,54,55, 56,57,58,59, 60,61,-1,-1, -1,-1,-1,-1,       
  17.         -1, 0, 1, 2,  3, 4, 5, 6,  7, 8, 9,10, 11,12,13,14,       
  18.         15,16,17,18, 19,20,21,22, 23,24,25,-1, -1,-1,-1,-1,       
  19.         -1,26,27,28, 29,30,31,32, 33,34,35,36, 37,38,39,40,       
  20.         41,42,43,44, 45,46,47,48, 49,50,51,-1, -1,-1,-1,-1       
  21. } ;   
  22.        
  23. char *base64_encode(const char *value, int vlen) {  
  24.     unsigned char oval = 0 ;        
  25.         char *result = (char *)malloc((vlen * 4) / 3 + 5) ;  
  26.         char *out = result;       
  27.     while (vlen >= 3) {       
  28.             *out++ = basis_64[value[0] >> 2];       
  29.             *out++ = basis_64[((value[0] << 4) & 0x30) | (value[1] >> 4)];       
  30.             *out++ = basis_64[((value[1] << 2) & 0x3C) | (value[2] >> 6)];       
  31.             *out++ = basis_64[value[2] & 0x3F];       
  32.             value += 3;       
  33.                vlen -= 3;       
  34.         }   
  35.     if (vlen > 0) {       
  36.             *out++ = basis_64[value[0] >> 2];       
  37.             oval = (value[0] << 4) & 0x30 ;       
  38.             if (vlen > 1) oval |= value[1] >> 4;       
  39.             *out++ = basis_64[oval];       
  40.             *out++ = (vlen < 2) ? '=' : basis_64[(value[1] << 2) & 0x3C];       
  41.             *out++ = '=';       
  42.     }       
  43.     *out = '\0';           
  44.     return result;  
  45. }       
  46.    
  47. unsigned char *base64_decode(const char *value, int *rlen)       
  48. {           
  49.     int c1, c2, c3, c4;                   
  50.         int vlen = strlen(value);       
  51.     unsigned char *result =(unsigned char *)malloc((vlen * 3) / 4 + 1);       
  52.     unsigned char *out = result;       
  53.        
  54.     *rlen = 0;   
  55.        
  56.     while (1) {       
  57.         if (value[0]==0) {   
  58.             *out = '\0' ;    
  59.             return result;       
  60.         }   
  61.             c1 = value[0];       
  62.                 if (CHAR64(c1) == -1) goto base64_decode_error;   
  63.                  c2 = value[1];       
  64.                  if (CHAR64(c2) == -1) goto base64_decode_error;   
  65.                  c3 = value[2];       
  66.                  if ((c3 != '=') && (CHAR64(c3) == -1)) goto base64_decode_error;   
  67.                  c4 = value[3];       
  68.                  if ((c4 != '=') && (CHAR64(c4) == -1)) goto base64_decode_error;       
  69.                      value += 4;       
  70.                  *out++ = (CHAR64(c1) << 2) | (CHAR64(c2) >> 4);       
  71.                  *rlen += 1;       
  72.                  if (c3 != '=') {       
  73.                      *out++ = ((CHAR64(c2) << 4) & 0xf0) | (CHAR64(c3) >> 2);       
  74.                     *rlen += 1;       
  75.                     if (c4 != '=') {       
  76.                         *out++ = ((CHAR64(c3) << 6) & 0xc0) | CHAR64(c4);       
  77.                             *rlen += 1;       
  78.                     }   
  79.                  }       
  80.     }       
  81.     base64_decode_error:       
  82.             *result = 0;       
  83.             *rlen = 0;       
  84.             return result;       
  85. }  
///
//base64.h
//base64编码与解码

#include <stdlib.h>
#include <string.h>

static char basis_64[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; 
 
#define CHAR64(c)  (((c) < 0 || (c) > 127) ? -1 : index_64[(c)]) 
     
static signed char index_64[128] = {     
        -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1,     
        -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1,     
        -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,62, -1,-1,-1,63,     
        52,53,54,55, 56,57,58,59, 60,61,-1,-1, -1,-1,-1,-1,     
        -1, 0, 1, 2,  3, 4, 5, 6,  7, 8, 9,10, 11,12,13,14,     
        15,16,17,18, 19,20,21,22, 23,24,25,-1, -1,-1,-1,-1,     
        -1,26,27,28, 29,30,31,32, 33,34,35,36, 37,38,39,40,     
        41,42,43,44, 45,46,47,48, 49,50,51,-1, -1,-1,-1,-1     
} ; 
     
char *base64_encode(const char *value, int vlen) {
    unsigned char oval = 0 ;      
        char *result = (char *)malloc((vlen * 4) / 3 + 5) ;
        char *out = result;     
    while (vlen >= 3) {     
            *out++ = basis_64[value[0] >> 2];     
            *out++ = basis_64[((value[0] << 4) & 0x30) | (value[1] >> 4)];     
            *out++ = basis_64[((value[1] << 2) & 0x3C) | (value[2] >> 6)];     
            *out++ = basis_64[value[2] & 0x3F];     
            value += 3;     
               vlen -= 3;     
        } 
    if (vlen > 0) {     
            *out++ = basis_64[value[0] >> 2];     
            oval = (value[0] << 4) & 0x30 ;     
            if (vlen > 1) oval |= value[1] >> 4;     
            *out++ = basis_64[oval];     
            *out++ = (vlen < 2) ? '=' : basis_64[(value[1] << 2) & 0x3C];     
            *out++ = '=';     
    }     
    *out = '\0';         
    return result;
}     
 
unsigned char *base64_decode(const char *value, int *rlen)     
{         
    int c1, c2, c3, c4;                 
        int vlen = strlen(value);     
    unsigned char *result =(unsigned char *)malloc((vlen * 3) / 4 + 1);     
    unsigned char *out = result;     
     
    *rlen = 0; 
     
    while (1) {     
        if (value[0]==0) { 
            *out = '\0' ;  
            return result;     
        } 
            c1 = value[0];     
                if (CHAR64(c1) == -1) goto base64_decode_error; 
                 c2 = value[1];     
                 if (CHAR64(c2) == -1) goto base64_decode_error; 
                 c3 = value[2];     
                 if ((c3 != '=') && (CHAR64(c3) == -1)) goto base64_decode_error; 
                 c4 = value[3];     
                 if ((c4 != '=') && (CHAR64(c4) == -1)) goto base64_decode_error;     
                     value += 4;     
                 *out++ = (CHAR64(c1) << 2) | (CHAR64(c2) >> 4);     
                 *rlen += 1;     
                 if (c3 != '=') {     
                     *out++ = ((CHAR64(c2) << 4) & 0xf0) | (CHAR64(c3) >> 2);     
                    *rlen += 1;     
                    if (c4 != '=') {     
                        *out++ = ((CHAR64(c3) << 6) & 0xc0) | CHAR64(c4);     
                            *rlen += 1;     
                    } 
                 }     
    }     
    base64_decode_error:     
            *result = 0;     
            *rlen = 0;     
            return result;     
}



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值