8 #define USERAGENT "neatmail (git://repo.or.cz/neatmail.git)"
10 static void msg_new(char **msg
, long *msglen
);
11 static int msg_reply(char *msg
, long msglen
, char **mod
, long *modlen
);
12 static int msg_forward(char *msg
, long msglen
, char **mod
, long *modlen
);
14 static char *segment(char *d
, char *s
, int m
)
16 char *r
= strchr(s
, m
);
17 char *e
= r
? r
+ 1 : strchr(s
, '\0');
23 static int msg_filter(char *msg
, long msglen
, char **mod
, long *modlen
, char *hdrs
)
25 struct sbuf
*sb
= sbuf_make();
26 char *hdr
= malloc(strlen(hdrs
) + 1);
28 char *e
= msg
+ msglen
;
29 while ((hdrs
= segment(hdr
, hdrs
, ':')) && hdr
[0]) {
30 char *val
= msg_get(msg
, msglen
, hdr
);
32 sbuf_mem(sb
, val
, hdrlen(val
, msg
+ msglen
- val
));
35 while (s
+ 1 < e
&& (s
[0] != '\n' || s
[1] != '\n'))
38 sbuf_mem(sb
, s
, e
- s
);
39 *modlen
= sbuf_len(sb
);
45 "usage: neatmail pg [options] mbox msg\n\n"
47 " -h hdrs \tthe list of headers to include\n"
48 " -m \tdecode mime message\n"
49 " -r \tgenerate a reply\n"
50 " -f \tgenerate a forward\n"
51 " -n \tgenerate a new message\n";
64 for (i
= 0; argv
[i
] && argv
[i
][0] == '-'; i
++) {
65 if (argv
[i
][1] == 'm')
67 if (argv
[i
][1] == 'r')
69 if (argv
[i
][1] == 'n')
71 if (argv
[i
][1] == 'f')
73 if (argv
[i
][1] == 'h') {
74 hdrs
= argv
[i
][2] ? argv
[i
] + 2 : argv
[++i
];
79 msg_new(&msg
, &msglen
);
80 xwrite(1, msg
, msglen
);
84 if (!argv
[i
] || !argv
[i
+ 1]) {
90 if (!mbox_ith(mbox
, atoi(addr
), &msg
, &msglen
)) {
91 if (demime
&& !msg_demime(msg
, msglen
, &mod
, &modlen
)) {
96 if (reply
&& !msg_reply(msg
, msglen
, &mod
, &modlen
)) {
101 if (hdrs
&& !msg_filter(msg
, msglen
, &mod
, &modlen
, hdrs
)) {
106 if (forward
&& !msg_forward(msg
, msglen
, &mod
, &modlen
)) {
111 xwrite(1, msg
, msglen
);
117 static void put_from_(struct sbuf
*sb
)
122 strftime(buf
, sizeof(buf
), "%a %b %d %H:%M:%S %Y", localtime(&t
));
123 sbuf_printf(sb
, "From %s %s\n",
124 getenv("LOGNAME") ? getenv("LOGNAME") : "me", buf
);
127 static void put_date(struct sbuf
*sb
)
132 strftime(buf
, sizeof(buf
), "%a, %d %b %Y %H:%M:%S %z", localtime(&t
));
133 sbuf_printf(sb
, "Date: %s\n", buf
);
136 static void put_id(struct sbuf
*sb
)
139 char host
[32] = "neatmail";
142 strftime(buf
, sizeof(buf
), "%Y%d%m%H%M%S", localtime(&t
));
143 sbuf_printf(sb
, "Message-ID: <%s.%s>\n", host
, buf
);
146 static void put_agent(struct sbuf
*sb
)
148 sbuf_printf(sb
, "User-Agent: " USERAGENT
"\n");
151 static void msg_new(char **msg
, long *msglen
)
153 struct sbuf
*sb
= sbuf_make();
155 sbuf_printf(sb
, "From: \n");
156 sbuf_printf(sb
, "To: \n");
157 sbuf_printf(sb
, "Subject: \n");
162 *msglen
= sbuf_len(sb
);
163 *msg
= sbuf_done(sb
);
166 static char *hdr_val(char *hdr
)
168 hdr
= strchr(hdr
, ':') + 1;
169 while (isspace(*hdr
))
174 static int hdr_len(char *hdr
)
176 int l
= hdrlen(hdr
, 1024);
177 while (l
> 0 && strchr(" \r\n", (unsigned char) hdr
[l
- 1]))
182 static void put_subjreply(struct sbuf
*sb
, char *subj
)
184 subj
= hdr_val(subj
);
185 sbuf_str(sb
, "Subject: ");
186 if (tolower(subj
[0]) != 'r' || tolower(subj
[1]) != 'e')
187 sbuf_str(sb
, "Re: ");
188 sbuf_mem(sb
, subj
, hdr_len(subj
));
192 static void put_subjfwd(struct sbuf
*sb
, char *subj
)
194 subj
= hdr_val(subj
);
195 sbuf_str(sb
, "Subject: ");
196 sbuf_str(sb
, "Fwd: ");
197 sbuf_mem(sb
, subj
, hdr_len(subj
));
201 static void put_replyto(struct sbuf
*sb
, char *id
, char *ref
)
204 sbuf_str(sb
, "In-Reply-To: ");
205 sbuf_mem(sb
, id
, hdr_len(id
));
207 sbuf_str(sb
, "References: ");
210 sbuf_mem(sb
, ref
, hdr_len(ref
));
211 sbuf_str(sb
, "\n\t");
213 sbuf_mem(sb
, id
, hdr_len(id
));
217 static void put_reply(struct sbuf
*sb
, char *from
, char *to
, char *cc
, char *rply
)
220 char *hdr
= rply
? rply
: from
;
222 sbuf_str(sb
, "To: ");
223 sbuf_mem(sb
, hdr
, hdr_len(hdr
));
226 if (to
|| cc
|| (rply
&& from
)) {
228 sbuf_str(sb
, "Cc: ");
232 sbuf_str(sb
, "\n\t");
233 sbuf_mem(sb
, to
, hdr_len(to
));
236 from
= hdr_val(from
);
238 sbuf_str(sb
, "\n\t");
239 sbuf_mem(sb
, from
, hdr_len(from
));
244 sbuf_str(sb
, "\n\t");
245 sbuf_mem(sb
, cc
, hdr_len(cc
));
251 static void quote_body(struct sbuf
*sb
, char *msg
, long msglen
)
253 char *from
= msg_get(msg
, msglen
, "From:");
255 char *e
= msg
+ msglen
;
256 while (s
+ 1 < e
&& (s
[0] != '\n' || s
[1] != '\n'))
261 from
= hdr_val(from
);
262 sbuf_mem(sb
, from
, hdr_len(from
));
263 sbuf_str(sb
, " wrote:\n");
266 char *r
= memchr(s
, '\n', e
- s
);
270 sbuf_mem(sb
, s
, r
- s
+ 1);
275 static int msg_reply(char *msg
, long msglen
, char **mod
, long *modlen
)
277 struct sbuf
*sb
= sbuf_make();
278 char *id_hdr
= msg_get(msg
, msglen
, "Message-ID:");
279 char *ref_hdr
= msg_get(msg
, msglen
, "References:");
280 char *from_hdr
= msg_get(msg
, msglen
, "From:");
281 char *subj_hdr
= msg_get(msg
, msglen
, "Subject:");
282 char *to_hdr
= msg_get(msg
, msglen
, "To:");
283 char *cc_hdr
= msg_get(msg
, msglen
, "CC:");
284 char *rply_hdr
= msg_get(msg
, msglen
, "Reply-To:");
287 sbuf_printf(sb
, "From: \n");
288 put_reply(sb
, from_hdr
, to_hdr
, cc_hdr
, rply_hdr
);
290 put_subjreply(sb
, subj_hdr
);
293 put_replyto(sb
, id_hdr
, ref_hdr
);
295 quote_body(sb
, msg
, msglen
);
296 *modlen
= sbuf_len(sb
);
297 *mod
= sbuf_done(sb
);
301 static int msg_forward(char *msg
, long msglen
, char **mod
, long *modlen
)
303 struct sbuf
*sb
= sbuf_make();
304 char *subj_hdr
= msg_get(msg
, msglen
, "Subject:");
307 sbuf_printf(sb
, "From: \n");
308 sbuf_printf(sb
, "To: \n");
309 put_subjfwd(sb
, subj_hdr
);
312 sbuf_str(sb
, "\n-------- Original Message --------\n");
313 sbuf_mem(sb
, msg
, msglen
);
314 *modlen
= sbuf_len(sb
);
315 *mod
= sbuf_done(sb
);