/*
** Copyright 2000 Double Precision, Inc.  See COPYING for
** distribution information.
*/

#include "rfc2045_config.h"
#include	"rfc2045.h"
#include	"rfc2646.h"
#include	"rfc822/rfc2047.h"
#include	"rfc2045charset.h"
#include	"rfc822/rfc822.h"
#include	<stdio.h>
#include	<unistd.h>
#include	<stdlib.h>
#include	<string.h>
#include	<ctype.h>

static const char rcsid[]="$Id: rfc2045reply.c,v 1.9 2003/03/07 00:47:31 mrsam Exp $";

extern void rfc2045_enomem();

static int mkreply(struct rfc2045_mkreplyinfo *);
static int mkforward(struct rfc2045_mkreplyinfo *);
static struct rfc2045 *do_mixed_fwd(struct rfc2045 *, off_t *);

int rfc2045_makereply_do(struct rfc2045_mkreplyinfo *ri)
{
	if (strcmp(ri->replymode, "forward") == 0
	    || strcmp(ri->replymode, "forwardatt") == 0)
		return (mkforward(ri));

	return (mkreply(ri));
}

static int quotereply(const char *, size_t, void *);

static int flowreply(const char *, size_t, void *);

static void	replybody(struct rfc2045_mkreplyinfo *ri, struct rfc2045 *rfc)
{
	rfc=rfc2045_searchcontenttype(rfc, "text/plain");

	if (!rfc)
		return;

	if (rfc2045_isflowed(rfc))
	{
		struct rfc2646parser *parser;
		struct rfc2646reply *reply;

		reply=rfc2646reply_alloc(&flowreply, ri);
		if (!reply)
			rfc2045_enomem();
		parser=RFC2646REPLY_PARSEALLOC(reply);

		if (!parser)
		{
			rfc2646reply_free(reply);
			rfc2045_enomem();
		}

		(*ri->decodesectionfunc)(ri->fd, rfc, ri->charset,
					 &rfc2646_parse_cb, parser);

		rfc2646_free(parser);
		rfc2646reply_free(reply);
		return;
	}

	ri->start_line=1;
	(*ri->decodesectionfunc)(ri->fd, rfc, ri->charset,
				 &quotereply, ri);
}

static void writes(struct rfc2045_mkreplyinfo *ri, const char *c)
{
	(*ri->write_func)(c, strlen(c), ri->voidarg);
}

static int write_wrap_func(const char *c, size_t n, void *vp)
{
	struct rfc2045_mkreplyinfo *ri=(struct rfc2045_mkreplyinfo *)vp;

	(*ri->write_func)(c, n, ri->voidarg);
	return (0);
}

static int write_flowed_func(const char *c, size_t n, void *vp)
{
	struct rfc2646parser *p=(struct rfc2646parser *)vp;

	return (rfc2646_parse(p, c, n));
}

static int flowreply(const char *c, size_t l, void *voidptr)
{
	struct rfc2045_mkreplyinfo *ri=(struct rfc2045_mkreplyinfo *)voidptr;

	(*ri->write_func)(c, l, ri->voidarg);
	return (0);
}

static int quotereply(const char *p, size_t l, void *voidptr)
{
	struct rfc2045_mkreplyinfo *ri=(struct rfc2045_mkreplyinfo *)voidptr;
	size_t	i, j;

	for (i=j=0; i<l; i++)
	{
		if (p[i] == '\n')
		{
			if (ri->start_line)
				writes(ri, p[j] == '>' ? ">": "> ");
			ri->start_line=0;
			(*ri->write_func)(p+j, i-j, ri->voidarg);
			writes(ri, "\n");
			ri->start_line=1;
			j=i+1;
		}
	}

	if (j < i)
	{
		if (ri->start_line)
			writes(ri, p[j] == '>' ? ">": "> ");
		ri->start_line=0;
		(*ri->write_func)(p+j, i-j, ri->voidarg);
	}
	return (0);
}

static void forwardbody(struct rfc2045_mkreplyinfo *ri, long nbytes)
{
	char	buf[BUFSIZ];
	int	i;

	while ((i=nbytes > sizeof(buf) ? sizeof(buf):nbytes) > 0 &&
	       (i=read(ri->fd, buf, i)) > 0)
	{
		nbytes -= i;
		(*ri->write_func)(buf, i, ri->voidarg);
	}
}

static int mkforward(struct rfc2045_mkreplyinfo *ri)
{
	off_t	start_pos, end_pos, start_body;
	off_t	dummy;

	char	*header, *value;
	char	*subject=0;

	char	*boundary=0;
	struct	rfc2045 *mixed_fwd;
	off_t	orig_startpos;
	int is_flowed_fwd=0;

	struct rfc2045headerinfo *hi;

	rfc2045_mimepos(ri->rfc2045partp, &start_pos, &end_pos, &start_body,
		&dummy, &dummy);

	orig_startpos=start_pos;

	hi=rfc2045header_start(ri->fd, ri->rfc2045partp);

	if (!hi)
		return (-1);

	for (;;)
	{
		if (rfc2045header_get(hi, &header, &value, 0))
		{
			rfc2045header_end(hi);
			return (-1);
		}

		if (!header)
			break;
		if (strcmp(header, "subject") == 0)
		{
			if (subject)	free(subject);
			subject=malloc(strlen(value)+10);
			if (!subject)
				return (-1);

			strcpy(subject, value);
			if (strlen(subject) > 255)
				subject[255]='\0';
		}
	}

	rfc2045header_end(hi);

	writes(ri, "Subject: ");
	if (subject)
	{
		int	dummy;
		char	*s=rfc822_coresubj_nouc(subject, &dummy);

		if (!s)
			return (-1);

		writes(ri, s);
		free(s);
	}
	writes(ri, " (fwd)\nMime-Version: 1.0\n");

	if ((mixed_fwd=strcmp(ri->replymode, "forwardatt") == 0 ? 0:
	     do_mixed_fwd(ri->rfc2045partp, &start_pos)) != 0)
	{
		/* Borrow boundary from the message */

		boundary=strdup(rfc2045_boundary(ri->rfc2045partp));
		if (!boundary)
			return (-1);
 
		writes(ri, "Content-Type: multipart/mixed; boundary=\"");
		writes(ri, boundary);
		writes(ri, "\"\nContent-Transfer-Encoding: 8bit\n\n");
		writes(ri, RFC2045MIMEMSG);
		writes(ri, "--");
		writes(ri, boundary);
		writes(ri, "\n");

		if (rfc2045_isflowed(mixed_fwd))
			is_flowed_fwd=1;

	}
	else
		if (strcmp(ri->replymode, "forwardatt") == 0)
		{
			const char *content_type, *content_transfer_encoding,
				*charset;

			boundary=rfc2045_mk_boundary(ri->rfc2045partp,
						     ri->fd);
			if (!boundary)
				return (-1);

			rfc2045_mimeinfo(ri->rfc2045partp, &content_type,
					 &content_transfer_encoding, &charset);
			writes(ri,
			       "Content-Type: multipart/mixed; boundary=\"");
			writes(ri, boundary);
			writes(ri, "\"\nContent-Transfer-Encoding: ");
			writes(ri, content_transfer_encoding);
			writes(ri, "\n\n");
			writes(ri, RFC2045MIMEMSG);
			writes(ri, "--");
			writes(ri, boundary);
			writes(ri, "\n");
		}
		else if (rfc2045_isflowed(ri->rfc2045partp))
			is_flowed_fwd=1;

	writes(ri, "Content-Type: text/plain; charset=\"");
	writes(ri, ri->charset);
	writes(ri, "\"\n\n");
	(*ri->writesig_func)(ri->voidarg);
	writes(ri, "\n");

	if (!boundary)	/* Not forwarding as attachment */
	{
		if (ri->forwardsep)
		{
			writes(ri, ri->forwardsep);
			writes(ri, "\n");
		}

		/* Copy original headers. */
		
		if (lseek(ri->fd, orig_startpos, SEEK_SET) == -1)
			return (-1);

		forwardbody(ri, start_body - orig_startpos);

		start_pos=start_body;

	}
	else if (mixed_fwd)
	{
		if (ri->forwardsep)
		{
			writes(ri, ri->forwardsep);
			writes(ri, "\n");
		}

		/* Copy original headers. */
		
		if (lseek(ri->fd, orig_startpos, SEEK_SET) == -1)
			return (-1);

		forwardbody(ri, start_body - orig_startpos);

		/* Decode the body of the MIME section */

		if (is_flowed_fwd)
		{
			struct rfc2646fwd *p=rfc2646fwd_alloc(&write_wrap_func,
							      ri);
			struct rfc2646parser *parser;

			if (!p)
				return (-1);

			parser=RFC2646FWD_PARSEALLOC(p);

			if (!parser)
			{
				rfc2646fwd_free(p);
				return (-1);
			}

			(*ri->decodesectionfunc)(ri->fd, mixed_fwd,
						 ri->charset,
						 &write_flowed_func, parser);
			rfc2646_free(parser);
			rfc2646fwd_free(p);
			is_flowed_fwd=0;
		}
		else
			(*ri->decodesectionfunc)(ri->fd, mixed_fwd,
						 ri->charset,
						 &write_wrap_func, ri);

		writes(ri, "\n--");
		writes(ri, boundary);
		writes(ri, "\n");
	}
	else
	{
		writes(ri, "\n--");
		writes(ri, boundary);
		writes(ri, "\nContent-Type: message/rfc822\n");
		if (ri->forwarddescr)
		{
			char *p=rfc2047_encode_str(ri->forwarddescr,
						   ri->charset ?
						   ri->charset : "iso-8859-1");

			writes(ri, "Content-Description: ");
			writes(ri, p ? p:"");
			free(p);
			writes(ri, "\n");
		}
		writes(ri, "\n");
	}

	{
		off_t save_start_body=ri->rfc2045partp->startbody;
		off_t save_end_pos=ri->rfc2045partp->endpos;
		char *save_te=
			ri->rfc2045partp->content_transfer_encoding;

		ri->rfc2045partp->startbody=start_pos;
		ri->rfc2045partp->endpos=end_pos;
		ri->rfc2045partp->content_transfer_encoding="8bit";

		if (is_flowed_fwd)
		{
			struct rfc2646fwd *p=rfc2646fwd_alloc(&write_wrap_func,
							      ri);
			struct rfc2646parser *parser;

			if (!p)
				return (-1);

			ri->rfc2045partp->content_transfer_encoding=save_te;

			parser=RFC2646FWD_PARSEALLOC(p);

			if (!parser)
			{
				rfc2646fwd_free(p);
				return (-1);
			}

			(*ri->decodesectionfunc)(ri->fd, ri->rfc2045partp,
						 ri->charset,
						 &write_flowed_func, parser);
			rfc2646_free(parser);
			rfc2646fwd_free(p);
		}
		else if (strcmp(ri->replymode, "forwardatt") == 0)
		{
			if (lseek(ri->fd, start_pos, SEEK_SET) == 0)
				forwardbody(ri, end_pos - start_pos);
		}
		else	(*ri->decodesectionfunc)(ri->fd, ri->rfc2045partp,
						 ri->charset,
						 &write_wrap_func, ri);

		ri->rfc2045partp->startbody=save_start_body;
		ri->rfc2045partp->endpos=save_end_pos;
		ri->rfc2045partp->content_transfer_encoding=save_te;
	}

	if (boundary)
	{
		if (!mixed_fwd)	/* Already copied */
		{
			writes(ri, "\n--");
			writes(ri, boundary);
			writes(ri, "--\n");
		}
		free(boundary);
	}
	return (0);
}


static int writereferences(struct rfc2045_mkreplyinfo *ri,
			    const char *oldref, const char *oldmsgid)
{
char	*buf=malloc((oldref ? strlen(oldref):0)
		+ (oldmsgid ? strlen(oldmsgid):0)+2);
char	*p, *q;
struct	rfc822t *tp;
struct	rfc822a *ap;
int	i;

	if (!buf)
		return (-1);

	/* Create new references header */
	*buf=0;
	if (oldref)	strcat(buf, oldref);
	if (oldref && oldmsgid)	strcat(buf, " ");
	if (oldmsgid)	strcat(buf, oldmsgid);

	/* Do wrapping the RIGHT way, by
	** RFC822 parsing the References: header
	*/

	if ((tp=rfc822t_alloc_new(buf, NULL, NULL)) == 0 ||
		(ap=rfc822a_alloc(tp)) == 0)
	{
		free(buf);
		if (tp)
			rfc822t_free(tp);
		return (-1);
	}

	/* Keep only the last 20 message IDs */

	i=0;
	if (ap->naddrs > 20)	i=ap->naddrs-20;
	p="";
	while (i < ap->naddrs)
	{
		q=rfc822_gettok(ap->addrs[i].tokens);
		if (!q)
		{
			rfc822a_free(ap);
			rfc822t_free(tp);
			free(buf);
			return (-1);
		}

		writes(ri, p);
		writes(ri, "<");
		writes(ri, q);
		writes(ri, ">\n");
		p="            ";
		free(q);
		i++;
	}
	rfc822a_free(ap);
	rfc822t_free(tp);
	free(buf);
	return (0);
}

static char *mlcheck(struct rfc2045_mkreplyinfo *ri, const char *);

static int mkreply(struct rfc2045_mkreplyinfo *ri)
{
	char	*oldtocc, *oldfrom, *oldreplyto, *oldtolist;
	char	*subject;
	char	*oldmsgid;
	char	*oldreferences;
	char	*header, *value;

	char	*whowrote;
	off_t	start_pos, end_pos, start_body, dummy;
	int errflag=0;
	struct rfc2045headerinfo *hi;

	oldtocc=0;
	oldtolist=0;
	oldfrom=0;
	oldreplyto=0;
	subject=0;
	oldmsgid=0;
	oldreferences=0;
	whowrote=0;

	rfc2045_mimepos(ri->rfc2045partp, &start_pos, &end_pos, &start_body,
		&dummy, &dummy);

	hi=rfc2045header_start(ri->fd, ri->rfc2045partp);

	if (!hi)
		return (-1);

#define BLOWUP { \
		if (whowrote) free(whowrote); \
		if (subject) free(subject); \
		if (oldmsgid) free(oldmsgid); \
		if (oldreferences)	free(oldreferences); \
		if (oldtocc) free(oldtocc); \
		if (oldtolist) free(oldtolist); \
		if (oldfrom) free(oldfrom); \
		if (oldreplyto)	free(oldreplyto); \
		rfc2045header_end(hi); \
		return (-1); \
	}

	for (;;)
	{
		if (rfc2045header_get(hi, &header, &value, 0))
		{
			BLOWUP;
			return (-1);
		}

		if (!header)
			break;

		if (strcmp(header, "subject") == 0)
		{
			if (subject)	free(subject);
			subject=strdup(value);
			if (!subject)
				BLOWUP;
		}
		else if (strcmp(header, "reply-to") == 0)
		{
			if (oldreplyto)	free(oldreplyto);
			oldreplyto=strdup(value);
			if (!oldreplyto)
				BLOWUP;
		}
		else if (strcmp(header, "from") == 0)
		{
			if (oldfrom)	free(oldfrom);
			oldfrom=strdup(value);
			if (!oldfrom)
				BLOWUP;
		}
		else if (strcmp(header, "message-id") == 0)
		{
			if (oldmsgid)	free(oldmsgid);
			oldmsgid=strdup(value);
			if (!oldmsgid)
				BLOWUP;
		}
		else if (strcmp(header, "references") == 0)
		{
			if (oldreferences)	free(oldreferences);
			oldreferences=strdup(value);
			if (!oldreferences)
				BLOWUP;
		}
		else if ((strcmp(ri->replymode, "replyall") == 0
			  || strcmp(ri->replymode, "replylist") == 0) &&
			 (
			  strcmp(header, "to") == 0 ||
			  strcmp(header, "cc") == 0
			  )
			 )
		{
			char	*newh=malloc( (oldtocc ?
					       strlen(oldtocc):0)
					      + strlen(value)+2);
			char	*p;

				if (!newh)
					BLOWUP;

				*newh=0;
				if (oldtocc)
					strcat(strcpy(newh, oldtocc),
								",");
				strcat(newh, value);
				if (oldtocc)	free(oldtocc);
				oldtocc=newh;

				p=mlcheck(ri, value);
				if (!p || (newh=malloc((oldtolist ?
						       strlen(oldtolist):0)
					   + strlen(p)+2)) == NULL)
				{
					if (p)
						free(p);
					BLOWUP;
				}

				if (*p)
				{
					*newh=0;
					if (oldtolist)
						strcat(strcpy(newh, oldtolist),
						       ",");
					strcat(newh, p);
					if (oldtolist)
						free(oldtolist);
					oldtolist=newh;
				}
				free(p);
		}
	}

	rfc2045header_end(hi);

	/* Write:  "%s writes:" */

	if (oldfrom)
	{
		struct	rfc822t *rfcp=rfc822t_alloc_new(oldfrom, NULL, NULL);
		struct	rfc822a *rfcpa;
		char	*p, *q;

		if (!rfcp)
			BLOWUP;

		rfcpa=rfc822a_alloc(rfcp);
		if (!rfcpa)
		{
			rfc822t_free(rfcp);
			BLOWUP;
		}

		p= rfcpa->naddrs > 0 ?
			rfc822_getname(rfcpa, 0):0;
		rfc822a_free(rfcpa);
		rfc822t_free(rfcp);
		if (!p)	p=strdup(oldfrom);
		if (!p)
			BLOWUP;

		q=rfc2047_decode_enhanced(p, ri->charset);
		if (!q)
		{
			free(p);
			BLOWUP;
		}

		free(p);
		p=q;
		whowrote=malloc(strlen(p)+strlen(ri->replysalut)+1);
		if (!whowrote)
		{
			free(p);
			BLOWUP;
		}

		sprintf(whowrote, ri->replysalut, p);
		free(p);
	}

	if (oldreplyto)
	{
		if (oldfrom)	free(oldfrom);
		oldfrom=oldreplyto;
		oldreplyto=0;
	}

	/*
	** Replytolist: if we found mailing list addresses, drop
	** oldtocc, we'll use oldtolist.
	** Otherwise, drop oldtolist.
	*/

	if (strcmp(ri->replymode, "replylist") == 0)
	{
		if (oldtolist)
		{
			if (oldtocc)
			{
				free(oldtocc);
				oldtocc=0;
			}

			if (oldfrom)
			{
				free(oldfrom);
				oldfrom=0;
			}
		}
	}
	else
	{
		if (oldtolist)
		{
			free(oldtolist);
			oldtolist=NULL;
		}
	}

	/* Remove duplicate entries from new Cc header */

	if (oldtocc)
	{
		struct rfc822t	*rfccc, *rfcto;
		struct rfc822a	*arfccc, *arfcto;
		int	i, j;
		char	*new_addresses;

		rfccc=rfc822t_alloc_new(oldtocc, NULL, NULL);
		rfcto= oldfrom ? rfc822t_alloc_new(oldfrom, NULL,
						   NULL):NULL;
		arfccc=rfccc ? rfc822a_alloc(rfccc):NULL;
		arfcto=rfcto ? rfc822a_alloc(rfcto):NULL;

		for (i=0; arfccc && i <arfccc->naddrs; i++)
		{
			char	*addr=rfc822_getaddr(arfccc, i);

			if (!addr)	continue;

				/* Remove address from Cc if it is my address */

			if ( (ri->myaddr_func)(addr, ri->voidarg))
			{
				rfc822_deladdr(arfccc, i); --i;
				free(addr);
				continue;
			}

				/* Remove address from Cc if it appears in To: */

			for (j=0; arfcto && j < arfcto->naddrs; j++)
			{
				char *addr2=rfc822_getaddr(arfcto, j);

				if (!addr2)	continue;
				if (strcmp(addr, addr2) == 0)
				{
					free(addr2);
					break;
				}
				free(addr2);
			}
			if (arfcto && j < arfcto->naddrs)
			{
				rfc822_deladdr(arfccc, i); --i;
				free(addr);
				continue;
			}

				/* Remove outright duplicates in Cc */

			for (j=i+1; j<arfccc->naddrs; j++)
			{
				char *addr2=rfc822_getaddr(arfccc, j);

				if (!addr2)	continue;
				if (strcmp(addr, addr2) == 0)
				{
					rfc822_deladdr(arfccc, j);
					--j;
				}
				free(addr2);
			}
			free(addr);
		}
		new_addresses=rfc822_getaddrs(arfccc);
		free(oldtocc);
		oldtocc=new_addresses;
		if (arfccc)	rfc822a_free(arfccc);
		if (arfcto)	rfc822a_free(arfcto);
		rfc822t_free(rfccc);
		if (rfcto) rfc822t_free(rfcto);
	}

	if (oldtolist)
	{
		writes(ri, "To: ");
		writes(ri, oldtolist);
		writes(ri, "\n");
		free(oldtolist);
	}

	if (oldfrom)
	{
		writes(ri, "To: ");
		writes(ri, oldfrom);
		writes(ri, "\n");
		free(oldfrom);
	}

	if (oldtocc)
	{
		writes(ri, "Cc: ");
		writes(ri, oldtocc);
		writes(ri, "\n");
		free(oldtocc);
	}

	if (oldmsgid || oldreferences)
	{
		writes(ri, "References: ");
		if (writereferences(ri, oldreferences, oldmsgid))
			errflag= -1;
		if (oldreferences)	free(oldreferences);
	}
	if (oldmsgid)
	{
		writes(ri, "In-Reply-To: ");
		writes(ri, oldmsgid);
		writes(ri, "\n");
		free(oldmsgid);
	}
	writes(ri,"Subject: Re: ");
	if (subject)
	{
		int	dummy;
		char	*s=rfc822_coresubj_nouc(subject, &dummy);

		writes(ri, s ? s:"");
		if (s)	free(s);
		free(subject);
	}

	writes(ri, "\n\n");
	if (whowrote)
	{
		writes(ri, whowrote);
		free(whowrote);
		writes(ri, "\n\n");
	}
	if (lseek(ri->fd, start_body, SEEK_SET) == -1)
		return (-1);

	replybody(ri, ri->rfc2045partp);
	writes(ri, "\n");	/* First blank line in the reply */
	(*ri->writesig_func)(ri->voidarg);
	return (errflag);
}

/*****************************************************************************
**
** do_mixed_fwd determines if what we should create for forwarding should be
** a mixture of a portion of the original message, plus attachments.  This
** should happen when the original message has attachments.  Normally, we
** either forward the entire message as text/plain, or as a message/rfc822
** attachment.  When the original message has attachments, it's preferrable
** to keep the original attachments as attachments of the forward message,
** while putting the text portion of the original message in the forwarded
** body.
**
** So, what we check here is this:
**
** A) This is a multipart message with at least two parts.
** B) The first part is text/plain (if it's text/html we'll just quote the
**    whole mess too).  If the first part is multipart/alternative, look
**    inside the multipart/alternative for the text/plain section.
**
** If this is not the case, we return NULL.  Otherwise we return the
** rfc2045 pointer to the text/plain section, and the starting position
** of the first attachment (it's used to reset the starting position of
** the portion of the original message that's copied into the forwarding
** message).
*/

static struct rfc2045 *do_mixed_fwd(struct rfc2045 *p, off_t *f)
{
const char *content_type, *dummy;
off_t	dummyp;

	if (!p->firstpart || !p->firstpart->isdummy ||
		!p->firstpart->next || !p->firstpart->next->next)
		return (0);

	rfc2045_mimepos(p->firstpart->next->next, f, &dummyp, &dummyp,
		&dummyp, &dummyp);

	p=p->firstpart->next;

	rfc2045_mimeinfo(p, &content_type, &dummy, &dummy);

	if (strcmp(content_type, "text/plain") &&
		strcmp(content_type, "text/html") /* GRUMBLE */)
	{
		if (strcmp(content_type, "multipart/alternative"))
			return (0);

		for (p=p->firstpart; p; p=p->next)
		{
			if (p->isdummy)	continue;

			rfc2045_mimeinfo(p, &content_type, &dummy, &dummy);
			if (strcmp(content_type, "text/plain") == 0)
				break;
		}
		if (!p)	return (0);
	}
	return (p);
}

/*
** Accept a list of recipients, and return a list that contains only those
** recipients that are defined as mailing lists.
*/

static char *do_checkmailinglists(struct rfc822a *a,
				  struct rfc2045_mkreplyinfo *,
				  char *);

static char *mlcheck(struct rfc2045_mkreplyinfo *ri, const char *hdr)
{
	struct rfc822t *t;
	struct rfc822a *a;

	char *mlcopy;
	char *p;

	t=rfc822t_alloc_new(hdr, NULL, NULL);

	if (!t)
		return (0);

	a=rfc822a_alloc(t);

	if (!a)
	{
		rfc822t_free(t);
		return (0);
	}

	mlcopy=strdup(ri->mailinglists ? ri->mailinglists:"");
	if (!mlcopy)
		p=0;
	else
	{
		p=do_checkmailinglists(a, ri, mlcopy);
		free(mlcopy);
	}

	rfc822a_free(a);
	rfc822t_free(t);
	return (p);
}

static char *do_checkmailinglists(struct rfc822a *a,
				  struct rfc2045_mkreplyinfo *ri,
				  char *mlbuffer)
{
	int i;

	for (i=0; i<a->naddrs; i++)
	{
		char *p=rfc822_getaddr(a, i);
		char *q;

		if (!p)
			return (NULL);

		strcpy(mlbuffer, ri->mailinglists ? ri->mailinglists:"");

		for (q=mlbuffer; (q=strtok(q, "\n \t")) != NULL; q=NULL)
		{
			if (strcasecmp(p, q) == 0)
				break;
		}

		free(p);
		if (q == NULL)
		{
			rfc822_deladdr(a, i);
			--i;
		}
	}

	if (a->naddrs == 0)
		return (strdup(""));
	return (rfc822_getaddrs(a));
}
