imap以用户定义的方式导入自定义邮箱

#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <string.h>
#include <dirent.h>
#include <unistd.h>
#include <iconv.h>
#include<arpa/inet.h>
#define MSGLINE 5000
#define OUTSIZE 1024


/* hexadecimal lookup table */
static char hex[] = "0123456789ABCDEF";

/* URL unsafe printable characters */
static char urlunsafe[] = " \"#%&+:;<=>?@[\\]^`{|}";

/* UTF7 modified base64 alphabet */

static char base64chars[] =
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+,"; 
#define UNDEFINED 64

/* UTF16 definitions */
#define UTF16MASK       0x03FFUL
#define UTF16SHIFT      10
#define UTF16BASE       0x10000UL

#define UTF16HIGHSTART  0xD800UL
#define UTF16HIGHEND    0xDBFFUL
#define UTF16LOSTART    0xDC00UL
#define UTF16LOEND      0xDFFFUL


/* Convert an IMAP mailbox to a URL path
 *  dst needs to have roughly 4 times the storage space of src
 *    Hex encoding can triple the size of the input
 *    UTF-7 can be slightly denser than UTF-8
 *     (worst case: 8 octets UTF-7 becomes 9 octets UTF-8)
 */

void MailboxToURL(char *dst, char *src)
{
  unsigned char c, i, bitcount;
  unsigned long ucs4, utf16, bitbuf;
  unsigned char base64[256], utf8[6];

  /* initialize modified base64 decoding table */
  memset(base64, UNDEFINED, sizeof (base64));
 for (i = 0; i < sizeof (base64chars); ++i) {
   base64[base64chars[i]] = i;
 }

 /* loop until end of string */
 while (*src != '\0') {
   c = *src++;
   /* deal with literal characters and &- */
   if (c != '&' || *src == '-') {
     if (c < ' ' || c > '~' || strchr(urlunsafe, c) != NULL) {
       /* hex encode if necessary */
       dst[0] = '%';
       dst[1] = hex[c >> 4];
       dst[2] = hex[c & 0x0f];
       dst += 3;
     } else {
       /* encode literally */
       *dst++ = c;
     }
     /* skip over the '-' if this is an &- sequence */
     if (c == '&') ++src;
   } else {
     /* convert modified UTF-7 -> UTF-16 -> UCS-4 -> UTF-8 -> HEX */
     bitbuf = 0;
     bitcount = 0;
     ucs4 = 0;
     while ((c = base64[(unsigned char) *src]) != UNDEFINED) {
       ++src;
       bitbuf = (bitbuf << 6) | c;
       bitcount += 6;
       /* enough bits for a UTF-16 character? */
       if (bitcount >= 16) {
	 bitcount -= 16;
	 utf16 = (bitcount ? bitbuf >> bitcount
		  : bitbuf) & 0xffff;
	 /* convert UTF16 to UCS4 */
                    if
		      (utf16 >= UTF16HIGHSTART && utf16 <= UTF16HIGHEND) {
		      ucs4 = (utf16 - UTF16HIGHSTART) << UTF16SHIFT;
		      continue;
                    } else if
		      (utf16 >= UTF16LOSTART && utf16 <= UTF16LOEND) {
		      ucs4 += utf16 - UTF16LOSTART + UTF16BASE;
                    } else {
		      ucs4 = utf16;
                    }

  /* convert UTF-16 range of UCS4 to UTF-8 */
  if (ucs4 <= 0x7fUL) {
    utf8[0] = ucs4;
    i = 1;
  } else if (ucs4 <= 0x7ffUL) {
    utf8[0] = 0xc0 | (ucs4 >> 6);
    utf8[1] = 0x80 | (ucs4 & 0x3f);
    i = 2;
  } else if (ucs4 <= 0xffffUL) {
    utf8[0] = 0xe0 | (ucs4 >> 12);
    utf8[1] = 0x80 | ((ucs4 >> 6) & 0x3f);
    utf8[2] = 0x80 | (ucs4 & 0x3f);
    i = 3;
  } else {
    utf8[0] = 0xf0 | (ucs4 >> 18);
    utf8[1] = 0x80 | ((ucs4 >> 12) & 0x3f);
    utf8[2] = 0x80 | ((ucs4 >> 6) & 0x3f);
    utf8[3] = 0x80 | (ucs4 & 0x3f);
    i = 4;
  }
/* convert utf8 to hex */
 for (c = 0; c < i; ++c) {
   dst[0] = '%';
   dst[1] = hex[utf8[c] >> 4];
   dst[2] = hex[utf8[c] & 0x0f];
   dst += 3;
 }
       }
     }
     /* skip over trailing '-' in modified UTF-7 encoding */
     if (*src == '-') ++src;
   }
 }
 /* terminate destination string */
 *dst = '\0';

} 
/* Convert hex coded UTF-8 URL path to modified UTF-7 IMAP mailbox
 *  dst should be about twice the length of src to deal with non-hex
 *  coded URLs
 */

void URLtoMailbox(char *dst, char *src)
{
  unsigned int utf8pos, utf8total, i, c, utf7mode, bitstogo, utf16flag;
  unsigned long ucs4, bitbuf;
  unsigned char hextab[256];

  /* initialize hex lookup table */

  memset(hextab, 0, sizeof (hextab)); 

 for (i = 0; i < sizeof (hex); ++i) {
   hextab[hex[i]] = i;
   if (isupper(hex[i])) hextab[tolower(hex[i])] = i;
 }

 utf7mode = 0;
 utf8total = 0;
 bitstogo = 0;
 while ((c = *src) != '\0') {
   ++src;
   /* undo hex-encoding */
   if (c == '%' && src[0] != '\0' && src[1] != '\0') {
     c = (hextab[src[0]] << 4) | hextab[src[1]];
     src += 2;
   }
   /* normal character? */
   if (c >= ' ' && c <= '~') {
     /* switch out of UTF-7 mode */
     if (utf7mode) {
       if (bitstogo) {
	 *dst++ = base64chars[(bitbuf << (6 - bitstogo)) & 0x3F];
       }
       *dst++ = '-';
       utf7mode = 0;
     }
     *dst++ = c;
     /* encode '&' as '&-' */
     if (c == '&') {
       *dst++ = '-';
     }
     continue;
   }
   /* switch to UTF-7 mode */
   if (!utf7mode) {
     *dst++ = '&';
     utf7mode = 1;
   }
   /* Encode US-ASCII characters as themselves */
   if (c < 0x80) {
     ucs4 = c;
     utf8total = 1;
   } else if (utf8total) {
     /* save UTF8 bits into UCS4 */
     ucs4 = (ucs4 << 6) | (c & 0x3FUL);
     if (++utf8pos < utf8total) {
       continue;
     }
  } else {
    utf8pos = 1;
    if (c < 0xE0) {
      utf8total = 2;
      ucs4 = c & 0x1F;
    } else if (c < 0xF0) {
      utf8total = 3;
      ucs4 = c & 0x0F;
    } else {
      /* NOTE: can't convert UTF8 sequences longer than 4 */
      utf8total = 4;
      ucs4 = c & 0x03;
    }
    continue;
  }
   /* loop to split ucs4 into two utf16 chars if necessary */
   utf8total = 0;
   do {
     if (ucs4 >= UTF16BASE) {
       ucs4 -= UTF16BASE;
       bitbuf = (bitbuf << 16) | ((ucs4 >> UTF16SHIFT)
				  + UTF16HIGHSTART);
       ucs4 = (ucs4 & UTF16MASK) + UTF16LOSTART;
       utf16flag = 1;
     } else {
       bitbuf = (bitbuf << 16) | ucs4;
       utf16flag = 0;
     }
     bitstogo += 16;
     /* spew out base64 */
     while (bitstogo >= 6) {
       bitstogo -= 6;
       *dst++ = base64chars[(bitstogo ? (bitbuf >> bitstogo)
			     : bitbuf)
			   & 0x3F];
     }
   } while (utf16flag);
 }
 /* if in UTF-7 mode, finish in ASCII */
 if (utf7mode) {
   if (bitstogo) {
     *dst++ = base64chars[(bitbuf << (6 - bitstogo)) & 0x3F];
   }
   *dst++ = '-';
 }
 /* tie off string */
 *dst = '\0';

} 
int main(int argc, char **argv)
{
    if(argc < 5)
    {
        printf("usage: %s maildir serverip serverport passwd\n", argv[0]);
        exit(1);
    }

    /* open data directoty */
    DIR *dirp = opendir(argv[1]);
    if(!dirp)
    {
        printf("cannot access %s\n", argv[1]);
        exit(1);
    }

    char request[MSGLINE];
    char response[MSGLINE];
    struct dirent *dent;
    /* get user mail accounts */
    while((dent = readdir(dirp)))
    {
        if(dent->d_type != DT_DIR || *dent->d_name == '.')
            continue;

        int socket_fd = socket(AF_INET, SOCK_STREAM, 0);
        if(socket_fd < 0)
        {
            printf("create socket failed\n");
            exit(1);
        }

        struct sockaddr_in srvaddr;
        memset(&srvaddr,0,sizeof(srvaddr));
       AF_ srvaddr.sin_family = AF_INET;
        srvaddr.sin_addr.s_addr = inet_addr(argv[2]);
        srvaddr.sin_port = htons(atoi(argv[3]));

        if(connect(socket_fd, (struct sockaddr *)&srvaddr, sizeof(srvaddr)) < 0)
        {
            printf("connect to server failed\n");
            exit(1);
        }
        printf("USER: %s\n", dent->d_name);
        read(socket_fd, response, MSGLINE);
        sprintf(request, "lll login %s %s\r\n", dent->d_name, argv[4]);
        write(socket_fd, request, strlen(request));
        read(socket_fd, response, MSGLINE);
        if(strncmp(response, "lll ", 4) || strncmp(response+4, "OK", 2))
        {
            printf("%s login failed\n", dent->d_name);
            write(socket_fd, "ttt logout\r\n", strlen("ttt logout\r\n"));
            read(socket_fd, response, MSGLINE);
            close(socket_fd);
            continue;
//            exit(1);
        }
 
        char userfname[1024];
        sprintf(userfname, "%s/%s", argv[1], dent->d_name);
        DIR *userp = opendir(userfname);
        if(!userp)
        {
            printf("cannot access %s\n", userfname);
            exit(1);
        }
        struct dirent *userdent;
        /* get user's mailbox names */
        while((userdent = readdir(userp)))
        {
            if(userdent->d_type != DT_DIR || *userdent->d_name == '.')
                continue;
            if(strcmp(userdent->d_name, "Delbox") == 0)
                continue;

            char boxfname[1024];
            sprintf(boxfname, "%s/%s", userfname, userdent->d_name);
            DIR *boxp = opendir(boxfname);
            if(!boxp)
            {
                printf("cannot access %s\n", boxfname);
                exit(1);
            }
            char boxname[OUTSIZE];
            memset(boxname, 0, OUTSIZE);
			char midtrans[OUTSIZE];
			
			strcpy(boxname, userdent->d_name);
			MailboxToURL(midtrans,boxname);
			URLtoMailbox(boxname,midtrans);
   
			
            struct dirent *boxdent;
            /* get mails in the mailbox */
            while((boxdent = readdir(boxp)))
            {
                if(boxdent->d_type != DT_REG)
                    continue;

                char mailfname[1024];
                sprintf(mailfname, "%s/%s", boxfname, boxdent->d_name);
                int fd = open(mailfname, O_RDONLY);
                if(fd == -1)
                {
                    printf("open %s failed\n", mailfname);
                    exit(1);
                }

                int len = lseek(fd, 0, SEEK_END);
                lseek(fd, 0, SEEK_SET);
                /* compose append command and send to server */
                sprintf(request, "aaa append %s (\\Seen) {%d}\r\n", boxname, len-2);
                write(socket_fd, request, strlen(request));
                int sz = read(socket_fd, response, MSGLINE);
                response[sz] = 0;

                if(strncmp(response,"aaa NO [TRYCREATE]", strlen("aaa NO [TRYCREATE]")) == 0)
                {
                    sprintf(request, "ccc create %s\r\n", boxname);
                    write(socket_fd, request, strlen(request));
                    int sz = read(socket_fd, response, MSGLINE);
                    response[sz] = 0;
                    if(strncmp(response, "ccc OK", strlen("ccc OK")) == 0)
                    {
                        sprintf(request, "aaa append %s (\\Seen) {%d}\r\n", boxname, len-2);
                        write(socket_fd, request, strlen(request));
                        int sz = read(socket_fd, response, MSGLINE);
                        response[sz] = 0;
                    }
                    else
                    {
                        printf("create mailbox %s failed\n", userdent->d_name);
                        exit(1);
                    }
                }

                if(response[0] != '+')
                {
                    printf("submit %s failed, append cmd, error: %s\n", mailfname, response);
                    exit(1);
                }

                while(1)
                {
                    int num = read(fd, request, MSGLINE);
                    if(num < 0)
                    {
                        printf("read %s failed\n", mailfname);
                        exit(1);
                    }
                    if(num == 0) break;
                    int pos = 0;
                    while(num > 0)
                    {
                        int sz = write(socket_fd, request+pos, num);
                        if(sz < 0)
                        {
                            printf("write to socket failed\n");
                            exit(1);
                        }
                        pos += sz;
                        num -= sz;
                    }

//                    write(socket_fd, message, num);
                }
                close(fd);
                sz = read(socket_fd, response, MSGLINE);
                response[sz] = 0;
//                printf("response: %s\n", message);
                if(strncmp(response, "aaa OK", strlen("aaa OK")) == 0)
                    unlink(mailfname);
                else
                {
                    printf("submit %s failed, trans data, error: %s\n", mailfname, response);
                    exit(1);
                }
            }
            closedir(boxp);
            sleep(1);
        }
        closedir(userp);
        write(socket_fd, "ttt logout\r\n", strlen("ttt logout\r\n"));
        read(socket_fd, response, MSGLINE);
        close(socket_fd);


    }
    closedir(dirp);
}

  

posted @ 2017-07-10 10:51  never_comparison  阅读(134)  评论(0编辑  收藏  举报