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