2 * rfc822.c -- code for slicing and dicing RFC822 mail headers
4 * Copyright 1996 by Eric S. Raymond
6 * For license terms, see the file COPYING in this directory.
12 #if defined(STDC_HEADERS)
16 #include "fetchmail.h"
18 void reply_hack(buf, host)
19 /* hack message headers so replies will work properly */
20 char *buf; /* header to be hacked */
21 const char *host; /* server hostname */
24 int parendepth, state = 0, tokencount = 0;
25 char mycopy[POPBUFSIZE+1];
27 if (strncmp("From: ", buf, 6)
28 && strncmp("To: ", buf, 4)
29 && strncmp("Reply-", buf, 6)
30 && strncmp("Cc: ", buf, 4)
31 && strncmp("Bcc: ", buf, 5)) {
36 for (from = mycopy; *from; from++)
40 case 0: /* before header colon */
45 case 1: /* we've seen the colon, we're looking for addresses */
48 else if (*from == '(')
53 else if (*from == '<' || isalnum(*from))
55 else if (isspace(*from))
59 case 2: /* found a token boundary -- reset without copying */
60 if (*from != ' ' && *from != '\t')
68 case 3: /* we're in a quoted human name, copy and ignore */
73 case 4: /* we're in a parenthesized human name, copy and ignore */
76 else if (*from == ')')
82 case 5: /* the real work gets done here */
84 * We're in something that might be an address part,
85 * either a bare unquoted/unparenthesized text or text
86 * enclosed in <> as per RFC822.
88 /* if the address part contains an @, don't mess with it */
92 /* If the address token is not properly terminated, ignore it. */
93 else if (*from == ' ' || *from == '\t')
98 * The only lookahead case. If we're looking at space or tab,
99 * we might be looking at a local name immediately followed
102 for (cp = from; isspace(*cp); cp++)
114 * On proper termination with no @, insert hostname.
115 * Case '>' catches <>-enclosed mail IDs. Case ',' catches
116 * comma-separated bare IDs.
118 else if (strchr(">,", *from))
127 /* a single local name alone on the line */
128 else if (*from == '\n' && tokencount == 1)
136 /* everything else, including alphanumerics, just passes through */
139 case 6: /* we're in a remote mail ID, no need to append hostname */
140 if (*from == '>' || *from == ',' || isspace(*from))
145 /* all characters from the old buffer get copied to the new one */
152 /* parse addresses in succession out of a specified RFC822 header */
153 const char *hdr; /* header to be parsed, NUL to continue previous hdr */
155 static char *tp, address[POPBUFSIZE+1];
156 static const char *hp;
161 * Note 1: RFC822 escaping with \ is *not* handled. Note 2: it is
162 * important that this routine not stop on \r, since we use \r as
163 * a marker for RFC822 continuations elsewhere.
176 case 0: /* before header colon */
189 case 1: /* we've seen the colon, now grab the address */
190 if (*hp == '\n') /* end of address list */
194 return(tp = address);
196 else if (*hp == ',') /* end of address */
202 return(tp = address);
205 else if (*hp == '"') /* quoted string */
210 else if (*hp == '(') /* address comment -- ignore */
215 else if (*hp == '<') /* begin <address> */
220 else if (isspace(*hp)) /* ignore space */
222 else /* just take it */
229 case 2: /* we're in a quoted string, copy verbatim */
244 case 3: /* we're in a parenthesized comment, ignore */
255 case 4: /* possible <>-enclosed address */
256 if (*hp == '>') /* end of address */
261 return(tp = address);
263 else if (*hp == '<') /* nested <> */
265 else if (*hp == '"') /* quoted address */
270 else /* just copy address */
274 case 5: /* we're in a quoted address, copy verbatim */
275 if (*hp == '\n') /* mismatched quotes */
280 if (*hp != '"') /* just copy it if it isn't a quote */
282 else if (*hp == '"') /* end of quoted string */
289 case 6: /* after last address */
299 main(int argc, char *argv[])
301 char buf[POPBUFSIZE], *cp;
303 while (fgets(buf, sizeof(buf)-1, stdin))
305 if (strncmp("From: ", buf, 6)
306 && strncmp("To: ", buf, 4)
307 && strncmp("Reply-", buf, 6)
308 && strncmp("Cc: ", buf, 4)
309 && strncmp("Bcc: ", buf, 5))
312 if ((cp = nxtaddr(buf)) != (char *)NULL)
314 printf("Address: %s\n", cp);
316 ((cp = nxtaddr((char *)NULL)) != (char *)NULL);
320 #endif /* TESTMAIN */