chiark / gitweb /
Merge branches 'idx/verh' and 'idx/qmqpc'
[qmail] / qreceipt.c
1 #include "sig.h"
2 #include "env.h"
3 #include "substdio.h"
4 #include "stralloc.h"
5 #include "subfd.h"
6 #include "getln.h"
7 #include "alloc.h"
8 #include "str.h"
9 #include "hfield.h"
10 #include "token822.h"
11 #include "error.h"
12 #include "gen_alloc.h"
13 #include "gen_allocdefs.h"
14 #include "headerbody.h"
15 #include "exit.h"
16 #include "open.h"
17 #include "quote.h"
18 #include "qmail.h"
19
20 void die_noreceipt() { _exit(0); }
21 void die() { _exit(100); }
22 void die_temp() { _exit(111); }
23 void die_nomem() {
24  substdio_putsflush(subfderr,"qreceipt: fatal: out of memory\n"); die_temp(); }
25 void die_fork() {
26  substdio_putsflush(subfderr,"qreceipt: fatal: unable to fork\n"); die_temp(); }
27 void die_qqperm() {
28  substdio_putsflush(subfderr,"qreceipt: fatal: permanent qmail-queue error\n"); die(); }
29 void die_qqtemp() {
30  substdio_putsflush(subfderr,"qreceipt: fatal: temporary qmail-queue error\n"); die_temp(); }
31 void die_usage() {
32  substdio_putsflush(subfderr,
33  "qreceipt: usage: qreceipt deliveryaddress\n"); die(); }
34 void die_read() {
35  if (errno == error_nomem) die_nomem();
36  substdio_putsflush(subfderr,"qreceipt: fatal: read error\n"); die_temp(); }
37 void doordie(sa,r) stralloc *sa; int r; {
38  if (r == 1) return; if (r == -1) die_nomem();
39  substdio_putsflush(subfderr,"qreceipt: fatal: unable to parse this: ");
40  substdio_putflush(subfderr,sa->s,sa->len); die(); }
41
42 char *target;
43
44 int flagreceipt = 0;
45
46 char *returnpath;
47 stralloc messageid = {0};
48 stralloc sanotice = {0};
49
50 int rwnotice(addr) token822_alloc *addr; { token822_reverse(addr);
51  if (token822_unquote(&sanotice,addr) != 1) die_nomem();
52  if (sanotice.len == str_len(target))
53    if (!str_diffn(sanotice.s,target,sanotice.len))
54      flagreceipt = 1;
55  token822_reverse(addr); return 1; }
56
57 struct qmail qqt;
58
59 stralloc quoted = {0};
60
61 void finishheader()
62 {
63  char *qqx;
64
65  if (!flagreceipt) die_noreceipt();
66  if (str_equal(returnpath,"")) die_noreceipt();
67  if (str_equal(returnpath,"#@[]")) die_noreceipt();
68
69  if (!quote2(&quoted,returnpath)) die_nomem();
70
71  if (qmail_open(&qqt) == -1) die_fork();
72
73  qmail_puts(&qqt,"From: DELIVERY NOTICE SYSTEM <");
74  qmail_put(&qqt,quoted.s,quoted.len);
75  qmail_puts(&qqt,">\n");
76  qmail_puts(&qqt,"To: <");
77  qmail_put(&qqt,quoted.s,quoted.len);
78  qmail_puts(&qqt,">\n");
79  qmail_puts(&qqt,"Subject: success notice\n\
80 \n\
81 Hi! This is the qreceipt program. Your message was delivered to the\n\
82 following address: ");
83  qmail_puts(&qqt,target);
84  qmail_puts(&qqt,". Thanks for asking.\n");
85  if (messageid.s)
86   {
87    qmail_puts(&qqt,"Your ");
88    qmail_put(&qqt,messageid.s,messageid.len);
89   }
90
91  qmail_from(&qqt,"");
92  qmail_to(&qqt,returnpath);
93  qqx = qmail_close(&qqt);
94
95  if (*qqx)
96    if (*qqx == 'D') die_qqperm();
97    else die_qqtemp();
98 }
99
100 stralloc hfbuf = {0};
101 token822_alloc hfin = {0};
102 token822_alloc hfrewrite = {0};
103 token822_alloc hfaddr = {0};
104
105 void doheaderfield(h)
106 stralloc *h;
107 {
108  switch(hfield_known(h->s,h->len))
109   {
110    case H_MESSAGEID:
111      if (!stralloc_copy(&messageid,h)) die_nomem();
112      break;
113    case H_NOTICEREQUESTEDUPONDELIVERYTO:
114      doordie(h,token822_parse(&hfin,h,&hfbuf));
115      doordie(h,token822_addrlist(&hfrewrite,&hfaddr,&hfin,rwnotice));
116      break;
117   }
118 }
119
120 void dobody(h) stralloc *h; { ; }
121
122 void main(argc,argv)
123 int argc;
124 char **argv;
125 {
126  sig_pipeignore();
127  if (!(target = argv[1])) die_usage();
128  if (!(returnpath = env_get("SENDER"))) die_usage();
129  if (headerbody(subfdin,doheaderfield,finishheader,dobody) == -1) die_read();
130  die_noreceipt();
131 }