#include #include "alloc.h" #include "buffer.h" #include "env.h" #include "error.h" #include "exit.h" #include "getln.h" #include "open.h" #include "sig.h" #include "str.h" #include "stralloc.h" #include "headerbody.h" #include "hfield.h" #include "qmail.h" #include "quote.h" #include "token822.h" #define WHO "qreceipt" static void die_noreceipt() { _exit(0); } static void die() { _exit(100); } static void die_temp() { _exit(111); } static void die_nomem() { buffer_putsflush(buffer_2, "qreceipt: fatal: out of memory\n"); die_temp(); } static void die_fork() { buffer_putsflush(buffer_2, "qreceipt: fatal: unable to fork\n"); die_temp(); } static void die_qqperm() { buffer_putsflush(buffer_2, "qreceipt: fatal: permanent qmail-queue error\n"); die(); } static void die_qqtemp() { buffer_putsflush(buffer_2, "qreceipt: fatal: temporary qmail-queue error\n"); die_temp(); } static void die_usage() { buffer_putsflush(buffer_2, "qreceipt: usage: qreceipt deliveryaddress\n"); die(); } static void die_read() { if (errno == ENOMEM) die_nomem(); buffer_putsflush(buffer_2, "qreceipt: fatal: read error\n"); die_temp(); } static void doordie(stralloc *sa, int r) { if (r == 1) return; if (r == -1) die_nomem(); buffer_putsflush(buffer_2, "qreceipt: fatal: unable to parse this: "); buffer_putflush(buffer_2, sa->s, sa->len); die(); } char *target; int flagreceipt = 0; char *returnpath; stralloc messageid = {0}; stralloc sanotice = {0}; static int rwnotice(token822_alloc *addr) { token822_reverse(addr); if (token822_unquote(&sanotice, addr) != 1) die_nomem(); if (sanotice.len == str_len(target)) if (!str_diffn(sanotice.s, target, sanotice.len)) flagreceipt = 1; token822_reverse(addr); return 1; } struct qmail qqt; stralloc quoted = {0}; static void finishheader() { char *qqx; if (!flagreceipt) die_noreceipt(); if (str_equal(returnpath, "")) die_noreceipt(); if (str_equal(returnpath, "#@[]")) die_noreceipt(); if (!quote2("ed, returnpath)) die_nomem(); if (qmail_open(&qqt) == -1) die_fork(); qmail_puts(&qqt, "From: DELIVERY NOTICE SYSTEM <"); qmail_put(&qqt, quoted.s, quoted.len); qmail_puts(&qqt, ">\n"); qmail_puts(&qqt, "To: <"); qmail_put(&qqt, quoted.s, quoted.len); qmail_puts(&qqt, ">\n"); qmail_puts( &qqt, "Subject: success notice\n\n" "Hi! This is the qreceipt program. Your message was delivered to the\n" "following address: "); qmail_puts(&qqt, target); qmail_puts(&qqt, ". Thanks for asking.\n"); if (messageid.s) { qmail_puts(&qqt, "Your "); qmail_put(&qqt, messageid.s, messageid.len); } qmail_from(&qqt, ""); qmail_to(&qqt, returnpath); qqx = qmail_close(&qqt); if (*qqx) { if (*qqx == 'D') die_qqperm(); else die_qqtemp(); } } stralloc hfbuf = {0}; token822_alloc hfin = {0}; token822_alloc hfrewrite = {0}; token822_alloc hfaddr = {0}; static void doheaderfield(stralloc *h) { switch (hfield_known(h->s, h->len)) { case H_MESSAGEID: if (!stralloc_copy(&messageid, h)) die_nomem(); break; case H_NOTICEREQUESTEDUPONDELIVERYTO: doordie(h, token822_parse(&hfin, h, &hfbuf)); doordie(h, token822_addrlist(&hfrewrite, &hfaddr, &hfin, rwnotice)); break; } } static void dobody(stralloc *h) {} int main(int argc, char **argv) { sig_pipeignore(); if (!(target = argv[1])) die_usage(); if (!(returnpath = env_get("SENDER"))) die_usage(); if (headerbody(buffer_0, doheaderfield, finishheader, dobody) == -1) die_read(); die_noreceipt(); }