commit 6b67a5dcdb2e4219c8c5b7800a8eb5af43f9b45b
parent 9bf17f2af49577e5f529dfb92bd1be543131c303
Author: pancake@localhost.localdomain <unknown>
Date: Fri, 16 Oct 2009 19:39:05 +0200
* Added smtp.c with MX host resolution
* Add long help
* Add non-working -H flag
* Add year in copyright header
* Remove the parseoutput() function .. no longer used
Diffstat:
Makefile | | | 2 | +- |
dmc | | | 53 | ++++++++++++++++++++++++++++++++++++++++++++++------- |
imap4.c | | | 2 | +- |
pop3.c | | | 27 | ++++++++++----------------- |
smtp.c | | | 90 | ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++- |
5 files changed, 147 insertions(+), 27 deletions(-)
diff --git a/Makefile b/Makefile
@@ -5,7 +5,7 @@ CFLAGS?=-Wall
all: dmc-smtp dmc-pop3 dmc-imap4
dmc-smtp: smtp.o
- ${CC} ${LDFLAGS} smtp.o -o dmc-smtp
+ ${CC} ${LDFLAGS} smtp.o -o dmc-smtp -lresolv
dmc-pop3: pop3.o
${CC} ${LDFLAGS} pop3.o -o dmc-pop3
diff --git a/dmc b/dmc
@@ -1,15 +1,18 @@
#!/bin/sh
#
-# Dynamic Mail Client
+# dmc - dynamic mail client
+# Copyleft 2009 -- pancake <at> nopcode <dot> org
#
VERSION="0.1"
COPYRIGHT="Copyleft -- pancake@nopcode.org"
+HELP="Usage: dmc [-e acc] [-a addr] [-m addr subj] [-A file] [-s msg] [-hvdk]"
[ -n "${EDITOR}" ] && EDITOR=vim
mkdir -p ~/.dmc/mail
mkdir -p ~/.dmc/tmp
mkdir -p ~/.dmc/acc
+[ -e ~/.dmc/acc.default ] && . ~/.dmc/acc.default
function acc_daemon {
FIFO=~/.dmc/tmp/${NAME}.fifo
@@ -51,7 +54,7 @@ function print_account_template {
echo "HOST=serverhost.com"
echo "PORT=110"
echo "#SEND=acc-name"
- echo "SEND=|msmtp"
+ echo "SEND=!msmtp"
echo "MAIL=username@domain"
echo "USER='username'"
echo "PASS='password'"
@@ -101,10 +104,19 @@ function add_attachment {
}
function send_message {
- if [ "`echo \"$SEND\" | grep '|'`" ]; then
- echo "=> cat $1 | ${SEND}"
+ FILE=$1
+ # TODO: find a better name for the auto mode
+ if [ "${SEND}" = "!msmtp" ]; then
+ TO="`dmc -H To < $a`" # XXX
+ HOST=`dmc-smtp ${TO}` # XXX
+ msmtp --host=localhost --port=25 --read-envelope-from --auto-from=on < $a
+ if [ $? = 0 ]; then
+ echo "Mail sent! TODO: move from out/ to sent/"
+ fi
+ elif [ "`echo \"${SEND}\" | grep '|'`" ]; then
+ echo "=> cat $1 ${SEND}"
# TODO: setup environment for $TO $SUBJECT ...
- cat $1 | ${SEND}
+ eval cat $1 ${SEND}
else
echo "SEND method '${SEND}' not supported"
fi
@@ -151,6 +163,20 @@ case "$1" in
;;
"pull")
;;
+"-H"|"--header")
+ FILE=$1
+ [ "${FILE}" = "-" ] && FILE=""
+ while : ; do
+ shift
+ [ -z "$1" ] && break
+ grep -e : ${FILE} | grep -re ^$1 | cut -d : -f 2-
+ done
+ ;;
+"-s"|"--send")
+ for a in $* ; do
+ send_message $a
+ done
+ ;;
"-m"|"--mail")
TO="$2"
SUBJECT="$3"
@@ -173,8 +199,21 @@ case "$1" in
"-v"|"--version")
echo "dmc v${VERSION} ${COPYRIGHT}"
;;
-"--help"|"-h"|*)
- echo "Usage: dmc [-e acc] [-a addr] [-m addr subj] [-A file] [-hvdk]"
+"--help"|"-h")
+ echo ${HELP}
+ echo " -e account edit account information"
+ echo " -a name show addressbook email for contact"
+ echo " -m addr subj create mail with default account"
+ echo " -H header grep for header"
+ echo " -A file add attachment to mail"
+ echo " -s file send email"
+ echo " -d start daemon"
+ echo " -h show this help message"
+ echo " push send mails in box/*/out"
+ echo " pull update box/*/in folders"
+ ;;
+*)
+ echo "Usage: dmc [-e acc] [-a addr] [-m addr subj] [-A file] [-s msg] [-hvdk]"
;;
esac
diff --git a/imap4.c b/imap4.c
@@ -1,4 +1,4 @@
-/* dmc :: Copyleft -- pancake (at) nopcode (dot) org */
+/* dmc :: Copyleft 2009 -- pancake (at) nopcode (dot) org */
#include <stdio.h>
#include <string.h>
diff --git a/pop3.c b/pop3.c
@@ -1,4 +1,4 @@
-/* dmc :: Copyleft -- pancake (at) nopcode (dot) org */
+/* dmc :: Copyleft 2009 -- pancake (at) nopcode (dot) org */
#include <stdio.h>
#include <string.h>
@@ -108,13 +108,6 @@ static int doword(char *word) {
return ret;
}
-static void parseoutput(void) {
- while(!feof(stdin)) {
- sleep(1);
- printf("TODO\n");
- }
-}
-
static void cleanup(int foo) {
close(ff);
unlink(fifo);
@@ -122,18 +115,18 @@ static void cleanup(int foo) {
}
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) {
- fprintf(stderr, "Cannot open fifo file.\n");
- return 1;
- }
- waitreply(1);
- while(doword(getword()));
- cleanup(0);
- } else parseoutput();
- return 0;
+ if (ff != -1) {
+ waitreply(1);
+ while(doword(getword()));
+ cleanup(0);
+ ret = 0;
+ } else fprintf(stderr, "Cannot open fifo file.\n");
+ } else fprintf(stderr, "Usage: dmc-pop3 fifo | nc host 110 > fifo\n");
+ return ret;
}
diff --git a/smtp.c b/smtp.c
@@ -1,3 +1,91 @@
-int main() {
+/* dmc :: Copyleft 2009 -- pancake (at) nopcode (dot) org */
+
+#include <stdio.h>
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <netinet/in.h>
+#include <sys/types.h>
+#include <arpa/nameser.h>
+#include <resolv.h>
+#define BIND_4_COMPAT
+
+static int resmx(const char *domain) {
+ char host[NS_MAXDNAME+1];
+ char last[NS_MAXDNAME+1];
+ typedef union {
+ HEADER head;
+ char buf[PACKETSZ];
+ } pkt_t;
+ unsigned char buf[PACKETSZ];
+ unsigned char *rrptr;
+ pkt_t *pkt = (pkt_t *)buf;
+ int querylen, len, n, exprc;
+ int rrtype, antrrtype;
+ int rrpayloadsz;
+
+ querylen = res_querydomain(domain, "", C_IN,T_MX,
+ (void*)&buf, PACKETSZ);
+
+ if (ntohs(pkt->head.rcode) == NOERROR) {
+ n = ntohs(pkt->head.ancount);
+ if (n==0) {
+ fprintf(stderr, "No MX found\n");
+ return 1;
+ }
+
+ /* expand DNS query */
+ len = dn_expand( buf,
+ buf+querylen, buf+sizeof(HEADER),
+ host, sizeof(host));
+
+ if (len<0) {
+ fprintf(stderr, "No MX found\n");
+ return 1;
+ }
+
+ rrptr = buf+sizeof(HEADER)+4+len;
+
+ while(rrptr < buf+querylen) {
+ /* expand NAME resolved */
+ exprc = dn_expand(buf,buf+querylen,rrptr,host,sizeof(host));
+ if (exprc<0) {
+ fprintf(stderr, "No MX found\n");
+ return 1;
+ }
+ rrptr += exprc;
+ rrtype = (rrptr[0]<<8|rrptr[1]);
+ rrpayloadsz = (rrptr[8]<<8|rrptr[9]);
+ rrptr += 10;
+ switch(rrtype) {
+ /* TODO support for IPv6: case T_AAAA: */
+ case T_A:
+ if (strcmp(host, last)) {
+ printf("%s\n", host);
+ if (--n==0) querylen=0;
+ }
+ break;
+ }
+ antrrtype = rrtype;
+ rrptr += rrpayloadsz;
+ }
+ } else {
+ printf("%s\n", domain);
+ //fprintf(stderr, "No MX found\n");
+ return 1;
+ }
+ return 0;
+}
+
+int main(int argc, char **argv) {
+ if (argc>1) {
+ char *ch = strchr(argv[1], '@');
+ if (ch) return resmx(ch+1);
+ else {
+ /* do the daemon stuff here */
+ fprintf(stderr, "TODO: SMTP protocol not yet implemented\n");
+ }
+ } else printf("Usage: dmc-smtp [user@domain] # Get MX for domain\n"
+ "Usage: dmc-smtp fifo | nc host 25 > fifo\n");
return 0;
}