dmc

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

commit fdeff1b6e7b09bedb1f87326fc70a90716503980
parent 0288b48f2b47ad004b6b17020a238c1c371d868e
Author: pancake <nopcode.org>
Date:   Mon,  3 May 2010 01:38:06 +0200

* Explain how to configure msmtp in README
* dmc-cmd is now mostly implementing all the
  commands of the 'dmc' shellscript
Diffstat:
README | 17+++++++++++++++++
dmc-cmd.c | 234+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++----
2 files changed, 240 insertions(+), 11 deletions(-)

diff --git a/README b/README @@ -34,6 +34,23 @@ edited with Type your signature in ~/.dmc/signature +Configuring msmtp: +------------------ +To be able to send emails you have to properly configure msmtp. + +$ cat <<EOF > ~/.msmtprc +defaults + +account <account-name> +user <user-name> +auth login +from <email-address> +password <smtp-password> +host <smtp-host-name> + +account default : <account-name> +EOF + Running ------- Start one dmc mail daemon for each account diff --git a/dmc-cmd.c b/dmc-cmd.c @@ -1,32 +1,244 @@ #include <stdio.h> #include <string.h> +#include <dirent.h> #include <unistd.h> +#include <stdlib.h> +#include <sys/stat.h> + +#define DMCDIR "/home/pancake/.dmc" +#define EDITOR "vim" +#define VERSION "0.1" static char prompt[64]; +static char **acc; + +static int dmcstart(const char *name) { + return 0; +} + +static int dmcstop(const char *name) { + return 0; +} + +static char *dmccmd(const char *cmd, char *err, int errlen) { + return 0; +} + +static int dmcpull(const char *name) { + return 0; +} + +static int dmcpush(const char *name) { + return 0; +} + +#define MAXACC 4 +static char **dmcaccounts() { + struct dirent *de; + static char *accounts[MAXACC]; + char buf[256], *defacc = NULL; + DIR *dir; + int acc = 0; + memset (buf, 0, sizeof (buf)); + if (readlink (DMCDIR"/acc.default", buf, sizeof (buf))!=-1) { + defacc = buf + strlen (buf)-1; + while (*defacc != '/') + defacc--; + accounts[acc++] = strdup (++defacc); + } else fprintf (stderr, "No default account defined.\n"); + dir = opendir (DMCDIR"/acc"); + while ((de = readdir (dir))) + if (*de->d_name != '.' && (!defacc || strcmp (de->d_name, defacc))) + accounts[acc++] = strdup (de->d_name); + accounts[acc] = NULL; + return accounts; +} +static void charrfree(char **ptr) { + char **p = ptr; + while (*p) { + free(*p); + p++; + } + *ptr = NULL; +} static int dmcline(const char *line) { + char err[128]; char *ptr = strchr (line, ' '); if (ptr) *ptr = '\0'; - printf ("--> (%s)\n", ptr); - if (!strcmp (line, "")) { - + if (!strcmp (line, "?")) { + printf ("Usage: push pull exit\n"); + } else + if (!strcmp (line, "push")) { + dmcpush (acc[0]); + } else + if (!strcmp (line, "pull")) { + dmcstart (acc[0]); + dmcpull (acc[0]); + dmcstop (acc[0]); + } else + if (!strcmp (line, "exit")) { + return 0; } else { /* bypass to child */ + ptr = dmccmd (line, err, sizeof (err)); + if (ptr) { + printf ("%s\n", ptr); + fprintf (stderr, "%s\n", err); + free (ptr); + } else fprintf (stderr, "## No reply\n"); } return 1; } +static int usage(const char *argv0, int lon) { + fprintf (stderr, "Usage: %s [-hv] [-s file] [-e acc] [-a addr] [-m [A|S A]] [-l [box]]\n", argv0); + if (lon) { + fprintf (stderr, + " -m [A|S A .. ] ; create mail (Subject, Address, ..)\n" + " -c [cmd] ; command shell\n" + " -e [acc] ; list/edit/set default accounts\n" + " -a [addr] ; grep in addressbook\n" + " -l [box] ; list mails in specified box of def account\n" + " -s [file] ; send mail\n" + " -v ; show version\n" + ""); + } + return 0; +} + +static int fexist(const char *path) { + struct stat st; + int ret = stat (path, &st); + return (ret != -1); +} + +static int fsize(const char *path) { + FILE *fd = fopen (path, "r"); + int len = 0; + if (fd) { + len = fseek (fd, 0, SEEK_END); + fclose (fd); + } + return len; +} + int main(int argc, char **argv) { - char line[128]; - strcpy (prompt, "dmc> "); - do { - write (1, prompt, strlen (prompt)); - read (0, line, sizeof (line)); - if (feof (stdin)) - strcpy (line, "exit\n"); - } while (dmcline (line)); + char file[128], line[128]; + struct dirent *de; + DIR *dir; + int i; + + if (argc < 2) + return usage (argv[0], 0); + + acc = dmcaccounts (); + + if (argv[1][0] == '-') + switch (argv[1][1]) { + case 'l': + if (argc>2) { + snprintf (line, sizeof (line), DMCDIR"/box/%s/in/%s.eml", acc[0], argv[2]); + if (fexist (line)) { + snprintf (line, sizeof (line), "cat '"DMCDIR"/box/%s/in/%s.eml'", + acc[0], argv[2]); + system (line); // implement native cat + break; + } + snprintf (line, sizeof (line), DMCDIR"/box/%s", argv[2]); + } else snprintf (line, sizeof (line), DMCDIR"/box/%s/in", acc[0]); + charrfree (acc); + if ((dir = opendir (line))) { + while ((de = readdir (dir))) { + if (*de->d_name!='.') + printf ("%s:\n", de->d_name); + } + closedir (dir); + } + break; + case 'v': + printf ("dmc v"VERSION"\n"); + break; + case 's': + case 'm': + fprintf (stderr, "TODO\n"); + break; + case 'e': + if (argc<3) { + for (i=0; acc[i]; i++) + printf ("%s\n", acc[i]); + } else { + snprintf (file, sizeof (file), DMCDIR"/acc/%s", argv[2]); + if (!fexist (file)) { + /* create template */ + FILE *fd = fopen (file, "w"); + if (fd) { + fprintf (fd, + "NAME=test\n" + "SSL=0\n" + "LIMIT=50 # get only 50 mails for each folder\n" + "PROTOCOL=pop3 # imap4\n" + "HOST=serverhost.com\n" + "PORT=110\n" + "#SEND=acc-name\n" + "SEND=!msmtp\n" + "MAIL=username@domain.com\n" + "USER=username\n" + "PASS=password\n"); + fclose (fd); + } else { + fprintf (stderr, "Cannot write in %s\n", file); + return 1; + } + } + snprintf (line, sizeof (line), EDITOR" %s", file); + system (line); + if (fsize(file)<32) { + printf ("Abort\n"); + unlink (file); + } else { + printf ("Default account has changed.\n"); + unlink (DMCDIR"/acc.default"); + symlink (file, DMCDIR"/acc.default"); + } + } + charrfree (acc); + return 0; + case 'a': + if (argc<3) { + snprintf (line, sizeof (line), EDITOR" '"DMCDIR"/addrbook'"); + system (line); + } else { + FILE *fd = fopen (DMCDIR"/addrbook", "r"); + if (fd) { + while (!feof (fd)) { + fgets (line, sizeof (line), fd); + for (i=2; i<argc; i++) { + if (strstr (line, argv[i])) + printf ("%s", line); + } + } + fclose (fd); + } + } + break; + case 'c': + strcpy (prompt, "dmc> "); + do { + write (1, prompt, strlen (prompt)); + fgets(line, sizeof (line), stdin); + if (feof (stdin)) + strcpy (line, "exit"); + else line[strlen (line)-1] = '\0'; + } while (dmcline (line)); + break; + default: + return usage (argv[0], 1); + } + + charrfree (acc); return 0; }