dmc

dynamic mail client
git clone git://git.suckless.org/dmc
Log | Files | Refs | README | LICENSE

commit 791bb51ca8e1028a05498811b0c6f9a5cfaf63c2
parent 77b880cd884118c14096fd073f08184f91b32bda
Author: pancake@localhost.localdomain <unknown>
Date:   Mon, 19 Oct 2009 01:59:41 +0200

* Initial working version of dmc-imap4 client
  - Uses openssl s_client -quiet
  - Kinda ugly and incomplete source
  - Works as a standalone imap4 shell
    ls, rmdir, mkdir, mvdir, cat, head, ..
Diffstat:
FAQ | 6++++++
dmc | 2+-
imap4.c | 175++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++---------------
pop3.c | 19++++++++++---------
4 files changed, 160 insertions(+), 42 deletions(-)

diff --git a/FAQ b/FAQ @@ -41,6 +41,12 @@ situations and be a guide for the TODO points. account default : radare +* How can I get a pop3/imap4 shell? + + $ dmc-imap4 fifo | openssl s_client -quiet -host yourhost -port 993 > fifo + + $ dmc-pop3 fifo | nc yourhost -port 110 > fifo + * How to add attachment files to a mail? cat mail.txt | dmc-pack file1.zip file2.zip > mail.eml diff --git a/dmc b/dmc @@ -20,7 +20,7 @@ function acc_daemon { OUTPUT=~/.dmc/tmp/${NAME}.output if [ ${SSL} = 1 ]; then - NETCMD="openssl s_client -host $HOST -port $POST" + NETCMD="openssl s_client -quiet -host $HOST -port $POST" else NETCMD="nc $HOST $PORT" fi diff --git a/imap4.c b/imap4.c @@ -3,30 +3,106 @@ #include <stdio.h> #include <string.h> #include <stdlib.h> +#include <signal.h> +#include <unistd.h> +#include <fcntl.h> +#include <poll.h> +#include <sys/types.h> +#include <sys/stat.h> -static char word[1024]; + +static char *cmd = NULL; +static char word[4096]; static int ctr = 1; +static char *fifo; +static int ff; +static char *dir; +/* XXX full of bugs and ugly code */ static char *getword() { - fscanf(stdin, "%127s", word); + char *p = NULL; + char *str = word; + *word=0; +reread: + fscanf(stdin, "%255s", str); if (feof(stdin)) - *word = '\0'; + *str = '\0'; + else { + if (str == word) { + if (*word=='"') { + strcpy(word, word+1); + p = strchr(word, '"'); + if (p) { + *p=0; + } else { + str = word+strlen(word); + *str = ' '; + str++; + *str = 0; + goto reread; + } + } + } else { + p = strchr(str, '"'); + if (p) { + *p=0; + } else { + *str = ' '; + *str = 0; + str++; + goto reread; + } + } + } return word; } +static int ready() { + struct pollfd fds[1]; + fds[0].fd = ff; + fds[0].events = POLLIN|POLLPRI; + fds[0].revents = POLLNVAL|POLLHUP|POLLERR; + return poll((struct pollfd *)&fds, 1, 10); +} + static int waitreply() { - char *str; - int ret = -1; - fgets(word, sizeof(word), stdin); - if (atoi(word) != ctr-1) - fprintf(stderr, "Invalid sequence number received\n"); - if ( (str = strchr(word, ' ')) ) { - if (!memcmp(str+1, "OK", 3)) - ret = 1; - else if (!memcmp(str+1, "NO", 4)) - ret = 0; + char *ptr, *str = word; + int lock = 1; + int line = 0; + int ret, reply = -1; + fflush(stdout); +// XXX ugly sleep hack + while(lock || !ready()) { + lock = 0; + ret = read(ff, str, 1024); + if (ret<1) { + fprintf(stderr, " BREAK BREAK\n"); + break; + } + str[ret] = 0; + if (line == 0) { + ptr = strchr(word, ' '); + if (ptr) { + if (!memcmp(ptr+1, "OK", 2)) + reply = 1; + else + if (!memcmp(ptr+1, "NO", 2)) + reply = 0; + else // TODO: Make 'BAD' be -1 ? + if (!memcmp(ptr+1, "BAD", 3)) + reply = 0; + } + // XXX: Fix output, just show first line + fprintf(stderr, "### %s %d \"%s\"\n", cmd, reply, str); + } + str = str+strlen(str); + line++; + // fprintf(stderr, "--> %s\n", str); } - return ret; // 1 if true, 0 if false + fprintf(stderr, "==> (((%s)))\n", word); + fflush(stderr); + write(2, "\x00", 1); // end of output + return reply; } #if 0 @@ -41,33 +117,40 @@ RECENT - show the number of recent messages #endif static int doword(char *word) { int ret = 1; - if (*word == '\0' || !strcmp(word, "exit")) { + free (cmd); + cmd = strdup(word); + if (*word == '\0') { + /* Do nothing */ + } else + if (!strcmp(word, "exit")) { printf("%d LOGOUT\n", ctr++); waitreply(); ret = 0; } else if (!strcmp(word, "help") || !strcmp(word, "?")) { - fprintf(stderr, "Use: ls lsdir cat head rm rmdir login exit mvdir\n"); + fprintf(stderr, "Use: login exit ls cat head rm rmdir mkdir mvdir\n"); } else - if (!strcmp(word, "ls")) { -// TODO: - printf("LIST\n"); - waitreply(); + if (!strcmp(word, "pwd")) { + fprintf(stderr, "%s\n", dir); } else if (!strcmp(word, "cd")) { - printf("%d SELECT %s\n", ctr++, getword()); + free(dir); + dir = strdup(getword()); + if (!strcmp(dir, "\"\"")) + *dir=0; + printf("%d SELECT \"%s\"\n", ctr++, dir); waitreply(); } else if (!strcmp(word, "search")) { printf("%d SEARCH TEXT \"%s\"\n", ctr++, getword()); waitreply(); } else - if (!strcmp(word, "lsdir")) { - printf("%d LIST \"\" *\n", ctr++); + if (!strcmp(word, "ls")) { + printf("%d LIST \"%s\" *\n", ctr++, dir); waitreply(); } else if (!strcmp(word, "cat")) { - printf("%d FETCH %d ALL\n", + printf("%d FETCH %d body[]\n", ctr++, atoi(getword())); waitreply(); } else @@ -80,19 +163,27 @@ static int doword(char *word) { printf("%d RENAME %s %s\n", ctr++, getword(), getword()); } else + if (!strcmp(word, "mkdir")) { + printf("%d CREATE \"%s\"\n", + ctr++, getword()); + } else if (!strcmp(word, "rm")) { // TODO: - printf("DELE %d\n", atoi(getword())); + printf("%d DELE %d\n", ctr++, atoi(getword())); waitreply(); } else if (!strcmp(word, "rmdir")) { - printf("%d DELETE %d\n", - ctr++, atoi(getword())); + printf("%d DELETE \"%s\"\n", + ctr++, getword()); waitreply(); } else if (!strcmp(word, "login")) { - printf("%d LOGIN %s %s\n", - ctr++, getword(), getword()); + char * user = strdup(getword()); + char * pass = strdup(getword()); + printf("%d LOGIN \"%s\" \"%s\"\n", + ctr++, user, pass); + free(user); + free(pass); waitreply(); } else { printf("%d NOOP\n", ctr++); @@ -101,7 +192,27 @@ static int doword(char *word) { return ret; } -int main() { - while(doword(getword())); - return 0; +/* TODO: make it shared btwn pop3 + imap + smtp? */ +static void cleanup(int foo) { + close(ff); + unlink(fifo); + exit(0); +} + +int main(int argc, char **argv) { + int ret = 0; + if (argc>1) { + signal(SIGINT, cleanup); + fifo = argv[1]; + mkfifo(fifo, 0600); + ff = open(fifo, O_RDONLY); + if (ff != -1) { + dir = strdup(""); + waitreply(); + while(doword(getword())); + cleanup(0); + ret = 0; + } else fprintf(stderr, "Cannot open fifo file.\n"); + } else fprintf(stderr, "Usage: dmc-imap4 fifo | nc host 443 > fifo\n"); + return ret; } diff --git a/pop3.c b/pop3.c @@ -32,8 +32,9 @@ static int ready() { return poll((struct pollfd *)&fds, 1, 10); } -static int waitreply(int lock) { +static int waitreply() { char *ch, *str = word; + int lock = 1; int ret, reply = -1; fflush(stdout); while(lock || ready()) { @@ -77,7 +78,7 @@ static int doword(char *word) { } else if (!strcmp(word, "exit")) { printf("QUIT\n"); - waitreply(1); + waitreply(); ret = 0; } else if (!strcmp(word, "help") || !strcmp(word, "?")) { @@ -85,25 +86,25 @@ static int doword(char *word) { } else if (!strcmp(word, "ls")) { printf("LIST\n"); - waitreply(1); + waitreply(); } else if (!strcmp(word, "cat")) { printf("RETR %d\n", atoi(getword())); - waitreply(1); + waitreply(); } else if (!strcmp(word, "head")) { printf("TOP %d\n", atoi(getword())); - waitreply(1); + waitreply(); } else if (!strcmp(word, "rm")) { printf("DELE %d\n", atoi(getword())); - waitreply(1); + waitreply(); } else if (!strcmp(word, "login")) { printf("USER %s\n", getword()); - waitreply(1); + waitreply(); printf("PASS %s\n", getword()); - waitreply(1); + waitreply(); } else printf("NOOP\n"); return ret; } @@ -122,7 +123,7 @@ int main(int argc, char **argv) { mkfifo(fifo, 0600); ff = open(fifo, O_RDONLY); if (ff != -1) { - waitreply(1); + waitreply(); while(doword(getword())); cleanup(0); ret = 0;