dmc

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

commit 625edc38d5fcd59e99432a53e483abb53672e057
parent 37ac0f1aaaf679dd350bc6da395014f82d202287
Author: pancake <nopcode.org>
Date:   Fri, 30 Apr 2010 20:36:28 +0200

* Enhace documentation in README
* Check account before using it
* Some fixes in pop3 backend
Diffstat:
README | 63+++++++++++++++++++++++++++++++++++++++++++++++++++------------
dmc | 21++++++++++++++++++++-
dmc.1 | 11++++++++++-
doc/design | 2+-
pop3.c | 10+++++-----
5 files changed, 87 insertions(+), 20 deletions(-)

diff --git a/README b/README @@ -1,6 +1,6 @@ dmc - dynamic mail client ========================= -dmc is a minimalist email client solution +dmc is a minimalist e-mail client solution Requirements @@ -19,35 +19,74 @@ If you want to build dmc without SSL edit config.mk or type: make HAVE_SSL=0 +NOTE that default prefix is /usr, not /usr/local + +If you want to install dmc into a chroot, just set the DESTDIR: + + make install DESTDIR=/path/to/my/chroot Configuration ------------- Accounting information is stored in ~/.dmc/acc and can be edited with - dmc -e myaccount + dmc -e myaccount Type your signature in ~/.dmc/signature Running ------- -Start it in daemon mode +Start one dmc mail daemon for each account + + $ dmc start + +You can start a shell to the default account using the following command: - dmc -d + $ dmc -c + +In the same way you can just execute a command and get the output of it: + + $ dmc -c ls > mails + +You can change the default account by using 'dmc -e' To send a mail add the contact to your addressbook - echo 'user <foo@bar.com>' > ~/.dmc/addrbook + $ echo 'user <foo@bar.com>' >> ~/.dmc/addrbook + +or edit the addressbook + + $ dmc -a + +Create a mail: + + $ dmc -m "Hello World" + +Attach files to the last mail created with 'dmc -m': + + dmc -A file.zip + #dmc-mime msg attach1.zip | dmc -m `dmc -a user` + +Manually construct the final mail with encoded attachments: + + $ cd ~/.dmc/box/myaccount/out/ + $ dmc-pack mail.lv3s6l.d/* < mail.lv3s6l /tmp/mail.eml + +Send all the mails in the 'out' box: - or edit the addressbook + $ dmc push - dmc -a +Fetch new mail: -Then type the mail: + $ dmc pull - XXX: This is not correct +Stop the daemons -Add attachments: + $ dmc stop - $EDITOR msg - dmc-mime msg attach1.zip | dmc -m `dmc -a user` +TODO +---- +* Create a mail with attachments (dmc -m addr subject file1 file2 file3 ..) +* Attach file to mail without hacky commands +* Define a list of 'subscribed' folders for IMAP +* Pull specific folder (dmc pull [folder]) diff --git a/dmc b/dmc @@ -11,7 +11,15 @@ mkdir -p ~/.dmc/tmp mkdir -p ~/.dmc/acc [ -e ~/.dmc/acc.default ] && . ~/.dmc/acc.default +chkcfg () { + if [ -z "${NAME}" ]; then + echo "No selected mail account. Use 'dmc -e'" + exit 1 + fi +} + acc_daemon () { + chkcfg LOCK=~/.dmc/tmp/${NAME}.lock INPUT=~/.dmc/tmp/${NAME}.input OUTPUT=~/.dmc/tmp/${NAME}.output @@ -22,7 +30,7 @@ acc_daemon () { mkfifo "${LOCK}" "${INPUT}" # wait 1 connect message and 1 login message - ( head -n 2 ${LOCK} ; dmc_cmd "login ${USER} ${PASS}" ) & + (head -n 2 ${LOCK} ; dmc_cmd "login ${USER} ${PASS}" ; dmc_cmd "ls" ; ) & (while : ; do cat ${INPUT} 2> /dev/null ; done) | \ dmc-${PROTOCOL} ${HOST} ${PORT} ${SSL} 2> ${OUTPUT} > ${LOCK} rm -f "${LOCK}" "${INPUT}" "${OUTPUT}" @@ -36,6 +44,7 @@ dmc_cmd () { } start_account_daemons () { + chkcfg i=0 for a in ~/.dmc/acc/* ; do ( . $a ; acc_daemon ) & @@ -64,6 +73,7 @@ print_account_template () { } edit_message () { + chkcfg OUTDIR=~/.dmc/box/${NAME}/out mkdir -p ${OUTDIR} OUT="`mktemp ${OUTDIR}/mail.XXXXXX`" @@ -92,6 +102,7 @@ edit_message () { } add_attachment () { + chkcfg OUT="`readlink ~/.dmc/mail.last`" if [ -z "${OUT}" ]; then echo "No ~/.dmc/mail.last found. 'dmc -m' or manual symlink required." @@ -107,6 +118,7 @@ add_attachment () { } send_message () { + chkcfg FILE=$1 if [ ! -e "${FILE}" ]; then echo "Cannot find '${FILE}'" @@ -138,6 +150,7 @@ send_message () { } pull_mails () { + chkcfg echo "Pulling mails from account '${NAME}'" # This is pop3-only i=1 @@ -218,6 +231,7 @@ case "$1" in fi ;; "-c"|"--cmd") + chkcfg if [ -z "$2" ]; then while [ ! "$A" = "exit" ] ; do printf "> " @@ -231,6 +245,11 @@ case "$1" in ;; "-s"|"--send") shift + chkcfg + if [ -z "$*" ]; then + echo "Usage: dmc -s mail1 mail2 ..." + exit 1 + fi for a in $* ; do send_message $a done diff --git a/dmc.1 b/dmc.1 @@ -1,4 +1,4 @@ -.Dd Oct 20, 2009 +.Dd Apr 29, 2010 .Dt DMC 1 .Os .Sh NAME @@ -42,6 +42,15 @@ Stop all running dmc mail daemons Retrieve ${LIMIT} mails of configured accounts .It Ar push Send all mails in outbox +.Sh EXAMPLE +First of all you have to configure your mail account. + + $ dmc -e mymail # create/edit/setdefault mail account + $ dmc start # start one + $ dmc -c ls > mails # run 'ls' on remote mail server and get output in 'mails' + $ dmc stop # shutdown mail servers + + See README for more information .Sh FILES ~/.dmc/signature .Sh AUTHORS diff --git a/doc/design b/doc/design @@ -38,7 +38,7 @@ The sync process is done independently from the backend. - for a in list get checksum of header if header checksum not found in cache - - TODO + - order of mails depends on fetch time, so we can just use an integerjj: diff --git a/pop3.c b/pop3.c @@ -17,26 +17,26 @@ static char *cmd = NULL; static char word[1024]; static char *getword() { - fscanf (stdin, "%255s", word); + fscanf (stdin, "%s", word); if (feof (stdin)) *word = '\0'; return word; } static int waitreply(int res) { - char result[1024]; + char result[4096]; char *ch, *str; int reply = -1; ftruncate (2, 0); lseek (2, 0, SEEK_SET); result[0] = '\0'; - while (sock_ready () && sock_read (word, 512) > 1) { + while (sock_ready () && sock_read (word, sizeof(word)) > 1) { str = word; if (reply == -1 && (reply = (word[0] == '+'))) { if ((ch = strchr (str, '\r')) || (ch = strchr (str, '\n'))) { *ch = '\0'; - snprintf (result, 1023, "### %s %d \"%s\"\n", cmd, reply, str); + snprintf (result, sizeof (result), "### %s %d \"%s\"\n", cmd, reply, str); str = ch + (ch[1] == '\n' ? 2 : 1); } } @@ -48,7 +48,7 @@ static int waitreply(int res) { write (2, "\n", 1); if (res) { if (result[0] == '\0') - snprintf (result, 1023, "### %s %d \"\"\n", cmd, reply); + snprintf (result, sizeof (result), "### %s %d \"\"\n", cmd, reply); write (1, result, strlen (result)); } return reply;