dmc

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

commit 204e884a419d33e9323a0bc13ee1b1a2090f3cb6
parent 23994ab79d4c9e22873526f9c928f934160f8d97
Author: pancake <nopcode.org>
Date:   Tue, 11 May 2010 01:22:08 +0200

* Added DEBUG configuration variable
* Fix dmc-tag double-tagging bug
* Initial implementation of 'pull' command
  - uses dmcstore() and parsedate()
  - not yet functional, but does some work
  - backends should specify the range of mails to check
Diffstat:
config.def.h | 1+
dmc-tag | 3++-
dmc.c | 114++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++---------
3 files changed, 104 insertions(+), 14 deletions(-)

diff --git a/config.def.h b/config.def.h @@ -7,3 +7,4 @@ #define REPMSG "On {Date: }, {From: } wrote:\n" #define FWDSUB "Fwd: " #define REPSUB "Re: " +#define DEBUG 0 diff --git a/dmc-tag b/dmc-tag @@ -115,7 +115,8 @@ case "$1" in set_file "$1" untag "${FILE}" while [ -n "$2" ] ; do - echo "${FILE}" >> ${DMCTAG_ROOT}/$2 + [ -z "`grep $FILE ${DMCTAG_ROOT}/$2`" ] && \ + echo "$FILE" >> ${DMCTAG_ROOT}/$2 shift done fi diff --git a/dmc.c b/dmc.c @@ -31,6 +31,7 @@ static DmcQuery reply; static void dmcstop(); static int dmcsend(const char *file); +static int dmcstore(const char *body); static int fexist(const char *path); #if 0 @@ -336,7 +337,7 @@ static int dmccmd(const char *cmd) { if (cmd && *cmd && *cmd != '\n') { snprintf (buf, sizeof (buf), "%s\n", cmd); write (dmc_in[1], buf, strlen (buf)); - printf ("-(wri)-> (%s)\n", cmd); + if (DEBUG) printf ("-(wri)-> (%s)\n", cmd); cmd = NULL; } } @@ -344,10 +345,6 @@ static int dmccmd(const char *cmd) { return 1; } -static int dmcpull(const char *name) { - return 0; -} - static void dmcpush(const char *name) { struct dirent *de; char path[256], file[512]; @@ -391,6 +388,86 @@ static int fsize(const char *path) { return len; } +static char *parsedate(const char *str) { + static char buf[256]; + char *ch; + strncpy (buf, str, sizeof (buf)); + if ((ch = strchr (buf, ','))) { + int year, month, day = atoi (ch+1); + if (!day) + return 0; + ch = strchr (ch+2, ' '); + while (*ch==' ')ch++; + if (ch) { + char *q, *p = strchr (ch+3, ' '); + if (p) { + *p = 0; + printf ("MONTH (%c%c%c)\n", ch[0], ch[1], ch[2]); + month = 0; // TODO + year = atoi (p+1); + if (year) { + q = strchr (p+1, ' '); + if (q) { + int h,m,s; + *q = 0; + sscanf (p+1, "%d:%d:%d", &h, &m, &s); + snprintf (buf, sizeof (buf), + "%s/box/%s/in/%04d%02d%02d-%02d%02d%02d", + dmcdir, defacc, year, month, day, h, m, s); + /* return 0: FUCK YEAH!!1 */ + } else return 0; + } else return 0; + } else return 0; + } else return 0; + } else return 0; + return buf; +} + +// TODO: support to store only the header, not full mail +static int dmcstore(const char *body) { + char dmctag[512], *file, *end, *ptr = strstr (body, "Date: "); // TODO: use gethdr..on buffer, not file + if (ptr) { + ptr = ptr + 6; + end = strchr (ptr, '\n'); + // generate filename from date + file = parsedate (ptr); + if (file) { +printf ("FILE IS =%s\n", file); + if (!fexist (file)) { + FILE *fd = fopen (file, "w"); + if (fd) { + fputs (body, fd); + fclose (fd); + // TODO extract attachments + // TODO save only body + snprintf (dmctag, sizeof (dmctag), + "dmc-tag '%s' new `dmc-tag %s`", file, file); + system (dmctag); + return 1; + } else fprintf (stderr, "Cannot write file '%s'\n", file); + } else fprintf (stderr, "Already downloaded.\n"); + } else fprintf (stderr, "Cannot generate file name for (%s)\n", body); + } else fprintf (stderr, "Cannot find date header.\n"); + return 0; +} + +static int dmcpull(int num, int lim, int dir) { + int ret, count = 0; + char cmd[64]; + for (;num!=lim;num+=dir) { + snprintf (cmd, sizeof (cmd), "cat %d\n", num); + ret = dmccmd (cmd); + printf ("RETURN IS = %d\n", ret); + ret = dmcstore (reply.err); // TODO: add support for folders + printf ("dmcstore ret = %d\n", ret); + if (!ret) + break; + count ++; + } + printf ("%d new messages\n", count); + return count; +} + static char **dmcaccounts() { struct dirent *de; static char *accounts[MAXACC]; @@ -440,6 +517,7 @@ static int dmcsend(const char *file) { } static int dmcline(const char *line) { + int ret = 1; char cmd[128]; if (!strcmp (line, "?")) { printf ("Usage: on off push pull exit ls lsd cat ..\n"); @@ -458,6 +536,15 @@ static int dmcline(const char *line) { if (!dmccmd (NULL)) printf ("Error.\n"); } else + if (!memcmp (line, "get ", 4)) { + snprintf (cmd, sizeof (cmd), "cat %s", line+4); + if (dmc_pid != -1) { + dmccmd (cmd); + printf ("CHECK (%s)\n", reply.out); + // TODO. if (check).. + dmcstore (reply.err); + } else fprintf (stderr, "Not connected.\n"); + } else if (!strcmp (line, "off")) { dmcstop (); } else @@ -475,19 +562,20 @@ static int dmcline(const char *line) { dmcpush (defacc); } else if (!strcmp (line, "pull")) { - if (dmcstart (acc[0])) { - dmcpull (acc[0]); - dmcstop (); - } + dmcpull (5, 9, 1); // pop3 test } else if (!strcmp (line, "exit")) { return 0; } else { /* bypass to child */ - if (dmccmd (line)) { - printf ("-(out)-> %s\n", reply.out); - printf ("-(err)-> %s\n", reply.err); - } else fprintf (stderr, "## No reply\n"); + if (!dmccmd (line)) { + fprintf (stderr, "## No reply\n"); + ret = 0; + } + } + if (ret) { + printf ("-(out)-> %s\n", reply.out); + //printf ("-(err)-> %s\n", reply.err); } return 1; }