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

 直接贴代码吧~~~~

1. mail.c

///
//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");
	return 0;
    }
    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");
	goto FREE_USER;
    }
    if(mail->send(&mail->data, user) == 0)
    {
        printf("发送成功!\n");
    }
    else
    {
        printf("发送失败!\n");
    }
    delete_mail(mail);
FREE_USER:
    delete_account(user);
    return 0;
}


2. mail.h

///
//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

///
//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;     
}



  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Quagger

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值